/**
 * Pure session state tracker — zero external imports.
 *
 * Lives in `core/` so that `ToolExecutionContext` (in `core-types.ts`) can
 * reference it without violating the boundary rule that `core/` never imports
 * from `app/`.
 *
 * Combines two concerns:
 *   1. Read-before-edit tracking — which files has the agent read this session?
 *   2. File-unchanged optimization — content hash per file so tools can skip
 *      re-reading files whose content hasn't changed since the last read.
 *   3. Session-scoped filesystem approval grants.
 */
/**
 * Tracks per-file read state and an internal turn counter for the agent session.
 *
 * All paths must be absolute. The class does not normalize or validate paths —
 * callers are responsible for canonicalization.
 */
export class SessionState {
    /** Backing store: absolute path -> read snapshot (used for hash caching). */
    _reads = new Map();
    /** Paths that have been read at any point — never cleared by markModified. */
    _everRead = new Set();
    /** Monotonically increasing turn counter. */
    _currentTurn = 0;
    /** Session-scoped filesystem approval grants. */
    _filesystemApprovalGrants = [];
    // ---------------------------------------------------------------------------
    // Turn management
    // ---------------------------------------------------------------------------
    /** Current turn number. */
    get currentTurn() {
        return this._currentTurn;
    }
    /** Advance the turn counter by one. Call once per agent loop iteration. */
    incrementTurn() {
        this._currentTurn++;
    }
    // ---------------------------------------------------------------------------
    // Read tracking
    // ---------------------------------------------------------------------------
    /**
     * Record that a file was read with the given content hash at a specific turn.
     *
     * @param absolutePath — Canonical absolute path of the file.
     * @param contentHash  — Hash of the file content at read time.
     * @param turnNumber   — The turn in which the read occurred.
     */
    markRead(absolutePath, contentHash, turnNumber) {
        this._reads.set(absolutePath, { hash: contentHash, turnNumber });
        this._everRead.add(absolutePath);
    }
    /** Whether the file has been read at any point during this session. */
    hasBeenRead(absolutePath) {
        return this._everRead.has(absolutePath);
    }
    /**
     * Return the cached read state for a file, or `undefined` if the file has
     * not been read (or was invalidated by {@link markModified}).
     */
    getReadState(absolutePath) {
        return this._reads.get(absolutePath);
    }
    /**
     * Invalidate cached read state for a file.
     *
     * Call this when a tool modifies a file so the next read returns full
     * content instead of a "file unchanged" short-circuit.
     */
    markModified(absolutePath) {
        this._reads.delete(absolutePath);
    }
    // ---------------------------------------------------------------------------
    // Filesystem approval grants
    // ---------------------------------------------------------------------------
    grantFilesystemAccess(path, access, scope) {
        const alreadyGranted = this._filesystemApprovalGrants.some((grant) => grant.path === path && grant.access === access && grant.scope === scope);
        if (!alreadyGranted) {
            this._filesystemApprovalGrants.push({ path, access, scope });
        }
    }
    getFilesystemApprovalGrants() {
        return [...this._filesystemApprovalGrants];
    }
}
//# sourceMappingURL=session-state.js.map