@code-yeongyu/senpi 2026.8.19 → 2026.8.20
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 +117 -0
- package/dist/cli-main.js +4 -0
- package/dist/cli-main.js.map +1 -1
- package/dist/cli.js +31 -3
- package/dist/cli.js.map +1 -1
- package/dist/compile-cache.d.ts +2 -0
- package/dist/compile-cache.d.ts.map +1 -0
- package/dist/compile-cache.js +33 -0
- package/dist/compile-cache.js.map +1 -0
- package/dist/core/agent-session.d.ts +5 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +94 -12
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +6 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +13 -0
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/cursor-exec-bridge-session.d.ts +2 -1
- package/dist/core/cursor-exec-bridge-session.d.ts.map +1 -1
- package/dist/core/cursor-exec-bridge-session.js +5 -2
- package/dist/core/cursor-exec-bridge-session.js.map +1 -1
- package/dist/core/cursor-exec-bridge.d.ts +9 -1
- package/dist/core/cursor-exec-bridge.d.ts.map +1 -1
- package/dist/core/cursor-exec-bridge.js +26 -2
- package/dist/core/cursor-exec-bridge.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/custom-tools.d.ts +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/custom-tools.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/custom-tools.js +5 -2
- package/dist/core/extensions/builtin/claude-sdk-oauth/custom-tools.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.d.ts +6 -4
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.js +24 -2
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.lazy.d.ts +39 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.lazy.d.ts.map +1 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.lazy.js +31 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/sdk-boundary.lazy.js.map +1 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.d.ts +2 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.js +35 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-continuity.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.d.ts +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.js +1 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-observability.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.d.ts +8 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js +4 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.js +28 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-turn-attempt.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/stream.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/stream.js +5 -2
- package/dist/core/extensions/builtin/claude-sdk-oauth/stream.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +5 -0
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/log.d.ts +1 -1
- package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/log.js +1 -0
- package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.d.ts +1 -0
- package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.js +4 -0
- package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/index.js +13 -10
- package/dist/core/extensions/builtin/config-reload/index.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-engine.d.ts +8 -1
- package/dist/core/extensions/builtin/config-reload/watch-engine.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-engine.js +98 -18
- package/dist/core/extensions/builtin/config-reload/watch-engine.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-event-source.d.ts +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-event-source.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/watch-event-source.js +7 -2
- package/dist/core/extensions/builtin/config-reload/watch-event-source.js.map +1 -1
- package/dist/core/extensions/builtin/goal/elapsed-ticker.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/elapsed-ticker.js +15 -1
- package/dist/core/extensions/builtin/goal/elapsed-ticker.js.map +1 -1
- package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/index.js +7 -22
- package/dist/core/extensions/builtin/goal/index.js.map +1 -1
- package/dist/core/extensions/builtin/goal/stale-context.d.ts +9 -0
- package/dist/core/extensions/builtin/goal/stale-context.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/stale-context.js +11 -0
- package/dist/core/extensions/builtin/goal/stale-context.js.map +1 -0
- package/dist/core/extensions/builtin/goal/wait-ticker.d.ts +8 -0
- package/dist/core/extensions/builtin/goal/wait-ticker.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/wait-ticker.js +37 -3
- package/dist/core/extensions/builtin/goal/wait-ticker.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/index.js +12 -1
- package/dist/core/extensions/builtin/mcp/index.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-url-widget.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-url-widget.js +7 -15
- package/dist/core/extensions/builtin/prompt-url-widget.js.map +1 -1
- package/dist/core/extensions/builtin/rules/ui/rules-banner.d.ts.map +1 -1
- package/dist/core/extensions/builtin/rules/ui/rules-banner.js +21 -25
- package/dist/core/extensions/builtin/rules/ui/rules-banner.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/index.js +20 -0
- package/dist/core/extensions/builtin/todotools/index.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/native-todo-mirror.d.ts +3 -0
- package/dist/core/extensions/builtin/todotools/native-todo-mirror.d.ts.map +1 -0
- package/dist/core/extensions/builtin/todotools/native-todo-mirror.js +22 -0
- package/dist/core/extensions/builtin/todotools/native-todo-mirror.js.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/content.lazy.d.ts +17 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/content.lazy.d.ts.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/content.lazy.js +22 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/content.lazy.js.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.js +3 -3
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.js.map +1 -1
- package/dist/core/messages.d.ts +9 -2
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +13 -18
- package/dist/core/messages.js.map +1 -1
- package/dist/core/retry-fallback/hint-policy.d.ts +3 -2
- package/dist/core/retry-fallback/hint-policy.d.ts.map +1 -1
- package/dist/core/retry-fallback/hint-policy.js +19 -8
- package/dist/core/retry-fallback/hint-policy.js.map +1 -1
- package/dist/core/retry-fallback/settings.js.map +1 -1
- package/dist/core/session-discovery.d.ts +16 -0
- package/dist/core/session-discovery.d.ts.map +1 -0
- package/dist/core/session-discovery.js +101 -0
- package/dist/core/session-discovery.js.map +1 -0
- package/dist/core/session-manager.d.ts +2 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +4 -170
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-record.d.ts +14 -0
- package/dist/core/session-record.d.ts.map +1 -0
- package/dist/core/session-record.js +47 -0
- package/dist/core/session-record.js.map +1 -0
- package/dist/core/session-summary-cache.d.ts +40 -0
- package/dist/core/session-summary-cache.d.ts.map +1 -0
- package/dist/core/session-summary-cache.js +79 -0
- package/dist/core/session-summary-cache.js.map +1 -0
- package/dist/core/session-summary-lru.d.ts +54 -0
- package/dist/core/session-summary-lru.d.ts.map +1 -0
- package/dist/core/session-summary-lru.js +72 -0
- package/dist/core/session-summary-lru.js.map +1 -0
- package/dist/core/session-summary.d.ts +29 -0
- package/dist/core/session-summary.d.ts.map +1 -0
- package/dist/core/session-summary.js +90 -0
- package/dist/core/session-summary.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/inspector-policy.d.ts +6 -0
- package/dist/inspector-policy.d.ts.map +1 -1
- package/dist/inspector-policy.js +6 -1
- package/dist/inspector-policy.js.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.js +8 -8
- package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
- package/dist/modes/interactive/components/progressive-transcript-container.d.ts +72 -0
- package/dist/modes/interactive/components/progressive-transcript-container.d.ts.map +1 -0
- package/dist/modes/interactive/components/progressive-transcript-container.js +150 -0
- package/dist/modes/interactive/components/progressive-transcript-container.js.map +1 -0
- package/dist/modes/interactive/components/status-indicator.d.ts +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +8 -2
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +127 -65
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/split-trailing-assistant-text.d.ts +7 -0
- package/dist/modes/interactive/split-trailing-assistant-text.d.ts.map +1 -0
- package/dist/modes/interactive/split-trailing-assistant-text.js +19 -0
- package/dist/modes/interactive/split-trailing-assistant-text.js.map +1 -0
- package/dist/senpi +31 -3
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +12 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +38 -3
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.d.ts +8 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.js +25 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/assistant-terminal-state.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +284 -209
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts +37 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js +110 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-task-args.d.ts +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-task-args.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-task-args.js +17 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-task-args.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/cursor/selection-descriptor.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/cursor/selection-descriptor.js +27 -11
- package/node_modules/@earendil-works/pi-ai/dist/cursor/selection-descriptor.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/amazon-bedrock.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/baseten.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.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/dist/tool-call-middleware/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts +30 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +33 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +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":"watch-engine.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/config-reload/watch-engine.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { lstatSync, readdirSync, readFileSync, type Stats } from \"node:fs\";\nimport { basename, isAbsolute, join, normalize, resolve, sep } from \"node:path\";\n\nexport { createFsWatchEventSource } from \"./watch-event-source.ts\";\n\nexport type WatchTarget = {\n\treadonly id: string;\n\treadonly kind: \"dir\" | \"dir-recursive\";\n\treadonly path: string;\n\treadonly allowList?: readonly string[];\n\treadonly filter?: (relPath: string) => boolean;\n};\n\nexport type WatchEventListener = (eventType: string, filename: string | null) => void;\n\nexport type WatchEventSource = (\n\tpath: string,\n\tlistener: WatchEventListener,\n\toptions?: { readonly recursive: boolean },\n) => () => void;\n\nexport type WatchClock = {\n\tsetTimeout(callback: () => void, delayMs: number): ReturnType<typeof setTimeout>;\n\tclearTimeout(timer: ReturnType<typeof setTimeout>): void;\n};\n\nexport type RealChange = {\n\treadonly changedPaths: readonly string[];\n\treadonly created: readonly string[];\n\treadonly deleted: readonly string[];\n};\n\nexport type ConfigReloadWatchEngineOptions = {\n\treadonly targets: readonly WatchTarget[];\n\treadonly subscribe: WatchEventSource;\n\treadonly onRealChange: (change: RealChange) => void;\n\treadonly onError?: (error: unknown, path: string) => void;\n\treadonly debounceMs?: number;\n\treadonly clock?: WatchClock;\n\t/** Test seam. Production callers use SHA-256 of file bytes. */\n\treadonly hashFile?: (path: string) => string;\n};\n\ntype TargetState = {\n\treadonly target: ResolvedWatchTarget;\n\treadonly hashes: Map<string, string>;\n\treadonly allowedDirectories: Set<string>;\n};\n\ntype ResolvedWatchTarget = Omit<WatchTarget, \"path\"> & { readonly path: string };\n\ntype ScanResult = {\n\treadonly hashes: Map<string, string>;\n\treadonly allowedDirectories: Set<string>;\n};\n\nconst DEFAULT_DEBOUNCE_MS = 200;\nconst DEFAULT_CLOCK: WatchClock = {\n\tsetTimeout: (callback, delayMs) => setTimeout(callback, delayMs),\n\tclearTimeout: (timer) => clearTimeout(timer),\n};\n\n/**\n * Hash-gates filesystem events. Targets are directories by design: watching a\n * file directly breaks when editors atomically rename a replacement over it.\n */\nexport class ConfigReloadWatchEngine {\n\treadonly #states: TargetState[];\n\treadonly #unsubscribes: (() => void)[] = [];\n\treadonly #subscribe: WatchEventSource;\n\treadonly #onRealChange: (change: RealChange) => void;\n\treadonly #onError: (error: unknown, path: string) => void;\n\treadonly #hashFile: (path: string) => string;\n\treadonly #clock: WatchClock;\n\treadonly #debounceMs: number;\n\treadonly #pending = new Map<TargetState, Set<string> | null>();\n\t#timer: ReturnType<typeof setTimeout> | undefined;\n\t#closed = false;\n\n\tconstructor(options: ConfigReloadWatchEngineOptions) {\n\t\tthis.#subscribe = options.subscribe;\n\t\tthis.#onRealChange = options.onRealChange;\n\t\tthis.#onError = options.onError ?? (() => {});\n\t\tthis.#hashFile = options.hashFile ?? hashFile;\n\t\tthis.#clock = options.clock ?? DEFAULT_CLOCK;\n\t\tthis.#debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n\t\tthis.#states = options.targets.map((target) => {\n\t\t\tconst resolvedTarget = { ...target, path: resolve(target.path) };\n\t\t\tconst scan = this.#scan(resolvedTarget);\n\t\t\treturn {\n\t\t\t\ttarget: resolvedTarget,\n\t\t\t\thashes: scan.hashes,\n\t\t\t\tallowedDirectories: scan.allowedDirectories,\n\t\t\t};\n\t\t});\n\n\t\tfor (const state of this.#states) {\n\t\t\ttry {\n\t\t\t\tthis.#unsubscribes.push(\n\t\t\t\t\tthis.#subscribe(\n\t\t\t\t\t\tstate.target.path,\n\t\t\t\t\t\t(eventType, filename) => {\n\t\t\t\t\t\t\tthis.#onEvent(state, eventType, filename);\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ recursive: state.target.kind === \"dir-recursive\" },\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tthis.#reportError(error, state.target.path);\n\t\t\t}\n\t\t}\n\t}\n\n\tclose(): void {\n\t\tif (this.#closed) {\n\t\t\treturn;\n\t\t}\n\t\tthis.#closed = true;\n\t\tif (this.#timer) {\n\t\t\tthis.#clock.clearTimeout(this.#timer);\n\t\t\tthis.#timer = undefined;\n\t\t}\n\t\tfor (const unsubscribe of this.#unsubscribes.splice(0)) {\n\t\t\ttry {\n\t\t\t\tunsubscribe();\n\t\t\t} catch (error) {\n\t\t\t\tthis.#reportError(error, \"watch subscription\");\n\t\t\t}\n\t\t}\n\t}\n\n\tgetBaselineSnapshot(): ReadonlyMap<string, string> {\n\t\tconst snapshot = new Map<string, string>();\n\t\tfor (const state of this.#states) {\n\t\t\tfor (const [path, hash] of state.hashes) {\n\t\t\t\tsnapshot.set(path, hash);\n\t\t\t}\n\t\t}\n\t\treturn snapshot;\n\t}\n\n\t#onEvent(state: TargetState, _eventType: string, filename: string | null): void {\n\t\tif (this.#closed) {\n\t\t\treturn;\n\t\t}\n\t\tif (filename === null) {\n\t\t\tthis.#pending.set(state, null);\n\t\t} else if (this.#pending.get(state) !== null) {\n\t\t\tconst affected = this.#pending.get(state) ?? new Set<string>();\n\t\t\tconst relPath = normalizeRelativePath(filename);\n\t\t\tif (relPath && this.#matches(state.target, relPath)) {\n\t\t\t\taffected.add(relPath);\n\t\t\t\tthis.#pending.set(state, affected);\n\t\t\t}\n\t\t}\n\t\tthis.#schedule();\n\t}\n\n\t#schedule(): void {\n\t\tif (this.#timer) {\n\t\t\tthis.#clock.clearTimeout(this.#timer);\n\t\t}\n\t\tthis.#timer = this.#clock.setTimeout(() => {\n\t\t\tthis.#timer = undefined;\n\t\t\tthis.#evaluatePending();\n\t\t}, this.#debounceMs);\n\t}\n\n\t#evaluatePending(): void {\n\t\tif (this.#closed) {\n\t\t\treturn;\n\t\t}\n\t\tconst changes = new Map<string, { created: boolean; deleted: boolean }>();\n\t\tfor (const [state, affected] of this.#pending) {\n\t\t\tthis.#evaluateState(state, affected, changes);\n\t\t}\n\t\tthis.#pending.clear();\n\t\tif (changes.size > 0) {\n\t\t\tconst changedPaths = [...changes.keys()].sort();\n\t\t\tthis.#onRealChange({\n\t\t\t\tchangedPaths,\n\t\t\t\tcreated: changedPaths.filter((path) => changes.get(path)?.created),\n\t\t\t\tdeleted: changedPaths.filter((path) => changes.get(path)?.deleted),\n\t\t\t});\n\t\t}\n\t}\n\n\t#evaluateState(\n\t\tstate: TargetState,\n\t\taffected: Set<string> | null,\n\t\tchanges: Map<string, { created: boolean; deleted: boolean }>,\n\t): void {\n\t\tconst previousHashes = new Map(state.hashes);\n\t\tconst previousDirectories = new Set(state.allowedDirectories);\n\t\tconst next = affected === null ? this.#scan(state.target) : this.#scanAffected(state.target, affected, state);\n\n\t\tif (affected === null) {\n\t\t\tstate.hashes.clear();\n\t\t\tfor (const [path, hash] of next.hashes) {\n\t\t\t\tstate.hashes.set(path, hash);\n\t\t\t}\n\t\t\tstate.allowedDirectories.clear();\n\t\t\tfor (const path of next.allowedDirectories) {\n\t\t\t\tstate.allowedDirectories.add(path);\n\t\t\t}\n\t\t\tthis.#compare(previousHashes, previousDirectories, state.hashes, state.allowedDirectories, changes);\n\t\t\treturn;\n\t\t}\n\n\t\tconst prefixes = [...affected].map((relPath) => join(state.target.path, relPath));\n\t\tfor (const path of [...state.hashes.keys()]) {\n\t\t\tif (prefixes.some((prefix) => isWithin(path, prefix))) {\n\t\t\t\tstate.hashes.delete(path);\n\t\t\t}\n\t\t}\n\t\tfor (const path of [...state.allowedDirectories]) {\n\t\t\tif (prefixes.some((prefix) => isWithin(path, prefix))) {\n\t\t\t\tstate.allowedDirectories.delete(path);\n\t\t\t}\n\t\t}\n\t\tfor (const [path, hash] of next.hashes) {\n\t\t\tstate.hashes.set(path, hash);\n\t\t}\n\t\tfor (const path of next.allowedDirectories) {\n\t\t\tstate.allowedDirectories.add(path);\n\t\t}\n\t\tthis.#compare(previousHashes, previousDirectories, state.hashes, state.allowedDirectories, changes);\n\t}\n\n\t#scanAffected(target: ResolvedWatchTarget, affected: Set<string>, state: TargetState): ScanResult {\n\t\tconst result: ScanResult = { hashes: new Map(), allowedDirectories: new Set() };\n\t\tfor (const relPath of affected) {\n\t\t\tconst absolutePath = join(target.path, relPath);\n\t\t\tthis.#scanPath(target, absolutePath, relPath, result, state);\n\t\t}\n\t\treturn result;\n\t}\n\n\t#scan(target: ResolvedWatchTarget): ScanResult {\n\t\tconst result: ScanResult = { hashes: new Map(), allowedDirectories: new Set() };\n\t\tthis.#scanPath(target, target.path, \"\", result);\n\t\treturn result;\n\t}\n\n\t#scanPath(\n\t\ttarget: ResolvedWatchTarget,\n\t\tabsolutePath: string,\n\t\trelPath: string,\n\t\tresult: ScanResult,\n\t\tstate?: TargetState,\n\t): void {\n\t\tif (relPath && !this.#matches(target, relPath)) {\n\t\t\treturn;\n\t\t}\n\t\tlet entry: Stats;\n\t\ttry {\n\t\t\tentry = lstatSync(absolutePath);\n\t\t} catch (error) {\n\t\t\tif (state && !isMissing(error)) {\n\t\t\t\tthis.#reportError(error, absolutePath);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (entry.isSymbolicLink()) {\n\t\t\treturn;\n\t\t}\n\t\tif (entry.isFile()) {\n\t\t\ttry {\n\t\t\t\tresult.hashes.set(absolutePath, this.#hashFile(absolutePath));\n\t\t\t} catch (error) {\n\t\t\t\tthis.#reportError(error, absolutePath);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (!entry.isDirectory()) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst dotDirectory = relPath !== \"\" && basename(relPath).startsWith(\".\");\n\t\tconst explicitlyAllowedDirectory = relPath !== \"\" && this.#isExplicitlyAllowedDirectory(target, relPath);\n\t\tif (explicitlyAllowedDirectory) {\n\t\t\tresult.allowedDirectories.add(absolutePath);\n\t\t}\n\t\tif (relPath && target.kind === \"dir\") {\n\t\t\treturn;\n\t\t}\n\t\tif (dotDirectory && !explicitlyAllowedDirectory) {\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tfor (const child of readdirSync(absolutePath, { withFileTypes: true })) {\n\t\t\t\tif (child.isSymbolicLink() || child.name === \"node_modules\" || child.name === \".git\") {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst childRelPath = relPath ? join(relPath, child.name) : child.name;\n\t\t\t\tif (\n\t\t\t\t\tchild.isDirectory() &&\n\t\t\t\t\tchild.name.startsWith(\".\") &&\n\t\t\t\t\t!this.#isExplicitlyAllowedDirectory(target, childRelPath)\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthis.#scanPath(target, join(absolutePath, child.name), childRelPath, result, state);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.#reportError(error, absolutePath);\n\t\t}\n\t}\n\n\t#compare(\n\t\tpreviousHashes: ReadonlyMap<string, string>,\n\t\tpreviousDirectories: ReadonlySet<string>,\n\t\tnextHashes: ReadonlyMap<string, string>,\n\t\tnextDirectories: ReadonlySet<string>,\n\t\tchanges: Map<string, { created: boolean; deleted: boolean }>,\n\t): void {\n\t\tfor (const [path, hash] of nextHashes) {\n\t\t\tconst oldHash = previousHashes.get(path);\n\t\t\tif (oldHash !== hash) {\n\t\t\t\tchanges.set(path, { created: oldHash === undefined, deleted: false });\n\t\t\t}\n\t\t}\n\t\tfor (const path of previousHashes.keys()) {\n\t\t\tif (!nextHashes.has(path)) {\n\t\t\t\tchanges.set(path, { created: false, deleted: true });\n\t\t\t}\n\t\t}\n\t\tfor (const path of nextDirectories) {\n\t\t\tif (!previousDirectories.has(path)) {\n\t\t\t\tchanges.set(path, { created: true, deleted: false });\n\t\t\t}\n\t\t}\n\t\tfor (const path of previousDirectories) {\n\t\t\tif (!nextDirectories.has(path)) {\n\t\t\t\tchanges.set(path, { created: false, deleted: true });\n\t\t\t}\n\t\t}\n\t}\n\n\t#matches(target: ResolvedWatchTarget, relPath: string): boolean {\n\t\tif (!target.kind.includes(\"recursive\") && relPath.includes(sep)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (\n\t\t\ttarget.allowList &&\n\t\t\t!target.allowList.some((allowed) => relPath === allowed || relPath.startsWith(`${allowed}${sep}`))\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\treturn target.filter?.(relPath) ?? true;\n\t}\n\n\t#isExplicitlyAllowedDirectory(target: ResolvedWatchTarget, relPath: string): boolean {\n\t\treturn (\n\t\t\ttarget.allowList?.some((allowed) => relPath === allowed || relPath.startsWith(`${allowed}${sep}`)) ?? false\n\t\t);\n\t}\n\n\t#reportError(error: unknown, path: string): void {\n\t\ttry {\n\t\t\tthis.#onError(error, path);\n\t\t} catch {\n\t\t\t// Error reporting must not take down the watcher.\n\t\t}\n\t}\n}\n\nfunction hashFile(path: string): string {\n\treturn createHash(\"sha256\").update(readFileSync(path)).digest(\"hex\");\n}\n\nfunction normalizeRelativePath(filename: string): string | undefined {\n\tif (isAbsolute(filename)) {\n\t\treturn undefined;\n\t}\n\tconst normalized = normalize(filename);\n\treturn normalized === \".\" || normalized === \"..\" || normalized.startsWith(`..${sep}`) ? undefined : normalized;\n}\n\nfunction isWithin(path: string, prefix: string): boolean {\n\treturn path === prefix || path.startsWith(`${prefix}${sep}`);\n}\n\nfunction isMissing(error: unknown): boolean {\n\treturn typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\";\n}\n"]}
|
|
1
|
+
{"version":3,"file":"watch-engine.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/config-reload/watch-engine.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { lstatSync, readdirSync, readFileSync, type Stats } from \"node:fs\";\nimport { basename, isAbsolute, join, normalize, relative, resolve, sep } from \"node:path\";\n\nexport { createFsWatchEventSource } from \"./watch-event-source.ts\";\n\nexport type WatchTarget = {\n\treadonly id: string;\n\treadonly kind: \"dir\" | \"dir-recursive\";\n\treadonly path: string;\n\treadonly allowList?: readonly string[];\n\treadonly filter?: (relPath: string) => boolean;\n};\n\nexport type WatchEventListener = (eventType: string, filename: string | null) => void;\n\nexport type WatchEventSource = (\n\tpath: string,\n\tlistener: WatchEventListener,\n\toptions?: { readonly recursive: boolean },\n) => () => void;\n\nexport type WatchClock = {\n\tsetTimeout(callback: () => void, delayMs: number): ReturnType<typeof setTimeout>;\n\tclearTimeout(timer: ReturnType<typeof setTimeout>): void;\n};\n\nexport type RealChange = {\n\treadonly changedPaths: readonly string[];\n\treadonly created: readonly string[];\n\treadonly deleted: readonly string[];\n};\n\nexport type ConfigReloadWatchEngineOptions = {\n\treadonly targets: readonly WatchTarget[];\n\treadonly subscribe: WatchEventSource;\n\treadonly onRealChange: (change: RealChange) => void;\n\treadonly onError?: (error: unknown, path: string) => void;\n\treadonly debounceMs?: number;\n\treadonly clock?: WatchClock;\n\t/** Test seam. Production callers use SHA-256 of file bytes. */\n\treadonly hashFile?: (path: string) => string;\n};\n\ntype TargetState = {\n\treadonly target: ResolvedWatchTarget;\n\treadonly hashes: Map<string, string>;\n\treadonly allowedDirectories: Set<string>;\n\t/**\n\t * Directories the scan actually descended into, which are exactly the\n\t * directories worth handing to the OS. Recursive targets subscribe per entry\n\t * here instead of registering their whole subtree.\n\t */\n\treadonly watchedDirectories: Map<string, () => void>;\n\t/** Directories currently in scope, refreshed by every scan. */\n\tscannedDirectories: Set<string>;\n};\n\ntype ResolvedWatchTarget = Omit<WatchTarget, \"path\"> & { readonly path: string };\n\ntype ScanResult = {\n\treadonly hashes: Map<string, string>;\n\treadonly allowedDirectories: Set<string>;\n\t/** Directories visited by the scan, i.e. the in-scope directory set. */\n\treadonly scannedDirectories: Set<string>;\n};\n\nconst DEFAULT_DEBOUNCE_MS = 200;\nconst DEFAULT_CLOCK: WatchClock = {\n\tsetTimeout: (callback, delayMs) => setTimeout(callback, delayMs),\n\tclearTimeout: (timer) => clearTimeout(timer),\n};\n\n/**\n * Hash-gates filesystem events. Targets are directories by design: watching a\n * file directly breaks when editors atomically rename a replacement over it.\n */\nexport class ConfigReloadWatchEngine {\n\treadonly #states: TargetState[];\n\treadonly #unsubscribes: (() => void)[] = [];\n\treadonly #subscribe: WatchEventSource;\n\treadonly #onRealChange: (change: RealChange) => void;\n\treadonly #onError: (error: unknown, path: string) => void;\n\treadonly #hashFile: (path: string) => string;\n\treadonly #clock: WatchClock;\n\treadonly #debounceMs: number;\n\treadonly #pending = new Map<TargetState, Set<string> | null>();\n\t#timer: ReturnType<typeof setTimeout> | undefined;\n\t#closed = false;\n\n\tconstructor(options: ConfigReloadWatchEngineOptions) {\n\t\tthis.#subscribe = options.subscribe;\n\t\tthis.#onRealChange = options.onRealChange;\n\t\tthis.#onError = options.onError ?? (() => {});\n\t\tthis.#hashFile = options.hashFile ?? hashFile;\n\t\tthis.#clock = options.clock ?? DEFAULT_CLOCK;\n\t\tthis.#debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n\t\tthis.#states = options.targets.map((target) => {\n\t\t\tconst resolvedTarget = { ...target, path: resolve(target.path) };\n\t\t\tconst scan = this.#scan(resolvedTarget);\n\t\t\treturn {\n\t\t\t\ttarget: resolvedTarget,\n\t\t\t\thashes: scan.hashes,\n\t\t\t\tallowedDirectories: scan.allowedDirectories,\n\t\t\t\twatchedDirectories: new Map<string, () => void>(),\n\t\t\t\tscannedDirectories: scan.scannedDirectories,\n\t\t\t};\n\t\t});\n\n\t\tfor (const state of this.#states) {\n\t\t\tthis.#attach(state, state.scannedDirectories);\n\t\t}\n\t}\n\n\t/**\n\t * Subscribes to exactly the in-scope directories.\n\t *\n\t * A `dir-recursive` target used to hand its root to `fs.watch({recursive:true})`,\n\t * which registers the entire subtree with the OS watcher (FSEvents on macOS).\n\t * The target `filter` only discards events after delivery, so an extensions or\n\t * skills directory containing `node_modules` still cost a full-subtree\n\t * registration per session. The scan already knows which directories are in\n\t * scope — it skips `node_modules`, `.git`, symlinks, and filtered paths — so\n\t * watching that set directly gives identical coverage at a fraction of the\n\t * OS-level cost.\n\t */\n\t#attach(state: TargetState, directories: ReadonlySet<string>): void {\n\t\tconst recursive = state.target.kind === \"dir-recursive\";\n\t\t// The root is always watched so that creations directly beneath it are seen.\n\t\tconst wanted = recursive ? new Set([state.target.path, ...directories]) : new Set([state.target.path]);\n\t\tfor (const directory of wanted) {\n\t\t\tif (state.watchedDirectories.has(directory)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst unsubscribe = this.#subscribe(\n\t\t\t\t\tdirectory,\n\t\t\t\t\t(eventType, filename) => {\n\t\t\t\t\t\tthis.#onEvent(state, eventType, filename, directory);\n\t\t\t\t\t},\n\t\t\t\t\t{ recursive: false },\n\t\t\t\t);\n\t\t\t\tstate.watchedDirectories.set(directory, unsubscribe);\n\t\t\t\tthis.#unsubscribes.push(unsubscribe);\n\t\t\t} catch (error) {\n\t\t\t\tthis.#reportError(error, directory);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Drops subscriptions for directories that left scope (deleted or filtered out). */\n\t#detachMissing(state: TargetState, live: ReadonlySet<string>): void {\n\t\tfor (const [directory, unsubscribe] of [...state.watchedDirectories]) {\n\t\t\tif (directory === state.target.path || live.has(directory)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tstate.watchedDirectories.delete(directory);\n\t\t\tconst index = this.#unsubscribes.indexOf(unsubscribe);\n\t\t\tif (index >= 0) {\n\t\t\t\tthis.#unsubscribes.splice(index, 1);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tunsubscribe();\n\t\t\t} catch (error) {\n\t\t\t\tthis.#reportError(error, directory);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Marks the engine inert synchronously, then drains the unsubscribe loop off\n\t * the caller's stack. A single `fs.watch` unsubscribe can block for seconds on\n\t * a loaded machine, and a reload awaits this call; every dispatch path already\n\t * checks `#closed`, so the still-attached subscriptions are silent while the\n\t * returned promise settles. Await it only to observe teardown completion.\n\t */\n\tclose(): Promise<void> {\n\t\tif (this.#closed) {\n\t\t\treturn Promise.resolve();\n\t\t}\n\t\tthis.#closed = true;\n\t\tif (this.#timer) {\n\t\t\tthis.#clock.clearTimeout(this.#timer);\n\t\t\tthis.#timer = undefined;\n\t\t}\n\t\tconst unsubscribes = this.#unsubscribes.splice(0);\n\t\treturn new Promise<void>((settle) => {\n\t\t\tthis.#clock.setTimeout(() => {\n\t\t\t\tfor (const unsubscribe of unsubscribes) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tunsubscribe();\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthis.#reportError(error, \"watch subscription\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsettle();\n\t\t\t}, 0);\n\t\t});\n\t}\n\n\tgetBaselineSnapshot(): ReadonlyMap<string, string> {\n\t\tconst snapshot = new Map<string, string>();\n\t\tfor (const state of this.#states) {\n\t\t\tfor (const [path, hash] of state.hashes) {\n\t\t\t\tsnapshot.set(path, hash);\n\t\t\t}\n\t\t}\n\t\treturn snapshot;\n\t}\n\n\t#onEvent(state: TargetState, _eventType: string, filename: string | null, watchedDirectory?: string): void {\n\t\tif (this.#closed) {\n\t\t\treturn;\n\t\t}\n\t\tif (filename === null) {\n\t\t\tthis.#pending.set(state, null);\n\t\t} else if (this.#pending.get(state) !== null) {\n\t\t\tconst affected = this.#pending.get(state) ?? new Set<string>();\n\t\t\t// Per-directory subscriptions report names relative to their own directory,\n\t\t\t// so re-anchor them to the target root before matching.\n\t\t\tconst relPath = normalizeRelativePath(\n\t\t\t\twatchedDirectory && watchedDirectory !== state.target.path\n\t\t\t\t\t? join(relative(state.target.path, watchedDirectory), filename)\n\t\t\t\t\t: filename,\n\t\t\t);\n\t\t\tif (relPath && this.#matches(state.target, relPath)) {\n\t\t\t\taffected.add(relPath);\n\t\t\t\tthis.#pending.set(state, affected);\n\t\t\t}\n\t\t}\n\t\tthis.#schedule();\n\t}\n\n\t#schedule(): void {\n\t\tif (this.#timer) {\n\t\t\tthis.#clock.clearTimeout(this.#timer);\n\t\t}\n\t\tthis.#timer = this.#clock.setTimeout(() => {\n\t\t\tthis.#timer = undefined;\n\t\t\tthis.#evaluatePending();\n\t\t}, this.#debounceMs);\n\t}\n\n\t#evaluatePending(): void {\n\t\tif (this.#closed) {\n\t\t\treturn;\n\t\t}\n\t\tconst changes = new Map<string, { created: boolean; deleted: boolean }>();\n\t\tfor (const [state, affected] of this.#pending) {\n\t\t\tthis.#evaluateState(state, affected, changes);\n\t\t}\n\t\tthis.#pending.clear();\n\t\tif (changes.size > 0) {\n\t\t\tconst changedPaths = [...changes.keys()].sort();\n\t\t\tthis.#onRealChange({\n\t\t\t\tchangedPaths,\n\t\t\t\tcreated: changedPaths.filter((path) => changes.get(path)?.created),\n\t\t\t\tdeleted: changedPaths.filter((path) => changes.get(path)?.deleted),\n\t\t\t});\n\t\t}\n\t}\n\n\t#evaluateState(\n\t\tstate: TargetState,\n\t\taffected: Set<string> | null,\n\t\tchanges: Map<string, { created: boolean; deleted: boolean }>,\n\t): void {\n\t\tconst previousHashes = new Map(state.hashes);\n\t\tconst previousDirectories = new Set(state.allowedDirectories);\n\t\tconst next = affected === null ? this.#scan(state.target) : this.#scanAffected(state.target, affected, state);\n\n\t\tif (affected === null) {\n\t\t\tstate.hashes.clear();\n\t\t\tfor (const [path, hash] of next.hashes) {\n\t\t\t\tstate.hashes.set(path, hash);\n\t\t\t}\n\t\t\tstate.allowedDirectories.clear();\n\t\t\tfor (const path of next.allowedDirectories) {\n\t\t\t\tstate.allowedDirectories.add(path);\n\t\t\t}\n\t\t\tstate.scannedDirectories = next.scannedDirectories;\n\t\t\tthis.#detachMissing(state, state.scannedDirectories);\n\t\t\tthis.#attach(state, state.scannedDirectories);\n\t\t\tthis.#compare(previousHashes, previousDirectories, state.hashes, state.allowedDirectories, changes);\n\t\t\treturn;\n\t\t}\n\n\t\tconst prefixes = [...affected].map((relPath) => join(state.target.path, relPath));\n\t\tfor (const path of [...state.hashes.keys()]) {\n\t\t\tif (prefixes.some((prefix) => isWithin(path, prefix))) {\n\t\t\t\tstate.hashes.delete(path);\n\t\t\t}\n\t\t}\n\t\tfor (const path of [...state.allowedDirectories]) {\n\t\t\tif (prefixes.some((prefix) => isWithin(path, prefix))) {\n\t\t\t\tstate.allowedDirectories.delete(path);\n\t\t\t}\n\t\t}\n\t\tfor (const path of [...state.scannedDirectories]) {\n\t\t\tif (prefixes.some((prefix) => isWithin(path, prefix))) {\n\t\t\t\tstate.scannedDirectories.delete(path);\n\t\t\t}\n\t\t}\n\t\tfor (const [path, hash] of next.hashes) {\n\t\t\tstate.hashes.set(path, hash);\n\t\t}\n\t\tfor (const path of next.allowedDirectories) {\n\t\t\tstate.allowedDirectories.add(path);\n\t\t}\n\t\tfor (const path of next.scannedDirectories) {\n\t\t\tstate.scannedDirectories.add(path);\n\t\t}\n\t\t// A partial rescan can both create and remove directories in scope, so the\n\t\t// subscription set is reconciled in both directions here too.\n\t\tthis.#detachMissing(state, state.scannedDirectories);\n\t\tthis.#attach(state, state.scannedDirectories);\n\t\tthis.#compare(previousHashes, previousDirectories, state.hashes, state.allowedDirectories, changes);\n\t}\n\n\t#scanAffected(target: ResolvedWatchTarget, affected: Set<string>, state: TargetState): ScanResult {\n\t\tconst result: ScanResult = { hashes: new Map(), allowedDirectories: new Set(), scannedDirectories: new Set() };\n\t\tfor (const relPath of affected) {\n\t\t\tconst absolutePath = join(target.path, relPath);\n\t\t\tthis.#scanPath(target, absolutePath, relPath, result, state);\n\t\t}\n\t\treturn result;\n\t}\n\n\t#scan(target: ResolvedWatchTarget): ScanResult {\n\t\tconst result: ScanResult = { hashes: new Map(), allowedDirectories: new Set(), scannedDirectories: new Set() };\n\t\tthis.#scanPath(target, target.path, \"\", result);\n\t\treturn result;\n\t}\n\n\t#scanPath(\n\t\ttarget: ResolvedWatchTarget,\n\t\tabsolutePath: string,\n\t\trelPath: string,\n\t\tresult: ScanResult,\n\t\tstate?: TargetState,\n\t): void {\n\t\tif (relPath && !this.#matches(target, relPath)) {\n\t\t\treturn;\n\t\t}\n\t\tlet entry: Stats;\n\t\ttry {\n\t\t\tentry = lstatSync(absolutePath);\n\t\t} catch (error) {\n\t\t\tif (state && !isMissing(error)) {\n\t\t\t\tthis.#reportError(error, absolutePath);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (entry.isSymbolicLink()) {\n\t\t\treturn;\n\t\t}\n\t\tif (entry.isFile()) {\n\t\t\ttry {\n\t\t\t\tresult.hashes.set(absolutePath, this.#hashFile(absolutePath));\n\t\t\t} catch (error) {\n\t\t\t\tthis.#reportError(error, absolutePath);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (!entry.isDirectory()) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst dotDirectory = relPath !== \"\" && basename(relPath).startsWith(\".\");\n\t\tconst explicitlyAllowedDirectory = relPath !== \"\" && this.#isExplicitlyAllowedDirectory(target, relPath);\n\t\tif (explicitlyAllowedDirectory) {\n\t\t\tresult.allowedDirectories.add(absolutePath);\n\t\t}\n\t\tif (relPath && target.kind === \"dir\") {\n\t\t\treturn;\n\t\t}\n\t\tif (dotDirectory && !explicitlyAllowedDirectory) {\n\t\t\treturn;\n\t\t}\n\t\t// Recorded before descending: this is the set the OS watcher subscribes to.\n\t\tresult.scannedDirectories.add(absolutePath);\n\t\ttry {\n\t\t\tfor (const child of readdirSync(absolutePath, { withFileTypes: true })) {\n\t\t\t\tif (child.isSymbolicLink() || child.name === \"node_modules\" || child.name === \".git\") {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst childRelPath = relPath ? join(relPath, child.name) : child.name;\n\t\t\t\tif (\n\t\t\t\t\tchild.isDirectory() &&\n\t\t\t\t\tchild.name.startsWith(\".\") &&\n\t\t\t\t\t!this.#isExplicitlyAllowedDirectory(target, childRelPath)\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthis.#scanPath(target, join(absolutePath, child.name), childRelPath, result, state);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.#reportError(error, absolutePath);\n\t\t}\n\t}\n\n\t#compare(\n\t\tpreviousHashes: ReadonlyMap<string, string>,\n\t\tpreviousDirectories: ReadonlySet<string>,\n\t\tnextHashes: ReadonlyMap<string, string>,\n\t\tnextDirectories: ReadonlySet<string>,\n\t\tchanges: Map<string, { created: boolean; deleted: boolean }>,\n\t): void {\n\t\tfor (const [path, hash] of nextHashes) {\n\t\t\tconst oldHash = previousHashes.get(path);\n\t\t\tif (oldHash !== hash) {\n\t\t\t\tchanges.set(path, { created: oldHash === undefined, deleted: false });\n\t\t\t}\n\t\t}\n\t\tfor (const path of previousHashes.keys()) {\n\t\t\tif (!nextHashes.has(path)) {\n\t\t\t\tchanges.set(path, { created: false, deleted: true });\n\t\t\t}\n\t\t}\n\t\tfor (const path of nextDirectories) {\n\t\t\tif (!previousDirectories.has(path)) {\n\t\t\t\tchanges.set(path, { created: true, deleted: false });\n\t\t\t}\n\t\t}\n\t\tfor (const path of previousDirectories) {\n\t\t\tif (!nextDirectories.has(path)) {\n\t\t\t\tchanges.set(path, { created: false, deleted: true });\n\t\t\t}\n\t\t}\n\t}\n\n\t#matches(target: ResolvedWatchTarget, relPath: string): boolean {\n\t\tif (!target.kind.includes(\"recursive\") && relPath.includes(sep)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (\n\t\t\ttarget.allowList &&\n\t\t\t!target.allowList.some((allowed) => relPath === allowed || relPath.startsWith(`${allowed}${sep}`))\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t\treturn target.filter?.(relPath) ?? true;\n\t}\n\n\t#isExplicitlyAllowedDirectory(target: ResolvedWatchTarget, relPath: string): boolean {\n\t\treturn (\n\t\t\ttarget.allowList?.some((allowed) => relPath === allowed || relPath.startsWith(`${allowed}${sep}`)) ?? false\n\t\t);\n\t}\n\n\t#reportError(error: unknown, path: string): void {\n\t\ttry {\n\t\t\tthis.#onError(error, path);\n\t\t} catch {\n\t\t\t// Error reporting must not take down the watcher.\n\t\t}\n\t}\n}\n\nfunction hashFile(path: string): string {\n\treturn createHash(\"sha256\").update(readFileSync(path)).digest(\"hex\");\n}\n\nfunction normalizeRelativePath(filename: string): string | undefined {\n\tif (isAbsolute(filename)) {\n\t\treturn undefined;\n\t}\n\tconst normalized = normalize(filename);\n\treturn normalized === \".\" || normalized === \"..\" || normalized.startsWith(`..${sep}`) ? undefined : normalized;\n}\n\nfunction isWithin(path: string, prefix: string): boolean {\n\treturn path === prefix || path.startsWith(`${prefix}${sep}`);\n}\n\nfunction isMissing(error: unknown): boolean {\n\treturn typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\";\n}\n"]}
|
|
@@ -10,6 +10,6 @@ export type FsWatchEventSourceOptions = {
|
|
|
10
10
|
readonly platform?: NodeJS.Platform;
|
|
11
11
|
readonly createRecursiveWorker?: RecursiveWatchWorkerFactory;
|
|
12
12
|
};
|
|
13
|
-
/** Production event source.
|
|
13
|
+
/** Production event source. Recursive setup and teardown run off the interactive main thread. */
|
|
14
14
|
export declare function createFsWatchEventSource(onError?: (error: unknown, path: string) => void, options?: FsWatchEventSourceOptions): WatchEventSource;
|
|
15
15
|
//# sourceMappingURL=watch-event-source.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch-event-source.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/config-reload/watch-event-source.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE9E,MAAM,WAAW,oBAAoB;IACpC,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IACjE,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IAC3D,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACpC,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,MAAM,2BAA2B,GAAG,MAAM,oBAAoB,CAAC;AAErE,MAAM,MAAM,yBAAyB,GAAG;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IACpC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,2BAA2B,CAAC;CAC7D,CAAC;
|
|
1
|
+
{"version":3,"file":"watch-event-source.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/config-reload/watch-event-source.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE9E,MAAM,WAAW,oBAAoB;IACpC,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;IACjE,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IAC3D,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACpC,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED,MAAM,MAAM,2BAA2B,GAAG,MAAM,oBAAoB,CAAC;AAErE,MAAM,MAAM,yBAAyB,GAAG;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IACpC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,2BAA2B,CAAC;CAC7D,CAAC;AA4EF,iGAAiG;AACjG,wBAAgB,wBAAwB,CACvC,OAAO,GAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,IAAe,EAC1D,OAAO,GAAE,yBAA8B,GACrC,gBAAgB,CAkDlB"}
|
|
@@ -62,7 +62,12 @@ function isRecursiveWatchMessage(message) {
|
|
|
62
62
|
"filename" in message &&
|
|
63
63
|
(message.filename === null || typeof message.filename === "string"));
|
|
64
64
|
}
|
|
65
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* Platforms whose recursive fs.watch handles are expensive to create and tear down on the
|
|
67
|
+
* interactive main thread: inotify tree walks on Linux, FSEvents stream teardown on macOS.
|
|
68
|
+
*/
|
|
69
|
+
const WORKER_OFFLOADED_RECURSIVE_PLATFORMS = new Set(["linux", "darwin"]);
|
|
70
|
+
/** Production event source. Recursive setup and teardown run off the interactive main thread. */
|
|
66
71
|
export function createFsWatchEventSource(onError = () => { }, options = {}) {
|
|
67
72
|
const recursiveSubscriptions = new Map();
|
|
68
73
|
let recursiveWorker;
|
|
@@ -91,7 +96,7 @@ export function createFsWatchEventSource(onError = () => { }, options = {}) {
|
|
|
91
96
|
return worker;
|
|
92
97
|
};
|
|
93
98
|
return (path, listener, watchOptions) => {
|
|
94
|
-
if ((options.platform ?? process.platform)
|
|
99
|
+
if (WORKER_OFFLOADED_RECURSIVE_PLATFORMS.has(options.platform ?? process.platform) && watchOptions?.recursive) {
|
|
95
100
|
const id = nextSubscriptionId++;
|
|
96
101
|
const worker = ensureRecursiveWorker();
|
|
97
102
|
recursiveSubscriptions.set(id, { path, listener });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch-event-source.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/config-reload/watch-event-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAqBtE,MAAM,6BAA6B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2CrC,CAAC;AAEF,SAAS,0BAA0B;IAClC,OAAO,IAAI,MAAM,CAAC,6BAA6B,EAAE;QAChD,IAAI,EAAE,IAAI;KACV,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAAC,OAAgB;IAChD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1F,IAAI,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,OAAO,OAAO,CAAC,EAAE,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACvE,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,SAAS,IAAI,OAAO,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC;IACjG,OAAO,CACN,OAAO,CAAC,IAAI,KAAK,OAAO;QACxB,WAAW,IAAI,OAAO;QACtB,OAAO,OAAO,CAAC,SAAS,KAAK,QAAQ;QACrC,UAAU,IAAI,OAAO;QACrB,CAAC,OAAO,CAAC,QAAQ,KAAK,IAAI,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CACnE,CAAC;AACH,CAAC;AAED,
|
|
1
|
+
{"version":3,"file":"watch-event-source.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/config-reload/watch-event-source.ts"],"names":[],"mappings":"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","sourcesContent":["import { Worker } from \"node:worker_threads\";\nimport { watchWithErrorHandler } from \"../../../../utils/fs-watch.ts\";\nimport type { WatchEventListener, WatchEventSource } from \"./watch-engine.ts\";\n\nexport interface RecursiveWatchWorker {\n\ton(event: \"message\", listener: (message: unknown) => void): this;\n\ton(event: \"error\", listener: (error: Error) => void): this;\n\tpostMessage(message: unknown): void;\n\tterminate(): Promise<number>;\n}\n\nexport type RecursiveWatchWorkerFactory = () => RecursiveWatchWorker;\n\nexport type FsWatchEventSourceOptions = {\n\treadonly platform?: NodeJS.Platform;\n\treadonly createRecursiveWorker?: RecursiveWatchWorkerFactory;\n};\n\ntype RecursiveWatchMessage =\n\t| { readonly kind: \"event\"; readonly id: number; readonly eventType: string; readonly filename: string | null }\n\t| { readonly kind: \"error\"; readonly id: number; readonly message: string };\n\nconst RECURSIVE_WATCH_WORKER_SOURCE = `\nconst { watch } = require(\"node:fs\");\nconst { parentPort } = require(\"node:worker_threads\");\n\nif (!parentPort) throw new Error(\"Recursive watch worker requires a parent port\");\n\nconst watchers = new Map();\nparentPort.on(\"message\", (message) => {\n\tif (message.kind === \"unwatch\") {\n\t\twatchers.get(message.id)?.close();\n\t\twatchers.delete(message.id);\n\t\treturn;\n\t}\n\tif (message.kind !== \"watch\") return;\n\ttry {\n\t\tconst watcher = watch(\n\t\t\tmessage.path,\n\t\t\t{ recursive: true, encoding: \"utf8\" },\n\t\t\t(eventType, filename) => {\n\t\t\t\tparentPort.postMessage({\n\t\t\t\t\tkind: \"event\",\n\t\t\t\t\tid: message.id,\n\t\t\t\t\teventType,\n\t\t\t\t\tfilename: typeof filename === \"string\" ? filename : null,\n\t\t\t\t});\n\t\t\t},\n\t\t);\n\t\twatcher.on(\"error\", (error) => {\n\t\t\tparentPort.postMessage({\n\t\t\t\tkind: \"error\",\n\t\t\t\tid: message.id,\n\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t});\n\t\t});\n\t\twatchers.set(message.id, watcher);\n\t} catch (error) {\n\t\tparentPort.postMessage({\n\t\t\tkind: \"error\",\n\t\t\tid: message.id,\n\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t});\n\t}\n});\n`;\n\nfunction createRecursiveWatchWorker(): RecursiveWatchWorker {\n\treturn new Worker(RECURSIVE_WATCH_WORKER_SOURCE, {\n\t\teval: true,\n\t});\n}\n\nfunction isRecursiveWatchMessage(message: unknown): message is RecursiveWatchMessage {\n\tif (typeof message !== \"object\" || message === null || !(\"kind\" in message)) return false;\n\tif (!(\"id\" in message) || typeof message.id !== \"number\") return false;\n\tif (message.kind === \"error\") return \"message\" in message && typeof message.message === \"string\";\n\treturn (\n\t\tmessage.kind === \"event\" &&\n\t\t\"eventType\" in message &&\n\t\ttypeof message.eventType === \"string\" &&\n\t\t\"filename\" in message &&\n\t\t(message.filename === null || typeof message.filename === \"string\")\n\t);\n}\n\n/**\n * Platforms whose recursive fs.watch handles are expensive to create and tear down on the\n * interactive main thread: inotify tree walks on Linux, FSEvents stream teardown on macOS.\n */\nconst WORKER_OFFLOADED_RECURSIVE_PLATFORMS: ReadonlySet<NodeJS.Platform> = new Set([\"linux\", \"darwin\"]);\n\n/** Production event source. Recursive setup and teardown run off the interactive main thread. */\nexport function createFsWatchEventSource(\n\tonError: (error: unknown, path: string) => void = () => {},\n\toptions: FsWatchEventSourceOptions = {},\n): WatchEventSource {\n\tconst recursiveSubscriptions = new Map<number, { readonly path: string; readonly listener: WatchEventListener }>();\n\tlet recursiveWorker: RecursiveWatchWorker | undefined;\n\tlet nextSubscriptionId = 1;\n\n\tconst ensureRecursiveWorker = (): RecursiveWatchWorker => {\n\t\tif (recursiveWorker) return recursiveWorker;\n\t\tconst worker = (options.createRecursiveWorker ?? createRecursiveWatchWorker)();\n\t\tworker.on(\"message\", (message) => {\n\t\t\tif (!isRecursiveWatchMessage(message)) return;\n\t\t\tconst subscription = recursiveSubscriptions.get(message.id);\n\t\t\tif (!subscription) return;\n\t\t\tif (message.kind === \"event\") {\n\t\t\t\tsubscription.listener(message.eventType, message.filename);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tonError(new Error(message.message), subscription.path);\n\t\t});\n\t\tworker.on(\"error\", (error) => {\n\t\t\tfor (const subscription of recursiveSubscriptions.values()) onError(error, subscription.path);\n\t\t});\n\t\trecursiveWorker = worker;\n\t\treturn worker;\n\t};\n\n\treturn (path, listener, watchOptions) => {\n\t\tif (WORKER_OFFLOADED_RECURSIVE_PLATFORMS.has(options.platform ?? process.platform) && watchOptions?.recursive) {\n\t\t\tconst id = nextSubscriptionId++;\n\t\t\tconst worker = ensureRecursiveWorker();\n\t\t\trecursiveSubscriptions.set(id, { path, listener });\n\t\t\tworker.postMessage({ kind: \"watch\", id, path });\n\t\t\treturn () => {\n\t\t\t\tif (!recursiveSubscriptions.delete(id)) return;\n\t\t\t\tif (recursiveSubscriptions.size > 0) {\n\t\t\t\t\tworker.postMessage({ kind: \"unwatch\", id });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\trecursiveWorker = undefined;\n\t\t\t\tvoid worker.terminate().catch((error: unknown) => onError(error, path));\n\t\t\t};\n\t\t}\n\n\t\tconst watcher = watchWithErrorHandler(\n\t\t\tpath,\n\t\t\tlistener,\n\t\t\t() => onError(new Error(`fs.watch failed for ${path}`), path),\n\t\t\t{ recursive: watchOptions?.recursive ?? false },\n\t\t);\n\t\treturn () => watcher?.close();\n\t};\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"elapsed-ticker.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/elapsed-ticker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"elapsed-ticker.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/elapsed-ticker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,4EAA4E;AAC5E,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAElD,iFAAiF;AACjF,MAAM,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,KAAK,IAAI,CAAC;AAExG,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,wDAAwD;IACxD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,EAAE,wBAAwB,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAGpH;AAED;;;;;GAKG;AACH,qBAAa,iBAAiB;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAC3C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,GAAG,CAA+B;IAC1C,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,CAAC,wBAAwB,CAAK;IACrC,OAAO,CAAC,wBAAwB,CAAqB;gBAEzC,OAAO,EAAE,wBAAwB;IAK7C,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;;OAGG;IACH,IAAI,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,wBAAwB,EAAE,MAAM,GAAG,IAAI;IAY/E,qEAAqE;IACrE,IAAI,IAAI,IAAI;IAUZ,OAAO,CAAC,IAAI;CAoBZ"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { formatGoalElapsedSeconds } from "./format.js";
|
|
2
|
+
import { isStaleExtensionContextError } from "./stale-context.js";
|
|
2
3
|
/** Footer live-elapsed refresh cadence while a goal is actively pursued. */
|
|
3
4
|
export const GOAL_ELAPSED_TICK_INTERVAL_MS = 1000;
|
|
4
5
|
/**
|
|
@@ -60,7 +61,20 @@ export class GoalElapsedTicker {
|
|
|
60
61
|
if (elapsedLabel === this.lastRenderedElapsedLabel)
|
|
61
62
|
return;
|
|
62
63
|
this.lastRenderedElapsedLabel = elapsedLabel;
|
|
63
|
-
|
|
64
|
+
try {
|
|
65
|
+
this.render(this.ctx, this.goal, liveElapsedSeconds);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
// A retired ctx (session replacement/reload) throws on every render from
|
|
69
|
+
// now on; retire instead of spinning dead forever. This stop() renders
|
|
70
|
+
// nothing, so it is safe against the same stale ctx. The next sync() with
|
|
71
|
+
// a live ctx re-arms the ticker.
|
|
72
|
+
if (isStaleExtensionContextError(error)) {
|
|
73
|
+
this.stop();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
64
78
|
}
|
|
65
79
|
}
|
|
66
80
|
//# sourceMappingURL=elapsed-ticker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"elapsed-ticker.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/elapsed-ticker.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"elapsed-ticker.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/elapsed-ticker.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExtensionContext } from \"../../types.ts\";\nimport { formatGoalElapsedSeconds } from \"./format.ts\";\nimport { isStaleExtensionContextError } from \"./stale-context.ts\";\nimport type { Goal } from \"./types.ts\";\n\n/** Footer live-elapsed refresh cadence while a goal is actively pursued. */\nexport const GOAL_ELAPSED_TICK_INTERVAL_MS = 1000;\n\n/** Renders the goal footer segment for the current live elapsed second count. */\nexport type GoalElapsedRender = (ctx: ExtensionContext, goal: Goal, liveElapsedSeconds: number) => void;\n\nexport interface GoalElapsedTickerOptions {\n\treadonly render: GoalElapsedRender;\n\t/** Injectable clock for tests; defaults to Date.now. */\n\treadonly now?: () => number;\n}\n\n/**\n * Live elapsed seconds for an actively pursued goal: the committed\n * `timeUsedSeconds` plus whole seconds since the current measurement window\n * opened. Mirrors the rounding in `accountCurrentAgentTurn` so the footer never\n * disagrees with what the next turn commits.\n */\nexport function goalLiveElapsedSeconds(goal: Goal, measuredFromMilliseconds: number, nowMilliseconds: number): number {\n\tconst elapsedSeconds = Math.max(0, Math.round((nowMilliseconds - measuredFromMilliseconds) / 1000));\n\treturn goal.timeUsedSeconds + elapsedSeconds;\n}\n\n/**\n * Drives a once-per-second footer refresh while a goal is active so the\n * \"Pursuing goal (…)\" elapsed time advances live instead of freezing between\n * usage-accounting checkpoints. The interval is unref'd so it never keeps the\n * process alive.\n */\nexport class GoalElapsedTicker {\n\tprivate readonly render: GoalElapsedRender;\n\tprivate readonly now: () => number;\n\tprivate intervalId: NodeJS.Timeout | undefined;\n\tprivate ctx: ExtensionContext | undefined;\n\tprivate goal: Goal | undefined;\n\tprivate measuredFromMilliseconds = 0;\n\tprivate lastRenderedElapsedLabel: string | undefined;\n\n\tconstructor(options: GoalElapsedTickerOptions) {\n\t\tthis.render = options.render;\n\t\tthis.now = options.now ?? Date.now;\n\t}\n\n\tget running(): boolean {\n\t\treturn this.intervalId !== undefined;\n\t}\n\n\t/**\n\t * Point the ticker at the current goal and measurement window, render once\n\t * immediately, and start the interval if it is not already running.\n\t */\n\tsync(ctx: ExtensionContext, goal: Goal, measuredFromMilliseconds: number): void {\n\t\tthis.ctx = ctx;\n\t\tthis.goal = goal;\n\t\tthis.measuredFromMilliseconds = measuredFromMilliseconds;\n\t\tthis.lastRenderedElapsedLabel = undefined;\n\t\tthis.tick();\n\t\tif (this.intervalId !== undefined) return;\n\t\tconst handle = setInterval(() => this.tick(), GOAL_ELAPSED_TICK_INTERVAL_MS);\n\t\thandle.unref();\n\t\tthis.intervalId = handle;\n\t}\n\n\t/** Stop the interval and drop the retained context/goal snapshot. */\n\tstop(): void {\n\t\tif (this.intervalId !== undefined) {\n\t\t\tclearInterval(this.intervalId);\n\t\t\tthis.intervalId = undefined;\n\t\t}\n\t\tthis.ctx = undefined;\n\t\tthis.goal = undefined;\n\t\tthis.lastRenderedElapsedLabel = undefined;\n\t}\n\n\tprivate tick(): void {\n\t\tif (this.ctx === undefined || this.goal === undefined) return;\n\t\tconst liveElapsedSeconds = goalLiveElapsedSeconds(this.goal, this.measuredFromMilliseconds, this.now());\n\t\tconst elapsedLabel = formatGoalElapsedSeconds(liveElapsedSeconds);\n\t\tif (elapsedLabel === this.lastRenderedElapsedLabel) return;\n\t\tthis.lastRenderedElapsedLabel = elapsedLabel;\n\t\ttry {\n\t\t\tthis.render(this.ctx, this.goal, liveElapsedSeconds);\n\t\t} catch (error) {\n\t\t\t// A retired ctx (session replacement/reload) throws on every render from\n\t\t\t// now on; retire instead of spinning dead forever. This stop() renders\n\t\t\t// nothing, so it is safe against the same stale ctx. The next sync() with\n\t\t\t// a live ctx re-arms the ticker.\n\t\t\tif (isStaleExtensionContextError(error)) {\n\t\t\t\tthis.stop();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AAkCrE,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AAkCrE,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAgY5D"}
|
|
@@ -12,6 +12,7 @@ import { isResumeOfStoppedGoal, queueGoalContinuation } from "./lifecycle-helper
|
|
|
12
12
|
import { GOAL_CONTINUATION_SCHEDULED_EVENT, MonitorAwareGoalContinuation } from "./monitor-continuation.js";
|
|
13
13
|
import { migrateLegacyGoalFile } from "./persistence.js";
|
|
14
14
|
import { reengageGoalAfterReload } from "./reload-reengagement.js";
|
|
15
|
+
import { isStaleExtensionContextError } from "./stale-context.js";
|
|
15
16
|
import { accountGoalUsage, readGoal, updateGoal } from "./store.js";
|
|
16
17
|
import { GOAL_STORE_CHANGED_EVENT, isGoalStoreChangedEvent } from "./store-changed-event.js";
|
|
17
18
|
import { goalStoreRef as buildGoalStoreRef } from "./store-ref.js";
|
|
@@ -23,7 +24,6 @@ import { updateGoalUi } from "./ui.js";
|
|
|
23
24
|
import { GOAL_WAIT_STATUS_KEY, GoalWaitTicker } from "./wait-ticker.js";
|
|
24
25
|
const RESUME_GOAL_CHOICE = "Resume goal";
|
|
25
26
|
const LEAVE_GOAL_STOPPED_CHOICE = "Leave stopped";
|
|
26
|
-
const STALE_EXTENSION_CONTEXT_ERROR_PREFIX = "This extension ctx is stale after session replacement or reload.";
|
|
27
27
|
export default function goalExtension(pi) {
|
|
28
28
|
let agentTurnInProgress = false;
|
|
29
29
|
let staleGoalReminderSentThisTurn = false;
|
|
@@ -33,17 +33,11 @@ export default function goalExtension(pi) {
|
|
|
33
33
|
let continuationPending = false;
|
|
34
34
|
let activeContext;
|
|
35
35
|
const turnUsage = new TurnUsageTracker();
|
|
36
|
+
// No stale-ctx swallow here: GoalWaitTicker retires itself on a stale render
|
|
37
|
+
// (a ticker that keeps ticking against a retired ctx freezes the footer
|
|
38
|
+
// countdown forever); non-stale render errors still propagate.
|
|
36
39
|
const goalWaitTicker = new GoalWaitTicker({
|
|
37
|
-
render: (renderCtx, status) =>
|
|
38
|
-
try {
|
|
39
|
-
renderCtx.ui.setStatus(GOAL_WAIT_STATUS_KEY, status);
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
if (error instanceof Error && error.message.startsWith(STALE_EXTENSION_CONTEXT_ERROR_PREFIX))
|
|
43
|
-
return;
|
|
44
|
-
throw error;
|
|
45
|
-
}
|
|
46
|
-
},
|
|
40
|
+
render: (renderCtx, status) => renderCtx.ui.setStatus(GOAL_WAIT_STATUS_KEY, status),
|
|
47
41
|
});
|
|
48
42
|
const monitorContinuation = new MonitorAwareGoalContinuation(pi, () => continuationPending, () => {
|
|
49
43
|
continuationPending = true;
|
|
@@ -56,16 +50,7 @@ export default function goalExtension(pi) {
|
|
|
56
50
|
resumeAfterSuppressedLoad: (resumeCtx, goal) => queueGoalContinuationForCurrentSession(pi, resumeCtx, goal),
|
|
57
51
|
});
|
|
58
52
|
const goalTicker = new GoalElapsedTicker({
|
|
59
|
-
render: (renderCtx, renderGoal, live) =>
|
|
60
|
-
try {
|
|
61
|
-
updateGoalUi(renderCtx, renderGoal, live);
|
|
62
|
-
}
|
|
63
|
-
catch (error) {
|
|
64
|
-
if (error instanceof Error && error.message.startsWith(STALE_EXTENSION_CONTEXT_ERROR_PREFIX))
|
|
65
|
-
return;
|
|
66
|
-
throw error;
|
|
67
|
-
}
|
|
68
|
-
},
|
|
53
|
+
render: (renderCtx, renderGoal, live) => updateGoalUi(renderCtx, renderGoal, live),
|
|
69
54
|
});
|
|
70
55
|
pi.registerEntryRenderer(GOAL_CACHE_WARMUP_ENTRY_TYPE, renderGoalCacheWarmupEntry);
|
|
71
56
|
registerGoalTools(pi, {
|
|
@@ -358,7 +343,7 @@ export default function goalExtension(pi) {
|
|
|
358
343
|
refreshGoalUi(ctx, goal);
|
|
359
344
|
}
|
|
360
345
|
catch (error) {
|
|
361
|
-
if (error
|
|
346
|
+
if (isStaleExtensionContextError(error)) {
|
|
362
347
|
return;
|
|
363
348
|
}
|
|
364
349
|
throw error;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { GOAL_CONTINUATION_MESSAGE_TYPE } from \"../../../messages.ts\";\nimport type { SessionEntry } from \"../../../session-manager.ts\";\nimport type { ExtensionAPI, ExtensionContext } from \"../../types.ts\";\nimport { continueGoalAfterAgentEnd } from \"./agent-end-continuation.ts\";\nimport { GOAL_CACHE_WARMUP_ENTRY_TYPE } from \"./cache-warm.ts\";\nimport { renderGoalCacheWarmupEntry } from \"./cache-warm-renderer.ts\";\nimport { registerGoalCommand } from \"./command-registration.ts\";\nimport { GOAL_CONTINUATION_CAP } from \"./continuation.ts\";\nimport { continuationCapRecoveryHint, PROVIDER_ERROR_BLOCKED_REASON } from \"./continuation-recovery.ts\";\nimport { GoalDirectInputLifecycle } from \"./direct-input-lifecycle.ts\";\nimport { GoalElapsedTicker } from \"./elapsed-ticker.ts\";\nimport { formatGoalForTool, goalStatusLabel } from \"./format.ts\";\nimport { isResumeOfStoppedGoal, queueGoalContinuation } from \"./lifecycle-helpers.ts\";\nimport { GOAL_CONTINUATION_SCHEDULED_EVENT, MonitorAwareGoalContinuation } from \"./monitor-continuation.ts\";\nimport { migrateLegacyGoalFile } from \"./persistence.ts\";\nimport { reengageGoalAfterReload } from \"./reload-reengagement.ts\";\nimport { accountGoalUsage, readGoal, updateGoal } from \"./store.ts\";\nimport { GOAL_STORE_CHANGED_EVENT, isGoalStoreChangedEvent } from \"./store-changed-event.ts\";\nimport { goalStoreRef as buildGoalStoreRef } from \"./store-ref.ts\";\nimport { didTerminalProviderErrorEndTurn } from \"./terminal-provider-error.ts\";\nimport { staleGoalTodoReminder, todoResultAddsOpenTasks } from \"./todo-gate.ts\";\nimport { registerGoalTools } from \"./tool-registration.ts\";\nimport { TurnUsageTracker } from \"./turn-usage.ts\";\nimport type { Goal, GoalAccountingMode, GoalStoreRef } from \"./types.ts\";\nimport { updateGoalUi } from \"./ui.ts\";\nimport { GOAL_WAIT_STATUS_KEY, GoalWaitTicker } from \"./wait-ticker.ts\";\n\nconst RESUME_GOAL_CHOICE = \"Resume goal\";\nconst LEAVE_GOAL_STOPPED_CHOICE = \"Leave stopped\";\nconst STALE_EXTENSION_CONTEXT_ERROR_PREFIX = \"This extension ctx is stale after session replacement or reload.\";\n\ntype AgentGoalAccounting = {\n\tgoalId: string;\n\tmeasuredFromMilliseconds: number;\n};\n\nexport default function goalExtension(pi: ExtensionAPI): void {\n\tlet agentTurnInProgress = false;\n\tlet staleGoalReminderSentThisTurn = false;\n\tlet agentGoalAccounting: AgentGoalAccounting | null = null;\n\tlet blockedThisTurnGoalId: string | null = null;\n\tlet completedThisTurnGoalId: string | null = null;\n\tlet continuationPending = false;\n\tlet activeContext: ExtensionContext | undefined;\n\tconst turnUsage = new TurnUsageTracker();\n\tconst goalWaitTicker = new GoalWaitTicker({\n\t\trender: (renderCtx, status) => {\n\t\t\ttry {\n\t\t\t\trenderCtx.ui.setStatus(GOAL_WAIT_STATUS_KEY, status);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error && error.message.startsWith(STALE_EXTENSION_CONTEXT_ERROR_PREFIX)) return;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t});\n\tconst monitorContinuation = new MonitorAwareGoalContinuation(\n\t\tpi,\n\t\t() => continuationPending,\n\t\t() => {\n\t\t\tcontinuationPending = true;\n\t\t},\n\t\tgoalWaitTicker,\n\t);\n\tconst directInputLifecycle = new GoalDirectInputLifecycle({\n\t\tmonitor: monitorContinuation,\n\t\tgoalStoreRef,\n\t\tbeginAgentGoalAccounting,\n\t\trefreshGoalUi: refreshGoalUiBestEffort,\n\t\tresumeAfterSuppressedLoad: (resumeCtx, goal) => queueGoalContinuationForCurrentSession(pi, resumeCtx, goal),\n\t});\n\n\tconst goalTicker = new GoalElapsedTicker({\n\t\trender: (renderCtx, renderGoal, live) => {\n\t\t\ttry {\n\t\t\t\tupdateGoalUi(renderCtx, renderGoal, live);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error && error.message.startsWith(STALE_EXTENSION_CONTEXT_ERROR_PREFIX)) return;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t});\n\n\tpi.registerEntryRenderer(GOAL_CACHE_WARMUP_ENTRY_TYPE, renderGoalCacheWarmupEntry);\n\tregisterGoalTools(pi, {\n\t\tgoalStoreRef: (ctx) => buildGoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\taccountCurrentAgentTurn,\n\t\tbeginAgentGoalAccounting: (goal) => {\n\t\t\tmonitorContinuation.noteContinuationStarted();\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t},\n\t\tmarkGoalBlockedThisTurn,\n\t\tmarkGoalCompletedThisTurn,\n\t\trefreshGoalUi,\n\t});\n\tregisterGoalCommand(pi, {\n\t\tgoalStoreRef: (ctx) => buildGoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\taccountCurrentAgentTurn,\n\t\tbeginAgentGoalAccounting,\n\t\tstopAgentGoalAccounting,\n\t\tclearAgentGoalAccounting,\n\t\tqueueGoalContinuation: (extensionApi, commandCtx, goal) => {\n\t\t\tvoid queueGoalContinuationForCurrentSession(extensionApi, commandCtx, goal);\n\t\t},\n\t\trefreshGoalUi,\n\t});\n\n\tconst unsubscribeGoalStoreChanged =\n\t\tpi.events?.on(GOAL_STORE_CHANGED_EVENT, async (data) => {\n\t\t\tif (!isGoalStoreChangedEvent(data)) return;\n\t\t\tconst ctx = data.ctx ?? activeContext;\n\t\t\tif (\n\t\t\t\tctx === undefined ||\n\t\t\t\tctx.sessionManager.getSessionId() !== data.threadId ||\n\t\t\t\t!ctx.isIdle() ||\n\t\t\t\tctx.hasPendingMessages()\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\t\tif (goal?.status !== \"active\") return;\n\t\t\tmonitorContinuation.syncGoal(goal);\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t\trefreshGoalUiBestEffort(ctx, goal);\n\t\t\tpi.events?.emit(GOAL_CONTINUATION_SCHEDULED_EVENT, {\n\t\t\t\tgoalId: goal.id,\n\t\t\t\tdelayMs: 0,\n\t\t\t\tactiveMonitorCount: 0,\n\t\t\t\twakeSources: {},\n\t\t\t\treason: GOAL_STORE_CHANGED_EVENT,\n\t\t\t});\n\t\t\tawait queueGoalContinuationForCurrentSession(pi, ctx, goal);\n\t\t}) ?? (() => {});\n\n\tpi.on(\"session_start\", async (event, ctx) => {\n\t\tactiveContext = ctx;\n\t\tmonitorContinuation.start(ctx);\n\t\tdirectInputLifecycle.reset();\n\t\tconst ref = goalStoreRef(ctx);\n\t\tawait migrateLegacyGoalFile(ref);\n\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\tif (goal?.status === \"active\") {\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t} else {\n\t\t\tclearAgentGoalAccounting();\n\t\t}\n\t\trefreshGoalUi(ctx, goal);\n\t\tif (await maybePromptResumeStoppedGoal(pi, ctx, event.reason, goal)) {\n\t\t\treturn;\n\t\t}\n\t\tif (goal && event.reason === \"reload\") {\n\t\t\t// A reload retires the extension generation and every armed continuation\n\t\t\t// timer with it. Re-engage through the reload path: stopped goals stay\n\t\t\t// stopped, active goals resume the wait the reload tore down.\n\t\t\tawait reengageGoalAfterReload({\n\t\t\t\tctx,\n\t\t\t\tgoal,\n\t\t\t\tmonitor: monitorContinuation,\n\t\t\t\tcountTrailingContinuations: () => countTrailingGoalContinuationEntries(ctx.sessionManager.getBranch()),\n\t\t\t\tqueueContinuation: () => queueGoalContinuationForCurrentSession(pi, ctx, goal),\n\t\t\t});\n\t\t} else if (goal) {\n\t\t\t// Migration-lite admission: a resumed session carrying a trailing flood of\n\t\t\t// historical continuations must not reignite on load. Skip the auto-queue,\n\t\t\t// leave the goal active (no status rewrite), and tell the user how to resume.\n\t\t\tconst trailingContinuations = countTrailingGoalContinuationEntries(ctx.sessionManager.getBranch());\n\t\t\tif (trailingContinuations >= GOAL_CONTINUATION_CAP) {\n\t\t\t\t// The load-time flood suppression parks the goal without rewriting its\n\t\t\t\t// status, so the only resume signal left is the user's next message.\n\t\t\t\t// Arm the one-shot latch the direct-input lifecycle fires when that\n\t\t\t\t// message is accepted; without it the promise in the notice is a lie\n\t\t\t\t// and the resumed session sits idle until the goal is recreated.\n\t\t\t\tdirectInputLifecycle.armSuppressedLoadResume();\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Goal auto-continuation suppressed for this resumed session (${trailingContinuations} historical continuations). Send a message to resume.`,\n\t\t\t\t\t\"info\",\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tawait queueGoalContinuationForCurrentSession(pi, ctx, goal);\n\t\t\t}\n\t\t}\n\t});\n\n\tpi.on(\"input\", async (event, ctx) => {\n\t\tawait directInputLifecycle.onInput(event, ctx);\n\t});\n\n\tpi.on(\"input_disposition\", async (event, ctx) => {\n\t\tawait directInputLifecycle.onDisposition(event, ctx);\n\t});\n\n\tpi.on(\"turn_start\", async () => {\n\t\tstaleGoalReminderSentThisTurn = false;\n\t});\n\n\t// When the model starts tracking new open todo work while the thread has no\n\t// goal (or only a stale, already-complete one), append a system reminder to\n\t// the todo result so the model registers the goal when the work warrants it.\n\tpi.on(\"tool_result\", async (event, ctx) => {\n\t\tif (event.toolName !== \"todo\" || event.isError || staleGoalReminderSentThisTurn) return undefined;\n\t\tif (!todoResultAddsOpenTasks(event.details)) return undefined;\n\t\tconst reminder = staleGoalTodoReminder(await readGoal(goalStoreRef(ctx)));\n\t\tif (reminder === undefined) return undefined;\n\t\tstaleGoalReminderSentThisTurn = true;\n\t\treturn { content: [...event.content, { type: \"text\" as const, text: reminder }] };\n\t});\n\n\tpi.on(\"agent_start\", async (_event, ctx) => {\n\t\tconst continuationStarted = continuationPending;\n\t\tcontinuationPending = false;\n\t\tif (continuationStarted) monitorContinuation.noteContinuationStarted();\n\t\tagentTurnInProgress = true;\n\t\tblockedThisTurnGoalId = null;\n\t\tcompletedThisTurnGoalId = null;\n\t\tturnUsage.reset();\n\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\tif (goal?.status === \"active\") {\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t} else {\n\t\t\tagentGoalAccounting = null;\n\t\t}\n\t});\n\n\tpi.on(\"message_end\", async (event) => {\n\t\tturnUsage.noteMessageEnd(event.message);\n\t});\n\n\tpi.on(\"agent_end\", async (event, ctx) => {\n\t\tconst mode: GoalAccountingMode =\n\t\t\tblockedThisTurnGoalId !== null\n\t\t\t\t? \"activeOrBlocked\"\n\t\t\t\t: completedThisTurnGoalId === null\n\t\t\t\t\t? \"active\"\n\t\t\t\t\t: \"activeOrComplete\";\n\t\tlet goal = await accountCurrentAgentTurn(ctx, mode, event.messages);\n\t\tagentTurnInProgress = false;\n\t\tblockedThisTurnGoalId = null;\n\t\tcompletedThisTurnGoalId = null;\n\t\tif (event.aborted === true && event.abortSource === \"user\" && goal?.status === \"active\") {\n\t\t\tgoal = await updateGoal(\n\t\t\t\tgoalStoreRef(ctx),\n\t\t\t\t{ status: \"blocked\", reason: \"user interrupted the turn\" },\n\t\t\t\t\"model\",\n\t\t\t);\n\t\t} else if (didTerminalProviderErrorEndTurn(event) && goal?.status === \"active\") {\n\t\t\tgoal = await updateGoal(\n\t\t\t\tgoalStoreRef(ctx),\n\t\t\t\t{ status: \"blocked\", reason: PROVIDER_ERROR_BLOCKED_REASON },\n\t\t\t\t\"model\",\n\t\t\t);\n\t\t\tif (ctx.hasUI) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Goal ${goalStatusLabel(goal.status)}\\n${formatGoalForTool(goal)}\\n${continuationCapRecoveryHint(PROVIDER_ERROR_BLOCKED_REASON)}`,\n\t\t\t\t\t\"warning\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (goal?.status === \"active\") {\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t} else {\n\t\t\tclearAgentGoalAccounting();\n\t\t}\n\t\trefreshGoalUiBestEffort(ctx, goal);\n\t\tconst continuationGoal = await continueGoalAfterAgentEnd(monitorContinuation, { ctx, event, goal });\n\t\tif (continuationGoal !== goal) {\n\t\t\tgoal = continuationGoal;\n\t\t\tsyncContinuationGoal(ctx, goal);\n\t\t}\n\t});\n\n\tpi.on(\"agent_settled\", async (_event, ctx) => {\n\t\tconst goal = await monitorContinuation.afterAgentSettled();\n\t\tif (goal !== undefined) syncContinuationGoal(ctx, goal);\n\t});\n\n\tpi.on(\"session_abort\", async (_event, ctx) => {\n\t\tcontinuationPending = false;\n\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\tif (goal?.status !== \"active\") return;\n\t\tconst accounted = await accountCurrentAgentTurn(ctx, \"active\");\n\t\tif (accounted?.status === \"active\") {\n\t\t\tconst blocked = await updateGoal(\n\t\t\t\tgoalStoreRef(ctx),\n\t\t\t\t{ status: \"blocked\", reason: \"user interrupted the turn\" },\n\t\t\t\t\"model\",\n\t\t\t);\n\t\t\tclearAgentGoalAccounting();\n\t\t\trefreshGoalUiBestEffort(ctx, blocked);\n\t\t}\n\t});\n\n\tpi.on(\"session_shutdown\", async (_event, ctx) => {\n\t\tactiveContext = undefined;\n\t\tunsubscribeGoalStoreChanged();\n\t\tif (agentGoalAccounting !== null) {\n\t\t\tawait accountCurrentAgentTurn(ctx, \"active\");\n\t\t}\n\t\tclearAgentGoalAccounting();\n\t\tgoalTicker.stop();\n\t\tmonitorContinuation.dispose();\n\t});\n\n\tasync function maybePromptResumeStoppedGoal(\n\t\tpi: ExtensionAPI,\n\t\tctx: ExtensionContext,\n\t\tsessionStartReason: string,\n\t\tgoal: Goal | null,\n\t): Promise<boolean> {\n\t\tif (!isResumeOfStoppedGoal(ctx, sessionStartReason, goal)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst choice = await ctx.ui.select(`Resume ${goal.status} goal?\\nGoal: ${goal.objective}`, [\n\t\t\tRESUME_GOAL_CHOICE,\n\t\t\tLEAVE_GOAL_STOPPED_CHOICE,\n\t\t]);\n\t\tif (choice !== RESUME_GOAL_CHOICE) return true;\n\n\t\tconst resumed = await updateGoal(goalStoreRef(ctx), { status: \"active\" }, \"user\");\n\t\tbeginAgentGoalAccounting(resumed);\n\t\trefreshGoalUi(ctx, resumed);\n\t\tctx.ui.notify(`Goal ${goalStatusLabel(resumed.status)}\\n${formatGoalForTool(resumed)}`, \"info\");\n\t\tawait queueGoalContinuationForCurrentSession(pi, ctx, resumed);\n\t\treturn true;\n\t}\n\n\tasync function queueGoalContinuationForCurrentSession(\n\t\textensionApi: ExtensionAPI,\n\t\tctx: ExtensionContext,\n\t\tgoal: Goal,\n\t): Promise<void> {\n\t\tconst continuedGoal = await queueGoalContinuation(extensionApi, ctx, goal, {\n\t\t\tcontinuationPending,\n\t\t\tmarkContinuationPending: () => {\n\t\t\t\tcontinuationPending = true;\n\t\t\t},\n\t\t});\n\t\tif (continuedGoal === null) {\n\t\t\tclearAgentGoalAccounting();\n\t\t\trefreshGoalUiBestEffort(ctx, null);\n\t\t\treturn;\n\t\t}\n\t\tif (continuedGoal.status === goal.status) return;\n\t\tif (continuedGoal.status === \"active\") beginAgentGoalAccounting(continuedGoal);\n\t\telse clearAgentGoalAccounting();\n\t\trefreshGoalUiBestEffort(ctx, continuedGoal);\n\t}\n\n\tfunction beginAgentGoalAccounting(goal: Goal): void {\n\t\tif (goal.status !== \"active\") return;\n\t\tif (agentGoalAccounting?.goalId === goal.id) return;\n\t\tturnUsage.discardPending();\n\t\tagentGoalAccounting = { goalId: goal.id, measuredFromMilliseconds: Date.now() };\n\t}\n\n\tfunction markGoalBlockedThisTurn(goal: Goal): void {\n\t\tif (agentTurnInProgress) blockedThisTurnGoalId = goal.id;\n\t}\n\n\tfunction markGoalCompletedThisTurn(goal: Goal): void {\n\t\tif (!agentTurnInProgress) return;\n\t\tcompletedThisTurnGoalId = goal.id;\n\t\tagentGoalAccounting = { goalId: goal.id, measuredFromMilliseconds: Date.now() };\n\t}\n\n\tfunction stopAgentGoalAccounting(goalId: string): void {\n\t\tif (agentGoalAccounting?.goalId === goalId) {\n\t\t\tagentGoalAccounting = null;\n\t\t}\n\t\tif (blockedThisTurnGoalId === goalId) {\n\t\t\tblockedThisTurnGoalId = null;\n\t\t}\n\t\tif (completedThisTurnGoalId === goalId) {\n\t\t\tcompletedThisTurnGoalId = null;\n\t\t}\n\t}\n\n\tfunction clearAgentGoalAccounting(): void {\n\t\tagentGoalAccounting = null;\n\t\tblockedThisTurnGoalId = null;\n\t\tcompletedThisTurnGoalId = null;\n\t}\n\n\tfunction syncContinuationGoal(ctx: ExtensionContext, goal: Goal | null): void {\n\t\tif (goal?.status === \"active\") beginAgentGoalAccounting(goal);\n\t\telse clearAgentGoalAccounting();\n\t\trefreshGoalUiBestEffort(ctx, goal);\n\t}\n\n\tfunction refreshGoalUi(ctx: ExtensionContext, goal: Goal | null): void {\n\t\tmonitorContinuation.syncGoal(goal);\n\t\tconst accounting = agentGoalAccounting;\n\t\tif (ctx.hasUI && goal?.status === \"active\" && accounting?.goalId === goal.id) {\n\t\t\tgoalTicker.sync(ctx, goal, accounting.measuredFromMilliseconds);\n\t\t\treturn;\n\t\t}\n\t\tgoalTicker.stop();\n\t\tupdateGoalUi(ctx, goal);\n\t}\n\n\tfunction refreshGoalUiBestEffort(ctx: ExtensionContext, goal: Goal | null): void {\n\t\ttry {\n\t\t\trefreshGoalUi(ctx, goal);\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && error.message.startsWith(STALE_EXTENSION_CONTEXT_ERROR_PREFIX)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function accountCurrentAgentTurn(\n\t\tctx: ExtensionContext,\n\t\tmode: GoalAccountingMode,\n\t\tagentRunMessages?: unknown[],\n\t): Promise<Goal | null> {\n\t\tconst accounting = agentGoalAccounting;\n\t\tconst ref = goalStoreRef(ctx);\n\t\tif (accounting === null) return readGoal(ref);\n\n\t\tconst usage =\n\t\t\tagentRunMessages === undefined ? turnUsage.takePending() : turnUsage.takeRemaining(agentRunMessages);\n\t\tconst now = Date.now();\n\t\tconst elapsedSeconds = Math.max(0, Math.round((now - accounting.measuredFromMilliseconds) / 1000));\n\t\tconst goal = await accountGoalUsage(ref, usage, elapsedSeconds, mode, accounting.goalId);\n\t\tif (goal?.id === accounting.goalId) {\n\t\t\tagentGoalAccounting = { goalId: accounting.goalId, measuredFromMilliseconds: now };\n\t\t} else {\n\t\t\tclearAgentGoalAccounting();\n\t\t}\n\t\treturn goal;\n\t}\n}\n\n/**\n * Counts goal-continuation entries queued since the most recent real user message\n * in the current branch (mirrors the todo-gate / todo-bridge backward branch read).\n * A real user message is the only reset: the assistant turns in between are exactly\n * the unattended loop this admission guard exists to stop.\n */\nfunction countTrailingGoalContinuationEntries(entries: readonly SessionEntry[]): number {\n\tlet count = 0;\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (entry?.type === \"message\" && entry.message.role === \"user\") break;\n\t\tif (entry?.type === \"custom_message\" && entry.customType === GOAL_CONTINUATION_MESSAGE_TYPE) count += 1;\n\t}\n\treturn count;\n}\n\nfunction goalStoreRef(ctx: ExtensionContext): GoalStoreRef {\n\treturn buildGoalStoreRef(ctx.sessionManager, ctx.cwd);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AAGtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;AACxG,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAE,iCAAiC,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AAC5G,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAC7F,OAAO,EAAE,YAAY,IAAI,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAE,+BAA+B,EAAE,MAAM,8BAA8B,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAExE,MAAM,kBAAkB,GAAG,aAAa,CAAC;AACzC,MAAM,yBAAyB,GAAG,eAAe,CAAC;AAOlD,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EAAgB;IACrD,IAAI,mBAAmB,GAAG,KAAK,CAAC;IAChC,IAAI,6BAA6B,GAAG,KAAK,CAAC;IAC1C,IAAI,mBAAmB,GAA+B,IAAI,CAAC;IAC3D,IAAI,qBAAqB,GAAkB,IAAI,CAAC;IAChD,IAAI,uBAAuB,GAAkB,IAAI,CAAC;IAClD,IAAI,mBAAmB,GAAG,KAAK,CAAC;IAChC,IAAI,aAA2C,CAAC;IAChD,MAAM,SAAS,GAAG,IAAI,gBAAgB,EAAE,CAAC;IACzC,6EAA6E;IAC7E,wEAAwE;IACxE,+DAA+D;IAC/D,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC;QACzC,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,oBAAoB,EAAE,MAAM,CAAC;KACnF,CAAC,CAAC;IACH,MAAM,mBAAmB,GAAG,IAAI,4BAA4B,CAC3D,EAAE,EACF,GAAG,EAAE,CAAC,mBAAmB,EACzB,GAAG,EAAE;QACJ,mBAAmB,GAAG,IAAI,CAAC;IAC5B,CAAC,EACD,cAAc,CACd,CAAC;IACF,MAAM,oBAAoB,GAAG,IAAI,wBAAwB,CAAC;QACzD,OAAO,EAAE,mBAAmB;QAC5B,YAAY;QACZ,wBAAwB;QACxB,aAAa,EAAE,uBAAuB;QACtC,yBAAyB,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,sCAAsC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC;KAC3G,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,IAAI,iBAAiB,CAAC;QACxC,MAAM,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,CAAC;KAClF,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,CAAC,4BAA4B,EAAE,0BAA0B,CAAC,CAAC;IACnF,iBAAiB,CAAC,EAAE,EAAE;QACrB,YAAY,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,GAAG,CAAC;QACrE,uBAAuB;QACvB,wBAAwB,EAAE,CAAC,IAAI,EAAE,EAAE;YAClC,mBAAmB,CAAC,uBAAuB,EAAE,CAAC;YAC9C,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;QACD,uBAAuB;QACvB,yBAAyB;QACzB,aAAa;KACb,CAAC,CAAC;IACH,mBAAmB,CAAC,EAAE,EAAE;QACvB,YAAY,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,GAAG,CAAC;QACrE,uBAAuB;QACvB,wBAAwB;QACxB,uBAAuB;QACvB,wBAAwB;QACxB,qBAAqB,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE;YACzD,KAAK,sCAAsC,CAAC,YAAY,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;QAC7E,CAAC;QACD,aAAa;KACb,CAAC,CAAC;IAEH,MAAM,2BAA2B,GAChC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,wBAAwB,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtD,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC;YAAE,OAAO;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,aAAa,CAAC;QACtC,IACC,GAAG,KAAK,SAAS;YACjB,GAAG,CAAC,cAAc,CAAC,YAAY,EAAE,KAAK,IAAI,CAAC,QAAQ;YACnD,CAAC,GAAG,CAAC,MAAM,EAAE;YACb,GAAG,CAAC,kBAAkB,EAAE,EACvB,CAAC;YACF,OAAO;QACR,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/C,IAAI,IAAI,EAAE,MAAM,KAAK,QAAQ;YAAE,OAAO;QACtC,mBAAmB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACnC,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAC/B,uBAAuB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACnC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,iCAAiC,EAAE;YAClD,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,OAAO,EAAE,CAAC;YACV,kBAAkB,EAAE,CAAC;YACrB,WAAW,EAAE,EAAE;YACf,MAAM,EAAE,wBAAwB;SAChC,CAAC,CAAC;QACH,MAAM,sCAAsC,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAC7D,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAElB,EAAE,CAAC,EAAE,CAAC,eAAe,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAC3C,aAAa,GAAG,GAAG,CAAC;QACpB,mBAAmB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,oBAAoB,CAAC,KAAK,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,qBAAqB,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/C,IAAI,IAAI,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACP,wBAAwB,EAAE,CAAC;QAC5B,CAAC;QACD,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACzB,IAAI,MAAM,4BAA4B,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;YACrE,OAAO;QACR,CAAC;QACD,IAAI,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YACvC,yEAAyE;YACzE,uEAAuE;YACvE,8DAA8D;YAC9D,MAAM,uBAAuB,CAAC;gBAC7B,GAAG;gBACH,IAAI;gBACJ,OAAO,EAAE,mBAAmB;gBAC5B,0BAA0B,EAAE,GAAG,EAAE,CAAC,oCAAoC,CAAC,GAAG,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;gBACtG,iBAAiB,EAAE,GAAG,EAAE,CAAC,sCAAsC,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC;aAC9E,CAAC,CAAC;QACJ,CAAC;aAAM,IAAI,IAAI,EAAE,CAAC;YACjB,2EAA2E;YAC3E,2EAA2E;YAC3E,8EAA8E;YAC9E,MAAM,qBAAqB,GAAG,oCAAoC,CAAC,GAAG,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC,CAAC;YACnG,IAAI,qBAAqB,IAAI,qBAAqB,EAAE,CAAC;gBACpD,uEAAuE;gBACvE,qEAAqE;gBACrE,oEAAoE;gBACpE,qEAAqE;gBACrE,iEAAiE;gBACjE,oBAAoB,CAAC,uBAAuB,EAAE,CAAC;gBAC/C,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,+DAA+D,qBAAqB,uDAAuD,EAC3I,MAAM,CACN,CAAC;YACH,CAAC;iBAAM,CAAC;gBACP,MAAM,sCAAsC,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YAC7D,CAAC;QACF,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACnC,MAAM,oBAAoB,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,mBAAmB,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAC/C,MAAM,oBAAoB,CAAC,aAAa,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE;QAC9B,6BAA6B,GAAG,KAAK,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,4EAA4E;IAC5E,4EAA4E;IAC5E,6EAA6E;IAC7E,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACzC,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,6BAA6B;YAAE,OAAO,SAAS,CAAC;QAClG,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC,OAAO,CAAC;YAAE,OAAO,SAAS,CAAC;QAC9D,MAAM,QAAQ,GAAG,qBAAqB,CAAC,MAAM,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC1E,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC7C,6BAA6B,GAAG,IAAI,CAAC;QACrC,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACnF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;QAC1C,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;QAChD,mBAAmB,GAAG,KAAK,CAAC;QAC5B,IAAI,mBAAmB;YAAE,mBAAmB,CAAC,uBAAuB,EAAE,CAAC;QACvE,mBAAmB,GAAG,IAAI,CAAC;QAC3B,qBAAqB,GAAG,IAAI,CAAC;QAC7B,uBAAuB,GAAG,IAAI,CAAC;QAC/B,SAAS,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/C,IAAI,IAAI,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACP,mBAAmB,GAAG,IAAI,CAAC;QAC5B,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QACpC,SAAS,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACvC,MAAM,IAAI,GACT,qBAAqB,KAAK,IAAI;YAC7B,CAAC,CAAC,iBAAiB;YACnB,CAAC,CAAC,uBAAuB,KAAK,IAAI;gBACjC,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,kBAAkB,CAAC;QACxB,IAAI,IAAI,GAAG,MAAM,uBAAuB,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QACpE,mBAAmB,GAAG,KAAK,CAAC;QAC5B,qBAAqB,GAAG,IAAI,CAAC;QAC7B,uBAAuB,GAAG,IAAI,CAAC;QAC/B,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,IAAI,KAAK,CAAC,WAAW,KAAK,MAAM,IAAI,IAAI,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;YACzF,IAAI,GAAG,MAAM,UAAU,CACtB,YAAY,CAAC,GAAG,CAAC,EACjB,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,2BAA2B,EAAE,EAC1D,OAAO,CACP,CAAC;QACH,CAAC;aAAM,IAAI,+BAA+B,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;YAChF,IAAI,GAAG,MAAM,UAAU,CACtB,YAAY,CAAC,GAAG,CAAC,EACjB,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,6BAA6B,EAAE,EAC5D,OAAO,CACP,CAAC;YACF,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBACf,GAAG,CAAC,EAAE,CAAC,MAAM,CACZ,QAAQ,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,iBAAiB,CAAC,IAAI,CAAC,KAAK,2BAA2B,CAAC,6BAA6B,CAAC,EAAE,EACjI,SAAS,CACT,CAAC;YACH,CAAC;QACF,CAAC;QACD,IAAI,IAAI,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACP,wBAAwB,EAAE,CAAC;QAC5B,CAAC;QACD,uBAAuB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACnC,MAAM,gBAAgB,GAAG,MAAM,yBAAyB,CAAC,mBAAmB,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpG,IAAI,gBAAgB,KAAK,IAAI,EAAE,CAAC;YAC/B,IAAI,GAAG,gBAAgB,CAAC;YACxB,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACjC,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;QAC5C,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,iBAAiB,EAAE,CAAC;QAC3D,IAAI,IAAI,KAAK,SAAS;YAAE,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;QAC5C,mBAAmB,GAAG,KAAK,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/C,IAAI,IAAI,EAAE,MAAM,KAAK,QAAQ;YAAE,OAAO;QACtC,MAAM,SAAS,GAAG,MAAM,uBAAuB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC/D,IAAI,SAAS,EAAE,MAAM,KAAK,QAAQ,EAAE,CAAC;YACpC,MAAM,OAAO,GAAG,MAAM,UAAU,CAC/B,YAAY,CAAC,GAAG,CAAC,EACjB,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,2BAA2B,EAAE,EAC1D,OAAO,CACP,CAAC;YACF,wBAAwB,EAAE,CAAC;YAC3B,uBAAuB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACvC,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;QAC/C,aAAa,GAAG,SAAS,CAAC;QAC1B,2BAA2B,EAAE,CAAC;QAC9B,IAAI,mBAAmB,KAAK,IAAI,EAAE,CAAC;YAClC,MAAM,uBAAuB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC9C,CAAC;QACD,wBAAwB,EAAE,CAAC;QAC3B,UAAU,CAAC,IAAI,EAAE,CAAC;QAClB,mBAAmB,CAAC,OAAO,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,KAAK,UAAU,4BAA4B,CAC1C,EAAgB,EAChB,GAAqB,EACrB,kBAA0B,EAC1B,IAAiB;QAEjB,IAAI,CAAC,qBAAqB,CAAC,GAAG,EAAE,kBAAkB,EAAE,IAAI,CAAC,EAAE,CAAC;YAC3D,OAAO,KAAK,CAAC;QACd,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,UAAU,IAAI,CAAC,MAAM,iBAAiB,IAAI,CAAC,SAAS,EAAE,EAAE;YAC1F,kBAAkB;YAClB,yBAAyB;SACzB,CAAC,CAAC;QACH,IAAI,MAAM,KAAK,kBAAkB;YAAE,OAAO,IAAI,CAAC;QAE/C,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,MAAM,CAAC,CAAC;QAClF,wBAAwB,CAAC,OAAO,CAAC,CAAC;QAClC,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC5B,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,iBAAiB,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAChG,MAAM,sCAAsC,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;QAC/D,OAAO,IAAI,CAAC;IACb,CAAC;IAED,KAAK,UAAU,sCAAsC,CACpD,YAA0B,EAC1B,GAAqB,EACrB,IAAU;QAEV,MAAM,aAAa,GAAG,MAAM,qBAAqB,CAAC,YAAY,EAAE,GAAG,EAAE,IAAI,EAAE;YAC1E,mBAAmB;YACnB,uBAAuB,EAAE,GAAG,EAAE;gBAC7B,mBAAmB,GAAG,IAAI,CAAC;YAC5B,CAAC;SACD,CAAC,CAAC;QACH,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;YAC5B,wBAAwB,EAAE,CAAC;YAC3B,uBAAuB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACnC,OAAO;QACR,CAAC;QACD,IAAI,aAAa,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM;YAAE,OAAO;QACjD,IAAI,aAAa,CAAC,MAAM,KAAK,QAAQ;YAAE,wBAAwB,CAAC,aAAa,CAAC,CAAC;;YAC1E,wBAAwB,EAAE,CAAC;QAChC,uBAAuB,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAC7C,CAAC;IAED,SAAS,wBAAwB,CAAC,IAAU;QAC3C,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ;YAAE,OAAO;QACrC,IAAI,mBAAmB,EAAE,MAAM,KAAK,IAAI,CAAC,EAAE;YAAE,OAAO;QACpD,SAAS,CAAC,cAAc,EAAE,CAAC;QAC3B,mBAAmB,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,wBAAwB,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACjF,CAAC;IAED,SAAS,uBAAuB,CAAC,IAAU;QAC1C,IAAI,mBAAmB;YAAE,qBAAqB,GAAG,IAAI,CAAC,EAAE,CAAC;IAC1D,CAAC;IAED,SAAS,yBAAyB,CAAC,IAAU;QAC5C,IAAI,CAAC,mBAAmB;YAAE,OAAO;QACjC,uBAAuB,GAAG,IAAI,CAAC,EAAE,CAAC;QAClC,mBAAmB,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,wBAAwB,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACjF,CAAC;IAED,SAAS,uBAAuB,CAAC,MAAc;QAC9C,IAAI,mBAAmB,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;YAC5C,mBAAmB,GAAG,IAAI,CAAC;QAC5B,CAAC;QACD,IAAI,qBAAqB,KAAK,MAAM,EAAE,CAAC;YACtC,qBAAqB,GAAG,IAAI,CAAC;QAC9B,CAAC;QACD,IAAI,uBAAuB,KAAK,MAAM,EAAE,CAAC;YACxC,uBAAuB,GAAG,IAAI,CAAC;QAChC,CAAC;IACF,CAAC;IAED,SAAS,wBAAwB;QAChC,mBAAmB,GAAG,IAAI,CAAC;QAC3B,qBAAqB,GAAG,IAAI,CAAC;QAC7B,uBAAuB,GAAG,IAAI,CAAC;IAChC,CAAC;IAED,SAAS,oBAAoB,CAAC,GAAqB,EAAE,IAAiB;QACrE,IAAI,IAAI,EAAE,MAAM,KAAK,QAAQ;YAAE,wBAAwB,CAAC,IAAI,CAAC,CAAC;;YACzD,wBAAwB,EAAE,CAAC;QAChC,uBAAuB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,SAAS,aAAa,CAAC,GAAqB,EAAE,IAAiB;QAC9D,mBAAmB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,UAAU,GAAG,mBAAmB,CAAC;QACvC,IAAI,GAAG,CAAC,KAAK,IAAI,IAAI,EAAE,MAAM,KAAK,QAAQ,IAAI,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC;YAC9E,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC,wBAAwB,CAAC,CAAC;YAChE,OAAO;QACR,CAAC;QACD,UAAU,CAAC,IAAI,EAAE,CAAC;QAClB,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACzB,CAAC;IAED,SAAS,uBAAuB,CAAC,GAAqB,EAAE,IAAiB;QACxE,IAAI,CAAC;YACJ,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,4BAA4B,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzC,OAAO;YACR,CAAC;YACD,MAAM,KAAK,CAAC;QACb,CAAC;IACF,CAAC;IAED,KAAK,UAAU,uBAAuB,CACrC,GAAqB,EACrB,IAAwB,EACxB,gBAA4B;QAE5B,MAAM,UAAU,GAAG,mBAAmB,CAAC;QACvC,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,UAAU,KAAK,IAAI;YAAE,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC;QAE9C,MAAM,KAAK,GACV,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC;QACtG,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,UAAU,CAAC,wBAAwB,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QACnG,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;QACzF,IAAI,IAAI,EAAE,EAAE,KAAK,UAAU,CAAC,MAAM,EAAE,CAAC;YACpC,mBAAmB,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAAC;QACpF,CAAC;aAAM,CAAC;YACP,wBAAwB,EAAE,CAAC;QAC5B,CAAC;QACD,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED;;;;;GAKG;AACH,SAAS,oCAAoC,CAAC,OAAgC;IAC7E,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,KAAK,EAAE,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM;YAAE,MAAM;QACtE,IAAI,KAAK,EAAE,IAAI,KAAK,gBAAgB,IAAI,KAAK,CAAC,UAAU,KAAK,8BAA8B;YAAE,KAAK,IAAI,CAAC,CAAC;IACzG,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CAAC,GAAqB;IAC1C,OAAO,iBAAiB,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;AACvD,CAAC","sourcesContent":["import { GOAL_CONTINUATION_MESSAGE_TYPE } from \"../../../messages.ts\";\nimport type { SessionEntry } from \"../../../session-manager.ts\";\nimport type { ExtensionAPI, ExtensionContext } from \"../../types.ts\";\nimport { continueGoalAfterAgentEnd } from \"./agent-end-continuation.ts\";\nimport { GOAL_CACHE_WARMUP_ENTRY_TYPE } from \"./cache-warm.ts\";\nimport { renderGoalCacheWarmupEntry } from \"./cache-warm-renderer.ts\";\nimport { registerGoalCommand } from \"./command-registration.ts\";\nimport { GOAL_CONTINUATION_CAP } from \"./continuation.ts\";\nimport { continuationCapRecoveryHint, PROVIDER_ERROR_BLOCKED_REASON } from \"./continuation-recovery.ts\";\nimport { GoalDirectInputLifecycle } from \"./direct-input-lifecycle.ts\";\nimport { GoalElapsedTicker } from \"./elapsed-ticker.ts\";\nimport { formatGoalForTool, goalStatusLabel } from \"./format.ts\";\nimport { isResumeOfStoppedGoal, queueGoalContinuation } from \"./lifecycle-helpers.ts\";\nimport { GOAL_CONTINUATION_SCHEDULED_EVENT, MonitorAwareGoalContinuation } from \"./monitor-continuation.ts\";\nimport { migrateLegacyGoalFile } from \"./persistence.ts\";\nimport { reengageGoalAfterReload } from \"./reload-reengagement.ts\";\nimport { isStaleExtensionContextError } from \"./stale-context.ts\";\nimport { accountGoalUsage, readGoal, updateGoal } from \"./store.ts\";\nimport { GOAL_STORE_CHANGED_EVENT, isGoalStoreChangedEvent } from \"./store-changed-event.ts\";\nimport { goalStoreRef as buildGoalStoreRef } from \"./store-ref.ts\";\nimport { didTerminalProviderErrorEndTurn } from \"./terminal-provider-error.ts\";\nimport { staleGoalTodoReminder, todoResultAddsOpenTasks } from \"./todo-gate.ts\";\nimport { registerGoalTools } from \"./tool-registration.ts\";\nimport { TurnUsageTracker } from \"./turn-usage.ts\";\nimport type { Goal, GoalAccountingMode, GoalStoreRef } from \"./types.ts\";\nimport { updateGoalUi } from \"./ui.ts\";\nimport { GOAL_WAIT_STATUS_KEY, GoalWaitTicker } from \"./wait-ticker.ts\";\n\nconst RESUME_GOAL_CHOICE = \"Resume goal\";\nconst LEAVE_GOAL_STOPPED_CHOICE = \"Leave stopped\";\n\ntype AgentGoalAccounting = {\n\tgoalId: string;\n\tmeasuredFromMilliseconds: number;\n};\n\nexport default function goalExtension(pi: ExtensionAPI): void {\n\tlet agentTurnInProgress = false;\n\tlet staleGoalReminderSentThisTurn = false;\n\tlet agentGoalAccounting: AgentGoalAccounting | null = null;\n\tlet blockedThisTurnGoalId: string | null = null;\n\tlet completedThisTurnGoalId: string | null = null;\n\tlet continuationPending = false;\n\tlet activeContext: ExtensionContext | undefined;\n\tconst turnUsage = new TurnUsageTracker();\n\t// No stale-ctx swallow here: GoalWaitTicker retires itself on a stale render\n\t// (a ticker that keeps ticking against a retired ctx freezes the footer\n\t// countdown forever); non-stale render errors still propagate.\n\tconst goalWaitTicker = new GoalWaitTicker({\n\t\trender: (renderCtx, status) => renderCtx.ui.setStatus(GOAL_WAIT_STATUS_KEY, status),\n\t});\n\tconst monitorContinuation = new MonitorAwareGoalContinuation(\n\t\tpi,\n\t\t() => continuationPending,\n\t\t() => {\n\t\t\tcontinuationPending = true;\n\t\t},\n\t\tgoalWaitTicker,\n\t);\n\tconst directInputLifecycle = new GoalDirectInputLifecycle({\n\t\tmonitor: monitorContinuation,\n\t\tgoalStoreRef,\n\t\tbeginAgentGoalAccounting,\n\t\trefreshGoalUi: refreshGoalUiBestEffort,\n\t\tresumeAfterSuppressedLoad: (resumeCtx, goal) => queueGoalContinuationForCurrentSession(pi, resumeCtx, goal),\n\t});\n\n\tconst goalTicker = new GoalElapsedTicker({\n\t\trender: (renderCtx, renderGoal, live) => updateGoalUi(renderCtx, renderGoal, live),\n\t});\n\n\tpi.registerEntryRenderer(GOAL_CACHE_WARMUP_ENTRY_TYPE, renderGoalCacheWarmupEntry);\n\tregisterGoalTools(pi, {\n\t\tgoalStoreRef: (ctx) => buildGoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\taccountCurrentAgentTurn,\n\t\tbeginAgentGoalAccounting: (goal) => {\n\t\t\tmonitorContinuation.noteContinuationStarted();\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t},\n\t\tmarkGoalBlockedThisTurn,\n\t\tmarkGoalCompletedThisTurn,\n\t\trefreshGoalUi,\n\t});\n\tregisterGoalCommand(pi, {\n\t\tgoalStoreRef: (ctx) => buildGoalStoreRef(ctx.sessionManager, ctx.cwd),\n\t\taccountCurrentAgentTurn,\n\t\tbeginAgentGoalAccounting,\n\t\tstopAgentGoalAccounting,\n\t\tclearAgentGoalAccounting,\n\t\tqueueGoalContinuation: (extensionApi, commandCtx, goal) => {\n\t\t\tvoid queueGoalContinuationForCurrentSession(extensionApi, commandCtx, goal);\n\t\t},\n\t\trefreshGoalUi,\n\t});\n\n\tconst unsubscribeGoalStoreChanged =\n\t\tpi.events?.on(GOAL_STORE_CHANGED_EVENT, async (data) => {\n\t\t\tif (!isGoalStoreChangedEvent(data)) return;\n\t\t\tconst ctx = data.ctx ?? activeContext;\n\t\t\tif (\n\t\t\t\tctx === undefined ||\n\t\t\t\tctx.sessionManager.getSessionId() !== data.threadId ||\n\t\t\t\t!ctx.isIdle() ||\n\t\t\t\tctx.hasPendingMessages()\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\t\tif (goal?.status !== \"active\") return;\n\t\t\tmonitorContinuation.syncGoal(goal);\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t\trefreshGoalUiBestEffort(ctx, goal);\n\t\t\tpi.events?.emit(GOAL_CONTINUATION_SCHEDULED_EVENT, {\n\t\t\t\tgoalId: goal.id,\n\t\t\t\tdelayMs: 0,\n\t\t\t\tactiveMonitorCount: 0,\n\t\t\t\twakeSources: {},\n\t\t\t\treason: GOAL_STORE_CHANGED_EVENT,\n\t\t\t});\n\t\t\tawait queueGoalContinuationForCurrentSession(pi, ctx, goal);\n\t\t}) ?? (() => {});\n\n\tpi.on(\"session_start\", async (event, ctx) => {\n\t\tactiveContext = ctx;\n\t\tmonitorContinuation.start(ctx);\n\t\tdirectInputLifecycle.reset();\n\t\tconst ref = goalStoreRef(ctx);\n\t\tawait migrateLegacyGoalFile(ref);\n\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\tif (goal?.status === \"active\") {\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t} else {\n\t\t\tclearAgentGoalAccounting();\n\t\t}\n\t\trefreshGoalUi(ctx, goal);\n\t\tif (await maybePromptResumeStoppedGoal(pi, ctx, event.reason, goal)) {\n\t\t\treturn;\n\t\t}\n\t\tif (goal && event.reason === \"reload\") {\n\t\t\t// A reload retires the extension generation and every armed continuation\n\t\t\t// timer with it. Re-engage through the reload path: stopped goals stay\n\t\t\t// stopped, active goals resume the wait the reload tore down.\n\t\t\tawait reengageGoalAfterReload({\n\t\t\t\tctx,\n\t\t\t\tgoal,\n\t\t\t\tmonitor: monitorContinuation,\n\t\t\t\tcountTrailingContinuations: () => countTrailingGoalContinuationEntries(ctx.sessionManager.getBranch()),\n\t\t\t\tqueueContinuation: () => queueGoalContinuationForCurrentSession(pi, ctx, goal),\n\t\t\t});\n\t\t} else if (goal) {\n\t\t\t// Migration-lite admission: a resumed session carrying a trailing flood of\n\t\t\t// historical continuations must not reignite on load. Skip the auto-queue,\n\t\t\t// leave the goal active (no status rewrite), and tell the user how to resume.\n\t\t\tconst trailingContinuations = countTrailingGoalContinuationEntries(ctx.sessionManager.getBranch());\n\t\t\tif (trailingContinuations >= GOAL_CONTINUATION_CAP) {\n\t\t\t\t// The load-time flood suppression parks the goal without rewriting its\n\t\t\t\t// status, so the only resume signal left is the user's next message.\n\t\t\t\t// Arm the one-shot latch the direct-input lifecycle fires when that\n\t\t\t\t// message is accepted; without it the promise in the notice is a lie\n\t\t\t\t// and the resumed session sits idle until the goal is recreated.\n\t\t\t\tdirectInputLifecycle.armSuppressedLoadResume();\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Goal auto-continuation suppressed for this resumed session (${trailingContinuations} historical continuations). Send a message to resume.`,\n\t\t\t\t\t\"info\",\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tawait queueGoalContinuationForCurrentSession(pi, ctx, goal);\n\t\t\t}\n\t\t}\n\t});\n\n\tpi.on(\"input\", async (event, ctx) => {\n\t\tawait directInputLifecycle.onInput(event, ctx);\n\t});\n\n\tpi.on(\"input_disposition\", async (event, ctx) => {\n\t\tawait directInputLifecycle.onDisposition(event, ctx);\n\t});\n\n\tpi.on(\"turn_start\", async () => {\n\t\tstaleGoalReminderSentThisTurn = false;\n\t});\n\n\t// When the model starts tracking new open todo work while the thread has no\n\t// goal (or only a stale, already-complete one), append a system reminder to\n\t// the todo result so the model registers the goal when the work warrants it.\n\tpi.on(\"tool_result\", async (event, ctx) => {\n\t\tif (event.toolName !== \"todo\" || event.isError || staleGoalReminderSentThisTurn) return undefined;\n\t\tif (!todoResultAddsOpenTasks(event.details)) return undefined;\n\t\tconst reminder = staleGoalTodoReminder(await readGoal(goalStoreRef(ctx)));\n\t\tif (reminder === undefined) return undefined;\n\t\tstaleGoalReminderSentThisTurn = true;\n\t\treturn { content: [...event.content, { type: \"text\" as const, text: reminder }] };\n\t});\n\n\tpi.on(\"agent_start\", async (_event, ctx) => {\n\t\tconst continuationStarted = continuationPending;\n\t\tcontinuationPending = false;\n\t\tif (continuationStarted) monitorContinuation.noteContinuationStarted();\n\t\tagentTurnInProgress = true;\n\t\tblockedThisTurnGoalId = null;\n\t\tcompletedThisTurnGoalId = null;\n\t\tturnUsage.reset();\n\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\tif (goal?.status === \"active\") {\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t} else {\n\t\t\tagentGoalAccounting = null;\n\t\t}\n\t});\n\n\tpi.on(\"message_end\", async (event) => {\n\t\tturnUsage.noteMessageEnd(event.message);\n\t});\n\n\tpi.on(\"agent_end\", async (event, ctx) => {\n\t\tconst mode: GoalAccountingMode =\n\t\t\tblockedThisTurnGoalId !== null\n\t\t\t\t? \"activeOrBlocked\"\n\t\t\t\t: completedThisTurnGoalId === null\n\t\t\t\t\t? \"active\"\n\t\t\t\t\t: \"activeOrComplete\";\n\t\tlet goal = await accountCurrentAgentTurn(ctx, mode, event.messages);\n\t\tagentTurnInProgress = false;\n\t\tblockedThisTurnGoalId = null;\n\t\tcompletedThisTurnGoalId = null;\n\t\tif (event.aborted === true && event.abortSource === \"user\" && goal?.status === \"active\") {\n\t\t\tgoal = await updateGoal(\n\t\t\t\tgoalStoreRef(ctx),\n\t\t\t\t{ status: \"blocked\", reason: \"user interrupted the turn\" },\n\t\t\t\t\"model\",\n\t\t\t);\n\t\t} else if (didTerminalProviderErrorEndTurn(event) && goal?.status === \"active\") {\n\t\t\tgoal = await updateGoal(\n\t\t\t\tgoalStoreRef(ctx),\n\t\t\t\t{ status: \"blocked\", reason: PROVIDER_ERROR_BLOCKED_REASON },\n\t\t\t\t\"model\",\n\t\t\t);\n\t\t\tif (ctx.hasUI) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Goal ${goalStatusLabel(goal.status)}\\n${formatGoalForTool(goal)}\\n${continuationCapRecoveryHint(PROVIDER_ERROR_BLOCKED_REASON)}`,\n\t\t\t\t\t\"warning\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (goal?.status === \"active\") {\n\t\t\tbeginAgentGoalAccounting(goal);\n\t\t} else {\n\t\t\tclearAgentGoalAccounting();\n\t\t}\n\t\trefreshGoalUiBestEffort(ctx, goal);\n\t\tconst continuationGoal = await continueGoalAfterAgentEnd(monitorContinuation, { ctx, event, goal });\n\t\tif (continuationGoal !== goal) {\n\t\t\tgoal = continuationGoal;\n\t\t\tsyncContinuationGoal(ctx, goal);\n\t\t}\n\t});\n\n\tpi.on(\"agent_settled\", async (_event, ctx) => {\n\t\tconst goal = await monitorContinuation.afterAgentSettled();\n\t\tif (goal !== undefined) syncContinuationGoal(ctx, goal);\n\t});\n\n\tpi.on(\"session_abort\", async (_event, ctx) => {\n\t\tcontinuationPending = false;\n\t\tconst goal = await readGoal(goalStoreRef(ctx));\n\t\tif (goal?.status !== \"active\") return;\n\t\tconst accounted = await accountCurrentAgentTurn(ctx, \"active\");\n\t\tif (accounted?.status === \"active\") {\n\t\t\tconst blocked = await updateGoal(\n\t\t\t\tgoalStoreRef(ctx),\n\t\t\t\t{ status: \"blocked\", reason: \"user interrupted the turn\" },\n\t\t\t\t\"model\",\n\t\t\t);\n\t\t\tclearAgentGoalAccounting();\n\t\t\trefreshGoalUiBestEffort(ctx, blocked);\n\t\t}\n\t});\n\n\tpi.on(\"session_shutdown\", async (_event, ctx) => {\n\t\tactiveContext = undefined;\n\t\tunsubscribeGoalStoreChanged();\n\t\tif (agentGoalAccounting !== null) {\n\t\t\tawait accountCurrentAgentTurn(ctx, \"active\");\n\t\t}\n\t\tclearAgentGoalAccounting();\n\t\tgoalTicker.stop();\n\t\tmonitorContinuation.dispose();\n\t});\n\n\tasync function maybePromptResumeStoppedGoal(\n\t\tpi: ExtensionAPI,\n\t\tctx: ExtensionContext,\n\t\tsessionStartReason: string,\n\t\tgoal: Goal | null,\n\t): Promise<boolean> {\n\t\tif (!isResumeOfStoppedGoal(ctx, sessionStartReason, goal)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst choice = await ctx.ui.select(`Resume ${goal.status} goal?\\nGoal: ${goal.objective}`, [\n\t\t\tRESUME_GOAL_CHOICE,\n\t\t\tLEAVE_GOAL_STOPPED_CHOICE,\n\t\t]);\n\t\tif (choice !== RESUME_GOAL_CHOICE) return true;\n\n\t\tconst resumed = await updateGoal(goalStoreRef(ctx), { status: \"active\" }, \"user\");\n\t\tbeginAgentGoalAccounting(resumed);\n\t\trefreshGoalUi(ctx, resumed);\n\t\tctx.ui.notify(`Goal ${goalStatusLabel(resumed.status)}\\n${formatGoalForTool(resumed)}`, \"info\");\n\t\tawait queueGoalContinuationForCurrentSession(pi, ctx, resumed);\n\t\treturn true;\n\t}\n\n\tasync function queueGoalContinuationForCurrentSession(\n\t\textensionApi: ExtensionAPI,\n\t\tctx: ExtensionContext,\n\t\tgoal: Goal,\n\t): Promise<void> {\n\t\tconst continuedGoal = await queueGoalContinuation(extensionApi, ctx, goal, {\n\t\t\tcontinuationPending,\n\t\t\tmarkContinuationPending: () => {\n\t\t\t\tcontinuationPending = true;\n\t\t\t},\n\t\t});\n\t\tif (continuedGoal === null) {\n\t\t\tclearAgentGoalAccounting();\n\t\t\trefreshGoalUiBestEffort(ctx, null);\n\t\t\treturn;\n\t\t}\n\t\tif (continuedGoal.status === goal.status) return;\n\t\tif (continuedGoal.status === \"active\") beginAgentGoalAccounting(continuedGoal);\n\t\telse clearAgentGoalAccounting();\n\t\trefreshGoalUiBestEffort(ctx, continuedGoal);\n\t}\n\n\tfunction beginAgentGoalAccounting(goal: Goal): void {\n\t\tif (goal.status !== \"active\") return;\n\t\tif (agentGoalAccounting?.goalId === goal.id) return;\n\t\tturnUsage.discardPending();\n\t\tagentGoalAccounting = { goalId: goal.id, measuredFromMilliseconds: Date.now() };\n\t}\n\n\tfunction markGoalBlockedThisTurn(goal: Goal): void {\n\t\tif (agentTurnInProgress) blockedThisTurnGoalId = goal.id;\n\t}\n\n\tfunction markGoalCompletedThisTurn(goal: Goal): void {\n\t\tif (!agentTurnInProgress) return;\n\t\tcompletedThisTurnGoalId = goal.id;\n\t\tagentGoalAccounting = { goalId: goal.id, measuredFromMilliseconds: Date.now() };\n\t}\n\n\tfunction stopAgentGoalAccounting(goalId: string): void {\n\t\tif (agentGoalAccounting?.goalId === goalId) {\n\t\t\tagentGoalAccounting = null;\n\t\t}\n\t\tif (blockedThisTurnGoalId === goalId) {\n\t\t\tblockedThisTurnGoalId = null;\n\t\t}\n\t\tif (completedThisTurnGoalId === goalId) {\n\t\t\tcompletedThisTurnGoalId = null;\n\t\t}\n\t}\n\n\tfunction clearAgentGoalAccounting(): void {\n\t\tagentGoalAccounting = null;\n\t\tblockedThisTurnGoalId = null;\n\t\tcompletedThisTurnGoalId = null;\n\t}\n\n\tfunction syncContinuationGoal(ctx: ExtensionContext, goal: Goal | null): void {\n\t\tif (goal?.status === \"active\") beginAgentGoalAccounting(goal);\n\t\telse clearAgentGoalAccounting();\n\t\trefreshGoalUiBestEffort(ctx, goal);\n\t}\n\n\tfunction refreshGoalUi(ctx: ExtensionContext, goal: Goal | null): void {\n\t\tmonitorContinuation.syncGoal(goal);\n\t\tconst accounting = agentGoalAccounting;\n\t\tif (ctx.hasUI && goal?.status === \"active\" && accounting?.goalId === goal.id) {\n\t\t\tgoalTicker.sync(ctx, goal, accounting.measuredFromMilliseconds);\n\t\t\treturn;\n\t\t}\n\t\tgoalTicker.stop();\n\t\tupdateGoalUi(ctx, goal);\n\t}\n\n\tfunction refreshGoalUiBestEffort(ctx: ExtensionContext, goal: Goal | null): void {\n\t\ttry {\n\t\t\trefreshGoalUi(ctx, goal);\n\t\t} catch (error) {\n\t\t\tif (isStaleExtensionContextError(error)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync function accountCurrentAgentTurn(\n\t\tctx: ExtensionContext,\n\t\tmode: GoalAccountingMode,\n\t\tagentRunMessages?: unknown[],\n\t): Promise<Goal | null> {\n\t\tconst accounting = agentGoalAccounting;\n\t\tconst ref = goalStoreRef(ctx);\n\t\tif (accounting === null) return readGoal(ref);\n\n\t\tconst usage =\n\t\t\tagentRunMessages === undefined ? turnUsage.takePending() : turnUsage.takeRemaining(agentRunMessages);\n\t\tconst now = Date.now();\n\t\tconst elapsedSeconds = Math.max(0, Math.round((now - accounting.measuredFromMilliseconds) / 1000));\n\t\tconst goal = await accountGoalUsage(ref, usage, elapsedSeconds, mode, accounting.goalId);\n\t\tif (goal?.id === accounting.goalId) {\n\t\t\tagentGoalAccounting = { goalId: accounting.goalId, measuredFromMilliseconds: now };\n\t\t} else {\n\t\t\tclearAgentGoalAccounting();\n\t\t}\n\t\treturn goal;\n\t}\n}\n\n/**\n * Counts goal-continuation entries queued since the most recent real user message\n * in the current branch (mirrors the todo-gate / todo-bridge backward branch read).\n * A real user message is the only reset: the assistant turns in between are exactly\n * the unattended loop this admission guard exists to stop.\n */\nfunction countTrailingGoalContinuationEntries(entries: readonly SessionEntry[]): number {\n\tlet count = 0;\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (entry?.type === \"message\" && entry.message.role === \"user\") break;\n\t\tif (entry?.type === \"custom_message\" && entry.customType === GOAL_CONTINUATION_MESSAGE_TYPE) count += 1;\n\t}\n\treturn count;\n}\n\nfunction goalStoreRef(ctx: ExtensionContext): GoalStoreRef {\n\treturn buildGoalStoreRef(ctx.sessionManager, ctx.cwd);\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detection for the error a retired extension context throws when used after
|
|
3
|
+
* session replacement or reload (thrown by the extension runner; see
|
|
4
|
+
* agent-session). Long-lived goal tickers retain a ctx across ticks, so they
|
|
5
|
+
* must recognize this error and retire instead of spinning dead forever.
|
|
6
|
+
*/
|
|
7
|
+
export declare const STALE_EXTENSION_CONTEXT_ERROR_PREFIX = "This extension ctx is stale after session replacement or reload.";
|
|
8
|
+
export declare function isStaleExtensionContextError(error: unknown): error is Error;
|
|
9
|
+
//# sourceMappingURL=stale-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stale-context.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/stale-context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,oCAAoC,qEAAqE,CAAC;AAEvH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,KAAK,CAE3E"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detection for the error a retired extension context throws when used after
|
|
3
|
+
* session replacement or reload (thrown by the extension runner; see
|
|
4
|
+
* agent-session). Long-lived goal tickers retain a ctx across ticks, so they
|
|
5
|
+
* must recognize this error and retire instead of spinning dead forever.
|
|
6
|
+
*/
|
|
7
|
+
export const STALE_EXTENSION_CONTEXT_ERROR_PREFIX = "This extension ctx is stale after session replacement or reload.";
|
|
8
|
+
export function isStaleExtensionContextError(error) {
|
|
9
|
+
return error instanceof Error && error.message.startsWith(STALE_EXTENSION_CONTEXT_ERROR_PREFIX);
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=stale-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stale-context.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/stale-context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAAG,kEAAkE,CAAC;AAEvH,MAAM,UAAU,4BAA4B,CAAC,KAAc;IAC1D,OAAO,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,oCAAoC,CAAC,CAAC;AACjG,CAAC","sourcesContent":["/**\n * Detection for the error a retired extension context throws when used after\n * session replacement or reload (thrown by the extension runner; see\n * agent-session). Long-lived goal tickers retain a ctx across ticks, so they\n * must recognize this error and retire instead of spinning dead forever.\n */\nexport const STALE_EXTENSION_CONTEXT_ERROR_PREFIX = \"This extension ctx is stale after session replacement or reload.\";\n\nexport function isStaleExtensionContextError(error: unknown): error is Error {\n\treturn error instanceof Error && error.message.startsWith(STALE_EXTENSION_CONTEXT_ERROR_PREFIX);\n}\n"]}
|
|
@@ -34,6 +34,14 @@ export declare class GoalWaitTicker {
|
|
|
34
34
|
setChannelCounts(channelCounts: ResumptionChannelCounts): void;
|
|
35
35
|
/** Stop ticking, clear the footer segment, and drop the retained context. */
|
|
36
36
|
stop(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Drop the interval and retained ctx without a final render. Used when a tick
|
|
39
|
+
* discovers the ctx was retired by a session replacement or reload: every
|
|
40
|
+
* render against it throws from now on, and a ticker that keeps ticking dead
|
|
41
|
+
* renders freezes the footer forever without crashing. The next sync() with a
|
|
42
|
+
* live ctx re-arms everything.
|
|
43
|
+
*/
|
|
44
|
+
private retire;
|
|
37
45
|
private tick;
|
|
38
46
|
}
|
|
39
47
|
//# sourceMappingURL=wait-ticker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wait-ticker.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/wait-ticker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"wait-ticker.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/goal/wait-ticker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAE/E,OAAO,EAA0C,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAErG,6EAA6E;AAC7E,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAC/C,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAEhD,uFAAuF;AACvF,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;AAEzF,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,wDAAwD;IACxD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,qBAAa,cAAc;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,GAAG,CAA+B;IAC1C,OAAO,CAAC,IAAI,CAA2B;IACvC,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,kBAAkB,CAAqB;gBAEnC,OAAO,EAAE,qBAAqB;IAK1C,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,0EAA0E;IAC1E,IAAI,CAAC,GAAG,EAAE,gBAAgB,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAc5D,uEAAuE;IACvE,gBAAgB,CAAC,aAAa,EAAE,uBAAuB,GAAG,IAAI;IAM9D,6EAA6E;IAC7E,IAAI,IAAI,IAAI;IAmBZ;;;;;;OAMG;IACH,OAAO,CAAC,MAAM;IAUd,OAAO,CAAC,IAAI;CAoBZ"}
|