import type { AsyncLineIterator } from '../../io/async_line_iterator.ts'; import { type EnvEntries } from '../../secrets/config.ts'; import type { ShellArray } from '../../shell/array.ts'; import type { ShellVar } from '../../shell/variable.ts'; import type { AdmissionRules, Decision, HideReason, ProfileScript } from '../../policy/types.ts'; import { type CommandsJSON, type DecisionJSON, type ScriptJSON } from './serialize.ts'; import type { HiddenPaths, HiddenVars, ShownPaths } from '../../types.ts'; import type { MountMode } from '../../types.ts'; /** * What a child shell gets its own copy of, and the parent gets back * afterwards. A `( … )` subshell and a nested `bash`/`sh` are both child * shells and both read this shape, so neither can drift into isolating a * field the other leaks, and adding a field here is a compile error * until `snapshot` and `restore` both carry it. `lastExitCode` is * deliberately absent: `$?` after a child shell is the child's status, * which is the one thing it reports back. `sourceDepth` is here because a * child shell starts outside any `source` its caller is inside. */ export interface ChildShellState { cwd: string; logicalCwd: string | undefined; sourceDepth: number; vars: Record; functions: Record; readonlyFunctions: Set; shellOptions: Record; positionalArgs: string[]; scriptName: string | null; lastBgJobId: number | null; getoptsPos: number; getoptsOptind: number | null; shopts: Record; aliases: Record; umask: number; execStdout: string | null; execStdoutAppend: boolean; execStderr: string | null; execStderrAppend: boolean; execStdin: Uint8Array | null; execOpened: Set; } /** * Read one entry of a session record, ignoring anything inherited from * `Object.prototype`. Shell names are script-controlled, so a plain * `record[name]` lookup would hand back `Object.prototype` (or one of * its methods) for a name like `__proto__` or `toString`; Python's dicts * have no such shadow, so this guard is the TypeScript side only. */ export declare function sessionEntry(record: Record, name: string): T | undefined; /** * Write one entry of a session record as an own property. A plain * `record[name] = value` on the name `__proto__` runs the inherited * setter instead: it silently drops a string value and rewrites the * record's prototype for an array one. */ export declare function setSessionEntry(record: Record, name: string, value: T): void; /** * A copy of `record` with a null prototype. Session records (env, * functions, arrays) hold script-controlled names, so they must not * inherit from `Object.prototype`: on a plain object, reading a name * like `toString` hands back an inherited function and assigning * `__proto__` runs the inherited setter instead of storing the value. * With no prototype, every name is an ordinary key. Python's dicts * need no equivalent. */ export declare function ownRecord(record?: Record): Record; export interface SessionInit { sessionId: string; cwd?: string; logicalCwd?: string | undefined; vars?: Record; createdAt?: number; functions?: Record; readonlyFunctions?: Set; lastExitCode?: number; positionalArgs?: string[]; scriptName?: string | null; shellOptions?: Record; /** * Per-mount mode caps for this session. `null` (the default) means * no restriction: every mount in the workspace is reachable at its own * mode. When provided, a mount absent from the map is invisible * (dispatch / handle_command / Ops reject it with a capability error) * and a present mount is narrowed to the weaker of its own mode and * the session's mode. The workspace always implicitly grants its own * infrastructure mounts (implicit scratch root, observer, /dev). */ mountModes?: ReadonlyMap | null; /** * Per-session visibility narrowing, siblings of mountModes: null * means unrestricted, the doors enforce (data door for paths, the * session door for vars), fork carries them, toJSON serializes. */ hiddenPaths?: HiddenPaths | null; /** * The show half of the path axis: re-opened subtrees and per-subtree * modes, resolved against hiddenPaths by anchor depth. */ shownPaths?: ShownPaths | null; hiddenVars?: HiddenVars | null; /** * The operator's reasons for grouped hides: never rendered to the * agent (a reason on ENOENT would confirm the path exists), * persisted so the host's read-back doors survive a restart. */ hideReasons?: readonly HideReason[]; /** * The session's own command tier (`profiles..commands` tightened * by the inline document): allow patterns, ask and deny rules. A * durable restriction like hiddenPaths, so it persists. */ commands?: AdmissionRules | null; /** * The profile's per-command script, evaluated by ScriptPolicy at the * admission gate. A durable restriction like commands, so it * persists. */ script?: ProfileScript | null; /** * The name of the profile the session runs under, null for an * unrestricted session. What an owner-rendering command prints as the * group. Stamped by the profile like script, so it persists. */ profile?: string | null; /** * The host's standing answers to asked lines (design 3.9): session * state like functions and cwd, persisted, read and written through * the manager by id so a fork shares them, never another session's. */ decisions?: readonly Decision[]; generation?: number; pipelineTimeoutSeconds?: number | null; lastBgJobId?: number | null; } /** * Variable records for a plain name/value map. The one conversion from * the shape an embedder speaks (a process environment) to the shape the * session stores. * * Every seeded name is exported, because a process environment is by * definition the exported set: these are the names the embedder means a * child runtime to inherit, and `envSnapshot` hands on only what carries * the attribute. Seeding them plain would leave them visible to `$X` and * invisible to every runtime, which is not what an embedder passing an * env record is asking for. */ export declare function varsFromEnv(env: Record): Record; /** * Variable records for a stored session's two halves, the restore side * of `toJSON`. `env` carries every scalar and `attrs` the letter cluster * for the names that have one, so a name in `attrs` alone is bash's * declared-but-unset third state (`export Z`) and restores with no value. * * Not `varsFromEnv`: that one reads a bare record as a *process* * environment and exports all of it, which is right for an embedder * handing over an env record and wrong here, where the attributes were * recorded. Restoring through it promoted every plain `X=hello` to an * exported one on the first reload. */ export declare function varsFromDict(env: Record, attrs: Record): Record; /** * Variable records for a workspace env block. * * The declaration side of the env plane: a bare string is the literal * short form (exported, like `varsFromEnv`), a mapping is coerced * through `EnvVarSchema`, and a managed entry becomes bash's third * state -- exported, unset -- carrying the pointer as `ManagedRef`. * After this translation the session vars are the only truth the fill * step reads. */ export declare function varsFromEntries(entries: EnvEntries): Record; /** The wire shape `varsToFields` writes and `varsFromFields` reads. */ export interface VarFields { env?: Record; var_attrs?: Record; managed?: Record; } /** * The stored shape of a bare variable table. * * The three keys a stored session writes (`toJSON`): `env` holds the * plain scalars, `var_attrs` the letter clusters, `managed` the * pointers -- and a managed name serializes as its pointer, never its * value, the same rule the session codec states. This exists for the * workspace env template, a variable table with no session around it, * so a snapshot or copy can carry the declaration. */ export declare function varsToFields(table: Record): VarFields; /** * The variable table a `varsToFields` payload restores. * * `varsFromDict` reads the two plain halves; each managed name then * restores declared-but-unfetched, its value forced back to null so a * payload that smuggles one in is discarded rather than trusted -- * exactly how `fromJSON` restores a stored session's vars. */ export declare function varsFromFields(data: VarFields): Record; export declare class Session { sessionId: string; cwd: string; logicalCwd: string | undefined; vars: Record; createdAt: number; functions: Record; readonlyFunctions: Set; lastExitCode: number; positionalArgs: string[]; scriptName: string | null; shellOptions: Record; errexitImmune: boolean; sourceDepth: number; stdinBuffer: AsyncLineIterator | null; stdinSource: unknown; localVars: Map | null; getoptsPos: number; getoptsOptind: number | null; abortSignal: AbortSignal | null; cmdsubSeq: number; cmdsubStatus: number; shopts: Record; aliases: Record; aliasMarks: Map; aliasStack: string[]; parseSeq: number; parseCurrent: number; umask: number; execStdout: string | null; execStdoutAppend: boolean; execStderr: string | null; execStderrAppend: boolean; execStdin: Uint8Array | null; execOpened: Set; localFrames: Map[]; mountModes: ReadonlyMap | null; hiddenPaths: HiddenPaths | null; shownPaths: ShownPaths | null; hiddenVars: HiddenVars | null; hideReasons: readonly HideReason[]; commands: AdmissionRules | null; script: ProfileScript | null; profile: string | null; decisions: readonly Decision[]; generation: number; pipelineTimeoutSeconds: number | null; lastBgJobId: number | null; constructor(init: SessionInit); /** * Return a copy of this session with `overrides` applied. Mutable * containers (env, functions, readonlyVars, arrays, positionalArgs) * are shallow-copied so mutations on the fork do not leak back into * the source. Every field — including capability fields like * `mountModes` — is propagated, so callers cannot accidentally * forget one when adding new fields. * * A caller that moves the fork with `cwd` supplies a physical path * with no typed spelling behind it, so the source's logical name is * dropped rather than left describing where the fork is not — the same * reasoning as `shell_dirs.setCwd`. Deciding it here rather than at * each call site is what keeps `execute({cwd})` from reporting the * persistent session's old directory from `pwd`. `??` cannot express * this, since the value being chosen is `undefined`. */ fork(overrides?: Partial): Session; /** * What `$0` expands to. Null is the shell itself; a nested `bash`/`sh` * sets it to the script it is running, or to the name given after * `-c`. An empty name is a name, so it is not folded into the default: * GNU `bash -c 'echo "[$0]"' ""` prints `[]`. */ get argv0(): string; /** * The scalar variables, by name. * * A frozen read-only projection of `vars`, not a container: a writer * goes through `SessionView.set` (or `seedVar` when seeding a session * before it is narrowed), so a `pre_session` policy sees every write. * `state.ts` has always documented that rule; freezing the projection * is what stops it being walked around by assigning into storage, and * an assignment into a plain object would land in a throwaway and * vanish -- silent loss is the exact failure this store removes. */ get env(): Readonly>; /** The indexed arrays, by name. Read-only, like `env`. */ get arrays(): Readonly>; /** The associative arrays, by name. Read-only, like `env`. */ get assocs(): Readonly>>; /** The names `readonly` has marked. Read-only, like `env`. */ get readonlyVars(): ReadonlySet; /** * Copy the state a child shell runs on top of. The records go through * `ownRecord` because they hold script-controlled names and must keep * their null prototype across the round trip. */ snapshot(): ChildShellState; /** Put back a snapshot, ending a child shell. */ restore(state: ChildShellState): void; /** * The durable-field payload persisted by SessionStore and snapshots. * Keys are snake_case, byte-identical to Python's `Session.to_dict`, * so both languages can share one store (a py daemon creates the * session, a node kernel tier binds it). */ toJSON(): Record; static fromJSON(data: { session_id: string; cwd?: string; env?: Record; var_attrs?: Record; managed?: Record | null; created_at?: number; mount_modes?: Record | null; hidden_paths?: { paths?: string[]; patterns?: string[]; } | null; shown_paths?: { entries?: { path: string; mode?: MountMode; }[]; } | null; hide_reasons?: { patterns?: string[]; reason?: string; }[] | null; hidden_vars?: { names?: string[]; patterns?: string[]; } | null; commands?: CommandsJSON | null; script?: ScriptJSON | null; profile?: string | null; decisions?: DecisionJSON[] | null; generation?: number; }): Session; } //# sourceMappingURL=session.d.ts.map