@code-yeongyu/senpi 2026.9.4-3 → 2026.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/dist/core/agent-session.d.ts +17 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +62 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts +5 -0
- package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/model-usability-budget.js +11 -4
- package/dist/core/extensions/builtin/compaction/model-usability-budget.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts +9 -5
- package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js +20 -11
- package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js.map +1 -1
- package/dist/core/extensions/builtin/recommended-models/index.d.ts +1 -1
- package/dist/core/extensions/builtin/recommended-models/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/recommended-models/index.js +1 -0
- package/dist/core/extensions/builtin/recommended-models/index.js.map +1 -1
- package/dist/core/extensions/builtin/service-tier.d.ts.map +1 -1
- package/dist/core/extensions/builtin/service-tier.js +12 -4
- package/dist/core/extensions/builtin/service-tier.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/durable-command.d.ts +31 -0
- package/dist/core/extensions/builtin/terminal/durable-command.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/durable-command.js +96 -0
- package/dist/core/extensions/builtin/terminal/durable-command.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/durable-file.d.ts +42 -0
- package/dist/core/extensions/builtin/terminal/durable-file.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/durable-file.js +102 -0
- package/dist/core/extensions/builtin/terminal/durable-file.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/extension.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/extension.js +58 -13
- package/dist/core/extensions/builtin/terminal/extension.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-notify.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-notify.js +5 -1
- package/dist/core/extensions/builtin/terminal/monitor-notify.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts +29 -0
- package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-registry.js +49 -0
- package/dist/core/extensions/builtin/terminal/monitor-registry.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-status.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-status.js +21 -1
- package/dist/core/extensions/builtin/terminal/monitor-status.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/prompt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/prompt.js +9 -5
- package/dist/core/extensions/builtin/terminal/prompt.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/restore.d.ts +13 -0
- package/dist/core/extensions/builtin/terminal/restore.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/restore.js +31 -3
- package/dist/core/extensions/builtin/terminal/restore.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/shared.d.ts +25 -0
- package/dist/core/extensions/builtin/terminal/shared.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/shared.js +25 -0
- package/dist/core/extensions/builtin/terminal/shared.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/terminal-manifest-model.d.ts +91 -0
- package/dist/core/extensions/builtin/terminal/terminal-manifest-model.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/terminal-manifest-model.js +14 -0
- package/dist/core/extensions/builtin/terminal/terminal-manifest-model.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/terminal-manifest.d.ts +29 -77
- package/dist/core/extensions/builtin/terminal/terminal-manifest.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/terminal-manifest.js +61 -15
- package/dist/core/extensions/builtin/terminal/terminal-manifest.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/monitor.js +59 -11
- package/dist/core/extensions/builtin/terminal/tools/monitor.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +18 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/retry-fallback/chains.d.ts +1 -13
- package/dist/core/retry-fallback/chains.d.ts.map +1 -1
- package/dist/core/retry-fallback/chains.js +3 -49
- package/dist/core/retry-fallback/chains.js.map +1 -1
- package/dist/core/retry-fallback/controller.d.ts.map +1 -1
- package/dist/core/retry-fallback/controller.js +4 -9
- package/dist/core/retry-fallback/controller.js.map +1 -1
- package/dist/core/retry-fallback/expansion.js +1 -1
- package/dist/core/retry-fallback/expansion.js.map +1 -1
- package/dist/core/retry-fallback/settings.d.ts +2 -4
- package/dist/core/retry-fallback/settings.d.ts.map +1 -1
- package/dist/core/retry-fallback/settings.js +7 -36
- package/dist/core/retry-fallback/settings.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +10 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/settings.md +1 -0
- package/docs/terminal-tools.md +35 -4
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +12 -0
- package/node_modules/@code-yeongyu/senpi-codemode/README.md +2 -2
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/extension/session-manager.ts +8 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/display-image.js +162 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/prelude.ts +2 -2
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-runtime.js +29 -60
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/py/prelude.py +66 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +3 -3
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/types.ts +2 -2
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js +3 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-codex-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +14 -9
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.d.ts +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +6 -4
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +30 -0
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +30 -0
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.d.ts +3 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.js +27 -3
- package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/azure-openai-responses.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/github-copilot.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai-codex.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openai.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitor-registry.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/monitor-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomBytes } from \"node:crypto\";\nimport { type FSWatcher, watch } from \"node:fs\";\nimport { access, type FileHandle, lstat, open, realpath, stat } from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport type { TerminalRuntimeSession } from \"./runtime-session.ts\";\nimport { describeExit } from \"./tools/spawn.ts\";\n\nexport interface MonitorLineEvent {\n\treadonly type: \"line\";\n\treadonly id: string;\n\treadonly description: string;\n\treadonly line: string;\n}\n\nexport interface MonitorSummaryEvent {\n\treadonly type: \"summary\";\n\treadonly id: string;\n\treadonly description: string;\n\treadonly summary: string;\n}\n\nexport type MonitorEvent = MonitorLineEvent | MonitorSummaryEvent;\n\nexport type MonitorRearmResult = \"rearmed\" | \"not_paused\" | \"not_found\";\n\nexport interface MonitorResumeResult {\n\treadonly id: string;\n\treadonly mutedDropped: number;\n}\n\nconst MONITOR_ID_ALPHABET = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\n\n/** Allocate a stable monitor identity: \"mon_\" + 16 Crockford base-32 chars (80 random bits). */\nexport function allocateMonitorId(): string {\n\tlet id = \"mon_\";\n\tlet buffer = 0;\n\tlet bits = 0;\n\tfor (const byte of randomBytes(10)) {\n\t\tbuffer = (buffer << 8) | byte;\n\t\tbits += 8;\n\t\twhile (bits >= 5) {\n\t\t\tbits -= 5;\n\t\t\tid += MONITOR_ID_ALPHABET[(buffer >> bits) & 31];\n\t\t}\n\t}\n\treturn id;\n}\n\nexport interface MonitorSnapshotEntry {\n\treadonly id: string;\n\t/** Stable \"mon_\" identity carried alongside the runtime id; always set on live snapshots. */\n\treadonly monitorId?: string;\n\treadonly description: string;\n\treadonly paused: boolean;\n\t/** Epoch milliseconds when the watch registered; feeds the footer's live elapsed label. */\n\treadonly startedAtMs: number;\n}\n\nexport interface MonitorRegistryOptions {\n\t/** Observes every registry transition (register/pause/rearm/settle/dispose) with the live snapshot. */\n\treadonly onChange?: (snapshot: readonly MonitorSnapshotEntry[]) => void;\n\t/** Reserves one shared terminal capacity slot for a native watch. */\n\treadonly reserve?: () => (() => void) | null;\n}\n\nexport interface RegisterFileMonitorOptions {\n\treadonly description: string;\n\treadonly path: string;\n\t/** Caller-supplied stable identity so a restore can re-bind the same \"mon_\" id. */\n\treadonly monitorId?: string;\n\treadonly event: \"create\" | \"modify\";\n\treadonly timeoutMs: number;\n\treadonly cwd: string;\n\treadonly approvedParent?: string;\n}\n\nexport interface RegisterMonitorOptions {\n\treadonly id: string;\n\t/** Caller-supplied stable identity so a restore can re-bind the same \"mon_\" id. */\n\treadonly monitorId?: string;\n\treadonly description: string;\n\treadonly runtime: TerminalRuntimeSession;\n\treadonly filter?: RegExp;\n}\n\ninterface PendingFileRegistration {\n\trelease: (() => void) | undefined;\n\treadonly abort: AbortController;\n\treadonly deadline: ReturnType<typeof setTimeout>;\n\tsettled: boolean;\n}\n\ninterface FileMonitorRecord {\n\treadonly id: string;\n\treadonly monitorId: string;\n\treadonly sessionId: string;\n\treadonly description: string;\n\treadonly startedAtMs: number;\n\treadonly path: string;\n\treadonly canonicalPath: string;\n\treadonly canonicalParent: string;\n\treadonly event: \"create\" | \"modify\";\n\treadonly watcher: FSWatcher;\n\treadonly release: () => void;\n\treadonly poll: ReturnType<typeof setInterval>;\n\tpaused: boolean;\n\tsettled: boolean;\n\tpresent: boolean;\n\tmtimeMs: number;\n\tsize: number;\n\tdigest: string;\n\tdevice: number;\n\tinode: number;\n\tpendingChange: boolean;\n\tdirty: boolean;\n\tdirtyPasses: number;\n\tdirtyWindowStartedAt: number;\n\tchecking: Promise<void> | undefined;\n\treadonly deadline: ReturnType<typeof setTimeout>;\n}\n\ninterface MonitorRecord {\n\treadonly id: string;\n\treadonly monitorId: string;\n\treadonly sessionId: string;\n\treadonly description: string;\n\treadonly startedAtMs: number;\n\treadonly runtime: TerminalRuntimeSession;\n\treadonly filter: RegExp | undefined;\n\tlineBuffer: string;\n\tmutedDropped: number;\n\tpaused: boolean;\n\tsettled: boolean;\n\tunsubscribeOutput: (() => void) | undefined;\n\tunsubscribeExit: (() => void) | undefined;\n}\n\n/**\n * Tracks active monitor sessions alongside the terminal manager's existing bash-id registry.\n * Output is deliberately retained only by TerminalRuntimeSession's bounded history; this\n * registry holds at most one unfinished line for each live monitor.\n */\nexport class MonitorRegistry {\n\treadonly #records = new Map<string, MonitorRecord>();\n\treadonly #emit: (event: MonitorEvent) => void;\n\treadonly #onChange: ((snapshot: readonly MonitorSnapshotEntry[]) => void) | undefined;\n\treadonly #reserve: (() => (() => void) | null) | undefined;\n\treadonly #files = new Map<string, FileMonitorRecord>();\n\t#nextFileId = 1;\n\t#disposed = false;\n\t#pendingRegistrations = 0;\n\treadonly #pending = new Set<PendingFileRegistration>();\n\t#lifecycle = 0;\n\n\tconstructor(emit: (event: MonitorEvent) => void, options?: MonitorRegistryOptions) {\n\t\tthis.#emit = emit;\n\t\tthis.#onChange = options?.onChange;\n\t\tthis.#reserve = options?.reserve;\n\t}\n\n\tsnapshot(): readonly MonitorSnapshotEntry[] {\n\t\treturn [...this.#records.values(), ...this.#files.values()].map((record) => ({\n\t\t\tid: record.id,\n\t\t\tmonitorId: record.monitorId,\n\t\t\tdescription: record.description,\n\t\t\tpaused: record.paused,\n\t\t\tstartedAtMs: record.startedAtMs,\n\t\t}));\n\t}\n\n\tasync registerFile(options: RegisterFileMonitorOptions): Promise<{ id: string; monitorId: string }> {\n\t\tif (this.#disposed) throw new Error(\"Cannot create file monitor: monitor registry is disposed.\");\n\t\tthis.#pendingRegistrations += 1;\n\t\tconst lifecycle = this.#lifecycle;\n\t\tconst release = this.#reserve?.();\n\t\tif (this.#reserve && !release) {\n\t\t\tthis.#pendingRegistrations -= 1;\n\t\t\tthrow new Error(\"Cannot create file monitor: terminal capacity is already in use.\");\n\t\t}\n\t\tconst pending: PendingFileRegistration = {\n\t\t\trelease: release ?? undefined,\n\t\t\tabort: new AbortController(),\n\t\t\tdeadline: setTimeout(() => pending.abort.abort(), options.timeoutMs),\n\t\t\tsettled: false,\n\t\t};\n\t\tthis.#pending.add(pending);\n\t\tconst path = resolve(options.cwd, options.path);\n\t\tconst parent = dirname(path);\n\t\tlet approvedParent: string;\n\t\ttry {\n\t\t\tawait this.#registrationAwait(pending, access(parent));\n\t\t\tapprovedParent = await this.#registrationAwait(pending, realpath(parent));\n\t\t\tconst approvedParentAtPermission = options.approvedParent;\n\t\t\tif (approvedParentAtPermission !== undefined && approvedParent !== approvedParentAtPermission) {\n\t\t\t\tthrow new Error(`Cannot watch file: parent directory changed during permission approval: ${parent}`);\n\t\t\t}\n\t\t\tif (this.#disposed) throw new Error(\"Cannot create file monitor: monitor registry is disposed.\");\n\t\t} catch (error) {\n\t\t\tthis.#finishPending(pending);\n\t\t\tthis.#pendingRegistrations -= 1;\n\t\t\tif (error instanceof Error && error.message.includes(\"disposed\")) throw error;\n\t\t\tif ((error as NodeJS.ErrnoException)?.code !== \"ENOENT\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot access parent directory ${parent}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow new Error(`Cannot watch file: parent directory does not exist: ${parent}`);\n\t\t}\n\t\tlet initial: Awaited<ReturnType<typeof stat>> | null = null;\n\t\tlet initialHandle: FileHandle | undefined;\n\t\ttry {\n\t\t\tconst target = await this.#registrationAwait(pending, lstat(path));\n\t\t\tif (target.isSymbolicLink()) throw new Error(`Cannot watch file: target is a symbolic link: ${path}`);\n\t\t\tinitialHandle = await this.#registrationAwait(pending, open(path, \"r\"), async (handle) => {\n\t\t\t\tawait handle.close();\n\t\t\t});\n\t\t\tinitial = await this.#registrationAwait(pending, initialHandle.stat());\n\t\t\tif (!initial.isFile()) throw new Error(`Cannot watch file: target is not a regular file: ${path}`);\n\t\t\tconst resolvedTarget = await this.#registrationAwait(pending, realpath(path));\n\t\t\tif (resolvedTarget !== join(approvedParent, basename(path)))\n\t\t\t\tthrow new Error(`Cannot watch file: target identity changed: ${path}`);\n\t\t\tconst rebound = await this.#registrationAwait(pending, lstat(path));\n\t\t\tif (rebound.isSymbolicLink()) throw new Error(`Cannot watch file: target identity changed: ${path}`);\n\t\t\tconst reboundStat = await this.#registrationAwait(pending, stat(path));\n\t\t\tif (!reboundStat.isFile() || reboundStat.dev !== initial.dev || reboundStat.ino !== initial.ino)\n\t\t\t\tthrow new Error(`Cannot watch file: target identity changed: ${path}`);\n\t\t} catch (error) {\n\t\t\tawait initialHandle?.close();\n\t\t\tinitialHandle = undefined;\n\t\t\tif ((error as NodeJS.ErrnoException)?.code !== \"ENOENT\") {\n\t\t\t\tthis.#finishPending(pending);\n\t\t\t\tthis.#pendingRegistrations -= 1;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\tif (this.#disposed || lifecycle !== this.#lifecycle || this.#pendingRegistrations < 1) {\n\t\t\tthis.#finishPending(pending);\n\t\t\tthis.#pendingRegistrations -= 1;\n\t\t\tthrow new Error(\"Cannot create file monitor: monitor registry is disposed.\");\n\t\t}\n\t\tconst id = `watch_${this.#nextFileId++}`;\n\t\tlet watcher: FSWatcher;\n\t\ttry {\n\t\t\tconst activationParent = await this.#registrationAwait(pending, realpath(parent));\n\t\t\tif (activationParent !== approvedParent) {\n\t\t\t\tthrow new Error(`Cannot watch file: parent directory changed during registration: ${parent}`);\n\t\t\t}\n\t\t\twatcher = watch(activationParent, (_kind, name) => {\n\t\t\t\tif (!name || basename(String(name)) === basename(path)) void this.#checkFile(id);\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis.#finishPending(pending);\n\t\t\tthis.#pendingRegistrations -= 1;\n\t\t\tthrow new Error(`Cannot watch file ${path}: ${error instanceof Error ? error.message : String(error)}`);\n\t\t}\n\t\tlet registrationError: string | undefined;\n\t\twatcher.on(\"error\", (error) => {\n\t\t\tregistrationError = `watcher error: ${error instanceof Error ? error.message : String(error)}`;\n\t\t\tconst record = this.#files.get(id);\n\t\t\tif (record) this.#settleFile(record, registrationError);\n\t\t});\n\t\tlet registrationCleaned = false;\n\t\tconst finishRegistration = () => {\n\t\t\tif (registrationCleaned) return;\n\t\t\tregistrationCleaned = true;\n\t\t\tthis.#pendingRegistrations -= 1;\n\t\t};\n\t\tconst cleanupRegistration = () => {\n\t\t\tif (registrationCleaned) return;\n\t\t\twatcher.close();\n\t\t\tfinishRegistration();\n\t\t\tthis.#finishPending(pending);\n\t\t};\n\t\tif (this.#disposed || lifecycle !== this.#lifecycle) {\n\t\t\tcleanupRegistration();\n\t\t\tthrow new Error(\"Cannot create file monitor: monitor registry is disposed.\");\n\t\t}\n\t\tconst canonicalPath = join(approvedParent, basename(path));\n\t\tlet digest: string;\n\t\ttry {\n\t\t\tdigest =\n\t\t\t\tinitial && initialHandle\n\t\t\t\t\t? await this.#registrationAwait(pending, this.#digestHandle(initialHandle, pending.abort.signal))\n\t\t\t\t\t: \"\";\n\t\t} catch (error) {\n\t\t\tcleanupRegistration();\n\t\t\tawait initialHandle?.close();\n\t\t\tinitialHandle = undefined;\n\t\t\tif (registrationError) {\n\t\t\t\tthis.#emit({ type: \"summary\", id, description: options.description, summary: registrationError });\n\t\t\t\tthrow new Error(registrationError);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tawait initialHandle?.close();\n\t\tinitialHandle = undefined;\n\t\tif (registrationError) {\n\t\t\tcleanupRegistration();\n\t\t\tthis.#emit({ type: \"summary\", id, description: options.description, summary: registrationError });\n\t\t\tthrow new Error(registrationError);\n\t\t}\n\t\tif (this.#disposed || lifecycle !== this.#lifecycle) {\n\t\t\tcleanupRegistration();\n\t\t\tthrow new Error(\"Cannot create file monitor: monitor registry is disposed.\");\n\t\t}\n\t\tconst record: FileMonitorRecord = {\n\t\t\tid,\n\t\t\tmonitorId: options.monitorId ?? allocateMonitorId(),\n\t\t\tsessionId: id,\n\t\t\tdescription: options.description,\n\t\t\tstartedAtMs: Date.now(),\n\t\t\tpath,\n\t\t\tcanonicalPath,\n\t\t\tcanonicalParent: approvedParent,\n\t\t\tevent: options.event,\n\t\t\twatcher,\n\t\t\trelease: release ?? (() => {}),\n\t\t\tpoll: setInterval(() => void this.#checkFile(id), 250),\n\t\t\tpaused: false,\n\t\t\tsettled: false,\n\t\t\tpresent: initial !== null,\n\t\t\tmtimeMs: initial?.mtimeMs ?? 0,\n\t\t\tsize: initial?.size ?? 0,\n\t\t\tdigest,\n\t\t\tdevice: initial?.dev ?? 0,\n\t\t\tinode: initial?.ino ?? 0,\n\t\t\tpendingChange: false,\n\t\t\tdirty: false,\n\t\t\tdirtyPasses: 0,\n\t\t\tdirtyWindowStartedAt: 0,\n\t\t\tchecking: undefined,\n\t\t\tdeadline: setTimeout(() => {\n\t\t\t\tconst current = this.#files.get(id);\n\t\t\t\tif (current) this.#settleFile(current, \"watcher timed_out\");\n\t\t\t}, options.timeoutMs),\n\t\t};\n\t\tthis.#files.set(id, record);\n\t\tfinishRegistration();\n\t\tthis.#finishPending(pending, true);\n\t\tif (registrationError || this.#disposed || lifecycle !== this.#lifecycle) {\n\t\t\tthis.#settleFile(record, registrationError ?? \"watcher killed\");\n\t\t\tthrow new Error(registrationError ?? \"Cannot create file monitor: monitor registry is disposed.\");\n\t\t}\n\t\tthis.#notifyChange();\n\t\treturn { id, monitorId: record.monitorId };\n\t}\n\n\tasync stopFile(id: string): Promise<boolean> {\n\t\tconst record = this.#files.get(id);\n\t\tif (!record) return false;\n\t\tthis.#settleFile(record, \"watcher killed\");\n\t\treturn true;\n\t}\n\n\tasync stopAllFiles(): Promise<number> {\n\t\tthis.#lifecycle += 1;\n\t\tconst records = [...this.#files.values()];\n\t\tfor (const record of records) this.#settleFile(record, \"watcher killed\");\n\t\tfor (const pending of [...this.#pending]) this.#finishPending(pending);\n\t\treturn records.length;\n\t}\n\n\t#settleFile(record: FileMonitorRecord, summary: string): void {\n\t\tif (record.settled) return;\n\t\trecord.settled = true;\n\t\tclearInterval(record.poll);\n\t\tclearTimeout(record.deadline);\n\t\trecord.watcher.close();\n\t\trecord.release();\n\t\tthis.#files.delete(record.id);\n\t\tthis.#notifyChange();\n\t\tthis.#emit({ type: \"summary\", id: record.id, description: record.description, summary });\n\t}\n\n\tasync #checkFile(id: string): Promise<void> {\n\t\tconst record = this.#files.get(id);\n\t\tif (!record || record.settled) return;\n\t\tif (record.checking) {\n\t\t\trecord.dirty = true;\n\t\t\treturn;\n\t\t}\n\t\trecord.checking = this.#checkFileImpl(record)\n\t\t\t.catch((error) => {\n\t\t\t\tif (!record.settled)\n\t\t\t\t\tthis.#settleFile(record, `watcher error: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\trecord.checking = undefined;\n\t\t\t\tconst now = Date.now();\n\t\t\t\tif (now - record.dirtyWindowStartedAt >= 1_000) {\n\t\t\t\t\trecord.dirtyWindowStartedAt = now;\n\t\t\t\t\trecord.dirtyPasses = 0;\n\t\t\t\t}\n\t\t\t\tif (record.dirty && !record.settled && record.dirtyPasses < 1) {\n\t\t\t\t\trecord.dirty = false;\n\t\t\t\t\trecord.dirtyPasses += 1;\n\t\t\t\t\tvoid this.#checkFile(id);\n\t\t\t\t} else {\n\t\t\t\t\trecord.dirty = false;\n\t\t\t\t}\n\t\t\t});\n\t\treturn record.checking;\n\t}\n\n\tasync #checkFileImpl(record: FileMonitorRecord): Promise<void> {\n\t\tif (record.settled) return;\n\t\tlet current: Awaited<ReturnType<typeof stat>> | null = null;\n\t\tlet handle: FileHandle | undefined;\n\t\ttry {\n\t\t\tconst currentParent = await realpath(dirname(record.path));\n\t\t\tif (currentParent !== record.canonicalParent) {\n\t\t\t\tthis.#settleFile(record, `watcher error: monitored parent changed: ${dirname(record.path)}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst target = await lstat(record.canonicalPath);\n\t\t\tif (target.isSymbolicLink()) throw new Error(`Cannot watch file: target identity changed: ${record.path}`);\n\t\t\tconst resolvedTarget = await realpath(record.canonicalPath);\n\t\t\tif (resolvedTarget !== record.canonicalPath)\n\t\t\t\tthrow new Error(`Cannot watch file: target identity changed: ${record.path}`);\n\t\t\thandle = await open(record.canonicalPath, \"r\");\n\t\t\tconst opened = await handle.stat();\n\t\t\tif (!opened.isFile()) throw new Error(`Cannot watch file: target is not a regular file: ${record.path}`);\n\t\t\tif ((opened.dev !== record.device || opened.ino !== record.inode) && opened.nlink > 1)\n\t\t\t\tthrow new Error(`Cannot watch file: target identity changed: ${record.path}`);\n\t\t\tcurrent = opened;\n\t\t\tconst rebound = await lstat(record.canonicalPath);\n\t\t\tif (rebound.isSymbolicLink()) throw new Error(`Cannot watch file: target identity changed: ${record.path}`);\n\t\t\tconst reboundPath = await stat(record.canonicalPath);\n\t\t\tif (!reboundPath.isFile() || reboundPath.dev !== opened.dev || reboundPath.ino !== opened.ino)\n\t\t\t\tthrow new Error(`Cannot watch file: target identity changed: ${record.path}`);\n\t\t} catch (error) {\n\t\t\tawait handle?.close();\n\t\t\tif ((error as NodeJS.ErrnoException)?.code !== \"ENOENT\") {\n\t\t\t\tthis.#settleFile(record, `watcher error: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tconst present = current !== null;\n\t\tlet digest = \"\";\n\t\ttry {\n\t\t\tdigest = present && handle ? await this.#digestHandle(handle) : \"\";\n\t\t\tif (present && handle) {\n\t\t\t\tconst afterDigest = await stat(record.canonicalPath);\n\t\t\t\tconst opened = await handle.stat();\n\t\t\t\tif (afterDigest.dev !== opened.dev || afterDigest.ino !== opened.ino)\n\t\t\t\t\tthrow new Error(`Cannot watch file: target identity changed: ${record.path}`);\n\t\t\t}\n\t\t} finally {\n\t\t\tawait handle?.close();\n\t\t}\n\t\tconst changed =\n\t\t\trecord.event === \"create\"\n\t\t\t\t? !record.present && present\n\t\t\t\t: record.present &&\n\t\t\t\t\tpresent &&\n\t\t\t\t\t(current!.mtimeMs !== record.mtimeMs || current!.size !== record.size || digest !== record.digest);\n\t\trecord.pendingChange ||= changed;\n\t\tif (!record.present && current) {\n\t\t\trecord.device = current.dev;\n\t\t\trecord.inode = current.ino;\n\t\t}\n\t\trecord.present = present;\n\t\trecord.mtimeMs = current?.mtimeMs ?? 0;\n\t\trecord.size = current?.size ?? 0;\n\t\trecord.digest = digest;\n\t\tif (!record.pendingChange || record.paused || record.settled) return;\n\t\trecord.pendingChange = false;\n\t\tif (record.settled) return;\n\t\tthis.#emit({\n\t\t\ttype: \"line\",\n\t\t\tid: record.id,\n\t\t\tdescription: record.description,\n\t\t\tline: `${record.event} ${record.path}`,\n\t\t});\n\t\tthis.#settleFile(record, \"watcher completed\");\n\t}\n\n\tregister(options: RegisterMonitorOptions): string {\n\t\tconst record: MonitorRecord = {\n\t\t\tid: options.id,\n\t\t\tmonitorId: options.monitorId ?? allocateMonitorId(),\n\t\t\tsessionId: options.id,\n\t\t\tdescription: options.description,\n\t\t\tstartedAtMs: Date.now(),\n\t\t\truntime: options.runtime,\n\t\t\tfilter: options.filter,\n\t\t\tlineBuffer: \"\",\n\t\t\tmutedDropped: 0,\n\t\t\tpaused: false,\n\t\t\tsettled: false,\n\t\t\tunsubscribeOutput: undefined,\n\t\t\tunsubscribeExit: undefined,\n\t\t};\n\t\tthis.#records.set(record.id, record);\n\t\tthis.#notifyChange();\n\n\t\t// Runtime output is already bounded. Read what was produced before monitor registration,\n\t\t// then subscribe synchronously so a fast watcher cannot lose its first line.\n\t\tthis.#consume(record, record.runtime.fullOutput());\n\t\trecord.unsubscribeOutput = record.runtime.onOutput((chunk) => this.#consume(record, chunk));\n\t\trecord.unsubscribeExit = record.runtime.session.onExit(() => this.#settle(record));\n\t\tif (record.runtime.exited) this.#settle(record);\n\t\treturn record.monitorId;\n\t}\n\n\tpause(ids: readonly string[]): string[] {\n\t\tconst paused: string[] = [];\n\t\tfor (const id of ids) {\n\t\t\tconst record = this.#records.get(id) ?? this.#files.get(id);\n\t\t\tif (!record || record.paused) continue;\n\t\t\trecord.paused = true;\n\t\t\tpaused.push(record.id);\n\t\t}\n\t\tif (paused.length > 0) this.#notifyChange();\n\t\treturn paused;\n\t}\n\n\tpauseAll(): string[] {\n\t\treturn this.pause([...this.#records.keys(), ...this.#files.keys()]);\n\t}\n\n\tresume(ids?: readonly string[]): MonitorResumeResult[] {\n\t\tconst candidates = ids ?? [...this.#records.keys(), ...this.#files.keys()];\n\t\tconst resumed: MonitorResumeResult[] = [];\n\t\tfor (const id of candidates) {\n\t\t\tconst record = this.#records.get(id) ?? this.#files.get(id);\n\t\t\tif (!record?.paused) continue;\n\t\t\trecord.paused = false;\n\t\t\tconst mutedDropped = \"mutedDropped\" in record ? record.mutedDropped : 0;\n\t\t\tif (\"mutedDropped\" in record) record.mutedDropped = 0;\n\t\t\tresumed.push({ id: record.id, mutedDropped });\n\t\t\tif (\"pendingChange\" in record && record.pendingChange) void this.#checkFile(record.id);\n\t\t}\n\t\tif (resumed.length > 0) this.#notifyChange();\n\t\treturn resumed;\n\t}\n\n\tmutedDropped(id: string): number {\n\t\treturn this.#records.get(id)?.mutedDropped ?? 0;\n\t}\n\n\trearm(id: string): MonitorRearmResult {\n\t\tconst record = this.#records.get(id) ?? this.#files.get(id);\n\t\tif (!record) return \"not_found\";\n\t\tif (!record.paused) return \"not_paused\";\n\t\tthis.resume([id]);\n\t\treturn \"rearmed\";\n\t}\n\n\tdispose(): void {\n\t\tthis.#disposed = true;\n\t\tthis.#lifecycle += 1;\n\t\tfor (const record of this.#records.values()) this.#disposeRecord(record);\n\t\tfor (const record of this.#files.values()) this.#settleFile(record, \"watcher disposed\");\n\t\tfor (const pending of this.#pending) this.#finishPending(pending);\n\t\tthis.#records.clear();\n\t\tthis.#notifyChange();\n\t}\n\n\t#finishPending(pending: PendingFileRegistration, transfer = false): void {\n\t\tif (pending.settled) return;\n\t\tpending.settled = true;\n\t\tclearTimeout(pending.deadline);\n\t\tthis.#pending.delete(pending);\n\t\tif (transfer) pending.release = undefined;\n\t\telse {\n\t\t\tpending.abort.abort();\n\t\t\tpending.release?.();\n\t\t}\n\t}\n\n\tasync #registrationAwait<T>(\n\t\tpending: PendingFileRegistration,\n\t\toperation: Promise<T>,\n\t\tlateCleanup?: (value: T) => Promise<void>,\n\t): Promise<T> {\n\t\tif (pending.abort.signal.aborted) {\n\t\t\tvoid operation.then(\n\t\t\t\t(value) => lateCleanup?.(value),\n\t\t\t\t() => undefined,\n\t\t\t);\n\t\t\tthrow new Error(\"Cannot create file monitor: registration timed out or was disposed.\");\n\t\t}\n\t\tlet aborted = false;\n\t\tconst abort = new Promise<never>((_, reject) =>\n\t\t\tpending.abort.signal.addEventListener(\n\t\t\t\t\"abort\",\n\t\t\t\t() => {\n\t\t\t\t\taborted = true;\n\t\t\t\t\treject(new Error(\"Cannot create file monitor: registration timed out or was disposed.\"));\n\t\t\t\t},\n\t\t\t\t{ once: true },\n\t\t\t),\n\t\t);\n\t\tconst guarded = operation.then(\n\t\t\t(value) => {\n\t\t\t\tif (aborted) void lateCleanup?.(value);\n\t\t\t\treturn value;\n\t\t\t},\n\t\t\t(error) => {\n\t\t\t\tif (aborted) return undefined as T;\n\t\t\t\tthrow error;\n\t\t\t},\n\t\t);\n\t\treturn Promise.race([guarded, abort]);\n\t}\n\n\tasync #digestHandle(handle: FileHandle, signal?: AbortSignal): Promise<string> {\n\t\tconst SAMPLE_SIZE = 64 * 1024;\n\t\tif (signal?.aborted) throw new Error(\"file monitor registration cancelled\");\n\t\tconst metadata = await handle.stat();\n\t\tconst hash = createHash(\"sha256\");\n\t\tconst first = Buffer.alloc(Math.min(SAMPLE_SIZE, metadata.size));\n\t\tif (first.length > 0) {\n\t\t\tawait handle.read(first, 0, first.length, 0);\n\t\t\thash.update(first);\n\t\t}\n\t\tif (metadata.size > SAMPLE_SIZE) {\n\t\t\tconst middle = Buffer.alloc(SAMPLE_SIZE);\n\t\t\tawait handle.read(middle, 0, middle.length, Math.floor((metadata.size - middle.length) / 2));\n\t\t\thash.update(middle);\n\t\t\tconst last = Buffer.alloc(SAMPLE_SIZE);\n\t\t\tawait handle.read(last, 0, last.length, metadata.size - last.length);\n\t\t\thash.update(last);\n\t\t}\n\t\treturn `${metadata.size}:${hash.digest(\"hex\")}`;\n\t}\n\n\t#notifyChange(): void {\n\t\tthis.#onChange?.(this.snapshot());\n\t}\n\n\t#consume(record: MonitorRecord, chunk: string): void {\n\t\tif (record.settled || chunk.length === 0) return;\n\t\tlet remaining = record.lineBuffer + chunk;\n\t\tfor (;;) {\n\t\t\tconst newline = remaining.indexOf(\"\\n\");\n\t\t\tif (newline < 0) break;\n\t\t\tconst rawLine = remaining.slice(0, newline);\n\t\t\tremaining = remaining.slice(newline + 1);\n\t\t\tconst line = rawLine.endsWith(\"\\r\") ? rawLine.slice(0, -1) : rawLine;\n\t\t\tconst matchesFilter = !record.filter || record.filter.test(line);\n\t\t\tif (!matchesFilter) continue;\n\t\t\tif (record.paused) {\n\t\t\t\trecord.mutedDropped += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.#emit({ type: \"line\", id: record.id, description: record.description, line });\n\t\t}\n\t\trecord.lineBuffer = remaining;\n\t}\n\n\t#settle(record: MonitorRecord): void {\n\t\tif (record.settled) return;\n\t\trecord.settled = true;\n\t\trecord.unsubscribeOutput?.();\n\t\trecord.unsubscribeExit?.();\n\t\tthis.#records.delete(record.id);\n\t\tthis.#notifyChange();\n\t\tconst status = describeExit(record.runtime) ?? \"exited\";\n\t\tconst code = record.runtime.exitResult?.exitCode;\n\t\tconst codeText = code === null || code === undefined ? \"\" : ` (exit code ${code})`;\n\t\tthis.#emit({\n\t\t\ttype: \"summary\",\n\t\t\tid: record.id,\n\t\t\tdescription: record.description,\n\t\t\tsummary: `watcher ${status}${codeText}`,\n\t\t});\n\t}\n\n\t#disposeRecord(record: MonitorRecord): void {\n\t\trecord.settled = true;\n\t\trecord.unsubscribeOutput?.();\n\t\trecord.unsubscribeExit?.();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"monitor-registry.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/monitor-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomBytes } from \"node:crypto\";\nimport { type FSWatcher, watch } from \"node:fs\";\nimport { access, type FileHandle, lstat, open, realpath, stat } from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport type { TerminalRuntimeSession } from \"./runtime-session.ts\";\nimport { DEFAULT_DURABLE_MONITOR_FIRE_BUDGET, FIRE_BUDGET_AUTO_MUTE_SUMMARY, FIRE_BUDGET_WINDOW_MS } from \"./shared.ts\";\nimport type { MonitorDurabilityClass } from \"./terminal-manifest.ts\";\nimport { describeExit } from \"./tools/spawn.ts\";\n\nexport interface MonitorLineEvent {\n\treadonly type: \"line\";\n\treadonly id: string;\n\treadonly description: string;\n\treadonly line: string;\n}\n\nexport interface MonitorSummaryEvent {\n\treadonly type: \"summary\";\n\treadonly id: string;\n\treadonly description: string;\n\treadonly summary: string;\n}\n\nexport type MonitorEvent = MonitorLineEvent | MonitorSummaryEvent;\n\nexport type MonitorRearmResult = \"rearmed\" | \"not_paused\" | \"not_found\";\n\nexport interface MonitorResumeResult {\n\treadonly id: string;\n\treadonly mutedDropped: number;\n}\n\nconst MONITOR_ID_ALPHABET = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\n\n/** Allocate a stable monitor identity: \"mon_\" + 16 Crockford base-32 chars (80 random bits). */\nexport function allocateMonitorId(): string {\n\tlet id = \"mon_\";\n\tlet buffer = 0;\n\tlet bits = 0;\n\tfor (const byte of randomBytes(10)) {\n\t\tbuffer = (buffer << 8) | byte;\n\t\tbits += 8;\n\t\twhile (bits >= 5) {\n\t\t\tbits -= 5;\n\t\t\tid += MONITOR_ID_ALPHABET[(buffer >> bits) & 31];\n\t\t}\n\t}\n\treturn id;\n}\n\nexport type MonitorFireWindow = { startMs: number; count: number };\nexport interface MonitorSnapshotEntry {\n\treadonly id: string;\n\t/** Stable \"mon_\" identity carried alongside the runtime id; always set on live snapshots. */\n\treadonly monitorId?: string;\n\treadonly description: string;\n\treadonly paused: boolean;\n\t/** Epoch milliseconds when the watch registered; feeds the footer's live elapsed label. */\n\treadonly startedAtMs: number;\n\t/** Durability deadline of a restart-surviving watch; undefined for every ephemeral one. */\n\treadonly expiresAt?: number;\n\treadonly fireWindow?: MonitorFireWindow;\n}\n\nexport interface MonitorRegistryOptions {\n\t/** Observes every registry transition (register/pause/rearm/settle/dispose) with the live snapshot. */\n\treadonly onChange?: (snapshot: readonly MonitorSnapshotEntry[]) => void;\n\t/** Reserves one shared terminal capacity slot for a native watch. */\n\treadonly reserve?: () => (() => void) | null;\n}\n\nexport interface RegisterFileMonitorOptions {\n\treadonly description: string;\n\treadonly path: string;\n\t/** Caller-supplied stable identity so a restore can re-bind the same \"mon_\" id. */\n\treadonly monitorId?: string;\n\treadonly event: \"create\" | \"modify\";\n\treadonly timeoutMs: number;\n\treadonly cwd: string;\n\treadonly approvedParent?: string;\n\t/** Durability deadline of a `checkpointed-file` watch; omitted for a one-shot ephemeral one. */\n\treadonly expiresAt?: number;\n}\n\nexport interface RegisterMonitorOptions {\n\treadonly id: string;\n\t/** Caller-supplied stable identity so a restore can re-bind the same \"mon_\" id. */\n\treadonly monitorId?: string;\n\treadonly description: string;\n\treadonly runtime: TerminalRuntimeSession;\n\treadonly filter?: RegExp;\n\t/** Durability class from the manifest spec; non-ephemeral records carry the fire budget. */\n\treadonly durabilityClass?: MonitorDurabilityClass;\n\t/** Persisted fire window re-bound by a restore, so a restart cannot reset the budget. */\n\treadonly fireWindow?: MonitorFireWindow;\n\t/** Durability deadline of a durable watch; omitted for an ephemeral one. */\n\treadonly expiresAt?: number;\n}\n\ninterface PendingFileRegistration {\n\trelease: (() => void) | undefined;\n\treadonly abort: AbortController;\n\treadonly deadline: ReturnType<typeof setTimeout>;\n\tsettled: boolean;\n}\n\ninterface FileMonitorRecord {\n\treadonly id: string;\n\treadonly monitorId: string;\n\treadonly sessionId: string;\n\treadonly description: string;\n\treadonly startedAtMs: number;\n\treadonly expiresAt: number | undefined;\n\treadonly path: string;\n\treadonly canonicalPath: string;\n\treadonly canonicalParent: string;\n\treadonly event: \"create\" | \"modify\";\n\treadonly watcher: FSWatcher;\n\treadonly release: () => void;\n\treadonly poll: ReturnType<typeof setInterval>;\n\tpaused: boolean;\n\tsettled: boolean;\n\tpresent: boolean;\n\tmtimeMs: number;\n\tsize: number;\n\tdigest: string;\n\tdevice: number;\n\tinode: number;\n\tpendingChange: boolean;\n\tdirty: boolean;\n\tdirtyPasses: number;\n\tdirtyWindowStartedAt: number;\n\tchecking: Promise<void> | undefined;\n\treadonly deadline: ReturnType<typeof setTimeout>;\n}\n\ninterface MonitorRecord {\n\treadonly id: string;\n\treadonly monitorId: string;\n\treadonly sessionId: string;\n\treadonly description: string;\n\treadonly startedAtMs: number;\n\treadonly expiresAt: number | undefined;\n\treadonly runtime: TerminalRuntimeSession;\n\treadonly filter: RegExp | undefined;\n\tlineBuffer: string;\n\tmutedDropped: number;\n\tpaused: boolean;\n\tsettled: boolean;\n\tfireWindow: MonitorFireWindow | undefined;\n\tunsubscribeOutput: (() => void) | undefined;\n\tunsubscribeExit: (() => void) | undefined;\n}\n\n/**\n * Tracks active monitor sessions alongside the terminal manager's existing bash-id registry.\n * Output is deliberately retained only by TerminalRuntimeSession's bounded history; this\n * registry holds at most one unfinished line for each live monitor.\n */\nexport class MonitorRegistry {\n\treadonly #records = new Map<string, MonitorRecord>();\n\treadonly #emit: (event: MonitorEvent) => void;\n\treadonly #onChange: ((snapshot: readonly MonitorSnapshotEntry[]) => void) | undefined;\n\treadonly #reserve: (() => (() => void) | null) | undefined;\n\treadonly #files = new Map<string, FileMonitorRecord>();\n\t#nextFileId = 1;\n\t#disposed = false;\n\t#pendingRegistrations = 0;\n\treadonly #pending = new Set<PendingFileRegistration>();\n\t#lifecycle = 0;\n\n\tconstructor(emit: (event: MonitorEvent) => void, options?: MonitorRegistryOptions) {\n\t\tthis.#emit = emit;\n\t\tthis.#onChange = options?.onChange;\n\t\tthis.#reserve = options?.reserve;\n\t}\n\n\tsnapshot(): readonly MonitorSnapshotEntry[] {\n\t\treturn [...this.#records.values(), ...this.#files.values()].map((record) => ({\n\t\t\tid: record.id,\n\t\t\tmonitorId: record.monitorId,\n\t\t\tdescription: record.description,\n\t\t\tpaused: record.paused,\n\t\t\tstartedAtMs: record.startedAtMs,\n\t\t\texpiresAt: record.expiresAt,\n\t\t\tfireWindow: \"fireWindow\" in record ? record.fireWindow : undefined,\n\t\t}));\n\t}\n\n\tasync registerFile(options: RegisterFileMonitorOptions): Promise<{ id: string; monitorId: string }> {\n\t\tif (this.#disposed) throw new Error(\"Cannot create file monitor: monitor registry is disposed.\");\n\t\tthis.#pendingRegistrations += 1;\n\t\tconst lifecycle = this.#lifecycle;\n\t\tconst release = this.#reserve?.();\n\t\tif (this.#reserve && !release) {\n\t\t\tthis.#pendingRegistrations -= 1;\n\t\t\tthrow new Error(\"Cannot create file monitor: terminal capacity is already in use.\");\n\t\t}\n\t\tconst pending: PendingFileRegistration = {\n\t\t\trelease: release ?? undefined,\n\t\t\tabort: new AbortController(),\n\t\t\tdeadline: setTimeout(() => pending.abort.abort(), options.timeoutMs),\n\t\t\tsettled: false,\n\t\t};\n\t\tthis.#pending.add(pending);\n\t\tconst path = resolve(options.cwd, options.path);\n\t\tconst parent = dirname(path);\n\t\tlet approvedParent: string;\n\t\ttry {\n\t\t\tawait this.#registrationAwait(pending, access(parent));\n\t\t\tapprovedParent = await this.#registrationAwait(pending, realpath(parent));\n\t\t\tconst approvedParentAtPermission = options.approvedParent;\n\t\t\tif (approvedParentAtPermission !== undefined && approvedParent !== approvedParentAtPermission) {\n\t\t\t\tthrow new Error(`Cannot watch file: parent directory changed during permission approval: ${parent}`);\n\t\t\t}\n\t\t\tif (this.#disposed) throw new Error(\"Cannot create file monitor: monitor registry is disposed.\");\n\t\t} catch (error) {\n\t\t\tthis.#finishPending(pending);\n\t\t\tthis.#pendingRegistrations -= 1;\n\t\t\tif (error instanceof Error && error.message.includes(\"disposed\")) throw error;\n\t\t\tif ((error as NodeJS.ErrnoException)?.code !== \"ENOENT\") {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot access parent directory ${parent}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow new Error(`Cannot watch file: parent directory does not exist: ${parent}`);\n\t\t}\n\t\tlet initial: Awaited<ReturnType<typeof stat>> | null = null;\n\t\tlet initialHandle: FileHandle | undefined;\n\t\ttry {\n\t\t\tconst target = await this.#registrationAwait(pending, lstat(path));\n\t\t\tif (target.isSymbolicLink()) throw new Error(`Cannot watch file: target is a symbolic link: ${path}`);\n\t\t\tinitialHandle = await this.#registrationAwait(pending, open(path, \"r\"), async (handle) => {\n\t\t\t\tawait handle.close();\n\t\t\t});\n\t\t\tinitial = await this.#registrationAwait(pending, initialHandle.stat());\n\t\t\tif (!initial.isFile()) throw new Error(`Cannot watch file: target is not a regular file: ${path}`);\n\t\t\tconst resolvedTarget = await this.#registrationAwait(pending, realpath(path));\n\t\t\tif (resolvedTarget !== join(approvedParent, basename(path)))\n\t\t\t\tthrow new Error(`Cannot watch file: target identity changed: ${path}`);\n\t\t\tconst rebound = await this.#registrationAwait(pending, lstat(path));\n\t\t\tif (rebound.isSymbolicLink()) throw new Error(`Cannot watch file: target identity changed: ${path}`);\n\t\t\tconst reboundStat = await this.#registrationAwait(pending, stat(path));\n\t\t\tif (!reboundStat.isFile() || reboundStat.dev !== initial.dev || reboundStat.ino !== initial.ino)\n\t\t\t\tthrow new Error(`Cannot watch file: target identity changed: ${path}`);\n\t\t} catch (error) {\n\t\t\tawait initialHandle?.close();\n\t\t\tinitialHandle = undefined;\n\t\t\tif ((error as NodeJS.ErrnoException)?.code !== \"ENOENT\") {\n\t\t\t\tthis.#finishPending(pending);\n\t\t\t\tthis.#pendingRegistrations -= 1;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\tif (this.#disposed || lifecycle !== this.#lifecycle || this.#pendingRegistrations < 1) {\n\t\t\tthis.#finishPending(pending);\n\t\t\tthis.#pendingRegistrations -= 1;\n\t\t\tthrow new Error(\"Cannot create file monitor: monitor registry is disposed.\");\n\t\t}\n\t\tconst id = `watch_${this.#nextFileId++}`;\n\t\tlet watcher: FSWatcher;\n\t\ttry {\n\t\t\tconst activationParent = await this.#registrationAwait(pending, realpath(parent));\n\t\t\tif (activationParent !== approvedParent) {\n\t\t\t\tthrow new Error(`Cannot watch file: parent directory changed during registration: ${parent}`);\n\t\t\t}\n\t\t\twatcher = watch(activationParent, (_kind, name) => {\n\t\t\t\tif (!name || basename(String(name)) === basename(path)) void this.#checkFile(id);\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis.#finishPending(pending);\n\t\t\tthis.#pendingRegistrations -= 1;\n\t\t\tthrow new Error(`Cannot watch file ${path}: ${error instanceof Error ? error.message : String(error)}`);\n\t\t}\n\t\tlet registrationError: string | undefined;\n\t\twatcher.on(\"error\", (error) => {\n\t\t\tregistrationError = `watcher error: ${error instanceof Error ? error.message : String(error)}`;\n\t\t\tconst record = this.#files.get(id);\n\t\t\tif (record) this.#settleFile(record, registrationError);\n\t\t});\n\t\tlet registrationCleaned = false;\n\t\tconst finishRegistration = () => {\n\t\t\tif (registrationCleaned) return;\n\t\t\tregistrationCleaned = true;\n\t\t\tthis.#pendingRegistrations -= 1;\n\t\t};\n\t\tconst cleanupRegistration = () => {\n\t\t\tif (registrationCleaned) return;\n\t\t\twatcher.close();\n\t\t\tfinishRegistration();\n\t\t\tthis.#finishPending(pending);\n\t\t};\n\t\tif (this.#disposed || lifecycle !== this.#lifecycle) {\n\t\t\tcleanupRegistration();\n\t\t\tthrow new Error(\"Cannot create file monitor: monitor registry is disposed.\");\n\t\t}\n\t\tconst canonicalPath = join(approvedParent, basename(path));\n\t\tlet digest: string;\n\t\ttry {\n\t\t\tdigest =\n\t\t\t\tinitial && initialHandle\n\t\t\t\t\t? await this.#registrationAwait(pending, this.#digestHandle(initialHandle, pending.abort.signal))\n\t\t\t\t\t: \"\";\n\t\t} catch (error) {\n\t\t\tcleanupRegistration();\n\t\t\tawait initialHandle?.close();\n\t\t\tinitialHandle = undefined;\n\t\t\tif (registrationError) {\n\t\t\t\tthis.#emit({ type: \"summary\", id, description: options.description, summary: registrationError });\n\t\t\t\tthrow new Error(registrationError);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t\tawait initialHandle?.close();\n\t\tinitialHandle = undefined;\n\t\tif (registrationError) {\n\t\t\tcleanupRegistration();\n\t\t\tthis.#emit({ type: \"summary\", id, description: options.description, summary: registrationError });\n\t\t\tthrow new Error(registrationError);\n\t\t}\n\t\tif (this.#disposed || lifecycle !== this.#lifecycle) {\n\t\t\tcleanupRegistration();\n\t\t\tthrow new Error(\"Cannot create file monitor: monitor registry is disposed.\");\n\t\t}\n\t\tconst record: FileMonitorRecord = {\n\t\t\tid,\n\t\t\tmonitorId: options.monitorId ?? allocateMonitorId(),\n\t\t\tsessionId: id,\n\t\t\tdescription: options.description,\n\t\t\tstartedAtMs: Date.now(),\n\t\t\texpiresAt: options.expiresAt,\n\t\t\tpath,\n\t\t\tcanonicalPath,\n\t\t\tcanonicalParent: approvedParent,\n\t\t\tevent: options.event,\n\t\t\twatcher,\n\t\t\trelease: release ?? (() => {}),\n\t\t\tpoll: setInterval(() => void this.#checkFile(id), 250),\n\t\t\tpaused: false,\n\t\t\tsettled: false,\n\t\t\tpresent: initial !== null,\n\t\t\tmtimeMs: initial?.mtimeMs ?? 0,\n\t\t\tsize: initial?.size ?? 0,\n\t\t\tdigest,\n\t\t\tdevice: initial?.dev ?? 0,\n\t\t\tinode: initial?.ino ?? 0,\n\t\t\tpendingChange: false,\n\t\t\tdirty: false,\n\t\t\tdirtyPasses: 0,\n\t\t\tdirtyWindowStartedAt: 0,\n\t\t\tchecking: undefined,\n\t\t\tdeadline: setTimeout(() => {\n\t\t\t\tconst current = this.#files.get(id);\n\t\t\t\tif (current) this.#settleFile(current, \"watcher timed_out\");\n\t\t\t}, options.timeoutMs),\n\t\t};\n\t\tthis.#files.set(id, record);\n\t\tfinishRegistration();\n\t\tthis.#finishPending(pending, true);\n\t\tif (registrationError || this.#disposed || lifecycle !== this.#lifecycle) {\n\t\t\tthis.#settleFile(record, registrationError ?? \"watcher killed\");\n\t\t\tthrow new Error(registrationError ?? \"Cannot create file monitor: monitor registry is disposed.\");\n\t\t}\n\t\tthis.#notifyChange();\n\t\treturn { id, monitorId: record.monitorId };\n\t}\n\n\t/** Live identity tuple of one file watch; undefined when the id is not a live file watch. */\n\tfileCheckpoint(id: string) {\n\t\tconst r = this.#files.get(id);\n\t\treturn (\n\t\t\tr && { dev: r.device, ino: r.inode, size: r.size, mtimeMs: r.mtimeMs, digest: r.digest, present: r.present }\n\t\t);\n\t}\n\n\t/** Emit one restored-watch line through the SAME sink a live watch uses (coalescing, wake budget). */\n\temitFileLine(id: string, line: string): boolean {\n\t\tconst record = this.#files.get(id);\n\t\tif (!record || record.settled) return false;\n\t\tthis.#emit({ type: \"line\", id: record.id, description: record.description, line });\n\t\treturn true;\n\t}\n\n\tasync stopFile(id: string): Promise<boolean> {\n\t\tconst record = this.#files.get(id);\n\t\tif (!record) return false;\n\t\tthis.#settleFile(record, \"watcher killed\");\n\t\treturn true;\n\t}\n\n\tasync stopAllFiles(): Promise<number> {\n\t\tthis.#lifecycle += 1;\n\t\tconst records = [...this.#files.values()];\n\t\tfor (const record of records) this.#settleFile(record, \"watcher killed\");\n\t\tfor (const pending of [...this.#pending]) this.#finishPending(pending);\n\t\treturn records.length;\n\t}\n\n\t#settleFile(record: FileMonitorRecord, summary: string): void {\n\t\tif (record.settled) return;\n\t\trecord.settled = true;\n\t\tclearInterval(record.poll);\n\t\tclearTimeout(record.deadline);\n\t\trecord.watcher.close();\n\t\trecord.release();\n\t\tthis.#files.delete(record.id);\n\t\tthis.#notifyChange();\n\t\tthis.#emit({ type: \"summary\", id: record.id, description: record.description, summary });\n\t}\n\n\tasync #checkFile(id: string): Promise<void> {\n\t\tconst record = this.#files.get(id);\n\t\tif (!record || record.settled) return;\n\t\tif (record.checking) {\n\t\t\trecord.dirty = true;\n\t\t\treturn;\n\t\t}\n\t\trecord.checking = this.#checkFileImpl(record)\n\t\t\t.catch((error) => {\n\t\t\t\tif (!record.settled)\n\t\t\t\t\tthis.#settleFile(record, `watcher error: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\trecord.checking = undefined;\n\t\t\t\tconst now = Date.now();\n\t\t\t\tif (now - record.dirtyWindowStartedAt >= 1_000) {\n\t\t\t\t\trecord.dirtyWindowStartedAt = now;\n\t\t\t\t\trecord.dirtyPasses = 0;\n\t\t\t\t}\n\t\t\t\tif (record.dirty && !record.settled && record.dirtyPasses < 1) {\n\t\t\t\t\trecord.dirty = false;\n\t\t\t\t\trecord.dirtyPasses += 1;\n\t\t\t\t\tvoid this.#checkFile(id);\n\t\t\t\t} else {\n\t\t\t\t\trecord.dirty = false;\n\t\t\t\t}\n\t\t\t});\n\t\treturn record.checking;\n\t}\n\n\tasync #checkFileImpl(record: FileMonitorRecord): Promise<void> {\n\t\tif (record.settled) return;\n\t\tlet current: Awaited<ReturnType<typeof stat>> | null = null;\n\t\tlet handle: FileHandle | undefined;\n\t\ttry {\n\t\t\tconst currentParent = await realpath(dirname(record.path));\n\t\t\tif (currentParent !== record.canonicalParent) {\n\t\t\t\tthis.#settleFile(record, `watcher error: monitored parent changed: ${dirname(record.path)}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst target = await lstat(record.canonicalPath);\n\t\t\tif (target.isSymbolicLink()) throw new Error(`Cannot watch file: target identity changed: ${record.path}`);\n\t\t\tconst resolvedTarget = await realpath(record.canonicalPath);\n\t\t\tif (resolvedTarget !== record.canonicalPath)\n\t\t\t\tthrow new Error(`Cannot watch file: target identity changed: ${record.path}`);\n\t\t\thandle = await open(record.canonicalPath, \"r\");\n\t\t\tconst opened = await handle.stat();\n\t\t\tif (!opened.isFile()) throw new Error(`Cannot watch file: target is not a regular file: ${record.path}`);\n\t\t\tif ((opened.dev !== record.device || opened.ino !== record.inode) && opened.nlink > 1)\n\t\t\t\tthrow new Error(`Cannot watch file: target identity changed: ${record.path}`);\n\t\t\tcurrent = opened;\n\t\t\tconst rebound = await lstat(record.canonicalPath);\n\t\t\tif (rebound.isSymbolicLink()) throw new Error(`Cannot watch file: target identity changed: ${record.path}`);\n\t\t\tconst reboundPath = await stat(record.canonicalPath);\n\t\t\tif (!reboundPath.isFile() || reboundPath.dev !== opened.dev || reboundPath.ino !== opened.ino)\n\t\t\t\tthrow new Error(`Cannot watch file: target identity changed: ${record.path}`);\n\t\t} catch (error) {\n\t\t\tawait handle?.close();\n\t\t\tif ((error as NodeJS.ErrnoException)?.code !== \"ENOENT\") {\n\t\t\t\tthis.#settleFile(record, `watcher error: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tconst present = current !== null;\n\t\tlet digest = \"\";\n\t\ttry {\n\t\t\tdigest = present && handle ? await this.#digestHandle(handle) : \"\";\n\t\t\tif (present && handle) {\n\t\t\t\tconst afterDigest = await stat(record.canonicalPath);\n\t\t\t\tconst opened = await handle.stat();\n\t\t\t\tif (afterDigest.dev !== opened.dev || afterDigest.ino !== opened.ino)\n\t\t\t\t\tthrow new Error(`Cannot watch file: target identity changed: ${record.path}`);\n\t\t\t}\n\t\t} finally {\n\t\t\tawait handle?.close();\n\t\t}\n\t\tconst changed =\n\t\t\trecord.event === \"create\"\n\t\t\t\t? !record.present && present\n\t\t\t\t: record.present &&\n\t\t\t\t\tpresent &&\n\t\t\t\t\t(current!.mtimeMs !== record.mtimeMs || current!.size !== record.size || digest !== record.digest);\n\t\trecord.pendingChange ||= changed;\n\t\tif (!record.present && current) {\n\t\t\trecord.device = current.dev;\n\t\t\trecord.inode = current.ino;\n\t\t}\n\t\trecord.present = present;\n\t\trecord.mtimeMs = current?.mtimeMs ?? 0;\n\t\trecord.size = current?.size ?? 0;\n\t\trecord.digest = digest;\n\t\tif (!record.pendingChange || record.paused || record.settled) return;\n\t\trecord.pendingChange = false;\n\t\tif (record.settled) return;\n\t\tthis.#emit({\n\t\t\ttype: \"line\",\n\t\t\tid: record.id,\n\t\t\tdescription: record.description,\n\t\t\tline: `${record.event} ${record.path}`,\n\t\t});\n\t\tthis.#settleFile(record, \"watcher completed\");\n\t}\n\n\tregister(options: RegisterMonitorOptions): string {\n\t\tconst durable = options.durabilityClass !== undefined && options.durabilityClass !== \"ephemeral\";\n\t\tconst record: MonitorRecord = {\n\t\t\tid: options.id,\n\t\t\tmonitorId: options.monitorId ?? allocateMonitorId(),\n\t\t\tsessionId: options.id,\n\t\t\tdescription: options.description,\n\t\t\tstartedAtMs: Date.now(),\n\t\t\texpiresAt: options.expiresAt,\n\t\t\truntime: options.runtime,\n\t\t\tfilter: options.filter,\n\t\t\tlineBuffer: \"\",\n\t\t\tmutedDropped: 0,\n\t\t\tpaused: false,\n\t\t\tsettled: false,\n\t\t\tfireWindow: durable ? { ...(options.fireWindow ?? { startMs: Date.now(), count: 0 }) } : undefined,\n\t\t\tunsubscribeOutput: undefined,\n\t\t\tunsubscribeExit: undefined,\n\t\t};\n\t\tthis.#records.set(record.id, record);\n\t\tthis.#notifyChange();\n\n\t\t// Runtime output is already bounded. Read what was produced before monitor registration,\n\t\t// then subscribe synchronously so a fast watcher cannot lose its first line.\n\t\tthis.#consume(record, record.runtime.fullOutput());\n\t\trecord.unsubscribeOutput = record.runtime.onOutput((chunk) => this.#consume(record, chunk));\n\t\trecord.unsubscribeExit = record.runtime.session.onExit(() => this.#settle(record));\n\t\tif (record.runtime.exited) this.#settle(record);\n\t\treturn record.monitorId;\n\t}\n\n\tpause(ids: readonly string[]): string[] {\n\t\tconst paused: string[] = [];\n\t\tfor (const id of ids) {\n\t\t\tconst record = this.#records.get(id) ?? this.#files.get(id);\n\t\t\tif (!record || record.paused) continue;\n\t\t\trecord.paused = true;\n\t\t\tpaused.push(record.id);\n\t\t}\n\t\tif (paused.length > 0) this.#notifyChange();\n\t\treturn paused;\n\t}\n\n\tpauseAll(): string[] {\n\t\treturn this.pause([...this.#records.keys(), ...this.#files.keys()]);\n\t}\n\n\tresume(ids?: readonly string[]): MonitorResumeResult[] {\n\t\tconst candidates = ids ?? [...this.#records.keys(), ...this.#files.keys()];\n\t\tconst resumed: MonitorResumeResult[] = [];\n\t\tfor (const id of candidates) {\n\t\t\tconst record = this.#records.get(id) ?? this.#files.get(id);\n\t\t\tif (!record?.paused) continue;\n\t\t\trecord.paused = false;\n\t\t\tconst mutedDropped = \"mutedDropped\" in record ? record.mutedDropped : 0;\n\t\t\tif (\"mutedDropped\" in record) record.mutedDropped = 0;\n\t\t\t// A rearm (or any resume) restarts the rolling fire budget while keeping its window start.\n\t\t\tif (\"fireWindow\" in record && record.fireWindow !== undefined) record.fireWindow.count = 0;\n\t\t\tresumed.push({ id: record.id, mutedDropped });\n\t\t\tif (\"pendingChange\" in record && record.pendingChange) void this.#checkFile(record.id);\n\t\t}\n\t\tif (resumed.length > 0) this.#notifyChange();\n\t\treturn resumed;\n\t}\n\n\tmutedDropped(id: string): number {\n\t\treturn this.#records.get(id)?.mutedDropped ?? 0;\n\t}\n\n\trearm(id: string): MonitorRearmResult {\n\t\tconst record = this.#records.get(id) ?? this.#files.get(id);\n\t\tif (!record) return \"not_found\";\n\t\tif (!record.paused) return \"not_paused\";\n\t\tthis.resume([id]);\n\t\treturn \"rearmed\";\n\t}\n\n\t/** Re-bind a persisted fire window onto the record for a durable monitor id (a restore re-arms the budget). */\n\tadoptFireWindow(monitorId: string, fireWindow: MonitorFireWindow): boolean {\n\t\tfor (const record of this.#records.values()) {\n\t\t\tif (record.monitorId !== monitorId) continue;\n\t\t\trecord.fireWindow = { ...fireWindow };\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tdispose(): void {\n\t\tthis.#disposed = true;\n\t\tthis.#lifecycle += 1;\n\t\tfor (const record of this.#records.values()) this.#disposeRecord(record);\n\t\tfor (const record of this.#files.values()) this.#settleFile(record, \"watcher disposed\");\n\t\tfor (const pending of this.#pending) this.#finishPending(pending);\n\t\tthis.#records.clear();\n\t\tthis.#notifyChange();\n\t}\n\n\t#finishPending(pending: PendingFileRegistration, transfer = false): void {\n\t\tif (pending.settled) return;\n\t\tpending.settled = true;\n\t\tclearTimeout(pending.deadline);\n\t\tthis.#pending.delete(pending);\n\t\tif (transfer) pending.release = undefined;\n\t\telse {\n\t\t\tpending.abort.abort();\n\t\t\tpending.release?.();\n\t\t}\n\t}\n\n\tasync #registrationAwait<T>(\n\t\tpending: PendingFileRegistration,\n\t\toperation: Promise<T>,\n\t\tlateCleanup?: (value: T) => Promise<void>,\n\t): Promise<T> {\n\t\tif (pending.abort.signal.aborted) {\n\t\t\tvoid operation.then(\n\t\t\t\t(value) => lateCleanup?.(value),\n\t\t\t\t() => undefined,\n\t\t\t);\n\t\t\tthrow new Error(\"Cannot create file monitor: registration timed out or was disposed.\");\n\t\t}\n\t\tlet aborted = false;\n\t\tconst abort = new Promise<never>((_, reject) =>\n\t\t\tpending.abort.signal.addEventListener(\n\t\t\t\t\"abort\",\n\t\t\t\t() => {\n\t\t\t\t\taborted = true;\n\t\t\t\t\treject(new Error(\"Cannot create file monitor: registration timed out or was disposed.\"));\n\t\t\t\t},\n\t\t\t\t{ once: true },\n\t\t\t),\n\t\t);\n\t\tconst guarded = operation.then(\n\t\t\t(value) => {\n\t\t\t\tif (aborted) void lateCleanup?.(value);\n\t\t\t\treturn value;\n\t\t\t},\n\t\t\t(error) => {\n\t\t\t\tif (aborted) return undefined as T;\n\t\t\t\tthrow error;\n\t\t\t},\n\t\t);\n\t\treturn Promise.race([guarded, abort]);\n\t}\n\n\tasync #digestHandle(handle: FileHandle, signal?: AbortSignal): Promise<string> {\n\t\tconst SAMPLE_SIZE = 64 * 1024;\n\t\tif (signal?.aborted) throw new Error(\"file monitor registration cancelled\");\n\t\tconst metadata = await handle.stat();\n\t\tconst hash = createHash(\"sha256\");\n\t\tconst first = Buffer.alloc(Math.min(SAMPLE_SIZE, metadata.size));\n\t\tif (first.length > 0) {\n\t\t\tawait handle.read(first, 0, first.length, 0);\n\t\t\thash.update(first);\n\t\t}\n\t\tif (metadata.size > SAMPLE_SIZE) {\n\t\t\tconst middle = Buffer.alloc(SAMPLE_SIZE);\n\t\t\tawait handle.read(middle, 0, middle.length, Math.floor((metadata.size - middle.length) / 2));\n\t\t\thash.update(middle);\n\t\t\tconst last = Buffer.alloc(SAMPLE_SIZE);\n\t\t\tawait handle.read(last, 0, last.length, metadata.size - last.length);\n\t\t\thash.update(last);\n\t\t}\n\t\treturn `${metadata.size}:${hash.digest(\"hex\")}`;\n\t}\n\n\t#notifyChange(): void {\n\t\tthis.#onChange?.(this.snapshot());\n\t}\n\n\t#consume(record: MonitorRecord, chunk: string): void {\n\t\tif (record.settled || chunk.length === 0) return;\n\t\tlet remaining = record.lineBuffer + chunk;\n\t\tfor (;;) {\n\t\t\tconst newline = remaining.indexOf(\"\\n\");\n\t\t\tif (newline < 0) break;\n\t\t\tconst rawLine = remaining.slice(0, newline);\n\t\t\tremaining = remaining.slice(newline + 1);\n\t\t\tconst line = rawLine.endsWith(\"\\r\") ? rawLine.slice(0, -1) : rawLine;\n\t\t\tconst matchesFilter = !record.filter || record.filter.test(line);\n\t\t\tif (!matchesFilter) continue;\n\t\t\tif (record.paused) {\n\t\t\t\trecord.mutedDropped += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis.#emit({ type: \"line\", id: record.id, description: record.description, line });\n\t\t\tif (record.fireWindow !== undefined) {\n\t\t\t\tconst now = Date.now();\n\t\t\t\tif (now - record.fireWindow.startMs >= FIRE_BUDGET_WINDOW_MS)\n\t\t\t\t\trecord.fireWindow = { startMs: now, count: 0 };\n\t\t\t\trecord.fireWindow.count += 1;\n\t\t\t\tif (record.fireWindow.count >= DEFAULT_DURABLE_MONITOR_FIRE_BUDGET) {\n\t\t\t\t\trecord.paused = true;\n\t\t\t\t\tthis.#emit({\n\t\t\t\t\t\ttype: \"summary\",\n\t\t\t\t\t\tid: record.id,\n\t\t\t\t\t\tdescription: record.description,\n\t\t\t\t\t\tsummary: FIRE_BUDGET_AUTO_MUTE_SUMMARY,\n\t\t\t\t\t});\n\t\t\t\t\tthis.#notifyChange();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\trecord.lineBuffer = remaining;\n\t}\n\n\t#settle(record: MonitorRecord): void {\n\t\tif (record.settled) return;\n\t\trecord.settled = true;\n\t\trecord.unsubscribeOutput?.();\n\t\trecord.unsubscribeExit?.();\n\t\tthis.#records.delete(record.id);\n\t\tthis.#notifyChange();\n\t\tconst status = describeExit(record.runtime) ?? \"exited\";\n\t\tconst code = record.runtime.exitResult?.exitCode;\n\t\tconst codeText = code === null || code === undefined ? \"\" : ` (exit code ${code})`;\n\t\tthis.#emit({\n\t\t\ttype: \"summary\",\n\t\t\tid: record.id,\n\t\t\tdescription: record.description,\n\t\t\tsummary: `watcher ${status}${codeText}`,\n\t\t});\n\t}\n\n\t#disposeRecord(record: MonitorRecord): void {\n\t\trecord.settled = true;\n\t\trecord.unsubscribeOutput?.();\n\t\trecord.unsubscribeExit?.();\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitor-status.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/monitor-status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE,eAAO,MAAM,kBAAkB,aAAa,CAAC;AA2B7C;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAc1D;
|
|
1
|
+
{"version":3,"file":"monitor-status.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/monitor-status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE,eAAO,MAAM,kBAAkB,aAAa,CAAC;AA2B7C;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAc1D;AAsBD,sGAAsG;AACtG,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKtG;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAahH"}
|
|
@@ -46,6 +46,26 @@ export function formatElapsedSeconds(value) {
|
|
|
46
46
|
return `${hours}h`;
|
|
47
47
|
return `${hours}h ${remainingMinutes}m`;
|
|
48
48
|
}
|
|
49
|
+
/** Below this remaining lifetime a durable watch earns the footer's expiry warning. */
|
|
50
|
+
const EXPIRY_WARNING_MS = 24 * 60 * 60 * 1000;
|
|
51
|
+
/**
|
|
52
|
+
* Deliberately quiet deadline warning: `(expires in 1d)` only once a durable watch has less
|
|
53
|
+
* than a day left. A watch with more time, and every ephemeral watch (no `expiresAt` at all),
|
|
54
|
+
* gets nothing — the footer is not a countdown. The label always reads whole days rounded up,
|
|
55
|
+
* so the last day shows `1d` rather than a churning hour/minute figure.
|
|
56
|
+
*/
|
|
57
|
+
function formatExpirySuffix(snapshot, nowMs) {
|
|
58
|
+
let soonest = Number.POSITIVE_INFINITY;
|
|
59
|
+
for (const entry of snapshot) {
|
|
60
|
+
if (typeof entry.expiresAt !== "number")
|
|
61
|
+
continue;
|
|
62
|
+
soonest = Math.min(soonest, entry.expiresAt - nowMs);
|
|
63
|
+
}
|
|
64
|
+
if (!Number.isFinite(soonest) || soonest >= EXPIRY_WARNING_MS)
|
|
65
|
+
return "";
|
|
66
|
+
const days = Math.max(1, Math.ceil(soonest / (24 * 60 * 60 * 1000)));
|
|
67
|
+
return ` (expires in ${days}d)`;
|
|
68
|
+
}
|
|
49
69
|
/** Whole seconds since the oldest watch registered; never negative when the clock moves backwards. */
|
|
50
70
|
export function monitorElapsedSeconds(snapshot, nowMs) {
|
|
51
71
|
let oldest = Number.POSITIVE_INFINITY;
|
|
@@ -61,7 +81,7 @@ export function formatMonitorStatus(snapshot, nowMs) {
|
|
|
61
81
|
return undefined;
|
|
62
82
|
const pausedCount = snapshot.filter((entry) => entry.paused).length;
|
|
63
83
|
const pausedPart = pausedCount === 0 ? "" : pausedCount === snapshot.length ? ", muted" : `, ${pausedCount} muted`;
|
|
64
|
-
const suffix = ` (${formatElapsedSeconds(monitorElapsedSeconds(snapshot, nowMs))}${pausedPart})`;
|
|
84
|
+
const suffix = ` (${formatElapsedSeconds(monitorElapsedSeconds(snapshot, nowMs))}${pausedPart})${formatExpirySuffix(snapshot, nowMs)}`;
|
|
65
85
|
if (snapshot.length === 1) {
|
|
66
86
|
const head = `${WATCH_GLYPH} watching `;
|
|
67
87
|
const description = truncateEnd(snapshot[0]?.description ?? "", MAX_STATUS_LENGTH - head.length - suffix.length);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitor-status.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/monitor-status.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"monitor-status.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/monitor-status.ts"],"names":[],"mappings":"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","sourcesContent":["import type { MonitorSnapshotEntry } from \"./monitor-registry.ts\";\n\nexport const MONITOR_STATUS_KEY = \"monitors\";\n\n/** The footer shares one status line with other extensions; keep this brief. */\nconst MAX_STATUS_LENGTH = 48;\n/** Marks the status as a live watch at a glance (same glyph family as the session selector). */\nconst WATCH_GLYPH = \"◉\";\n\nfunction truncateEnd(text: string, max: number): string {\n\tif (text.length <= max) return text;\n\treturn `${text.slice(0, Math.max(0, max - 1))}…`;\n}\n\n/**\n * Fits as many whole descriptions as possible into the budget, folding the rest\n * into a `+N more` counter so the monitor count is never truncated away.\n */\nfunction packDescriptions(names: readonly string[], budget: number): string {\n\tfor (let kept = names.length; kept >= 1; kept--) {\n\t\tconst hiddenCount = names.length - kept;\n\t\tconst tail = hiddenCount > 0 ? ` +${hiddenCount} more` : \"\";\n\t\tconst joined = names.slice(0, kept).join(\", \");\n\t\tif (joined.length + tail.length <= budget) return joined + tail;\n\t}\n\tconst tail = names.length > 1 ? ` +${names.length - 1} more` : \"\";\n\treturn truncateEnd(names[0] ?? \"\", Math.max(1, budget - tail.length)) + tail;\n}\n\n/**\n * Goal-style compact elapsed label (`5s`, `3m`, `2h 30m`, `1d 2h 3m`). Mirrors\n * `formatGoalElapsedSeconds` in the goal builtin; kept local so this builtin stays\n * self-contained, matching the existing monitor/eval status-file duplication.\n */\nexport function formatElapsedSeconds(value: number): string {\n\tconst seconds = Math.max(0, Math.trunc(value));\n\tif (seconds < 60) return `${seconds}s`;\n\tconst minutes = Math.trunc(seconds / 60);\n\tif (minutes < 60) return `${minutes}m`;\n\tconst hours = Math.trunc(minutes / 60);\n\tconst remainingMinutes = minutes % 60;\n\tif (hours >= 24) {\n\t\tconst days = Math.trunc(hours / 24);\n\t\tconst remainingHours = hours % 24;\n\t\treturn `${days}d ${remainingHours}h ${remainingMinutes}m`;\n\t}\n\tif (remainingMinutes === 0) return `${hours}h`;\n\treturn `${hours}h ${remainingMinutes}m`;\n}\n\n/** Below this remaining lifetime a durable watch earns the footer's expiry warning. */\nconst EXPIRY_WARNING_MS = 24 * 60 * 60 * 1000;\n\n/**\n * Deliberately quiet deadline warning: `(expires in 1d)` only once a durable watch has less\n * than a day left. A watch with more time, and every ephemeral watch (no `expiresAt` at all),\n * gets nothing — the footer is not a countdown. The label always reads whole days rounded up,\n * so the last day shows `1d` rather than a churning hour/minute figure.\n */\nfunction formatExpirySuffix(snapshot: readonly MonitorSnapshotEntry[], nowMs: number): string {\n\tlet soonest = Number.POSITIVE_INFINITY;\n\tfor (const entry of snapshot) {\n\t\tif (typeof entry.expiresAt !== \"number\") continue;\n\t\tsoonest = Math.min(soonest, entry.expiresAt - nowMs);\n\t}\n\tif (!Number.isFinite(soonest) || soonest >= EXPIRY_WARNING_MS) return \"\";\n\tconst days = Math.max(1, Math.ceil(soonest / (24 * 60 * 60 * 1000)));\n\treturn ` (expires in ${days}d)`;\n}\n\n/** Whole seconds since the oldest watch registered; never negative when the clock moves backwards. */\nexport function monitorElapsedSeconds(snapshot: readonly MonitorSnapshotEntry[], nowMs: number): number {\n\tlet oldest = Number.POSITIVE_INFINITY;\n\tfor (const entry of snapshot) oldest = Math.min(oldest, entry.startedAtMs);\n\tif (!Number.isFinite(oldest)) return 0;\n\treturn Math.max(0, Math.round((nowMs - oldest) / 1000));\n}\n\n/** Brief footer text for the active monitors; undefined clears the status. */\nexport function formatMonitorStatus(snapshot: readonly MonitorSnapshotEntry[], nowMs: number): string | undefined {\n\tif (snapshot.length === 0) return undefined;\n\tconst pausedCount = snapshot.filter((entry) => entry.paused).length;\n\tconst pausedPart = pausedCount === 0 ? \"\" : pausedCount === snapshot.length ? \", muted\" : `, ${pausedCount} muted`;\n\tconst suffix = ` (${formatElapsedSeconds(monitorElapsedSeconds(snapshot, nowMs))}${pausedPart})${formatExpirySuffix(snapshot, nowMs)}`;\n\tif (snapshot.length === 1) {\n\t\tconst head = `${WATCH_GLYPH} watching `;\n\t\tconst description = truncateEnd(snapshot[0]?.description ?? \"\", MAX_STATUS_LENGTH - head.length - suffix.length);\n\t\treturn head + description + suffix;\n\t}\n\tconst head = `${WATCH_GLYPH} watching ${snapshot.length}: `;\n\tconst names = snapshot.map((entry) => entry.description);\n\treturn head + packDescriptions(names, MAX_STATUS_LENGTH - head.length - suffix.length) + suffix;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/prompt.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACrC,0GAA0G;IAC1G,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,qBAAqB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/prompt.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACrC,0GAA0G;IAC1G,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,qBAAqB,GAAG,MAAM,CA2CjF"}
|
|
@@ -31,11 +31,15 @@ manual \`&\` backgrounding — use the built-in session tools:
|
|
|
31
31
|
inside the command and print one sentinel (\`until <cond>; do sleep 1; done;
|
|
32
32
|
printf 'READY\\n'\`). Stream: \`tail -n 0 -F | grep --line-buffered\`. Filter noise at the
|
|
33
33
|
source and stop with \`kill_bash\`.
|
|
34
|
-
- \`${monitor}({ description, path, event? })\` natively watches one regular file and
|
|
35
|
-
prefer it over a shell poll loop. \`"create"\` (the default) fires only when the file
|
|
36
|
-
after registration, so watch an already-existing file with \`"modify"\`; registration needs
|
|
37
|
-
parent directory to exist already, so poll with a \`command\` when the run creates that
|
|
38
|
-
directory too. This branch takes no \`filter
|
|
34
|
+
- \`${monitor}({ description, path, event?, persistent? })\` natively watches one regular file and
|
|
35
|
+
fires once — prefer it over a shell poll loop. \`"create"\` (the default) fires only when the file
|
|
36
|
+
appears after registration, so watch an already-existing file with \`"modify"\`; registration needs
|
|
37
|
+
the parent directory to exist already, so poll with a \`command\` when the run creates that
|
|
38
|
+
directory too. This branch takes no \`filter\`.
|
|
39
|
+
A standing watch is marked \`persistent: true\`: it has no deadline, survives a session restart
|
|
40
|
+
(the command is re-run once, the file rescanned and any change missed while detached reported),
|
|
41
|
+
expires 7 days after creation, is capped at 5 per session, and is accounted for in one
|
|
42
|
+
restart-report line on session start.
|
|
39
43
|
Identical updates are deduped; repeated monitor-only wakes pause the noisy monitor(s) that
|
|
40
44
|
caused them, not all monitors. Completion still wakes the session, and
|
|
41
45
|
\`${monitor}({ action: "rearm", bash_id })\` resumes one while \`${monitor}({ action: "rearm" })\`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/prompt.ts"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAA8B;IACxE,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC;IACrD,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9D,OAAO;;;;;;MAMF,IAAI;;;;;;;;MAQJ,OAAO;;QAEL,OAAO;;;;;;QAMP,OAAO
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/prompt.ts"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAA8B;IACxE,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC;IACrD,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9D,OAAO;;;;;;MAMF,IAAI;;;;;;;;MAQJ,OAAO;;QAEL,OAAO;;;;;;QAMP,OAAO;;;;;;;;;;;MAWT,OAAO,wDAAwD,OAAO;;;;;;CAM3E,CAAC;AACF,CAAC","sourcesContent":["export interface TerminalPromptOptions {\n\t/** True when the session routes shell tools through eval cells, so call shapes must be `tool.<name>(`. */\n\treadonly evalOnly: boolean;\n}\n\n/**\n * System-prompt guidance for the persistent-terminal tool suite (CC-close, snake_case).\n *\n * `bash` and `monitor` leave the model's direct tool list whenever the session has an\n * `eval` tool, so their call shapes are rendered per branch: a hardcoded direct shape\n * would teach a call the model cannot make. The steering companions\n * (`bash_output`/`bash_input`/`bash_resize`/`kill_bash`) stay directly callable in both.\n */\nexport function buildTerminalPromptSection(options: TerminalPromptOptions): string {\n\tconst bash = options.evalOnly ? \"tool.bash\" : \"bash\";\n\tconst monitor = options.evalOnly ? \"tool.monitor\" : \"monitor\";\n\treturn `\n## Persistent terminal sessions\n\nThe \\`bash\\` tool is PTY-backed. For long-running or interactive work, do NOT use tmux or\nmanual \\`&\\` backgrounding — use the built-in session tools:\n\n- \\`${bash}({ command, run_in_background: true })\\` starts a persistent session and returns a\n \\`bash_id\\` immediately. Foreground calls still block and return output; their \\`timeout\\`\n (seconds) is a kill deadline. Background sessions ignore \\`timeout\\` and live until they\n exit or you call \\`kill_bash\\`.\n- \\`bash_output({ bash_id, filter, view })\\` peeks at a session without blocking: new output\n since the last read, the status line, or a rendered full-screen snapshot of TUIs via\n \\`view: \"screen\"\\`. Completion arrives as a notification carrying the exit code and output\n tail — peeking is for steering, never for waiting.\n- \\`${monitor}\\` subscribes you to a change. Pass \\`command\\` XOR \\`path\\` — one branch per call,\n never both:\n - \\`${monitor}({ description, command, filter?, timeout_ms?, persistent? })\\` watches a command:\n newline-terminated PTY output lines (stderr included) matching \\`filter\\` arrive as injected\n events while you keep working; command exit always delivers a summary. One-shot gate: wait\n inside the command and print one sentinel (\\`until <cond>; do sleep 1; done;\n printf 'READY\\\\n'\\`). Stream: \\`tail -n 0 -F | grep --line-buffered\\`. Filter noise at the\n source and stop with \\`kill_bash\\`.\n - \\`${monitor}({ description, path, event?, persistent? })\\` natively watches one regular file and\n fires once — prefer it over a shell poll loop. \\`\"create\"\\` (the default) fires only when the file\n appears after registration, so watch an already-existing file with \\`\"modify\"\\`; registration needs\n the parent directory to exist already, so poll with a \\`command\\` when the run creates that\n directory too. This branch takes no \\`filter\\`.\n A standing watch is marked \\`persistent: true\\`: it has no deadline, survives a session restart\n (the command is re-run once, the file rescanned and any change missed while detached reported),\n expires 7 days after creation, is capped at 5 per session, and is accounted for in one\n restart-report line on session start.\n Identical updates are deduped; repeated monitor-only wakes pause the noisy monitor(s) that\n caused them, not all monitors. Completion still wakes the session, and\n \\`${monitor}({ action: \"rearm\", bash_id })\\` resumes one while \\`${monitor}({ action: \"rearm\" })\\`\n resumes all paused monitors; real user input also resumes paused monitors.\n- \\`bash_input({ bash_id, input, keys, submit })\\` sends stdin or named keys (e.g.\n \\`[\"ctrl+c\"]\\`, \\`[\"enter\"]\\`) to steer a REPL or interrupt a process.\n- \\`bash_resize({ bash_id, cols, rows })\\` resizes the PTY so full-screen programs reflow.\n- \\`kill_bash({ bash_id })\\` (or \\`{ all: true }\\`) tears the session tree down with no orphans.\n`;\n}\n"]}
|
|
@@ -18,12 +18,25 @@ export declare function parseTerminalManifest(raw: unknown, ref: SidecarStoreRef
|
|
|
18
18
|
export type RestoreOutcome = "restored" | "lost" | "muted" | "attachedElsewhere";
|
|
19
19
|
export interface RestoreHandlerResult {
|
|
20
20
|
readonly outcome: RestoreOutcome;
|
|
21
|
+
/** Why a durable monitor could not be restored; diagnostic only, never part of the digest counts. */
|
|
22
|
+
readonly reason?: string;
|
|
21
23
|
}
|
|
22
24
|
export type RestoreHandler = (monitor: ManifestMonitor) => RestoreHandlerResult | Promise<RestoreHandlerResult>;
|
|
23
25
|
export interface RestoreHandlers {
|
|
24
26
|
readonly "restartable-command": RestoreHandler;
|
|
25
27
|
readonly "checkpointed-file": RestoreHandler;
|
|
26
28
|
}
|
|
29
|
+
/** The registry surface a restore handler needs to re-apply a persisted mute. */
|
|
30
|
+
export interface PersistedMuteRegistry {
|
|
31
|
+
pause(ids: readonly string[]): string[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Re-apply a persisted `deliveryPaused` mute to a freshly restored monitor and report the
|
|
35
|
+
* outcome it contributes to the digest. The mute MUST be applied by the FRESH runtime id
|
|
36
|
+
* (bash_N/watch_N) the restore just allocated: `MonitorRegistry.pause` resolves records by
|
|
37
|
+
* runtime id only, so passing the persisted `mon_` id silently no-ops and the mute is lost.
|
|
38
|
+
*/
|
|
39
|
+
export declare function reapplyPersistedMute(registry: PersistedMuteRegistry, monitor: Pick<ManifestMonitor, "deliveryPaused">, runtimeId: string): RestoreOutcome;
|
|
27
40
|
/** Stub durability handlers: every durable monitor is reported lost until later phases land. */
|
|
28
41
|
export declare const stubRestoreHandlers: RestoreHandlers;
|
|
29
42
|
export interface RestoreDigest {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/restore.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,wBAAwB,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACtH,OAAO,EAEN,KAAK,eAAe,EAEpB,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/restore.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,wBAAwB,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACtH,OAAO,EAEN,KAAK,eAAe,EAEpB,KAAK,gBAAgB,EAErB,MAAM,wBAAwB,CAAC;AAEhC,qBAAa,4BAA6B,SAAQ,wBAAwB;gBAC7D,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAI1D;AAiGD,kGAAkG;AAClG,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,eAAe,GAAG,gBAAgB,CAW1F;AAED,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,mBAAmB,CAAC;AAEjF,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,qGAAqG;IACrG,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,eAAe,KAAK,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAEhH,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,qBAAqB,EAAE,cAAc,CAAC;IAC/C,QAAQ,CAAC,mBAAmB,EAAE,cAAc,CAAC;CAC7C;AAED,iFAAiF;AACjF,MAAM,WAAW,qBAAqB;IACrC,KAAK,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;CACxC;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CACnC,QAAQ,EAAE,qBAAqB,EAC/B,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAChD,SAAS,EAAE,MAAM,GACf,cAAc,CAIhB;AAED,gGAAgG;AAChG,eAAO,MAAM,mBAAmB,EAAE,eAGjC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,2BAA2B;IAC3C,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAC;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAC7C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC5B;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,aAAa,CAAC,CAmCvG"}
|
|
@@ -34,6 +34,11 @@ function num(raw, field) {
|
|
|
34
34
|
invalid(`field ${field} must be a finite number`);
|
|
35
35
|
return raw[field];
|
|
36
36
|
}
|
|
37
|
+
function digest(raw, field) {
|
|
38
|
+
if (typeof raw[field] !== "string")
|
|
39
|
+
invalid(`field ${field} must be a string`);
|
|
40
|
+
return raw[field];
|
|
41
|
+
}
|
|
37
42
|
function bool(raw, field) {
|
|
38
43
|
if (!isBool(raw[field]))
|
|
39
44
|
invalid(`field ${field} must be a boolean`);
|
|
@@ -51,7 +56,16 @@ function oneOf(values, raw, field) {
|
|
|
51
56
|
function checkpoint(raw) {
|
|
52
57
|
if (!isObj(raw))
|
|
53
58
|
invalid("field lastCheckpoint must be an object");
|
|
54
|
-
return {
|
|
59
|
+
return {
|
|
60
|
+
dev: num(raw, "dev"),
|
|
61
|
+
ino: num(raw, "ino"),
|
|
62
|
+
size: num(raw, "size"),
|
|
63
|
+
mtimeMs: num(raw, "mtimeMs"),
|
|
64
|
+
// A checkpoint without a digest cannot detect a same-size, same-mtime rewrite, so the field is
|
|
65
|
+
// required — but an absent file legitimately checkpoints an empty digest, so "" is valid.
|
|
66
|
+
digest: digest(raw, "digest"),
|
|
67
|
+
present: bool(raw, "present"),
|
|
68
|
+
};
|
|
55
69
|
}
|
|
56
70
|
function fireWindow(raw) {
|
|
57
71
|
if (!isObj(raw))
|
|
@@ -79,7 +93,8 @@ function parseMonitor(entry) {
|
|
|
79
93
|
suspended: bool(entry, "suspended"),
|
|
80
94
|
lastCheckpoint: entry.lastCheckpoint === null ? null : checkpoint(entry.lastCheckpoint),
|
|
81
95
|
deliveryPaused: bool(entry, "deliveryPaused"),
|
|
82
|
-
|
|
96
|
+
// Unknown keys are ignored by this field-by-field parse, so a manifest written before
|
|
97
|
+
// `wakeCount` was dropped still reads back cleanly; no version bump is needed.
|
|
83
98
|
fireWindow: fireWindow(entry.fireWindow),
|
|
84
99
|
};
|
|
85
100
|
}
|
|
@@ -104,6 +119,18 @@ export function parseTerminalManifest(raw, ref) {
|
|
|
104
119
|
updatedAt: num(raw, "updatedAt"),
|
|
105
120
|
};
|
|
106
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* Re-apply a persisted `deliveryPaused` mute to a freshly restored monitor and report the
|
|
124
|
+
* outcome it contributes to the digest. The mute MUST be applied by the FRESH runtime id
|
|
125
|
+
* (bash_N/watch_N) the restore just allocated: `MonitorRegistry.pause` resolves records by
|
|
126
|
+
* runtime id only, so passing the persisted `mon_` id silently no-ops and the mute is lost.
|
|
127
|
+
*/
|
|
128
|
+
export function reapplyPersistedMute(registry, monitor, runtimeId) {
|
|
129
|
+
if (!monitor.deliveryPaused)
|
|
130
|
+
return "restored";
|
|
131
|
+
registry.pause([runtimeId]);
|
|
132
|
+
return "muted";
|
|
133
|
+
}
|
|
107
134
|
/** Stub durability handlers: every durable monitor is reported lost until later phases land. */
|
|
108
135
|
export const stubRestoreHandlers = {
|
|
109
136
|
"restartable-command": () => ({ outcome: "lost" }),
|
|
@@ -131,7 +158,8 @@ export async function restoreTerminalState(options) {
|
|
|
131
158
|
const now = (options.now ?? Date.now)();
|
|
132
159
|
const handlers = { ...stubRestoreHandlers, ...options.handlers };
|
|
133
160
|
for (const monitor of state.monitors) {
|
|
134
|
-
|
|
161
|
+
// At the deadline the entry is already expired: the handler must not see it at all.
|
|
162
|
+
if (monitor.expiresAt !== null && monitor.expiresAt <= now) {
|
|
135
163
|
digest.expired += 1;
|
|
136
164
|
continue;
|
|
137
165
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restore.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/restore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The terminal manifest's read side and restore orchestrator: the strict fail-closed\n * parse every persisted manifest must survive, plus `restoreTerminalState`, which\n * replays the manifest after a restart. Each monitor is classified by its durability\n * class and handed to that class's handler; ephemeral monitors and background sessions\n * are always lost, and an expired watch never reaches its handler. Both durable\n * handler slots ship as stubs reporting `lost` — later phases plug the real ones in.\n */\n\nimport { InvalidSidecarStoreError, type SidecarStore, type SidecarStoreRef } from \"../../../session-sidecar-store.ts\";\nimport {\n\ttype ManifestBackgroundSession,\n\ttype ManifestMonitor,\n\tTERMINAL_MANIFEST_VERSION,\n\ttype TerminalManifest,\n} from \"./terminal-manifest.ts\";\n\nexport class InvalidTerminalManifestError extends InvalidSidecarStoreError {\n\tconstructor(message: string, options?: { cause?: unknown }) {\n\t\tsuper(message, options);\n\t\tthis.name = \"InvalidTerminalManifestError\";\n\t}\n}\n\ntype Raw = Record<string, unknown>;\n\nconst RUNTIME_KINDS = [\"command\", \"file\"] as const;\nconst DURABILITY_CLASSES = [\"ephemeral\", \"restartable-command\", \"checkpointed-file\"] as const;\nconst FILE_EVENTS = [\"create\", \"modify\"] as const;\nconst isStr = (value: unknown): value is string => typeof value === \"string\" && value.length > 0;\nconst isNum = (value: unknown): value is number => typeof value === \"number\" && Number.isFinite(value);\nconst isBool = (value: unknown): value is boolean => typeof value === \"boolean\";\nconst isObj = (value: unknown): value is Raw => typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nfunction invalid(message: string): never {\n\tthrow new InvalidTerminalManifestError(`terminal manifest is invalid: ${message}`);\n}\n\nfunction str(raw: Raw, field: string): string {\n\tif (!isStr(raw[field])) invalid(`field ${field} must be a non-empty string`);\n\treturn raw[field];\n}\n\nfunction num(raw: Raw, field: string): number {\n\tif (!isNum(raw[field])) invalid(`field ${field} must be a finite number`);\n\treturn raw[field];\n}\n\nfunction bool(raw: Raw, field: string): boolean {\n\tif (!isBool(raw[field])) invalid(`field ${field} must be a boolean`);\n\treturn raw[field];\n}\n\nfunction opt<T>(raw: Raw, field: string, required: (raw: Raw, field: string) => T): T | undefined {\n\treturn raw[field] === undefined ? undefined : required(raw, field);\n}\n\nfunction oneOf<T extends string>(values: readonly T[], raw: Raw, field: string): T {\n\tconst value = raw[field];\n\tif (typeof value !== \"string\" || !values.includes(value as T))\n\t\tinvalid(`field ${field} must be one of: ${values.join(\", \")}`);\n\treturn value as T;\n}\n\nfunction checkpoint(raw: unknown): { dev: number; ino: number; size: number; mtimeMs: number } {\n\tif (!isObj(raw)) invalid(\"field lastCheckpoint must be an object\");\n\treturn { dev: num(raw, \"dev\"), ino: num(raw, \"ino\"), size: num(raw, \"size\"), mtimeMs: num(raw, \"mtimeMs\") };\n}\n\nfunction fireWindow(raw: unknown): { startMs: number; count: number } {\n\tif (!isObj(raw)) invalid(\"field fireWindow must be an object\");\n\treturn { startMs: num(raw, \"startMs\"), count: num(raw, \"count\") };\n}\n\nfunction parseMonitor(entry: unknown): ManifestMonitor {\n\tif (!isObj(entry)) invalid(\"a monitor entry must be an object\");\n\treturn {\n\t\tmonitorId: str(entry, \"monitorId\"),\n\t\tsessionId: str(entry, \"sessionId\"),\n\t\tdescription: str(entry, \"description\"),\n\t\truntimeKind: oneOf(RUNTIME_KINDS, entry, \"runtimeKind\"),\n\t\tdurabilityClass: oneOf(DURABILITY_CLASSES, entry, \"durabilityClass\"),\n\t\tcommand: opt(entry, \"command\", str),\n\t\tpath: opt(entry, \"path\", str),\n\t\tevent: opt(entry, \"event\", (raw, field) => oneOf(FILE_EVENTS, raw, field)),\n\t\tfilter: opt(entry, \"filter\", str),\n\t\tcwd: opt(entry, \"cwd\", str),\n\t\tapprovedParent: opt(entry, \"approvedParent\", str),\n\t\tcreatedAt: num(entry, \"createdAt\"),\n\t\texpiresAt: entry.expiresAt === undefined || entry.expiresAt === null ? null : num(entry, \"expiresAt\"),\n\t\tpersistent: bool(entry, \"persistent\"),\n\t\tsuspended: bool(entry, \"suspended\"),\n\t\tlastCheckpoint: entry.lastCheckpoint === null ? null : checkpoint(entry.lastCheckpoint),\n\t\tdeliveryPaused: bool(entry, \"deliveryPaused\"),\n\t\twakeCount: num(entry, \"wakeCount\"),\n\t\tfireWindow: fireWindow(entry.fireWindow),\n\t};\n}\n\nfunction parseBackgroundSession(entry: unknown): ManifestBackgroundSession {\n\tif (!isObj(entry)) invalid(\"a background session entry must be an object\");\n\treturn { id: str(entry, \"id\"), command: str(entry, \"command\"), startedAtMs: num(entry, \"startedAtMs\") };\n}\n\n/** Strict fail-closed domain parse; the sidecar store has already checked version and session. */\nexport function parseTerminalManifest(raw: unknown, ref: SidecarStoreRef): TerminalManifest {\n\tif (!isObj(raw)) invalid(\"the payload must be an object\");\n\tif (!Array.isArray(raw.monitors)) invalid(\"field monitors must be an array\");\n\tif (!Array.isArray(raw.backgroundSessions)) invalid(\"field backgroundSessions must be an array\");\n\treturn {\n\t\tversion: TERMINAL_MANIFEST_VERSION,\n\t\tsessionId: ref.sessionId,\n\t\tmonitors: raw.monitors.map(parseMonitor),\n\t\tbackgroundSessions: raw.backgroundSessions.map(parseBackgroundSession),\n\t\tupdatedAt: num(raw, \"updatedAt\"),\n\t};\n}\n\nexport type RestoreOutcome = \"restored\" | \"lost\" | \"muted\" | \"attachedElsewhere\";\n\nexport interface RestoreHandlerResult {\n\treadonly outcome: RestoreOutcome;\n}\n\nexport type RestoreHandler = (monitor: ManifestMonitor) => RestoreHandlerResult | Promise<RestoreHandlerResult>;\n\nexport interface RestoreHandlers {\n\treadonly \"restartable-command\": RestoreHandler;\n\treadonly \"checkpointed-file\": RestoreHandler;\n}\n\n/** Stub durability handlers: every durable monitor is reported lost until later phases land. */\nexport const stubRestoreHandlers: RestoreHandlers = {\n\t\"restartable-command\": () => ({ outcome: \"lost\" }),\n\t\"checkpointed-file\": () => ({ outcome: \"lost\" }),\n};\n\nexport interface RestoreDigest {\n\trestored: number;\n\tlost: number;\n\texpired: number;\n\tmuted: number;\n\tattachedElsewhere: number;\n\tstoreError: boolean;\n}\n\nexport interface RestoreTerminalStateOptions {\n\treadonly manifest: SidecarStore<TerminalManifest>;\n\treadonly handlers?: Partial<RestoreHandlers>;\n\treadonly now?: () => number;\n}\n\nexport async function restoreTerminalState(options: RestoreTerminalStateOptions): Promise<RestoreDigest> {\n\tconst digest: RestoreDigest = {\n\t\trestored: 0,\n\t\tlost: 0,\n\t\texpired: 0,\n\t\tmuted: 0,\n\t\tattachedElsewhere: 0,\n\t\tstoreError: false,\n\t};\n\tlet state: TerminalManifest | null;\n\ttry {\n\t\tstate = await options.manifest.read();\n\t} catch {\n\t\t// Fail closed: a corrupt or foreign manifest restores nothing and reports the store error.\n\t\treturn { ...digest, storeError: true };\n\t}\n\tif (state === null) return digest;\n\tconst now = (options.now ?? Date.now)();\n\tconst handlers: RestoreHandlers = { ...stubRestoreHandlers, ...options.handlers };\n\tfor (const monitor of state.monitors) {\n\t\tif (monitor.expiresAt !== null && monitor.expiresAt < now) {\n\t\t\tdigest.expired += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (monitor.durabilityClass === \"ephemeral\") {\n\t\t\tdigest.lost += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tconst outcome = (await handlers[monitor.durabilityClass](monitor)).outcome;\n\t\tdigest[outcome] += 1;\n\t}\n\t// Background sessions carry no durable identity: every one of them is lost.\n\tdigest.lost += state.backgroundSessions.length;\n\treturn digest;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"restore.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/restore.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The terminal manifest's read side and restore orchestrator: the strict fail-closed\n * parse every persisted manifest must survive, plus `restoreTerminalState`, which\n * replays the manifest after a restart. Each monitor is classified by its durability\n * class and handed to that class's handler; ephemeral monitors and background sessions\n * are always lost, and an expired watch never reaches its handler. Both durable\n * handler slots ship as stubs reporting `lost` — later phases plug the real ones in.\n */\n\nimport { InvalidSidecarStoreError, type SidecarStore, type SidecarStoreRef } from \"../../../session-sidecar-store.ts\";\nimport {\n\ttype ManifestBackgroundSession,\n\ttype ManifestMonitor,\n\tTERMINAL_MANIFEST_VERSION,\n\ttype TerminalManifest,\n\ttype TerminalManifestCheckpoint,\n} from \"./terminal-manifest.ts\";\n\nexport class InvalidTerminalManifestError extends InvalidSidecarStoreError {\n\tconstructor(message: string, options?: { cause?: unknown }) {\n\t\tsuper(message, options);\n\t\tthis.name = \"InvalidTerminalManifestError\";\n\t}\n}\n\ntype Raw = Record<string, unknown>;\n\nconst RUNTIME_KINDS = [\"command\", \"file\"] as const;\nconst DURABILITY_CLASSES = [\"ephemeral\", \"restartable-command\", \"checkpointed-file\"] as const;\nconst FILE_EVENTS = [\"create\", \"modify\"] as const;\nconst isStr = (value: unknown): value is string => typeof value === \"string\" && value.length > 0;\nconst isNum = (value: unknown): value is number => typeof value === \"number\" && Number.isFinite(value);\nconst isBool = (value: unknown): value is boolean => typeof value === \"boolean\";\nconst isObj = (value: unknown): value is Raw => typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nfunction invalid(message: string): never {\n\tthrow new InvalidTerminalManifestError(`terminal manifest is invalid: ${message}`);\n}\n\nfunction str(raw: Raw, field: string): string {\n\tif (!isStr(raw[field])) invalid(`field ${field} must be a non-empty string`);\n\treturn raw[field];\n}\n\nfunction num(raw: Raw, field: string): number {\n\tif (!isNum(raw[field])) invalid(`field ${field} must be a finite number`);\n\treturn raw[field];\n}\n\nfunction digest(raw: Raw, field: string): string {\n\tif (typeof raw[field] !== \"string\") invalid(`field ${field} must be a string`);\n\treturn raw[field];\n}\n\nfunction bool(raw: Raw, field: string): boolean {\n\tif (!isBool(raw[field])) invalid(`field ${field} must be a boolean`);\n\treturn raw[field];\n}\n\nfunction opt<T>(raw: Raw, field: string, required: (raw: Raw, field: string) => T): T | undefined {\n\treturn raw[field] === undefined ? undefined : required(raw, field);\n}\n\nfunction oneOf<T extends string>(values: readonly T[], raw: Raw, field: string): T {\n\tconst value = raw[field];\n\tif (typeof value !== \"string\" || !values.includes(value as T))\n\t\tinvalid(`field ${field} must be one of: ${values.join(\", \")}`);\n\treturn value as T;\n}\n\nfunction checkpoint(raw: unknown): TerminalManifestCheckpoint {\n\tif (!isObj(raw)) invalid(\"field lastCheckpoint must be an object\");\n\treturn {\n\t\tdev: num(raw, \"dev\"),\n\t\tino: num(raw, \"ino\"),\n\t\tsize: num(raw, \"size\"),\n\t\tmtimeMs: num(raw, \"mtimeMs\"),\n\t\t// A checkpoint without a digest cannot detect a same-size, same-mtime rewrite, so the field is\n\t\t// required — but an absent file legitimately checkpoints an empty digest, so \"\" is valid.\n\t\tdigest: digest(raw, \"digest\"),\n\t\tpresent: bool(raw, \"present\"),\n\t};\n}\n\nfunction fireWindow(raw: unknown): { startMs: number; count: number } {\n\tif (!isObj(raw)) invalid(\"field fireWindow must be an object\");\n\treturn { startMs: num(raw, \"startMs\"), count: num(raw, \"count\") };\n}\n\nfunction parseMonitor(entry: unknown): ManifestMonitor {\n\tif (!isObj(entry)) invalid(\"a monitor entry must be an object\");\n\treturn {\n\t\tmonitorId: str(entry, \"monitorId\"),\n\t\tsessionId: str(entry, \"sessionId\"),\n\t\tdescription: str(entry, \"description\"),\n\t\truntimeKind: oneOf(RUNTIME_KINDS, entry, \"runtimeKind\"),\n\t\tdurabilityClass: oneOf(DURABILITY_CLASSES, entry, \"durabilityClass\"),\n\t\tcommand: opt(entry, \"command\", str),\n\t\tpath: opt(entry, \"path\", str),\n\t\tevent: opt(entry, \"event\", (raw, field) => oneOf(FILE_EVENTS, raw, field)),\n\t\tfilter: opt(entry, \"filter\", str),\n\t\tcwd: opt(entry, \"cwd\", str),\n\t\tapprovedParent: opt(entry, \"approvedParent\", str),\n\t\tcreatedAt: num(entry, \"createdAt\"),\n\t\texpiresAt: entry.expiresAt === undefined || entry.expiresAt === null ? null : num(entry, \"expiresAt\"),\n\t\tpersistent: bool(entry, \"persistent\"),\n\t\tsuspended: bool(entry, \"suspended\"),\n\t\tlastCheckpoint: entry.lastCheckpoint === null ? null : checkpoint(entry.lastCheckpoint),\n\t\tdeliveryPaused: bool(entry, \"deliveryPaused\"),\n\t\t// Unknown keys are ignored by this field-by-field parse, so a manifest written before\n\t\t// `wakeCount` was dropped still reads back cleanly; no version bump is needed.\n\t\tfireWindow: fireWindow(entry.fireWindow),\n\t};\n}\n\nfunction parseBackgroundSession(entry: unknown): ManifestBackgroundSession {\n\tif (!isObj(entry)) invalid(\"a background session entry must be an object\");\n\treturn { id: str(entry, \"id\"), command: str(entry, \"command\"), startedAtMs: num(entry, \"startedAtMs\") };\n}\n\n/** Strict fail-closed domain parse; the sidecar store has already checked version and session. */\nexport function parseTerminalManifest(raw: unknown, ref: SidecarStoreRef): TerminalManifest {\n\tif (!isObj(raw)) invalid(\"the payload must be an object\");\n\tif (!Array.isArray(raw.monitors)) invalid(\"field monitors must be an array\");\n\tif (!Array.isArray(raw.backgroundSessions)) invalid(\"field backgroundSessions must be an array\");\n\treturn {\n\t\tversion: TERMINAL_MANIFEST_VERSION,\n\t\tsessionId: ref.sessionId,\n\t\tmonitors: raw.monitors.map(parseMonitor),\n\t\tbackgroundSessions: raw.backgroundSessions.map(parseBackgroundSession),\n\t\tupdatedAt: num(raw, \"updatedAt\"),\n\t};\n}\n\nexport type RestoreOutcome = \"restored\" | \"lost\" | \"muted\" | \"attachedElsewhere\";\n\nexport interface RestoreHandlerResult {\n\treadonly outcome: RestoreOutcome;\n\t/** Why a durable monitor could not be restored; diagnostic only, never part of the digest counts. */\n\treadonly reason?: string;\n}\n\nexport type RestoreHandler = (monitor: ManifestMonitor) => RestoreHandlerResult | Promise<RestoreHandlerResult>;\n\nexport interface RestoreHandlers {\n\treadonly \"restartable-command\": RestoreHandler;\n\treadonly \"checkpointed-file\": RestoreHandler;\n}\n\n/** The registry surface a restore handler needs to re-apply a persisted mute. */\nexport interface PersistedMuteRegistry {\n\tpause(ids: readonly string[]): string[];\n}\n\n/**\n * Re-apply a persisted `deliveryPaused` mute to a freshly restored monitor and report the\n * outcome it contributes to the digest. The mute MUST be applied by the FRESH runtime id\n * (bash_N/watch_N) the restore just allocated: `MonitorRegistry.pause` resolves records by\n * runtime id only, so passing the persisted `mon_` id silently no-ops and the mute is lost.\n */\nexport function reapplyPersistedMute(\n\tregistry: PersistedMuteRegistry,\n\tmonitor: Pick<ManifestMonitor, \"deliveryPaused\">,\n\truntimeId: string,\n): RestoreOutcome {\n\tif (!monitor.deliveryPaused) return \"restored\";\n\tregistry.pause([runtimeId]);\n\treturn \"muted\";\n}\n\n/** Stub durability handlers: every durable monitor is reported lost until later phases land. */\nexport const stubRestoreHandlers: RestoreHandlers = {\n\t\"restartable-command\": () => ({ outcome: \"lost\" }),\n\t\"checkpointed-file\": () => ({ outcome: \"lost\" }),\n};\n\nexport interface RestoreDigest {\n\trestored: number;\n\tlost: number;\n\texpired: number;\n\tmuted: number;\n\tattachedElsewhere: number;\n\tstoreError: boolean;\n}\n\nexport interface RestoreTerminalStateOptions {\n\treadonly manifest: SidecarStore<TerminalManifest>;\n\treadonly handlers?: Partial<RestoreHandlers>;\n\treadonly now?: () => number;\n}\n\nexport async function restoreTerminalState(options: RestoreTerminalStateOptions): Promise<RestoreDigest> {\n\tconst digest: RestoreDigest = {\n\t\trestored: 0,\n\t\tlost: 0,\n\t\texpired: 0,\n\t\tmuted: 0,\n\t\tattachedElsewhere: 0,\n\t\tstoreError: false,\n\t};\n\tlet state: TerminalManifest | null;\n\ttry {\n\t\tstate = await options.manifest.read();\n\t} catch {\n\t\t// Fail closed: a corrupt or foreign manifest restores nothing and reports the store error.\n\t\treturn { ...digest, storeError: true };\n\t}\n\tif (state === null) return digest;\n\tconst now = (options.now ?? Date.now)();\n\tconst handlers: RestoreHandlers = { ...stubRestoreHandlers, ...options.handlers };\n\tfor (const monitor of state.monitors) {\n\t\t// At the deadline the entry is already expired: the handler must not see it at all.\n\t\tif (monitor.expiresAt !== null && monitor.expiresAt <= now) {\n\t\t\tdigest.expired += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (monitor.durabilityClass === \"ephemeral\") {\n\t\t\tdigest.lost += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tconst outcome = (await handlers[monitor.durabilityClass](monitor)).outcome;\n\t\tdigest[outcome] += 1;\n\t}\n\t// Background sessions carry no durable identity: every one of them is lost.\n\tdigest.lost += state.backgroundSessions.length;\n\treturn digest;\n}\n"]}
|
|
@@ -24,6 +24,31 @@ export declare const BACKGROUND_START_GRACE_MS = 250;
|
|
|
24
24
|
* the agent blocked forever.
|
|
25
25
|
*/
|
|
26
26
|
export declare const KILLED_SESSION_EXIT_GRACE_MS = 5000;
|
|
27
|
+
/**
|
|
28
|
+
* Admission cap on durable (restart-surviving) monitors per session. Ephemeral monitors
|
|
29
|
+
* never count against it: only entries the manifest keeps across a restart do.
|
|
30
|
+
*/
|
|
31
|
+
export declare const MAX_DURABLE_MONITORS = 5;
|
|
32
|
+
/**
|
|
33
|
+
* Absolute lifetime of a durable monitor, measured from its registration. It is a deadline,
|
|
34
|
+
* never a sliding window: neither a restore nor a rearm extends it.
|
|
35
|
+
*/
|
|
36
|
+
export declare const DURABLE_MONITOR_EXPIRY_MS: number;
|
|
37
|
+
/**
|
|
38
|
+
* Per-monitor rolling fire budget: one durable command watch may deliver at most this many
|
|
39
|
+
* matched line events inside any FIRE_BUDGET_WINDOW_MS window before the registry auto-mutes
|
|
40
|
+
* it. The session-global wake budget only counts consecutive line-only wakes on an idle
|
|
41
|
+
* session, so a busy session needs this per-monitor backstop against a runaway watch.
|
|
42
|
+
*/
|
|
43
|
+
export declare const DEFAULT_DURABLE_MONITOR_FIRE_BUDGET = 200;
|
|
44
|
+
/** Width of the rolling fire-budget window: the budget replenishes after this span elapses. */
|
|
45
|
+
export declare const FIRE_BUDGET_WINDOW_MS: number;
|
|
46
|
+
/**
|
|
47
|
+
* The ONE summary emitted when the fire budget mutes a watch. Machine-consumed: the monitor
|
|
48
|
+
* notifier exempts exactly this summary from its completion handling, so the mute must not
|
|
49
|
+
* clear the session-global wake streak.
|
|
50
|
+
*/
|
|
51
|
+
export declare const FIRE_BUDGET_AUTO_MUTE_SUMMARY = "auto-muted: fire budget (200/24h) reached; rearm to resume";
|
|
27
52
|
/**
|
|
28
53
|
* Non-interactive environment for foreground one-shot commands (codex-style):
|
|
29
54
|
* cooperative tools (`gh`, `git`, pagers, color libs) skip spinners/colors at
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/shared.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,kBAAkB,SAAS,CAAC;AACzC,eAAO,MAAM,oBAAoB,gBAAgB,CAAC;AAClD,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAC9C,eAAO,MAAM,mBAAmB,eAAe,CAAC;AAChD,eAAO,MAAM,oBAAoB,gBAAgB,CAAC;AAClD,eAAO,MAAM,qBAAqB,YAAY,CAAC;AAE/C,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,+EAM3B,CAAC;AAEX,eAAO,MAAM,YAAY,MAAM,CAAC;AAChC,eAAO,MAAM,YAAY,KAAK,CAAC;AAC/B,eAAO,MAAM,kBAAkB,QAAS,CAAC;AACzC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,2FAA2F;AAC3F,eAAO,MAAM,wBAAwB,UAAY,CAAC;AAClD,gGAAgG;AAChG,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOrE,CAAC;AAiCF,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ7D;AAED,2FAA2F;AAC3F,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CASvF;AAED,oFAAoF;AACpF,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMzD"}
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/terminal/shared.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,kBAAkB,SAAS,CAAC;AACzC,eAAO,MAAM,oBAAoB,gBAAgB,CAAC;AAClD,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAC9C,eAAO,MAAM,mBAAmB,eAAe,CAAC;AAChD,eAAO,MAAM,oBAAoB,gBAAgB,CAAC;AAClD,eAAO,MAAM,qBAAqB,YAAY,CAAC;AAE/C,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,+EAM3B,CAAC;AAEX,eAAO,MAAM,YAAY,MAAM,CAAC;AAChC,eAAO,MAAM,YAAY,KAAK,CAAC;AAC/B,eAAO,MAAM,kBAAkB,QAAS,CAAC;AACzC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,2FAA2F;AAC3F,eAAO,MAAM,wBAAwB,UAAY,CAAC;AAClD,gGAAgG;AAChG,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC;;;GAGG;AACH,eAAO,MAAM,yBAAyB,QAA0B,CAAC;AACjE;;;;;GAKG;AACH,eAAO,MAAM,mCAAmC,MAAM,CAAC;AACvD,+FAA+F;AAC/F,eAAO,MAAM,qBAAqB,QAAsB,CAAC;AACzD;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,+DAAkG,CAAC;AAE7I;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOrE,CAAC;AAiCF,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ7D;AAED,2FAA2F;AAC3F,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CASvF;AAED,oFAAoF;AACpF,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMzD"}
|