@ashx-j/lunr 0.2.25 → 0.2.27
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 +31 -1
- package/LICENSE +22 -0
- package/dist/builtin-extensions/ashxj-thinking.d.ts +1 -1
- package/dist/builtin-extensions/ashxj-thinking.d.ts.map +1 -1
- package/dist/builtin-extensions/ashxj-thinking.js +1 -1
- package/dist/builtin-extensions/ashxj-thinking.js.map +1 -1
- package/dist/builtin-extensions/ashxj-tui.d.ts +11 -1
- package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
- package/dist/builtin-extensions/ashxj-tui.js +6 -10
- package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
- package/dist/builtin-extensions/index.d.ts.map +1 -1
- package/dist/builtin-extensions/index.js +1 -0
- package/dist/builtin-extensions/index.js.map +1 -1
- package/dist/builtin-extensions/lunr-computer-use.d.ts +3 -0
- package/dist/builtin-extensions/lunr-computer-use.d.ts.map +1 -0
- package/dist/builtin-extensions/lunr-computer-use.js +179 -0
- package/dist/builtin-extensions/lunr-computer-use.js.map +1 -0
- package/dist/builtin-extensions/lunr-cron.d.ts +4 -5
- package/dist/builtin-extensions/lunr-cron.d.ts.map +1 -1
- package/dist/builtin-extensions/lunr-cron.js +94 -108
- package/dist/builtin-extensions/lunr-cron.js.map +1 -1
- package/dist/builtin-extensions/lunr-local-providers/local-servers.d.ts.map +1 -1
- package/dist/builtin-extensions/lunr-local-providers/local-servers.js +3 -1
- package/dist/builtin-extensions/lunr-local-providers/local-servers.js.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/commands.d.ts.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/commands.js +2 -2
- package/dist/builtin-extensions/narumiruna-pi-goal/src/commands.js.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.d.ts.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.d.ts.map +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.js +1 -1
- package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.js.map +1 -1
- package/dist/builtin-extensions/pi-intercom/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-intercom/index.js +2 -2
- package/dist/builtin-extensions/pi-intercom/index.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.d.ts +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.js +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/bemol-extension/index.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/index.js +1 -15
- package/dist/builtin-extensions/pi-lsp-extension/src/index.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.d.ts +6 -0
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.js +187 -132
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-client.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.d.ts +8 -0
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.js +142 -112
- package/dist/builtin-extensions/pi-lsp-extension/src/lsp-manager.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.d.ts +12 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.js +14 -7
- package/dist/builtin-extensions/pi-lsp-extension/src/tools/code-rewrite.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.d.ts +11 -3
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.js +67 -41
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/rewrite-engine.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.d.ts +4 -2
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.js +3 -0
- package/dist/builtin-extensions/pi-lsp-extension/src/tree-sitter/search-engine.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/commands.d.ts +2 -1
- package/dist/builtin-extensions/pi-mcp-adapter/commands.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/commands.js +6 -6
- package/dist/builtin-extensions/pi-mcp-adapter/commands.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/config.d.ts +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/config.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/config.js +11 -5
- package/dist/builtin-extensions/pi-mcp-adapter/config.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js +2 -2
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/host-html-template.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/host-html-template.js +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/host-html-template.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/index.js +48 -40
- package/dist/builtin-extensions/pi-mcp-adapter/index.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/init.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/init.js +3 -1
- package/dist/builtin-extensions/pi-mcp-adapter/init.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.d.ts +12 -40
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.js +166 -235
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-auth-flow.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.d.ts +5 -0
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.js +43 -13
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-callback-server.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.d.ts +14 -3
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.js +73 -21
- package/dist/builtin-extensions/pi-mcp-adapter/mcp-oauth-provider.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/proxy-modes.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/proxy-modes.js +4 -4
- package/dist/builtin-extensions/pi-mcp-adapter/proxy-modes.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js +2 -2
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/state.d.ts +2 -0
- package/dist/builtin-extensions/pi-mcp-adapter/state.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/state.js.map +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/index.d.ts +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/index.js +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/index.js.map +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/models.d.ts +11 -5
- package/dist/builtin-extensions/pi-ollama-cloud/models.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-ollama-cloud/models.js +12 -32
- package/dist/builtin-extensions/pi-ollama-cloud/models.js.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/index.js +5 -3
- package/dist/builtin-extensions/pi-prompt-template-model/index.js.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.d.ts +2 -1
- package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js +21 -12
- package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js +7 -24
- package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js +39 -77
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +4 -4
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +8 -5
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js +15 -31
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js +7 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js +21 -4
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +11 -4
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +121 -25
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +25 -5
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/chain-outputs.d.ts +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/chain-outputs.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/chain-outputs.js +5 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/chain-outputs.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.js +2 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +7 -8
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js +60 -32
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/utils.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/utils.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/utils.js +15 -5
- package/dist/builtin-extensions/pi-subagents/src/shared/utils.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +4 -3
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/communication.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/communication.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/communication.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +2 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.js +22 -11
- package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/review.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js +3 -3
- package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js.map +1 -1
- package/dist/builtin-extensions/pi-tps.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-tps.js +20 -17
- package/dist/builtin-extensions/pi-tps.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/activity.d.ts +1 -0
- package/dist/builtin-extensions/pi-web-access/activity.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/activity.js +27 -5
- package/dist/builtin-extensions/pi-web-access/activity.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/bounded-body.d.ts +3 -0
- package/dist/builtin-extensions/pi-web-access/bounded-body.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-web-access/bounded-body.js +43 -0
- package/dist/builtin-extensions/pi-web-access/bounded-body.js.map +1 -0
- package/dist/builtin-extensions/pi-web-access/content-page.d.ts +24 -0
- package/dist/builtin-extensions/pi-web-access/content-page.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-web-access/content-page.js +57 -0
- package/dist/builtin-extensions/pi-web-access/content-page.js.map +1 -0
- package/dist/builtin-extensions/pi-web-access/extract.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/extract.js +7 -2
- package/dist/builtin-extensions/pi-web-access/extract.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/github-extract.d.ts +0 -1
- package/dist/builtin-extensions/pi-web-access/github-extract.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/github-extract.js +147 -36
- package/dist/builtin-extensions/pi-web-access/github-extract.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/index.js +48 -73
- package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts +12 -4
- package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/session-cleanup.js +35 -12
- package/dist/builtin-extensions/pi-web-access/session-cleanup.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/storage.d.ts +9 -6
- package/dist/builtin-extensions/pi-web-access/storage.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/storage.js +36 -24
- package/dist/builtin-extensions/pi-web-access/storage.js.map +1 -1
- package/dist/builtin-extensions/simple-pi-memory.d.ts +1 -1
- package/dist/builtin-extensions/simple-pi-memory.d.ts.map +1 -1
- package/dist/builtin-extensions/simple-pi-memory.js +1 -1
- package/dist/builtin-extensions/simple-pi-memory.js.map +1 -1
- package/dist/cli/install-cli.d.ts.map +1 -1
- package/dist/cli/install-cli.js +38 -30
- package/dist/cli/install-cli.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +13 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +75 -11
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +1 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +40 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +309 -76
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/browser/runtime.d.ts +2 -0
- package/dist/core/browser/runtime.d.ts.map +1 -1
- package/dist/core/browser/runtime.js +80 -45
- package/dist/core/browser/runtime.js.map +1 -1
- package/dist/core/browser/setup.d.ts.map +1 -1
- package/dist/core/browser/setup.js +12 -1
- package/dist/core/browser/setup.js.map +1 -1
- package/dist/core/computer-use/adapter.d.ts +28 -0
- package/dist/core/computer-use/adapter.d.ts.map +1 -0
- package/dist/core/computer-use/adapter.js +138 -0
- package/dist/core/computer-use/adapter.js.map +1 -0
- package/dist/core/computer-use/image.d.ts +27 -0
- package/dist/core/computer-use/image.d.ts.map +1 -0
- package/dist/core/computer-use/image.js +84 -0
- package/dist/core/computer-use/image.js.map +1 -0
- package/dist/core/computer-use/lease.d.ts +18 -0
- package/dist/core/computer-use/lease.d.ts.map +1 -0
- package/dist/core/computer-use/lease.js +129 -0
- package/dist/core/computer-use/lease.js.map +1 -0
- package/dist/core/computer-use/macos-runtime.d.ts +14 -0
- package/dist/core/computer-use/macos-runtime.d.ts.map +1 -0
- package/dist/core/computer-use/macos-runtime.js +148 -0
- package/dist/core/computer-use/macos-runtime.js.map +1 -0
- package/dist/core/computer-use/policy.d.ts +19 -0
- package/dist/core/computer-use/policy.d.ts.map +1 -0
- package/dist/core/computer-use/policy.js +67 -0
- package/dist/core/computer-use/policy.js.map +1 -0
- package/dist/core/computer-use/release.generated.d.ts +31 -0
- package/dist/core/computer-use/release.generated.d.ts.map +1 -0
- package/dist/core/computer-use/release.generated.js +36 -0
- package/dist/core/computer-use/release.generated.js.map +1 -0
- package/dist/core/computer-use/runtime.d.ts +13 -0
- package/dist/core/computer-use/runtime.d.ts.map +1 -0
- package/dist/core/computer-use/runtime.js +158 -0
- package/dist/core/computer-use/runtime.js.map +1 -0
- package/dist/core/computer-use/schemas.d.ts +100 -0
- package/dist/core/computer-use/schemas.d.ts.map +1 -0
- package/dist/core/computer-use/schemas.js +96 -0
- package/dist/core/computer-use/schemas.js.map +1 -0
- package/dist/core/computer-use/windows-desktop.d.ts +3 -0
- package/dist/core/computer-use/windows-desktop.d.ts.map +1 -0
- package/dist/core/computer-use/windows-desktop.js +48 -0
- package/dist/core/computer-use/windows-desktop.js.map +1 -0
- package/dist/core/computer-use/workflow.d.ts +38 -0
- package/dist/core/computer-use/workflow.d.ts.map +1 -0
- package/dist/core/computer-use/workflow.js +900 -0
- package/dist/core/computer-use/workflow.js.map +1 -0
- package/dist/core/cron/jobs.d.ts +26 -8
- package/dist/core/cron/jobs.d.ts.map +1 -1
- package/dist/core/cron/jobs.js +357 -232
- package/dist/core/cron/jobs.js.map +1 -1
- package/dist/core/cron/origin-context.d.ts +1 -0
- package/dist/core/cron/origin-context.d.ts.map +1 -1
- package/dist/core/cron/origin-context.js.map +1 -1
- package/dist/core/cron/scheduler.d.ts +22 -17
- package/dist/core/cron/scheduler.d.ts.map +1 -1
- package/dist/core/cron/scheduler.js +153 -73
- package/dist/core/cron/scheduler.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +4 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +8 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +8 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +4 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +22 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/large-subagent-launch.d.ts +1 -1
- package/dist/core/large-subagent-launch.d.ts.map +1 -1
- package/dist/core/large-subagent-launch.js +7 -7
- package/dist/core/large-subagent-launch.js.map +1 -1
- package/dist/core/model-registry.d.ts +2 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +5 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-runtime.d.ts +4 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +40 -4
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/permissions.d.ts +4 -4
- package/dist/core/permissions.d.ts.map +1 -1
- package/dist/core/permissions.js +25 -38
- package/dist/core/permissions.js.map +1 -1
- package/dist/core/plan-mode.d.ts +5 -13
- package/dist/core/plan-mode.d.ts.map +1 -1
- package/dist/core/plan-mode.js +135 -116
- package/dist/core/plan-mode.js.map +1 -1
- package/dist/core/project-trust.d.ts.map +1 -1
- package/dist/core/project-trust.js +1 -1
- package/dist/core/project-trust.js.map +1 -1
- package/dist/core/prompt-resource-bridge.d.ts +12 -0
- package/dist/core/prompt-resource-bridge.d.ts.map +1 -0
- package/dist/core/prompt-resource-bridge.js +9 -0
- package/dist/core/prompt-resource-bridge.js.map +1 -0
- package/dist/core/protected-targets.d.ts +6 -0
- package/dist/core/protected-targets.d.ts.map +1 -0
- package/dist/core/protected-targets.js +45 -0
- package/dist/core/protected-targets.js.map +1 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +7 -0
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/rollback.d.ts +19 -3
- package/dist/core/rollback.d.ts.map +1 -1
- package/dist/core/rollback.js +172 -56
- package/dist/core/rollback.js.map +1 -1
- package/dist/core/runtime-credentials.d.ts +3 -0
- package/dist/core/runtime-credentials.d.ts.map +1 -1
- package/dist/core/runtime-credentials.js +14 -1
- package/dist/core/runtime-credentials.js.map +1 -1
- package/dist/core/sdk.d.ts +3 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +6 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +95 -32
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-ownership.d.ts.map +1 -1
- package/dist/core/session-ownership.js +8 -3
- package/dist/core/session-ownership.js.map +1 -1
- package/dist/core/session-retention.d.ts.map +1 -1
- package/dist/core/session-retention.js +18 -7
- package/dist/core/session-retention.js.map +1 -1
- package/dist/core/session-startup-settings.d.ts +10 -0
- package/dist/core/session-startup-settings.d.ts.map +1 -0
- package/dist/core/session-startup-settings.js +70 -0
- package/dist/core/session-startup-settings.js.map +1 -0
- package/dist/core/settings-manager.d.ts +6 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +19 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/subagent-event-transport.d.ts +3 -0
- package/dist/core/subagent-event-transport.d.ts.map +1 -0
- package/dist/core/subagent-event-transport.js +61 -0
- package/dist/core/subagent-event-transport.js.map +1 -0
- package/dist/core/subscriptions.d.ts +16 -7
- package/dist/core/subscriptions.d.ts.map +1 -1
- package/dist/core/subscriptions.js +96 -55
- package/dist/core/subscriptions.js.map +1 -1
- package/dist/core/trust-manager.d.ts +2 -1
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +6 -1
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/core/update-check.d.ts.map +1 -1
- package/dist/core/update-check.js.map +1 -1
- package/dist/core/usage-adapters/kimi-coding.d.ts +2 -2
- package/dist/core/usage-adapters/kimi-coding.d.ts.map +1 -1
- package/dist/core/usage-adapters/kimi-coding.js +2 -2
- package/dist/core/usage-adapters/kimi-coding.js.map +1 -1
- package/dist/core/usage-adapters/openai-codex.d.ts +3 -2
- package/dist/core/usage-adapters/openai-codex.d.ts.map +1 -1
- package/dist/core/usage-adapters/openai-codex.js +3 -3
- package/dist/core/usage-adapters/openai-codex.js.map +1 -1
- package/dist/core/usage-adapters/xai.d.ts +2 -2
- package/dist/core/usage-adapters/xai.d.ts.map +1 -1
- package/dist/core/usage-adapters/xai.js +3 -3
- package/dist/core/usage-adapters/xai.js.map +1 -1
- package/dist/core/usage-adapters/zai.d.ts +2 -2
- package/dist/core/usage-adapters/zai.d.ts.map +1 -1
- package/dist/core/usage-adapters/zai.js +2 -2
- package/dist/core/usage-adapters/zai.js.map +1 -1
- package/dist/core/usage-service.d.ts +9 -2
- package/dist/core/usage-service.d.ts.map +1 -1
- package/dist/core/usage-service.js +95 -50
- package/dist/core/usage-service.js.map +1 -1
- package/dist/gateway/adapters/discord.d.ts.map +1 -1
- package/dist/gateway/adapters/discord.js +2 -2
- package/dist/gateway/adapters/discord.js.map +1 -1
- package/dist/gateway/agent-bridge.d.ts +9 -1
- package/dist/gateway/agent-bridge.d.ts.map +1 -1
- package/dist/gateway/agent-bridge.js +91 -37
- package/dist/gateway/agent-bridge.js.map +1 -1
- package/dist/gateway/approval.d.ts.map +1 -1
- package/dist/gateway/approval.js +3 -3
- package/dist/gateway/approval.js.map +1 -1
- package/dist/gateway/authz.d.ts +4 -4
- package/dist/gateway/authz.d.ts.map +1 -1
- package/dist/gateway/authz.js +8 -12
- package/dist/gateway/authz.js.map +1 -1
- package/dist/gateway/buttons.d.ts +8 -1
- package/dist/gateway/buttons.d.ts.map +1 -1
- package/dist/gateway/buttons.js +76 -18
- package/dist/gateway/buttons.js.map +1 -1
- package/dist/gateway/commands.d.ts +1 -0
- package/dist/gateway/commands.d.ts.map +1 -1
- package/dist/gateway/commands.js +12 -10
- package/dist/gateway/commands.js.map +1 -1
- package/dist/gateway/cron.d.ts +12 -11
- package/dist/gateway/cron.d.ts.map +1 -1
- package/dist/gateway/cron.js +85 -62
- package/dist/gateway/cron.js.map +1 -1
- package/dist/gateway/index.d.ts.map +1 -1
- package/dist/gateway/index.js +5 -4
- package/dist/gateway/index.js.map +1 -1
- package/dist/gateway/mobile-commands.d.ts +1 -0
- package/dist/gateway/mobile-commands.d.ts.map +1 -1
- package/dist/gateway/mobile-commands.js +64 -22
- package/dist/gateway/mobile-commands.js.map +1 -1
- package/dist/gateway/presenter.d.ts +12 -2
- package/dist/gateway/presenter.d.ts.map +1 -1
- package/dist/gateway/presenter.js +74 -39
- package/dist/gateway/presenter.js.map +1 -1
- package/dist/gateway/router.d.ts +2 -2
- package/dist/gateway/router.d.ts.map +1 -1
- package/dist/gateway/router.js +22 -9
- package/dist/gateway/router.js.map +1 -1
- package/dist/gateway/service.d.ts +2 -0
- package/dist/gateway/service.d.ts.map +1 -1
- package/dist/gateway/service.js +153 -0
- package/dist/gateway/service.js.map +1 -1
- package/dist/gateway/setup.d.ts.map +1 -1
- package/dist/gateway/setup.js +6 -4
- package/dist/gateway/setup.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +86 -33
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +6 -4
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/copyable-text.d.ts.map +1 -1
- package/dist/modes/interactive/components/copyable-text.js +3 -2
- package/dist/modes/interactive/components/copyable-text.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +1 -1
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +20 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +2 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +104 -109
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/smooth-streaming.d.ts.map +1 -1
- package/dist/modes/interactive/smooth-streaming.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +9 -1
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +2 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/node-runtime/adapter-247RTYLS.js +16 -0
- package/dist/node-runtime/agent-session-services-KDMSPQDY.js +53 -0
- package/dist/node-runtime/{brave-UWDA3I22.js → brave-2AFFAXNN.js} +1 -1
- package/dist/node-runtime/{builtin-extensions-ZLAX7TUH.js → builtin-extensions-OX6KELNX.js} +9 -7
- package/dist/node-runtime/{chunk-QH6YL7VK.js → chunk-252ZVPPF.js} +3 -3
- package/dist/node-runtime/{chunk-PCEW76PM.js → chunk-2OIPYKLZ.js} +6 -6
- package/dist/node-runtime/{chunk-XBWPBZBN.js → chunk-2SWW7KMW.js} +1 -1
- package/dist/node-runtime/{chunk-UQUCFAJ3.js → chunk-2VIW3IMF.js} +40 -7
- package/dist/node-runtime/{chunk-UOEDI7RP.js → chunk-4KNKQGHM.js} +2 -2
- package/dist/node-runtime/{chunk-FQMM2EZ2.js → chunk-64XTQNLA.js} +29 -7
- package/dist/node-runtime/{chunk-NRKGMJYU.js → chunk-6O3IW3IA.js} +2 -2
- package/dist/node-runtime/{chunk-5ZQXRPMC.js → chunk-6ZZHGUSA.js} +2 -2
- package/dist/node-runtime/chunk-A2WO6WIN.js +1197 -0
- package/dist/node-runtime/{chunk-ZXSGTGJ6.js → chunk-APVM5NEU.js} +169 -148
- package/dist/node-runtime/{chunk-RC7DMV45.js → chunk-AYHH7YSD.js} +205 -144
- package/dist/node-runtime/{chunk-LWYIVUGV.js → chunk-B2IBAXNX.js} +48 -31
- package/dist/node-runtime/{chunk-M3LZLQW2.js → chunk-BDRGN3L2.js} +1 -0
- package/dist/node-runtime/{chunk-GJ2RDBRL.js → chunk-BYC6RKCN.js} +4 -2
- package/dist/node-runtime/{chunk-KWIYUUZK.js → chunk-C3P6Q3B2.js} +469 -283
- package/dist/node-runtime/{chunk-YCUZEGJG.js → chunk-DQSCFU7R.js} +17 -8
- package/dist/node-runtime/chunk-EBLAZVSA.js +4170 -0
- package/dist/node-runtime/{chunk-2KIPT4HJ.js → chunk-EPR2F3GU.js} +68 -20
- package/dist/node-runtime/{chunk-CSFI6YXL.js → chunk-ES6PBSIE.js} +1 -1
- package/dist/node-runtime/{chunk-IF24A3FH.js → chunk-EVM653DD.js} +4 -4
- package/dist/node-runtime/{chunk-HTFRRDSF.js → chunk-F2SMQ6ES.js} +3 -2
- package/dist/node-runtime/chunk-F2V2F4ZG.js +114 -0
- package/dist/node-runtime/chunk-FE3WZI7F.js +290 -0
- package/dist/node-runtime/{chunk-GYIXXQAO.js → chunk-FIRA54AC.js} +2 -5
- package/dist/node-runtime/{chunk-6VYZ5UFP.js → chunk-FLGEEH27.js} +1 -1
- package/dist/node-runtime/{chunk-5EFIU3OM.js → chunk-FTKEZL27.js} +1 -1
- package/dist/node-runtime/chunk-FY4A63RK.js +73 -0
- package/dist/node-runtime/chunk-FYIFPFXE.js +98 -0
- package/dist/node-runtime/{chunk-HMBGROQK.js → chunk-GLDXBBL6.js} +3 -3
- package/dist/node-runtime/{chunk-KWA4OC2J.js → chunk-H6YBCWKG.js} +1 -1
- package/dist/node-runtime/{chunk-2MI5OPMN.js → chunk-HNNHHJAB.js} +68 -50
- package/dist/node-runtime/{chunk-6XL67VVY.js → chunk-HUD2RFJW.js} +17 -2
- package/dist/node-runtime/{chunk-I54LGHWM.js → chunk-I2H5QMWW.js} +3 -3
- package/dist/node-runtime/chunk-IAZSK7KK.js +108 -0
- package/dist/node-runtime/{chunk-2HHLJWGD.js → chunk-IHHTWSXN.js} +9 -9
- package/dist/node-runtime/{chunk-DAPBPCBP.js → chunk-IPP5BIV5.js} +25 -3
- package/dist/node-runtime/{chunk-QFWG2RVL.js → chunk-IXG6F4NT.js} +11 -0
- package/dist/node-runtime/{chunk-RDDAZOMU.js → chunk-JL4HYQXK.js} +1 -1
- package/dist/node-runtime/{chunk-CDVHZOOK.js → chunk-JQYNHAKX.js} +1 -1
- package/dist/node-runtime/{chunk-WF7PGWRZ.js → chunk-JWEVT363.js} +37 -28
- package/dist/node-runtime/{chunk-2HMIRK7W.js → chunk-LHV3V67B.js} +5 -5
- package/dist/node-runtime/{chunk-UAEOTO52.js → chunk-MNQXDFPV.js} +6 -2
- package/dist/node-runtime/{chunk-IJIFHRTB.js → chunk-MQPKUHRN.js} +165 -85
- package/dist/node-runtime/{chunk-MPKSOJBT.js → chunk-NHATCSOI.js} +4 -7
- package/dist/node-runtime/{chunk-RMQZU2YU.js → chunk-NNNR3QIY.js} +1 -1
- package/dist/node-runtime/{chunk-RWTKOC3B.js → chunk-QBTJG3UM.js} +1 -1
- package/dist/node-runtime/{chunk-E4D3IGP2.js → chunk-QNVMKNNN.js} +20 -17
- package/dist/node-runtime/{chunk-GS42T6MX.js → chunk-QW3AAHWN.js} +1 -1
- package/dist/node-runtime/{chunk-7S3T6YEA.js → chunk-R4WSB2MQ.js} +5 -5
- package/dist/node-runtime/{chunk-B4HP6ZWM.js → chunk-RHCGYWO7.js} +1 -1
- package/dist/node-runtime/{chunk-3XPLBUEM.js → chunk-RLGY2QIL.js} +49 -59
- package/dist/node-runtime/{chunk-KKUTQQV7.js → chunk-RYRGL7P4.js} +1 -1
- package/dist/node-runtime/{chunk-AD6VXAO7.js → chunk-TCT6PCUR.js} +47 -115
- package/dist/node-runtime/chunk-U5F4IC7R.js +53 -0
- package/dist/node-runtime/{chunk-OCVIXVTZ.js → chunk-UBWW2PID.js} +13 -2
- package/dist/node-runtime/{chunk-HFVZUPFJ.js → chunk-UNUZICC4.js} +3 -3
- package/dist/node-runtime/{chunk-LQP3RB67.js → chunk-UYRKUKFE.js} +1 -1
- package/dist/node-runtime/{chunk-DSIKTUPW.js → chunk-VSUEAI7O.js} +2993 -3820
- package/dist/node-runtime/{chunk-NAY6UUQZ.js → chunk-WDIVLMOH.js} +1 -1
- package/dist/node-runtime/{chunk-E24EO34J.js → chunk-WPXUR3HE.js} +1 -1
- package/dist/node-runtime/{chunk-SLVOAQOY.js → chunk-WXYNALHD.js} +113 -1
- package/dist/node-runtime/{chunk-KJ6DWS3K.js → chunk-XEOCUEUJ.js} +121 -60
- package/dist/node-runtime/chunk-YD3IZAZ7.js +47 -0
- package/dist/node-runtime/chunk-YSB6URMT.js +41 -0
- package/dist/node-runtime/{chunk-VQFSUJJG.js → chunk-ZDJUR45D.js} +430 -129
- package/dist/node-runtime/{chunk-YDO2F2IA.js → chunk-ZEVFBFNF.js} +95 -142
- package/dist/node-runtime/chunk-ZIQUS5QO.js +180 -0
- package/dist/node-runtime/cli-runtime.js +4 -4
- package/dist/node-runtime/{command-6WDOYKS6.js → command-3HMSY6W2.js} +5 -5
- package/dist/node-runtime/{commands-NZLSOHPE.js → commands-D6A6H4TS.js} +11 -16
- package/dist/node-runtime/commands-OCSSEEWJ.js +37 -0
- package/dist/node-runtime/{config-QDD5PUE2.js → config-CU7M7BTK.js} +1 -1
- package/dist/node-runtime/{config-D4QUPAHX.js → config-DS7XLMEM.js} +2 -2
- package/dist/node-runtime/{direct-tool-executor-77GW4F5P.js → direct-tool-executor-2QJXVQD2.js} +8 -10
- package/dist/node-runtime/{exa-LL64QZR2.js → exa-6VBZNPGE.js} +1 -1
- package/dist/node-runtime/{export-html-VM4J2MNR.js → export-html-BRWF5AHI.js} +4 -4
- package/dist/node-runtime/{extension-input-E7BJZ35H.js → extension-input-VBBMX7YV.js} +5 -5
- package/dist/node-runtime/{extension-selector-WU42XDTU.js → extension-selector-T5AOG5XB.js} +5 -5
- package/dist/node-runtime/{extract-EQJE7FZZ.js → extract-BFX2N35A.js} +3 -3
- package/dist/node-runtime/{gateway-INAYBF4Q.js → gateway-6623C2U3.js} +61 -53
- package/dist/node-runtime/{gemini-search-35OCRFLN.js → gemini-search-C66QHDT6.js} +2 -2
- package/dist/node-runtime/{gemini-url-context-UQY3PHHW.js → gemini-url-context-T7DEK73R.js} +3 -3
- package/dist/node-runtime/{github-extract-F64RZOEA.js → github-extract-HOGE3D6F.js} +107 -38
- package/dist/node-runtime/{goal-NJEE5CTU.js → goal-AIHEDUYA.js} +5 -5
- package/dist/node-runtime/index.js +54 -48
- package/dist/node-runtime/{init-HS6NQXSK.js → init-JBQJIPYI.js} +3 -4
- package/dist/node-runtime/{install-cli-KL4UDDAD.js → install-cli-INGHIVBY.js} +30 -25
- package/dist/node-runtime/interactive-mode-FM5DNUSW.js +74 -0
- package/dist/node-runtime/{interactive-view-NGFAMHPW.js → interactive-view-K33PM4OS.js} +8 -8
- package/dist/node-runtime/{lsp-manager-3ASUSO4T.js → lsp-manager-S554V5HR.js} +240 -155
- package/dist/node-runtime/{lunr-browser-IR7TL3J7.js → lunr-browser-H4FDOR3C.js} +7 -7
- package/dist/node-runtime/lunr-computer-use-VDP2QNRQ.js +158 -0
- package/dist/node-runtime/{lunr-cron-LWIZJM2N.js → lunr-cron-LKVA5CZZ.js} +94 -79
- package/dist/node-runtime/main.js +42 -39
- package/dist/node-runtime/{mobile-commands-J7OJEKFO.js → mobile-commands-XT3NQXLD.js} +13 -12
- package/dist/node-runtime/{model-runtime-OO5HFLWE.js → model-runtime-MZ2JMDV4.js} +4 -4
- package/dist/node-runtime/{openai-search-B3MSNCQA.js → openai-search-K72LJDYN.js} +1 -1
- package/dist/node-runtime/{package-manager-cli-VYZM5WHN.js → package-manager-cli-CYM262SI.js} +20 -19
- package/dist/node-runtime/{parallel-AI2MNSCU.js → parallel-X724NCNU.js} +1 -1
- package/dist/node-runtime/{perplexity-QVJW3I35.js → perplexity-RDHQHVMK.js} +2 -2
- package/dist/node-runtime/{pi-intercom-QM53RLTS.js → pi-intercom-NHHEPBMI.js} +2 -2
- package/dist/node-runtime/{pi-mcp-adapter-5UKBZP44.js → pi-mcp-adapter-PP3GQJQ2.js} +98 -94
- package/dist/node-runtime/{pi-ollama-cloud-2F3Y2QNM.js → pi-ollama-cloud-4MNWIMFN.js} +11 -24
- package/dist/node-runtime/{pi-prompt-template-model-QWTCGLJU.js → pi-prompt-template-model-FTGELLS5.js} +32 -36
- package/dist/node-runtime/{pi-subagents-DNY7EAIG.js → pi-subagents-LT3CTO4E.js} +114 -116
- package/dist/node-runtime/{pi-web-access-WTGMNZ32.js → pi-web-access-Z3LP246C.js} +144 -108
- package/dist/node-runtime/{print-mode-XSFM26EL.js → print-mode-2XHN5SUA.js} +4 -3
- package/dist/node-runtime/{process-registry-4FAKZQOL.js → process-registry-Q4QWIU33.js} +3 -3
- package/dist/node-runtime/{proxy-modes-LGEUYD7R.js → proxy-modes-VEGC6QG5.js} +9 -13
- package/dist/node-runtime/rpc-entry.js +42 -39
- package/dist/node-runtime/{rpc-mode-O3XV4SID.js → rpc-mode-32DHJPEJ.js} +4 -4
- package/dist/node-runtime/{runtime-4VA6JKNF.js → runtime-EDUUGAQD.js} +56 -46
- package/dist/node-runtime/runtime-UGXM4NPQ.js +21 -0
- package/dist/node-runtime/{runtime-bridges-VRDDR73P.js → runtime-bridges-DNKMNJCF.js} +8 -7
- package/dist/node-runtime/{service-MDQIPQ26.js → service-IHLGFLBT.js} +6 -4
- package/dist/node-runtime/{session-handoff-GWARVEWT.js → session-handoff-LNSPDTKY.js} +4 -4
- package/dist/node-runtime/{session-manager-JB5J6XBN.js → session-manager-YIFIAVGC.js} +3 -3
- package/dist/node-runtime/{session-selector-GIM4DHQ2.js → session-selector-I73U3EIO.js} +7 -7
- package/dist/node-runtime/{settings-manager-J4SPQPDJ.js → settings-manager-P2TKGYTR.js} +6 -5
- package/dist/node-runtime/{setup-JBKOLJ6F.js → setup-H7CCELIL.js} +15 -1
- package/dist/node-runtime/{setup-CQ2NLVK5.js → setup-OLQ4GXWS.js} +22 -21
- package/dist/node-runtime/{src-IVPNZ2BX.js → src-6RV4PXKJ.js} +64 -36
- package/dist/node-runtime/{subagent-executor-KZZQGAKV.js → subagent-executor-Q5F7DBVM.js} +141 -62
- package/dist/node-runtime/{tavily-WEZFVFP7.js → tavily-KZBFYQB6.js} +1 -1
- package/dist/node-runtime/{theme-UOO5RVFN.js → theme-YLVZKKZD.js} +2 -2
- package/dist/node-runtime/{trust-manager-MMISNCYO.js → trust-manager-ZCU76D23.js} +2 -2
- package/dist/node-runtime/{update-cli-GTFJC7XK.js → update-cli-F3XXJANQ.js} +7 -6
- package/dist/node-runtime/{usage-service-LFB2SWYV.js → usage-service-CPAGBED5.js} +1 -1
- package/dist/node-runtime/{video-extract-OOZHR7SU.js → video-extract-UPKYIBW3.js} +3 -3
- package/dist/node-runtime/workflow-ICDI4N3J.js +767 -0
- package/dist/node-runtime/{youtube-extract-FNPAUNHU.js → youtube-extract-77NT7FWH.js} +4 -4
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js +25 -10
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/image-resize-core.d.ts +2 -0
- package/dist/utils/image-resize-core.d.ts.map +1 -1
- package/dist/utils/image-resize-core.js +12 -0
- package/dist/utils/image-resize-core.js.map +1 -1
- package/dist/utils/paths.d.ts +4 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +33 -2
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/sanitize-terminal-text.d.ts +7 -0
- package/dist/utils/sanitize-terminal-text.d.ts.map +1 -0
- package/dist/utils/sanitize-terminal-text.js +67 -0
- package/dist/utils/sanitize-terminal-text.js.map +1 -0
- package/docs/browser.md +1 -1
- package/docs/computer-use.md +362 -0
- package/docs/custom-provider.md +3 -3
- package/docs/extensions.md +8 -4
- package/docs/features.md +22 -12
- package/docs/keybindings.md +1 -1
- package/docs/models.md +5 -5
- package/docs/packages.md +1 -1
- package/docs/providers.md +2 -2
- package/docs/rpc.md +7 -7
- package/docs/security.md +10 -5
- package/docs/sessions.md +2 -2
- package/docs/skills.md +1 -1
- package/docs/terminal-setup.md +7 -7
- package/docs/themes.md +1 -1
- package/docs/usage.md +1 -1
- package/examples/extensions/auto-commit-on-exit.ts +1 -1
- package/examples/extensions/bash-spawn-hook.ts +1 -1
- package/examples/extensions/built-in-tool-renderer.ts +1 -1
- package/examples/extensions/claude-rules.ts +1 -1
- package/examples/extensions/commands.ts +1 -1
- package/examples/extensions/custom-compaction.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/index.ts +3 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/doom-overlay/index.ts +1 -1
- package/examples/extensions/git-merge-and-resolve.ts +2 -2
- package/examples/extensions/gondolin/index.ts +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/hidden-thinking-label.ts +1 -1
- package/examples/extensions/inline-bash.ts +2 -2
- package/examples/extensions/input-transform-streaming.ts +2 -2
- package/examples/extensions/input-transform.ts +2 -2
- package/examples/extensions/interactive-shell.ts +1 -1
- package/examples/extensions/kimi-deferred-tools.ts +1 -1
- package/examples/extensions/mac-system-theme.ts +1 -1
- package/examples/extensions/minimal-mode.ts +1 -1
- package/examples/extensions/modal-editor.ts +1 -1
- package/examples/extensions/model-status.ts +1 -1
- package/examples/extensions/notify.ts +3 -3
- package/examples/extensions/overlay-qa-tests.ts +1 -1
- package/examples/extensions/overlay-test.ts +1 -1
- package/examples/extensions/pirate.ts +1 -1
- package/examples/extensions/preset.ts +3 -3
- package/examples/extensions/project-trust.ts +4 -4
- package/examples/extensions/prompt-customizer.ts +1 -1
- package/examples/extensions/rainbow-editor.ts +1 -1
- package/examples/extensions/rpc-demo.ts +1 -1
- package/examples/extensions/sandbox/index.ts +7 -7
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/shutdown-command.ts +5 -5
- package/examples/extensions/ssh.ts +2 -2
- package/examples/extensions/subagent/README.md +3 -3
- package/examples/extensions/subagent/index.ts +2 -2
- package/examples/extensions/titlebar-spinner.ts +1 -1
- package/examples/extensions/tool-override.ts +1 -1
- package/examples/extensions/tools.ts +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/extensions/working-indicator.ts +1 -1
- package/examples/extensions/working-message-test.ts +1 -1
- package/examples/sdk/01-minimal.ts +1 -1
- package/examples/sdk/03-custom-prompt.ts +1 -1
- package/examples/sdk/04-skills.ts +1 -1
- package/examples/sdk/06-extensions.ts +2 -2
- package/examples/sdk/08-prompt-templates.ts +1 -1
- package/install-lock/package-lock.json +3841 -0
- package/install-lock/package.json +18 -0
- package/native/computer-use/LICENSE.md +21 -0
- package/npm-shrinkwrap.json +3858 -0
- package/package.json +15 -9
- package/dist/modes/interactive/components/exit-card.d.ts +0 -22
- package/dist/modes/interactive/components/exit-card.d.ts.map +0 -1
- package/dist/modes/interactive/components/exit-card.js +0 -69
- package/dist/modes/interactive/components/exit-card.js.map +0 -1
- package/dist/node-runtime/agent-session-services-YXXFCP5J.js +0 -49
- package/dist/node-runtime/chunk-4HXHDDCF.js +0 -16
- package/dist/node-runtime/chunk-4TLO4PO2.js +0 -3427
- package/dist/node-runtime/chunk-AUXVGBO4.js +0 -19
- package/dist/node-runtime/chunk-OVX6X377.js +0 -50
- package/dist/node-runtime/chunk-QTU6AKNJ.js +0 -773
- package/dist/node-runtime/chunk-TORR5XBV.js +0 -356
- package/dist/node-runtime/commands-QC6VUZJQ.js +0 -36
- package/dist/node-runtime/interactive-mode-Z5M7WYYZ.js +0 -72
- package/dist/node-runtime/mcp-auth-flow-QIXHW6QN.js +0 -32
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.js","sourceRoot":"","sources":["../../../src/core/computer-use/workflow.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport type { ImageContent, TextContent } from \"@ashx-j/lunr-ai\";\nimport { type ComputerDriver, DriverCallError, type DriverReply } from \"./adapter.ts\";\nimport { type ImageRegion, prepareComputerImage, screenshotDimensions } from \"./image.ts\";\nimport { DesktopLease } from \"./lease.ts\";\nimport { computerSchemas } from \"./schemas.ts\";\n\nexport function driverData(reply: DriverReply): Record<string, unknown> {\n\tif (\n\t\treply.structuredContent &&\n\t\ttypeof reply.structuredContent === \"object\" &&\n\t\t!Array.isArray(reply.structuredContent)\n\t)\n\t\treturn Object.fromEntries(Object.entries(reply.structuredContent));\n\tif (Array.isArray(reply.content))\n\t\tfor (const item of reply.content) {\n\t\t\tif (item.type !== \"text\" || typeof item.text !== \"string\") continue;\n\t\t\ttry {\n\t\t\t\tconst value: unknown = JSON.parse(item.text);\n\t\t\t\tif (value && typeof value === \"object\" && !Array.isArray(value))\n\t\t\t\t\treturn Object.fromEntries(Object.entries(value));\n\t\t\t} catch {}\n\t\t}\n\treturn {};\n}\n\nfunction plainLaunchReason(reply: DriverReply): string | undefined {\n\tif (reply.structuredContent || !Array.isArray(reply.content)) return undefined;\n\tconst text = reply.content.find((item) => item.type === \"text\")?.text;\n\tif (typeof text !== \"string\") return undefined;\n\tif (/^App name lookup for .+ is (?:temporarily unavailable|unavailable).+No app was launched;/s.test(text))\n\t\treturn \"app_lookup_unavailable\";\n\tif (/^App .+ was not found in shell:AppsFolder or by Windows PATH\\/association lookup:/s.test(text))\n\t\treturn \"app_not_found\";\n\tif (/^Launch of .+ timed out after 15s/s.test(text)) return \"launch_timeout_unknown\";\n\tif (/^(?:Failed to launch|Task error): /s.test(text)) return \"launch_native_error_unknown\";\n\treturn undefined;\n}\n\nexport function driverRefused(reply: DriverReply): boolean {\n\tconst data = driverData(reply);\n\tconst acknowledged =\n\t\tdata.activated === true || data.success === true || data.verified === true || data.effect === \"confirmed\";\n\tconst uncertain = [data.status, data.effect].some((value) => value === \"partial\" || value === \"unverifiable\");\n\treturn (\n\t\treply.isError === true ||\n\t\tplainLaunchReason(reply) !== undefined ||\n\t\t(data.refusal !== undefined && data.refusal !== null && data.refusal !== false) ||\n\t\t(data.error !== undefined && data.error !== null && data.error !== false) ||\n\t\tdata.effect === \"refused\" ||\n\t\tdata.status === \"refused\" ||\n\t\tdata.status === \"failed\" ||\n\t\tdata.success === false ||\n\t\t[\n\t\t\t\"window_target_mismatch\",\n\t\t\t\"window_target_not_found\",\n\t\t\t\"background_unavailable\",\n\t\t\t\"foreground_unavailable\",\n\t\t\t\"type_text_incomplete\",\n\t\t\t\"verification_failed\",\n\t\t].includes(String(data.code)) ||\n\t\t(data.status !== undefined &&\n\t\t\t!acknowledged &&\n\t\t\t!uncertain &&\n\t\t\t![\"ok\", \"success\", \"completed\"].includes(String(data.status))) ||\n\t\t(data.code !== undefined && data.code !== 0 && !acknowledged && !uncertain)\n\t);\n}\n\nfunction record(value: unknown): Record<string, unknown> {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value)\n\t\t? Object.fromEntries(Object.entries(value))\n\t\t: {};\n}\n\nfunction select(data: Record<string, unknown>, keys: readonly string[]): Record<string, string | number | boolean> {\n\tconst result: Record<string, string | number | boolean> = {};\n\tfor (const key of keys) {\n\t\tconst value = data[key];\n\t\tif ([\"name\", \"app_name\", \"title\"].includes(key) && typeof value === \"string\") result[key] = value.slice(0, 240);\n\t\telse if ([\"active\", \"running\", \"is_on_screen\", \"minimized\"].includes(key) && typeof value === \"boolean\")\n\t\t\tresult[key] = value;\n\t\telse if (\n\t\t\t[\"pid\", \"window_id\", \"x\", \"y\", \"width\", \"height\"].includes(key) &&\n\t\t\ttypeof value === \"number\" &&\n\t\t\tNumber.isSafeInteger(value)\n\t\t)\n\t\t\tresult[key] = value;\n\t}\n\treturn result;\n}\n\nfunction typingRecovery(data: Record<string, unknown>, text: unknown) {\n\tif (typeof text !== \"string\") return {};\n\tconst requested = data.requested_chars;\n\tconst delivered = data.delivered_chars;\n\tif (\n\t\ttypeof requested !== \"number\" ||\n\t\t!Number.isSafeInteger(requested) ||\n\t\trequested < 0 ||\n\t\trequested > 20000 ||\n\t\trequested !== Array.from(text).length\n\t)\n\t\treturn {};\n\tconst validDelivered =\n\t\ttypeof delivered === \"number\" && Number.isSafeInteger(delivered) && delivered >= 0 && delivered <= requested;\n\treturn {\n\t\trequested_chars: requested,\n\t\tdelivered_chars: validDelivered ? delivered : undefined,\n\t\tretryable:\n\t\t\tvalidDelivered && data.retry_from_character === delivered && typeof data.retryable === \"boolean\"\n\t\t\t\t? data.retryable\n\t\t\t\t: undefined,\n\t\tretry_from_character: validDelivered && data.retry_from_character === delivered ? delivered : undefined,\n\t};\n}\n\nconst nativeCodes = new Set([\n\t\"background_unavailable\",\n\t\"background_occluded\",\n\t\"background_uipi_blocked\",\n\t\"window_target_mismatch\",\n\t\"window_target_not_found\",\n\t\"type_text_incomplete\",\n\t\"foreground_unavailable\",\n\t\"foreground_rejected\",\n\t\"stale_target\",\n\t\"target_not_found\",\n\t\"verification_failed\",\n\t\"tool_invocation_failed\",\n]);\nfunction safeCode(value: unknown): string | undefined {\n\treturn typeof value === \"string\" && nativeCodes.has(value) ? value : undefined;\n}\nfunction nativeReason(reply: DriverReply): string {\n\tconst data = driverData(reply);\n\tconst code =\n\t\tsafeCode(data.code) ??\n\t\tsafeCode(record(data.refusal).code) ??\n\t\tsafeCode(record(data.error).code) ??\n\t\tsafeCode(data.refusal) ??\n\t\tsafeCode(data.error);\n\tif (code) return code;\n\tif (plainLaunchReason(reply)) return plainLaunchReason(reply)!;\n\treturn \"native_error_unknown\";\n}\ntype FailurePhase =\n\t| \"validation\"\n\t| \"adapter_preflight\"\n\t| \"native_request\"\n\t| \"native_result\"\n\t| \"observation_capture\"\n\t| \"post_action_capture\"\n\t| \"cleanup\";\ntype InputState = \"not_dispatched\" | \"dispatched\" | \"partial\" | \"uncertain\";\ntype NativeOutcome = {\n\tphase: FailurePhase;\n\tcode?: string;\n\tnative_code?: string;\n\tstatus?: string;\n\teffect?: string;\n\tverified?: boolean;\n\tsuccess?: boolean;\n\tactivated?: boolean;\n\tescalation?: \"foreground\";\n\tinput: InputState;\n\tapplicationEffect: \"unverified\";\n\trequested_chars?: number;\n\tdelivered_chars?: number;\n\tretryable?: boolean;\n\tretry_from_character?: number;\n};\nfunction outcome(reply: DriverReply, text?: unknown): NativeOutcome {\n\tconst data = driverData(reply);\n\tconst refused = driverRefused(reply);\n\tconst partial = data.effect === \"partial\" || data.status === \"partial\";\n\treturn {\n\t\tphase: refused || partial ? \"native_result\" : \"native_request\",\n\t\tcode: refused || partial ? nativeReason(reply) : undefined,\n\t\tnative_code: safeCode(data.code) ?? safeCode(record(data.refusal).code) ?? safeCode(record(data.error).code),\n\t\tstatus:\n\t\t\ttypeof data.status === \"string\" &&\n\t\t\t[\"ok\", \"success\", \"completed\", \"partial\", \"refused\", \"failed\"].includes(data.status)\n\t\t\t\t? data.status\n\t\t\t\t: undefined,\n\t\teffect:\n\t\t\ttypeof data.effect === \"string\" && [\"confirmed\", \"partial\", \"unverifiable\", \"refused\"].includes(data.effect)\n\t\t\t\t? data.effect\n\t\t\t\t: undefined,\n\t\tverified: typeof data.verified === \"boolean\" ? data.verified : undefined,\n\t\tsuccess: typeof data.success === \"boolean\" ? data.success : undefined,\n\t\tactivated: typeof data.activated === \"boolean\" ? data.activated : undefined,\n\t\tescalation: record(data.escalation).recommended === \"foreground\" ? \"foreground\" : undefined,\n\t\tinput:\n\t\t\tpartial && typingRecovery(data, text).delivered_chars !== undefined\n\t\t\t\t? \"partial\"\n\t\t\t\t: refused || partial\n\t\t\t\t\t? \"uncertain\"\n\t\t\t\t\t: \"dispatched\",\n\t\tapplicationEffect: \"unverified\",\n\t\t...typingRecovery(data, text),\n\t};\n}\n\nfunction abortable<T>(pending: Promise<T>, signal: AbortSignal): Promise<T> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst abort = () => {\n\t\t\tsignal.removeEventListener(\"abort\", abort);\n\t\t\treject(signal.reason ?? new Error(\"Computer operation cancelled.\"));\n\t\t};\n\t\tsignal.addEventListener(\"abort\", abort, { once: true });\n\t\tpending.then(\n\t\t\t(value) => {\n\t\t\t\tsignal.removeEventListener(\"abort\", abort);\n\t\t\t\tresolve(value);\n\t\t\t},\n\t\t\t(error) => {\n\t\t\t\tsignal.removeEventListener(\"abort\", abort);\n\t\t\t\treject(error);\n\t\t\t},\n\t\t);\n\t\tif (signal.aborted) abort();\n\t});\n}\n\nconst freshActionGuidance =\n\t\"Get a fresh capture of the exact target before any next action, including window focus. Copy its token exactly. No input was sent by this call; earlier calls may have had an effect.\";\n\nclass CaptureError extends Error {\n\treadonly code: string;\n\tconstructor(code: string) {\n\t\tsuper(code);\n\t\tthis.code = code;\n\t}\n}\n\nclass ObservationError extends Error {\n\treadonly code: string;\n\tconstructor(code: string, message: string) {\n\t\tsuper(`Stale observation. ${message}`);\n\t\tthis.code = code;\n\t}\n}\n\ntype Target = { desktop: true } | { pid: number; window_id: number; desktop?: false };\ntype PreparedImage = Awaited<ReturnType<typeof prepareComputerImage>>;\ntype Observation = PreparedImage & {\n\ttoken: string;\n\ttarget: Target;\n\ttime: number;\n\tfingerprint: string;\n\tgeometry: string;\n};\ntype WorkflowState = \"ready\" | \"stopped\" | \"cleanup_unconfirmed\";\ntype Result = {\n\tcontent: (ImageContent | TextContent)[];\n\tdetails: { observation?: string; computer: { failed: boolean; workflow: WorkflowState } };\n\tisError: boolean;\n};\n\nfunction targetFrom(input: Record<string, unknown>): Target {\n\tif (input.desktop === true) {\n\t\tif (input.pid !== undefined || input.window_id !== undefined)\n\t\t\tthrow new Error(\"Desktop target cannot include pid/window_id.\");\n\t\treturn { desktop: true };\n\t}\n\tif (\n\t\ttypeof input.pid !== \"number\" ||\n\t\t!Number.isInteger(input.pid) ||\n\t\tinput.pid < 1 ||\n\t\ttypeof input.window_id !== \"number\" ||\n\t\t!Number.isInteger(input.window_id) ||\n\t\tinput.window_id < 1\n\t)\n\t\tthrow new Error(\"Window target requires positive integer pid and window_id.\");\n\treturn { pid: input.pid, window_id: input.window_id };\n}\n\nfunction sameTarget(a: Target, b: Target): boolean {\n\treturn a.desktop === true\n\t\t? b.desktop === true\n\t\t: b.desktop !== true && a.pid === b.pid && a.window_id === b.window_id;\n}\n\nexport class ComputerWorkflow {\n\tprivate observation?: Observation;\n\tprivate lastCapture?: { fingerprint: string; target: Target; repeats: number };\n\tprivate lastAction?: { signature: string; fingerprint: string; unchanged: boolean };\n\tprivate readonly abort = new AbortController();\n\tprivate closing?: Promise<void>;\n\tprivate readonly driver: ComputerDriver;\n\tprivate readonly lease: DesktopLease;\n\tconstructor(driver: ComputerDriver, lease = new DesktopLease()) {\n\t\tthis.driver = driver;\n\t\tthis.lease = lease;\n\t\tthis.driver.setProcessObserver?.((pid) => this.lease.trackProcess(pid));\n\t}\n\n\tprivate fresh(input: Record<string, unknown>, previous?: Observation): Observation {\n\t\tif (!previous) throw new ObservationError(\"observation_unavailable\", \"No active observation is available.\");\n\t\tif (previous.token !== input.observation)\n\t\t\tthrow new ObservationError(\"observation_mismatch\", \"Token does not match the active observation.\");\n\t\tif (!sameTarget(previous.target, targetFrom(input)))\n\t\t\tthrow new ObservationError(\"observation_target_mismatch\", \"Token belongs to a different target.\");\n\t\tif (Date.now() - previous.time > 30000)\n\t\t\tthrow new ObservationError(\"observation_expired\", \"The active observation is older than 30 seconds.\");\n\t\treturn previous;\n\t}\n\n\tprivate async capture(\n\t\ttarget: Target,\n\t\tsignal: AbortSignal,\n\t\tprevious?: Observation,\n\t\tcrop?: ImageRegion,\n\t): Promise<Observation> {\n\t\tconst time = Date.now();\n\t\tconst reply = await abortable(\n\t\t\tthis.driver.call(\n\t\t\t\ttarget.desktop ? \"get_desktop_state\" : \"get_window_state\",\n\t\t\t\ttarget.desktop\n\t\t\t\t\t? {}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tpid: target.pid,\n\t\t\t\t\t\t\twindow_id: target.window_id,\n\t\t\t\t\t\t\tinclude_accessibility_tree: false,\n\t\t\t\t\t\t\tinclude_screenshot: true,\n\t\t\t\t\t\t\tmax_dimension: 2560,\n\t\t\t\t\t\t},\n\t\t\t\tsignal,\n\t\t\t),\n\t\t\tsignal,\n\t\t);\n\t\tif (driverRefused(reply)) throw new CaptureError(nativeReason(reply));\n\t\tconst data = driverData(reply);\n\t\tconst images = Array.isArray(reply.content) ? reply.content.filter((item) => item.type === \"image\") : [];\n\t\tif (images.length !== 1 || typeof images[0].data !== \"string\" || typeof images[0].mimeType !== \"string\")\n\t\t\tthrow new CaptureError(\"screenshot_unavailable\");\n\t\tconst image: ImageContent = { type: \"image\", data: images[0].data, mimeType: images[0].mimeType };\n\t\tlet dimensions: { width: number; height: number };\n\t\ttry {\n\t\t\tdimensions = screenshotDimensions(image);\n\t\t} catch {\n\t\t\tthrow new CaptureError(\"image_decode_failed\");\n\t\t}\n\t\tif (\n\t\t\tdata.screenshot_frame_valid === false ||\n\t\t\tdata.screenshot_error != null ||\n\t\t\tdimensions.width !== data.screenshot_width ||\n\t\t\tdimensions.height !== data.screenshot_height\n\t\t)\n\t\t\tthrow new CaptureError(\"image_frame_invalid\");\n\t\tconst geometry = JSON.stringify(select(record(data.window_bounds), [\"x\", \"y\", \"width\", \"height\"]));\n\t\tif (\n\t\t\tcrop &&\n\t\t\tprevious &&\n\t\t\t(previous.sourceWidth !== dimensions.width ||\n\t\t\t\tprevious.sourceHeight !== dimensions.height ||\n\t\t\t\tprevious.geometry !== geometry)\n\t\t)\n\t\t\tthrow new CaptureError(\"target_geometry_changed\");\n\t\tlet prepared: PreparedImage;\n\t\ttry {\n\t\t\tprepared = await abortable(prepareComputerImage(image, crop), signal);\n\t\t} catch (error) {\n\t\t\tif (signal.aborted) throw error;\n\t\t\tthrow new CaptureError(\"image_decode_failed\");\n\t\t}\n\t\tsignal.throwIfAborted();\n\t\treturn { ...prepared, token: randomUUID(), target, time, fingerprint: prepared.fingerprint, geometry };\n\t}\n\n\tprivate imageResult(observation: Observation, extra: Record<string, unknown> = {}): Result {\n\t\tthis.observation = observation;\n\t\tconst { width, height, region, sourceWidth, sourceHeight, scaleX, scaleY, target, token } = observation;\n\t\tconst failed = extra.failed === true;\n\t\treturn {\n\t\t\tcontent: [\n\t\t\t\t{\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: JSON.stringify({\n\t\t\t\t\t\t...extra,\n\t\t\t\t\t\tobservation: token,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tcaptured_at: observation.time,\n\t\t\t\t\t\texpires_at: observation.time + 30000,\n\t\t\t\t\t\timage: { width, height },\n\t\t\t\t\t\tmapping: { sourceWidth, sourceHeight, ...region, scaleX, scaleY },\n\t\t\t\t\t\tcoordinates: \"Use returned-image pixels; mapping is applied automatically.\",\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t\tobservation.image,\n\t\t\t],\n\t\t\tdetails: { observation: token, computer: { failed, workflow: \"ready\" } },\n\t\t\tisError: failed,\n\t\t};\n\t}\n\n\tprivate crop(input: Record<string, unknown>, previous: Observation): ImageRegion {\n\t\tconst crop = record(input.crop);\n\t\tconst { x, y, width, height } = crop;\n\t\tif (\n\t\t\ttypeof x !== \"number\" ||\n\t\t\ttypeof y !== \"number\" ||\n\t\t\ttypeof width !== \"number\" ||\n\t\t\ttypeof height !== \"number\" ||\n\t\t\t![x, y, width, height].every(Number.isFinite) ||\n\t\t\tx < 0 ||\n\t\t\ty < 0 ||\n\t\t\twidth <= 0 ||\n\t\t\theight <= 0 ||\n\t\t\tx + width > previous.width ||\n\t\t\ty + height > previous.height ||\n\t\t\tObject.keys(crop).some((key) => ![\"x\", \"y\", \"width\", \"height\"].includes(key))\n\t\t)\n\t\t\tthrow new Error(\"Crop must fit the latest returned image.\");\n\t\tconst left = Math.floor(previous.region.x + x * previous.scaleX);\n\t\tconst top = Math.floor(previous.region.y + y * previous.scaleY);\n\t\tconst right = Math.min(previous.sourceWidth, Math.ceil(previous.region.x + (x + width) * previous.scaleX));\n\t\tconst bottom = Math.min(previous.sourceHeight, Math.ceil(previous.region.y + (y + height) * previous.scaleY));\n\t\treturn { x: left, y: top, width: right - left, height: bottom - top };\n\t}\n\n\tprivate action(name: string, input: Record<string, unknown>, previous: Observation) {\n\t\tconst args: Record<string, unknown> = previous.target.desktop\n\t\t\t? { scope: \"desktop\" }\n\t\t\t: { pid: previous.target.pid, window_id: previous.target.window_id };\n\t\tif (previous.target.desktop && input.foreground !== true)\n\t\t\tthrow new Error(\"Desktop input requires foreground=true.\");\n\t\tif (name !== \"computer_window\" && name !== \"computer_hover\")\n\t\t\targs.delivery_mode = input.foreground === true ? \"foreground\" : \"background\";\n\t\tfor (const key of [\"x\", \"y\", \"from_x\", \"from_y\", \"to_x\", \"to_y\"]) {\n\t\t\tif (name === \"computer_window\") break;\n\t\t\tconst value = input[key];\n\t\t\tif (value === undefined) continue;\n\t\t\tconst horizontal = key.endsWith(\"x\");\n\t\t\tif (\n\t\t\t\ttypeof value !== \"number\" ||\n\t\t\t\t!Number.isFinite(value) ||\n\t\t\t\tvalue < 0 ||\n\t\t\t\tvalue >= (horizontal ? previous.width : previous.height)\n\t\t\t)\n\t\t\t\tthrow new Error(\"Coordinate outside the observed image.\");\n\t\t\targs[key] =\n\t\t\t\t(horizontal ? previous.region.x : previous.region.y) +\n\t\t\t\tvalue * (horizontal ? previous.scaleX : previous.scaleY);\n\t\t}\n\t\tif ((input.x === undefined) !== (input.y === undefined)) throw new Error(\"Provide a complete x/y pair.\");\n\t\tif (previous.target.desktop && [\"computer_key\", \"computer_text\"].includes(name) && input.x !== undefined)\n\t\t\tthrow new Error(\n\t\t\t\t\"Desktop keyboard input uses the observed focused field. Change focus with a separate grounded click.\",\n\t\t\t);\n\t\tlet operation: string;\n\t\tswitch (name) {\n\t\t\tcase \"computer_hover\":\n\t\t\t\tif (\n\t\t\t\t\tprocess.platform !== \"win32\" ||\n\t\t\t\t\t!previous.target.desktop ||\n\t\t\t\t\tinput.desktop !== true ||\n\t\t\t\t\tinput.foreground !== true ||\n\t\t\t\t\tinput.x === undefined ||\n\t\t\t\t\tinput.y === undefined\n\t\t\t\t)\n\t\t\t\t\tthrow new Error(\"Hover requires a Windows foreground desktop image and x/y coordinates.\");\n\t\t\t\toperation = \"move_cursor\";\n\t\t\t\tbreak;\n\t\t\tcase \"computer_click\":\n\t\t\tcase \"computer_scroll\":\n\t\t\t\tif (input.x === undefined || input.y === undefined)\n\t\t\t\t\tthrow new Error(\"This action requires x/y image coordinates.\");\n\t\t\t\toperation = name === \"computer_click\" ? \"click\" : \"scroll\";\n\t\t\t\tfor (const key of name === \"computer_click\"\n\t\t\t\t\t? [\"button\", \"count\", \"modifier\"]\n\t\t\t\t\t: [\"direction\", \"amount\", \"by\"])\n\t\t\t\t\tif (input[key] !== undefined) args[key] = input[key];\n\t\t\t\tbreak;\n\t\t\tcase \"computer_drag\":\n\t\t\t\tif (![\"from_x\", \"from_y\", \"to_x\", \"to_y\"].every((key) => typeof args[key] === \"number\"))\n\t\t\t\t\tthrow new Error(\"Drag requires both endpoints.\");\n\t\t\t\toperation = \"drag\";\n\t\t\t\tbreak;\n\t\t\tcase \"computer_key\": {\n\t\t\t\tif ((input.key === undefined) === (input.keys === undefined)) throw new Error(\"Provide key OR keys.\");\n\t\t\t\tconst keys: readonly unknown[] | undefined = Array.isArray(input.keys) ? input.keys : undefined;\n\t\t\t\tconst last = keys?.at(-1);\n\t\t\t\tconst modifiers = new Set([\"ctrl\", \"control\", \"shift\", \"alt\", \"win\", \"windows\", \"cmd\", \"command\"]);\n\t\t\t\tconst foregroundShortcut =\n\t\t\t\t\tprocess.platform === \"win32\" &&\n\t\t\t\t\tinput.foreground === true &&\n\t\t\t\t\tinput.x === undefined &&\n\t\t\t\t\tkeys !== undefined &&\n\t\t\t\t\tkeys.length >= 2 &&\n\t\t\t\t\tkeys.slice(0, -1).every((key) => typeof key === \"string\" && modifiers.has(key.toLowerCase())) &&\n\t\t\t\t\ttypeof last === \"string\" &&\n\t\t\t\t\t!modifiers.has(last.toLowerCase());\n\t\t\t\t// Pinned Windows hotkey routes XAML through UIA before honoring foreground; press_key honors SendInput.\n\t\t\t\toperation = input.keys === undefined || foregroundShortcut ? \"press_key\" : \"hotkey\";\n\t\t\t\tif (foregroundShortcut) {\n\t\t\t\t\targs.key = last;\n\t\t\t\t\targs.modifiers = keys.slice(0, -1);\n\t\t\t\t} else args[input.keys === undefined ? \"key\" : \"keys\"] = input.keys ?? input.key;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"computer_text\":\n\t\t\t\toperation = \"type_text\";\n\t\t\t\targs.text = input.text;\n\t\t\t\tbreak;\n\t\t\tcase \"computer_window\":\n\t\t\t\tif (previous.target.desktop) throw new Error(\"Window management requires an exact window target.\");\n\t\t\t\tif (input.action === \"frame\") {\n\t\t\t\t\tfor (const key of [\"x\", \"y\", \"width\", \"height\"]) {\n\t\t\t\t\t\tconst value = input[key];\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\ttypeof value !== \"number\" ||\n\t\t\t\t\t\t\t!Number.isFinite(value) ||\n\t\t\t\t\t\t\t([\"width\", \"height\"].includes(key) && value <= 0)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\tthrow new Error(\"Frame requires valid x/y/width/height.\");\n\t\t\t\t\t\targs[key] = value;\n\t\t\t\t\t}\n\t\t\t\t\toperation = \"set_window_frame\";\n\t\t\t\t} else if (\n\t\t\t\t\tinput.action === \"focus\" &&\n\t\t\t\t\t[\"x\", \"y\", \"width\", \"height\"].every((key) => input[key] === undefined)\n\t\t\t\t)\n\t\t\t\t\toperation = \"bring_to_front\";\n\t\t\t\telse\n\t\t\t\t\tthrow new Error(\"Use frame or focus. Minimize/restore uses a fresh image click on the visible control.\");\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(\"Unknown computer action.\");\n\t\t}\n\t\treturn { operation, args };\n\t}\n\n\tasync execute(name: string, input: Record<string, unknown>, signal?: AbortSignal): Promise<Result> {\n\t\tconst combined = AbortSignal.any([\n\t\t\tthis.abort.signal,\n\t\t\tthis.lease.signal,\n\t\t\tAbortSignal.timeout(90000),\n\t\t\t...(signal ? [signal] : []),\n\t\t]);\n\t\tlet inputDispatched = false;\n\t\tlet failureCode = \"workflow_unavailable\";\n\t\tlet phase: FailurePhase = \"validation\";\n\t\tconst currentPhase = (): FailurePhase => phase;\n\t\tlet operationName = name;\n\t\tlet actionTarget: Target | undefined;\n\t\tlet actionOutcome: ReturnType<typeof outcome> | undefined;\n\t\ttry {\n\t\t\tconst result = await this.lease.run(async (): Promise<Result> => {\n\t\t\t\tfailureCode = \"invalid_arguments\";\n\t\t\t\tconst previous = this.observation;\n\t\t\t\tif (name !== \"computer_apps\") this.observation = undefined;\n\t\t\t\tif (!Object.hasOwn(computerSchemas, name)) throw new Error(\"Unknown computer operation.\");\n\t\t\t\tconst schema = computerSchemas[name as keyof typeof computerSchemas];\n\t\t\t\tif (Object.keys(input).some((key) => !Object.hasOwn(schema.properties, key)))\n\t\t\t\t\tthrow new Error(\"Unsupported computer argument. Use image coordinates only.\");\n\t\t\t\tif (name === \"computer_apps\" || name === \"computer_launch\") {\n\t\t\t\t\tconst operation =\n\t\t\t\t\t\tname === \"computer_launch\" ? \"launch_app\" : input.pid === undefined ? \"list_apps\" : \"list_windows\";\n\t\t\t\t\toperationName = operation;\n\t\t\t\t\tif (\n\t\t\t\t\t\tinput.include_windows !== undefined &&\n\t\t\t\t\t\t(name !== \"computer_apps\" ||\n\t\t\t\t\t\t\ttypeof input.include_windows !== \"boolean\" ||\n\t\t\t\t\t\t\t(input.include_windows &&\n\t\t\t\t\t\t\t\t(input.pid !== undefined || typeof input.query !== \"string\" || !input.query.trim())))\n\t\t\t\t\t)\n\t\t\t\t\t\tthrow new Error(\"include_windows requires a named app query without pid.\");\n\t\t\t\t\tif (\n\t\t\t\t\t\tinput.pid !== undefined &&\n\t\t\t\t\t\t(typeof input.pid !== \"number\" || !Number.isSafeInteger(input.pid) || input.pid < 1)\n\t\t\t\t\t)\n\t\t\t\t\t\tthrow new Error(\"Window lookup requires a positive pid.\");\n\t\t\t\t\tif (\n\t\t\t\t\t\tname === \"computer_launch\" &&\n\t\t\t\t\t\t(typeof input.name !== \"string\" || !input.name.trim() || input.name.length > 500)\n\t\t\t\t\t)\n\t\t\t\t\t\tthrow new Error(\"Launch requires a nonblank name.\");\n\t\t\t\t\tif (\n\t\t\t\t\t\tinput.query !== undefined &&\n\t\t\t\t\t\t(typeof input.query !== \"string\" || !input.query.trim() || Array.from(input.query).length > 240)\n\t\t\t\t\t)\n\t\t\t\t\t\tthrow new Error(\"Discovery query must be a nonblank string of at most 240 characters.\");\n\t\t\t\t\tconst query = typeof input.query === \"string\" ? input.query.trim() : undefined;\n\t\t\t\t\tconst needle = query?.toLowerCase();\n\t\t\t\t\tconst offset = input.offset ?? 0;\n\t\t\t\t\tif (typeof offset !== \"number\" || !Number.isSafeInteger(offset) || offset < 0)\n\t\t\t\t\t\tthrow new Error(\"Discovery offset must be a nonnegative safe integer.\");\n\t\t\t\t\tconst args =\n\t\t\t\t\t\tname === \"computer_launch\" ? { name: input.name } : input.pid === undefined ? {} : { pid: input.pid };\n\t\t\t\t\tcombined.throwIfAborted();\n\t\t\t\t\tinputDispatched = name === \"computer_launch\";\n\t\t\t\t\tphase = \"native_request\";\n\t\t\t\t\tfailureCode = \"discovery_failed\";\n\t\t\t\t\tconst reply = await abortable(this.driver.call(operation, args, combined), combined);\n\t\t\t\t\tconst data = driverData(reply);\n\t\t\t\t\tconst discovered = data.apps ?? data.windows;\n\t\t\t\t\tconst rows =\n\t\t\t\t\t\tArray.isArray(discovered) && needle\n\t\t\t\t\t\t\t? discovered.filter((row) => {\n\t\t\t\t\t\t\t\t\tconst item = record(row);\n\t\t\t\t\t\t\t\t\treturn [item.name, item.app_name, item.title].some(\n\t\t\t\t\t\t\t\t\t\t(value) => typeof value === \"string\" && value.toLowerCase().includes(needle),\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t: discovered;\n\t\t\t\t\tconst metadata = Array.isArray(rows)\n\t\t\t\t\t\t? rows.slice(offset, offset + 50).map((row) => {\n\t\t\t\t\t\t\t\tconst item = record(row);\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\t...select(item, [\n\t\t\t\t\t\t\t\t\t\t\"pid\",\n\t\t\t\t\t\t\t\t\t\t\"window_id\",\n\t\t\t\t\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\t\t\t\t\"app_name\",\n\t\t\t\t\t\t\t\t\t\t\"title\",\n\t\t\t\t\t\t\t\t\t\t\"active\",\n\t\t\t\t\t\t\t\t\t\t\"running\",\n\t\t\t\t\t\t\t\t\t\t\"is_on_screen\",\n\t\t\t\t\t\t\t\t\t\t\"minimized\",\n\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\tbounds: item.bounds ? select(record(item.bounds), [\"x\", \"y\", \"width\", \"height\"]) : undefined,\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\tconst remaining = Array.isArray(rows) ? Math.max(0, rows.length - offset - (metadata?.length ?? 0)) : 0;\n\t\t\t\t\tconst failed = driverRefused(reply);\n\t\t\t\t\tconst pid =\n\t\t\t\t\t\ttypeof data.pid === \"number\" && Number.isSafeInteger(data.pid) && data.pid > 0 ? data.pid : undefined;\n\t\t\t\t\tconst launchWindows = Array.isArray(data.windows)\n\t\t\t\t\t\t? data.windows.slice(0, 50).map((row) => {\n\t\t\t\t\t\t\t\tconst item = record(row);\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\t...select(item, [\"window_id\", \"title\", \"is_on_screen\", \"minimized\"]),\n\t\t\t\t\t\t\t\t\tbounds: item.bounds ? select(record(item.bounds), [\"x\", \"y\", \"width\", \"height\"]) : undefined,\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t: [];\n\t\t\t\t\tconst returnedId =\n\t\t\t\t\t\tdata.window_id ??\n\t\t\t\t\t\t(Array.isArray(data.windows) && data.windows.length === 1\n\t\t\t\t\t\t\t? record(data.windows[0]).window_id\n\t\t\t\t\t\t\t: undefined);\n\t\t\t\t\tconst windowId =\n\t\t\t\t\t\ttypeof returnedId === \"number\" && Number.isSafeInteger(returnedId) && returnedId > 0\n\t\t\t\t\t\t\t? returnedId\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\tlet windowsByPid:\n\t\t\t\t\t\t| { pid: number; windows?: typeof metadata; error?: string; omitted?: number; next_offset?: number }[]\n\t\t\t\t\t\t| undefined;\n\t\t\t\t\tlet guidance = remaining\n\t\t\t\t\t\t? \"Pass next_offset as offset with the same pid and query. Lists refresh per call.\"\n\t\t\t\t\t\t: input.pid !== undefined\n\t\t\t\t\t\t\t? \"Use computer_observe({pid,window_id}) for an exact returned window.\"\n\t\t\t\t\t\t\t: \"App query filters app identities, not every window title. Use computer_apps({pid}) to find windows for a running app.\";\n\t\t\t\t\tif (name === \"computer_apps\" && input.include_windows === true && !failed) {\n\t\t\t\t\t\tconst pids = [\n\t\t\t\t\t\t\t...new Set(\n\t\t\t\t\t\t\t\t(Array.isArray(rows) ? rows : [])\n\t\t\t\t\t\t\t\t\t.map((row) => record(row).pid)\n\t\t\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t\t\t(value): value is number =>\n\t\t\t\t\t\t\t\t\t\t\ttypeof value === \"number\" && Number.isSafeInteger(value) && value > 0,\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t];\n\t\t\t\t\t\tif (pids.length > 5)\n\t\t\t\t\t\t\tguidance =\n\t\t\t\t\t\t\t\t\"More than five running processes matched. Narrow the query or choose one positive pid with computer_apps({pid}); no arbitrary process was selected.\";\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\twindowsByPid = [];\n\t\t\t\t\t\t\tlet budget = 50;\n\t\t\t\t\t\t\tfor (const matchingPid of pids) {\n\t\t\t\t\t\t\t\tcombined.throwIfAborted();\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tconst windowsReply = await abortable(\n\t\t\t\t\t\t\t\t\t\tthis.driver.call(\"list_windows\", { pid: matchingPid }, combined),\n\t\t\t\t\t\t\t\t\t\tcombined,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tconst windows = driverData(windowsReply).windows;\n\t\t\t\t\t\t\t\t\tif (driverRefused(windowsReply) || !Array.isArray(windows)) {\n\t\t\t\t\t\t\t\t\t\twindowsByPid.push({\n\t\t\t\t\t\t\t\t\t\t\tpid: matchingPid,\n\t\t\t\t\t\t\t\t\t\t\terror: driverRefused(windowsReply)\n\t\t\t\t\t\t\t\t\t\t\t\t? nativeReason(windowsReply)\n\t\t\t\t\t\t\t\t\t\t\t\t: \"windows_unavailable\",\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tconst subset = windows.slice(0, budget).map((row) => {\n\t\t\t\t\t\t\t\t\t\tconst item = record(row);\n\t\t\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\t\t\t...select(item, [\n\t\t\t\t\t\t\t\t\t\t\t\t\"pid\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"window_id\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"name\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"app_name\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"title\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"active\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"running\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"is_on_screen\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"minimized\",\n\t\t\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t\t\t\t\t\tbounds: item.bounds\n\t\t\t\t\t\t\t\t\t\t\t\t? select(record(item.bounds), [\"x\", \"y\", \"width\", \"height\"])\n\t\t\t\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tconst omitted = windows.length - subset.length;\n\t\t\t\t\t\t\t\t\twindowsByPid.push({\n\t\t\t\t\t\t\t\t\t\tpid: matchingPid,\n\t\t\t\t\t\t\t\t\t\twindows: subset,\n\t\t\t\t\t\t\t\t\t\tomitted: omitted || undefined,\n\t\t\t\t\t\t\t\t\t\tnext_offset: omitted ? subset.length : undefined,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tbudget -= subset.length;\n\t\t\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t\t\tif (combined.aborted) throw error;\n\t\t\t\t\t\t\t\t\tif (error instanceof DriverCallError) throw error;\n\t\t\t\t\t\t\t\t\twindowsByPid.push({ pid: matchingPid, error: \"window_lookup_failed\" });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tguidance =\n\t\t\t\t\t\t\t\t\"Use computer_observe({pid,window_id}) for a returned window. For omitted windows use computer_apps({pid,offset:next_offset}). Per-PID failures need a targeted lookup.\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (name === \"computer_launch\")\n\t\t\t\t\t\tguidance =\n\t\t\t\t\t\t\tpid && windowId && !failed\n\t\t\t\t\t\t\t\t? `Use computer_observe({pid:${pid},window_id:${windowId}}) before input.`\n\t\t\t\t\t\t\t\t: `Launch ${failed ? \"may have completed despite an unsuccessful reply\" : \"returned no exact window\"}. Use computer_apps({${pid ? `pid:${pid}` : `query:${JSON.stringify(input.name)}`}}) before another launch or input.`;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\ttext: JSON.stringify({\n\t\t\t\t\t\t\t\t\tkind: name === \"computer_launch\" ? \"launch\" : input.pid === undefined ? \"apps\" : \"windows\",\n\t\t\t\t\t\t\t\t\toperation,\n\t\t\t\t\t\t\t\t\t...(name === \"computer_launch\"\n\t\t\t\t\t\t\t\t\t\t? outcome(reply)\n\t\t\t\t\t\t\t\t\t\t: { phase: \"native_result\", code: failed ? nativeReason(reply) : undefined }),\n\t\t\t\t\t\t\t\t\tinput: name === \"computer_launch\" ? \"not_applicable\" : undefined,\n\t\t\t\t\t\t\t\t\tlaunch:\n\t\t\t\t\t\t\t\t\t\tname === \"computer_launch\"\n\t\t\t\t\t\t\t\t\t\t\t? plainLaunchReason(reply) === \"app_lookup_unavailable\"\n\t\t\t\t\t\t\t\t\t\t\t\t? \"not_started\"\n\t\t\t\t\t\t\t\t\t\t\t\t: failed\n\t\t\t\t\t\t\t\t\t\t\t\t\t? \"completion_uncertain\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t: \"acknowledged\"\n\t\t\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\t\t\t...select(data, [\"pid\", \"window_id\", \"name\", \"title\"]),\n\t\t\t\t\t\t\t\t\twindow_id: name === \"computer_launch\" ? windowId : select(data, [\"window_id\"]).window_id,\n\t\t\t\t\t\t\t\t\twindows: name === \"computer_launch\" ? launchWindows : undefined,\n\t\t\t\t\t\t\t\t\titems: name === \"computer_launch\" ? undefined : metadata,\n\t\t\t\t\t\t\t\t\twindows_by_pid: windowsByPid,\n\t\t\t\t\t\t\t\t\tquery,\n\t\t\t\t\t\t\t\t\toffset,\n\t\t\t\t\t\t\t\t\ttotal: Array.isArray(rows) ? rows.length : undefined,\n\t\t\t\t\t\t\t\t\tomitted: remaining || undefined,\n\t\t\t\t\t\t\t\t\tnext_offset: remaining ? offset + 50 : undefined,\n\t\t\t\t\t\t\t\t\tguidance,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdetails: { computer: { failed, workflow: \"ready\" } },\n\t\t\t\t\t\tisError: failed,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tconst target = targetFrom(input);\n\t\t\t\tactionTarget = target;\n\t\t\t\tif (name === \"computer_observe\") {\n\t\t\t\t\tphase = \"observation_capture\";\n\t\t\t\t\tconst crop = input.crop === undefined ? undefined : this.crop(input, this.fresh(input, previous));\n\t\t\t\t\tfailureCode = \"capture_failed\";\n\t\t\t\t\tconst captured = await this.capture(target, combined, previous, crop);\n\t\t\t\t\tconst unchanged =\n\t\t\t\t\t\tthis.lastCapture?.fingerprint === captured.fingerprint && sameTarget(this.lastCapture.target, target);\n\t\t\t\t\tconst repeats = crop ? 0 : unchanged ? (this.lastCapture?.repeats ?? 0) + 1 : 1;\n\t\t\t\t\tthis.lastCapture = { fingerprint: captured.fingerprint, target, repeats };\n\t\t\t\t\tif (repeats >= 3)\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\ttext: JSON.stringify({\n\t\t\t\t\t\t\t\t\t\tphase: \"observation_capture\",\n\t\t\t\t\t\t\t\t\t\tcode: \"unchanged_polling_limit\",\n\t\t\t\t\t\t\t\t\t\tguidance:\n\t\t\t\t\t\t\t\t\t\t\t\"Three captures are unchanged. Stop polling and reconsider the target or approach. No input token issued.\",\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdetails: { computer: { failed: true, workflow: \"stopped\" } },\n\t\t\t\t\t\t\tisError: true,\n\t\t\t\t\t\t};\n\t\t\t\t\treturn this.imageResult(captured, { unchanged });\n\t\t\t\t}\n\t\t\t\tconst grounded = this.fresh(input, previous);\n\t\t\t\tconst { operation, args } = this.action(name, input, grounded);\n\t\t\t\tconst { button = \"left\", count = 1, modifier = [], ...clickArgs } = args;\n\t\t\t\tconst signature = JSON.stringify({\n\t\t\t\t\toperation,\n\t\t\t\t\targs:\n\t\t\t\t\t\toperation === \"click\"\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t...clickArgs,\n\t\t\t\t\t\t\t\t\tbutton,\n\t\t\t\t\t\t\t\t\tcount,\n\t\t\t\t\t\t\t\t\tmodifier: Array.isArray(modifier) ? [...new Set(modifier)].sort() : modifier,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: args,\n\t\t\t\t});\n\t\t\t\tif (\n\t\t\t\t\tthis.lastAction?.unchanged &&\n\t\t\t\t\tthis.lastAction.signature === signature &&\n\t\t\t\t\tthis.lastAction.fingerprint === grounded.fingerprint\n\t\t\t\t)\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"The identical action had no visible change. Choose a different grounded action; never retry blindly.\",\n\t\t\t\t\t);\n\t\t\t\tcombined.throwIfAborted();\n\t\t\t\tinputDispatched = true;\n\t\t\t\tphase = \"native_request\";\n\t\t\t\toperationName = operation;\n\t\t\t\tconst reply = await abortable(this.driver.call(operation, args, combined), combined);\n\t\t\t\tcombined.throwIfAborted();\n\t\t\t\tactionOutcome = outcome(reply, name === \"computer_text\" ? input.text : undefined);\n\t\t\t\tconst recoveryGuidance =\n\t\t\t\t\tactionOutcome.retry_from_character !== undefined\n\t\t\t\t\t\t? \"Verify the field in a fresh image before considering any remaining suffix. retry_from_character is a zero-based Unicode code-point offset, not UTF-16. retryable is driver advice, not authorization to retry.\"\n\t\t\t\t\t\t: undefined;\n\t\t\t\tconst failed =\n\t\t\t\t\tdriverRefused(reply) || driverData(reply).effect === \"partial\" || driverData(reply).status === \"partial\";\n\t\t\t\tconst backgroundUnavailable = actionOutcome.code === \"background_unavailable\";\n\t\t\t\tif (name === \"computer_hover\") await delay(700, undefined, { signal: combined });\n\t\t\t\tphase = \"post_action_capture\";\n\t\t\t\ttry {\n\t\t\t\t\tconst after = await this.capture(target, combined);\n\t\t\t\t\tconst unchanged = after.fingerprint === grounded.fingerprint;\n\t\t\t\t\tthis.lastAction = { signature, fingerprint: after.fingerprint, unchanged };\n\t\t\t\t\tthis.lastCapture = {\n\t\t\t\t\t\tfingerprint: after.fingerprint,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\trepeats:\n\t\t\t\t\t\t\tfailed &&\n\t\t\t\t\t\t\tthis.lastCapture?.fingerprint === after.fingerprint &&\n\t\t\t\t\t\t\tsameTarget(this.lastCapture.target, target)\n\t\t\t\t\t\t\t\t? this.lastCapture.repeats\n\t\t\t\t\t\t\t\t: 0,\n\t\t\t\t\t};\n\t\t\t\t\treturn this.imageResult(after, {\n\t\t\t\t\t\tkind: \"action\",\n\t\t\t\t\t\toperation,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\t...actionOutcome,\n\t\t\t\t\t\tfailed,\n\t\t\t\t\t\tunchanged,\n\t\t\t\t\t\tguidance: [\n\t\t\t\t\t\t\t\"Inspect the post-action image before another action. No visible change does not prove failure; never repeat blindly.\",\n\t\t\t\t\t\t\tbackgroundUnavailable\n\t\t\t\t\t\t\t\t? \"After this fresh capture, foreground input may be considered if permitted, not another background shortcut.\"\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t\trecoveryGuidance,\n\t\t\t\t\t\t]\n\t\t\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t\t\t.join(\" \"),\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcombined.throwIfAborted();\n\t\t\t\t\tif (!(error instanceof CaptureError)) throw error;\n\t\t\t\t\tthis.lastAction = { signature, fingerprint: grounded.fingerprint, unchanged: true };\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\ttext: JSON.stringify({\n\t\t\t\t\t\t\t\t\tkind: \"action\",\n\t\t\t\t\t\t\t\t\toperation,\n\t\t\t\t\t\t\t\t\ttarget,\n\t\t\t\t\t\t\t\t\t...actionOutcome,\n\t\t\t\t\t\t\t\t\tphase: \"post_action_capture\",\n\t\t\t\t\t\t\t\t\tcapture_error: error.code,\n\t\t\t\t\t\t\t\t\tobservation: \"unavailable\",\n\t\t\t\t\t\t\t\t\tguidance: `Input may have taken effect. ${\n\t\t\t\t\t\t\t\t\t\t[\"target_not_found\", \"window_target_not_found\", \"window_target_mismatch\"].includes(\n\t\t\t\t\t\t\t\t\t\t\terror.code,\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t? \"Use computer_apps({pid}) or observe the desktop to find the target.\"\n\t\t\t\t\t\t\t\t\t\t\t: \"Get a fresh capture of the exact target\"\n\t\t\t\t\t\t\t\t\t} before another action; never repeat blindly. ${recoveryGuidance ?? \"\"}`,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdetails: { computer: { failed: true, workflow: \"ready\" } },\n\t\t\t\t\t\tisError: true,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}, combined);\n\t\t\tif (result.details.computer.workflow !== \"ready\") return this.finish(result);\n\t\t\treturn result;\n\t\t} catch (error) {\n\t\t\tif (error instanceof DriverCallError && !(currentPhase() === \"post_action_capture\" && actionOutcome)) {\n\t\t\t\tphase = error.phase;\n\t\t\t\tinputDispatched = error.dispatched;\n\t\t\t}\n\t\t\tconst failurePhase = currentPhase();\n\t\t\tconst fatal =\n\t\t\t\tcombined.aborted ||\n\t\t\t\tthis.abort.signal.aborted ||\n\t\t\t\tthis.lease.signal.aborted ||\n\t\t\t\terror instanceof DriverCallError ||\n\t\t\t\t!(\n\t\t\t\t\terror instanceof ObservationError ||\n\t\t\t\t\terror instanceof CaptureError ||\n\t\t\t\t\tfailurePhase === \"validation\" ||\n\t\t\t\t\t(failurePhase === \"observation_capture\" && !inputDispatched)\n\t\t\t\t);\n\t\t\tconst code =\n\t\t\t\terror instanceof ObservationError || error instanceof CaptureError\n\t\t\t\t\t? error.code\n\t\t\t\t\t: inputDispatched && failurePhase === \"post_action_capture\"\n\t\t\t\t\t\t? \"capture_transport_failed\"\n\t\t\t\t\t\t: error instanceof DriverCallError\n\t\t\t\t\t\t\t? error.dispatched\n\t\t\t\t\t\t\t\t? \"input_dispatch_failed\"\n\t\t\t\t\t\t\t\t: \"adapter_preflight_failed\"\n\t\t\t\t\t\t\t: inputDispatched\n\t\t\t\t\t\t\t\t? \"input_dispatch_failed\"\n\t\t\t\t\t\t\t\t: failurePhase === \"validation\"\n\t\t\t\t\t\t\t\t\t? \"invalid_arguments\"\n\t\t\t\t\t\t\t\t\t: failureCode;\n\t\t\tconst message =\n\t\t\t\tname === \"computer_launch\"\n\t\t\t\t\t? inputDispatched\n\t\t\t\t\t\t? \"Launch request began; activation may have occurred.\"\n\t\t\t\t\t\t: \"No launch request was sent by this call.\"\n\t\t\t\t\t: inputDispatched\n\t\t\t\t\t\t? \"Input may have taken effect; request began.\"\n\t\t\t\t\t\t: \"No input was sent by this call.\";\n\t\t\tconst guidance = inputDispatched\n\t\t\t\t? name === \"computer_launch\"\n\t\t\t\t\t? `Use computer_apps({query:${JSON.stringify(input.name)}) before considering another launch.`\n\t\t\t\t\t: `Get a fresh capture of the exact target before another action. Input may have taken effect; inspect the field before deciding and never repeat blindly. ${actionOutcome?.retry_from_character !== undefined ? \"Verify the field in a fresh image before considering any remaining suffix. retry_from_character is a zero-based Unicode code-point offset, not UTF-16.\" : \"\"}`\n\t\t\t\t: freshActionGuidance;\n\t\t\tconst result: Result = {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: JSON.stringify({\n\t\t\t\t\t\t\tkind:\n\t\t\t\t\t\t\t\tname === \"computer_apps\"\n\t\t\t\t\t\t\t\t\t? \"apps\"\n\t\t\t\t\t\t\t\t\t: name === \"computer_launch\"\n\t\t\t\t\t\t\t\t\t\t? \"launch\"\n\t\t\t\t\t\t\t\t\t\t: name === \"computer_observe\"\n\t\t\t\t\t\t\t\t\t\t\t? \"observation\"\n\t\t\t\t\t\t\t\t\t\t\t: \"action\",\n\t\t\t\t\t\t\toperation: operationName,\n\t\t\t\t\t\t\ttarget: actionTarget,\n\t\t\t\t\t\t\t...actionOutcome,\n\t\t\t\t\t\t\taction_outcome: actionOutcome,\n\t\t\t\t\t\t\tphase: failurePhase,\n\t\t\t\t\t\t\tcode,\n\t\t\t\t\t\t\tinput:\n\t\t\t\t\t\t\t\tname === \"computer_apps\"\n\t\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t\t: name === \"computer_launch\"\n\t\t\t\t\t\t\t\t\t\t? \"not_applicable\"\n\t\t\t\t\t\t\t\t\t\t: inputDispatched\n\t\t\t\t\t\t\t\t\t\t\t? \"uncertain\"\n\t\t\t\t\t\t\t\t\t\t\t: \"not_dispatched\",\n\t\t\t\t\t\t\trequest: name === \"computer_launch\" ? (inputDispatched ? \"sent\" : \"not_sent\") : undefined,\n\t\t\t\t\t\t\tapplicationEffect: \"unverified\",\n\t\t\t\t\t\t\tobservation: \"unavailable\",\n\t\t\t\t\t\t\tcapture_error: failurePhase === \"post_action_capture\" ? code : undefined,\n\t\t\t\t\t\t\tmessage,\n\t\t\t\t\t\t\tguidance,\n\t\t\t\t\t\t}),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdetails: { computer: { failed: true, workflow: fatal ? \"stopped\" : \"ready\" } },\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t\treturn fatal ? this.finish(result) : result;\n\t\t}\n\t}\n\n\tprivate async finish(result: Result): Promise<Result> {\n\t\ttry {\n\t\t\tawait this.close();\n\t\t\treturn {\n\t\t\t\t...result,\n\t\t\t\tdetails: { ...result.details, computer: { failed: result.details.computer.failed, workflow: \"stopped\" } },\n\t\t\t};\n\t\t} catch {\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t...result.content,\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: JSON.stringify({\n\t\t\t\t\t\t\tphase: \"cleanup\",\n\t\t\t\t\t\t\tcleanup: \"unconfirmed\",\n\t\t\t\t\t\t\tguidance: \"Desktop ownership retained until shutdown is confirmed.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdetails: { ...result.details, computer: { failed: true, workflow: \"cleanup_unconfirmed\" } },\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\t}\n\n\tclose(): Promise<void> {\n\t\tthis.abort.abort();\n\t\tthis.observation = undefined;\n\t\tthis.closing ??= this.stop();\n\t\treturn this.closing;\n\t}\n\n\tprivate async stop(): Promise<void> {\n\t\tawait this.driver.close();\n\t\tawait this.lease.close();\n\t}\n}\n"]}
|
package/dist/core/cron/jobs.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Jobs persist at `<agentDir>/cron/jobs.json` (`{ jobs: [...], updated_at }`),
|
|
5
5
|
* agentDir resolved via getAgentDir() (honors PI_CODING_AGENT_DIR, defaults
|
|
6
6
|
* ~/.lunr/agent). Writes are atomic (tmp file in the same dir + rename) and
|
|
7
|
-
* serialized
|
|
7
|
+
* serialized with a cross-process read-modify-write lock over fresh data.
|
|
8
8
|
*
|
|
9
9
|
* Per-run output goes to `<agentDir>/cron/output/<jobId>/<YYYY-MM-DD_HH-MM-SS>.md`
|
|
10
10
|
* with a retention cap of the newest 50 files per job.
|
|
@@ -22,6 +22,8 @@ export interface CronSchedule {
|
|
|
22
22
|
expr?: string;
|
|
23
23
|
}
|
|
24
24
|
export interface CronJobOrigin {
|
|
25
|
+
/** Requester identity, absent on legacy jobs. Never persist adapter role grants. */
|
|
26
|
+
userId?: string;
|
|
25
27
|
platform: string;
|
|
26
28
|
chatId: string;
|
|
27
29
|
threadId?: string;
|
|
@@ -53,6 +55,15 @@ export interface CronJob {
|
|
|
53
55
|
/** Job IDs whose latest output (8K chars cap each) is prepended to the prompt. */
|
|
54
56
|
contextFrom?: string[];
|
|
55
57
|
workdir?: string;
|
|
58
|
+
/** Unknown interrupted effects require an explicit run, rather than ordinary resume. */
|
|
59
|
+
interrupted?: boolean;
|
|
60
|
+
/** Durable claim written before dispatch. Interrupted claims require explicit retry. */
|
|
61
|
+
activeRun?: {
|
|
62
|
+
id: string;
|
|
63
|
+
scheduledAt: string | null;
|
|
64
|
+
startedAt: string;
|
|
65
|
+
advancedTo?: string | null;
|
|
66
|
+
};
|
|
56
67
|
}
|
|
57
68
|
export interface CreateJobInput {
|
|
58
69
|
prompt: string;
|
|
@@ -89,9 +100,11 @@ export declare const OUTPUT_RETENTION = 50;
|
|
|
89
100
|
export declare const CONTEXT_OUTPUT_CAP = 8000;
|
|
90
101
|
/**
|
|
91
102
|
* Override the base dir (defaults to the agent dir) and reset the in-memory
|
|
92
|
-
*
|
|
103
|
+
* transaction queue. Passing undefined restores the default. For tests.
|
|
93
104
|
*/
|
|
94
105
|
export declare function setCronBaseDir(dir: string | undefined): void;
|
|
106
|
+
/** Acquire the non-preemptive profile scheduler lease. A live PID is never displaced. */
|
|
107
|
+
export declare function acquireSchedulerLease(): Promise<(() => Promise<void>) | null>;
|
|
95
108
|
export interface ParsedSchedule {
|
|
96
109
|
schedule: CronSchedule;
|
|
97
110
|
scheduleDisplay: string;
|
|
@@ -136,14 +149,13 @@ export declare function removeJob(idOrName: string): Promise<CronJob>;
|
|
|
136
149
|
/**
|
|
137
150
|
* Jobs due to fire now. Skips disabled/paused/completed jobs and jobs without a
|
|
138
151
|
* nextRunAt. One-shots fire up to 120s late (flat recovery grace); beyond that
|
|
139
|
-
* they are marked state "error" and skipped. Recurring
|
|
140
|
-
*
|
|
141
|
-
* to their next future slot but still fire ONCE now (collapse backlog, no burst).
|
|
152
|
+
* they are marked state "error" and skipped. Recurring backlog fires once;
|
|
153
|
+
* claiming the occurrence advances it to the next future slot without a burst.
|
|
142
154
|
*/
|
|
143
155
|
export declare function getDueJobs(now?: Date): Promise<CronJob[]>;
|
|
144
156
|
/**
|
|
145
|
-
* Advance a recurring job to its next slot.
|
|
146
|
-
*
|
|
157
|
+
* Advance a recurring job to its next slot. Scheduler dispatch uses claimJobRun
|
|
158
|
+
* instead so one-shots and recurring work both retain a durable claim.
|
|
147
159
|
*/
|
|
148
160
|
export declare function advanceNextRun(jobId: string): Promise<CronJob>;
|
|
149
161
|
/**
|
|
@@ -154,7 +166,13 @@ export declare function advanceNextRun(jobId: string): Promise<CronJob>;
|
|
|
154
166
|
export declare function markJobRun(jobId: string, result: {
|
|
155
167
|
status: CronJobStatus;
|
|
156
168
|
error?: string;
|
|
157
|
-
|
|
169
|
+
runId?: string;
|
|
170
|
+
}): Promise<CronJob | null>;
|
|
171
|
+
/** Claim only a still-due, enabled occurrence from the fresh store. */
|
|
172
|
+
export declare function claimJobRun(jobId: string, now: Date, manual?: boolean): Promise<CronJob | null>;
|
|
173
|
+
/** Recover uncertain interrupted work without replaying its external effects. */
|
|
174
|
+
export declare function recoverInterruptedRuns(): Promise<void>;
|
|
175
|
+
export declare function deferJobRun(jobId: string, runId: string): Promise<void>;
|
|
158
176
|
/** Save a run's output and prune to the newest OUTPUT_RETENTION files. Returns the file path. */
|
|
159
177
|
export declare function saveJobOutput(jobId: string, content: string): Promise<string>;
|
|
160
178
|
/** Content of the newest output file for a job, or null when none exists. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../../../src/core/cron/jobs.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * lunR: cron job model + persistent store (Phase 1 of the cron/gateway roadmap).\n *\n * Jobs persist at `<agentDir>/cron/jobs.json` (`{ jobs: [...], updated_at }`),\n * agentDir resolved via getAgentDir() (honors PI_CODING_AGENT_DIR, defaults\n * ~/.lunr/agent). Writes are atomic (tmp file in the same dir + rename) and\n * serialized through an in-process promise queue — single-process, no locks.\n *\n * Per-run output goes to `<agentDir>/cron/output/<jobId>/<YYYY-MM-DD_HH-MM-SS>.md`\n * with a retention cap of the newest 50 files per job.\n *\n * Tests inject a base dir via setCronBaseDir() so no real agent dir is touched.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { isAbsolute, join, normalize, resolve } from \"node:path\";\nimport { Cron } from \"croner\";\nimport { getAgentDir } from \"../../config.ts\";\nimport {\n\tchatPlatformDeliverBlockedMessage,\n\tdeliverMentionsChatPlatform,\n\tisFeatureEnabled,\n} from \"../install-features.ts\";\n\n// ---------------------------------------------------------------------------\n// Model\n// ---------------------------------------------------------------------------\n\nexport type CronScheduleKind = \"once\" | \"interval\" | \"cron\";\n\nexport interface CronSchedule {\n\tkind: CronScheduleKind;\n\t/** ISO timestamp, one-shots only. */\n\trunAt?: string;\n\t/** Interval length in minutes, interval kind only. */\n\tminutes?: number;\n\t/** 5-field cron expression, cron kind only. */\n\texpr?: string;\n}\n\nexport interface CronJobOrigin {\n\tplatform: string;\n\tchatId: string;\n\tthreadId?: string;\n\tchatType?: string;\n}\n\nexport type CronJobState = \"scheduled\" | \"paused\" | \"completed\" | \"error\";\nexport type CronJobStatus = \"ok\" | \"error\";\n\nexport interface CronJob {\n\tid: string;\n\tname: string;\n\tprompt: string;\n\tschedule: CronSchedule;\n\tscheduleDisplay: string;\n\trepeat: { times: number | null; completed: number };\n\tenabled: boolean;\n\tstate: CronJobState;\n\tcreatedAt: string;\n\tnextRunAt: string | null;\n\tlastRunAt: string | null;\n\tlastStatus: CronJobStatus | null;\n\tlastError: string | null;\n\tlastDeliveryError: string | null;\n\t/** \"local\" | \"origin\" | \"telegram[:chatId]\" | \"discord[:chatId]\" (comma-combinable). v1 TUI only uses \"local\". */\n\tdeliver: string;\n\torigin?: CronJobOrigin | null;\n\t/** Job IDs whose latest output (8K chars cap each) is prepended to the prompt. */\n\tcontextFrom?: string[];\n\tworkdir?: string;\n}\n\nexport interface CreateJobInput {\n\tprompt: string;\n\t/** Raw schedule input, parsed by parseSchedule(). */\n\tschedule: string;\n\tname?: string;\n\t/** Repetition cap; null = forever. One-shots are always times=1. */\n\ttimes?: number | null;\n\tdeliver?: string;\n\tcontextFrom?: string[];\n\tworkdir?: string;\n\torigin?: CronJobOrigin | null;\n}\n\nexport interface JobPatch {\n\tname?: string;\n\tprompt?: string;\n\t/** Raw schedule input; reparsed and re-anchors nextRunAt. */\n\tschedule?: string;\n\tdeliver?: string;\n\tenabled?: boolean;\n\ttimes?: number | null;\n\tcontextFrom?: string[];\n\tworkdir?: string;\n\torigin?: CronJobOrigin | null;\n\t/** Internal: manual-run trigger and delivery-error bookkeeping. */\n\tnextRunAt?: string | null;\n\tlastDeliveryError?: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Flat recovery grace for one-shots: fire up to 120s late. */\nexport const ONE_SHOT_GRACE_MS = 120_000;\n/** Recurring grace window clamps: at least 120s, at most 2h. */\nconst MIN_GRACE_MS = 120_000;\nconst MAX_GRACE_MS = 7_200_000;\n/** Per-job output retention. */\nexport const OUTPUT_RETENTION = 50;\n/** Cap per upstream job output injected via contextFrom. */\nexport const CONTEXT_OUTPUT_CAP = 8000;\n\nconst MAX_NAME_LEN = 50;\n\n// ---------------------------------------------------------------------------\n// Paths + store state\n// ---------------------------------------------------------------------------\n\nlet baseDirOverride: string | undefined;\nlet cache: CronJob[] | undefined;\nlet writeQueue: Promise<void> = Promise.resolve();\n\n/**\n * Override the base dir (defaults to the agent dir) and reset the in-memory\n * cache + write queue. Passing undefined restores the default. For tests.\n */\nexport function setCronBaseDir(dir: string | undefined): void {\n\tbaseDirOverride = dir;\n\tcache = undefined;\n\twriteQueue = Promise.resolve();\n}\n\nfunction cronDir(): string {\n\treturn join(baseDirOverride ?? getAgentDir(), \"cron\");\n}\n\nfunction jobsFile(): string {\n\treturn join(cronDir(), \"jobs.json\");\n}\n\nfunction outputDir(jobId: string): string {\n\treturn join(cronDir(), \"output\", jobId);\n}\n\nfunction loadJobs(): CronJob[] {\n\tif (cache) return cache;\n\tconst file = jobsFile();\n\tif (!existsSync(file)) {\n\t\tcache = [];\n\t\treturn cache;\n\t}\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(file, \"utf-8\"));\n\t\tcache = Array.isArray(parsed?.jobs) ? (parsed.jobs as CronJob[]) : [];\n\t} catch {\n\t\tcache = [];\n\t}\n\treturn cache;\n}\n\n/** Queue an atomic write of the in-memory store. Rejects only for the caller; the chain self-heals. */\nfunction persist(): Promise<void> {\n\tconst snapshot = JSON.stringify({ jobs: cache ?? [], updated_at: new Date().toISOString() }, null, 2);\n\tconst p = writeQueue.then(() => {\n\t\tmkdirSync(cronDir(), { recursive: true });\n\t\tconst tmp = join(cronDir(), `.jobs.json.${process.pid}.${Date.now()}.tmp`);\n\t\twriteFileSync(tmp, snapshot, \"utf-8\");\n\t\trenameSync(tmp, jobsFile());\n\t});\n\twriteQueue = p.then(\n\t\t() => undefined,\n\t\t() => undefined,\n\t);\n\treturn p;\n}\n\n// ---------------------------------------------------------------------------\n// Schedule parsing\n// ---------------------------------------------------------------------------\n\nexport interface ParsedSchedule {\n\tschedule: CronSchedule;\n\tscheduleDisplay: string;\n}\n\nconst INTERVAL_RE = /^every\\s+(\\d+)\\s*([mhd])$/i;\nconst DURATION_RE = /^(\\d+)\\s*([mhd])$/i;\n\nfunction toMinutes(value: number, unit: string): number {\n\tconst u = unit.toLowerCase();\n\tconst factor = u === \"d\" ? 1440 : u === \"h\" ? 60 : 1;\n\treturn value * factor;\n}\n\n/**\n * Parse a schedule input:\n * - `every 30m` / `every 2h` / `every 1d` → interval (minutes; d = 1440)\n * - bare `30m` / `2h` / `1d` → one-shot at now + duration\n * - ISO timestamp → one-shot at that time\n * - 5-field cron expression (validated via croner; throws on invalid)\n */\nexport function parseSchedule(input: string, now: Date = new Date()): ParsedSchedule {\n\tconst text = input.trim().replace(/\\s+/g, \" \");\n\tif (!text) throw new Error(\"schedule is empty\");\n\n\tconst interval = INTERVAL_RE.exec(text);\n\tif (interval) {\n\t\tconst minutes = toMinutes(Number(interval[1]), interval[2]);\n\t\tif (minutes <= 0) throw new Error(`invalid interval: \"${text}\"`);\n\t\treturn {\n\t\t\tschedule: { kind: \"interval\", minutes },\n\t\t\tscheduleDisplay: `every ${Number(interval[1])}${interval[2].toLowerCase()}`,\n\t\t};\n\t}\n\n\tconst duration = DURATION_RE.exec(text);\n\tif (duration) {\n\t\tconst minutes = toMinutes(Number(duration[1]), duration[2]);\n\t\tif (minutes <= 0) throw new Error(`invalid duration: \"${text}\"`);\n\t\tconst runAt = new Date(now.getTime() + minutes * 60_000).toISOString();\n\t\treturn { schedule: { kind: \"once\", runAt }, scheduleDisplay: text };\n\t}\n\n\tif (/^\\d{4}-\\d{2}-\\d{2}/.test(text)) {\n\t\tconst ts = Date.parse(text);\n\t\tif (!Number.isNaN(ts)) {\n\t\t\tconst runAt = new Date(ts).toISOString();\n\t\t\treturn { schedule: { kind: \"once\", runAt }, scheduleDisplay: runAt };\n\t\t}\n\t}\n\n\tif (text.split(\" \").length === 5) {\n\t\ttry {\n\t\t\tnew Cron(text);\n\t\t} catch (err) {\n\t\t\tthrow new Error(`invalid cron expression \"${text}\": ${err instanceof Error ? err.message : String(err)}`);\n\t\t}\n\t\treturn { schedule: { kind: \"cron\", expr: text }, scheduleDisplay: text };\n\t}\n\n\tthrow new Error(\n\t\t`unrecognized schedule: \"${input}\" (expected \"every 30m\", \"2h\", an ISO timestamp, or a 5-field cron expression)`,\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// Next-run computation\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the next run time for a job:\n * - once: the stored runAt, recoverable within a 120s grace if never run; null after that or once run.\n * - interval: (lastRunAt ?? createdAt) + minutes.\n * - cron: croner nextRun after (lastRunAt ?? now).\n */\nexport function computeNextRun(job: CronJob, now: Date = new Date()): Date | null {\n\tconst s = job.schedule;\n\tif (s.kind === \"once\") {\n\t\tif (job.repeat.completed > 0) return null;\n\t\tif (!s.runAt) return null;\n\t\tconst runAt = new Date(s.runAt);\n\t\tif (Number.isNaN(runAt.getTime())) return null;\n\t\treturn now.getTime() - runAt.getTime() <= ONE_SHOT_GRACE_MS ? runAt : null;\n\t}\n\tif (s.kind === \"interval\") {\n\t\tconst base = job.lastRunAt ? new Date(job.lastRunAt) : new Date(job.createdAt);\n\t\treturn new Date(base.getTime() + (s.minutes ?? 0) * 60_000);\n\t}\n\tconst cron = new Cron(s.expr!);\n\treturn cron.nextRun(job.lastRunAt ? new Date(job.lastRunAt) : now);\n}\n\n/** Approximate schedule period in ms (recurring jobs only) for grace-window sizing. */\nfunction periodMs(job: CronJob, now: Date): number {\n\tif (job.schedule.kind === \"interval\") return (job.schedule.minutes ?? 0) * 60_000;\n\tif (job.schedule.kind === \"cron\") {\n\t\tconst cron = new Cron(job.schedule.expr!);\n\t\tconst a = cron.nextRun(now);\n\t\tif (!a) return MAX_GRACE_MS;\n\t\tconst b = cron.nextRun(a);\n\t\tif (!b) return MAX_GRACE_MS;\n\t\treturn Math.max(b.getTime() - a.getTime(), 1);\n\t}\n\treturn 0;\n}\n\n/** Next slot strictly after `after` for a recurring job. */\nfunction nextSlotAfter(job: CronJob, after: Date): Date | null {\n\tif (job.schedule.kind === \"interval\") {\n\t\tconst period = (job.schedule.minutes ?? 0) * 60_000;\n\t\tif (period <= 0) return null;\n\t\t// Step forward from the stored nextRunAt (or now) until strictly in the future of `after`.\n\t\tlet slot = job.nextRunAt ? new Date(job.nextRunAt).getTime() : new Date(job.createdAt).getTime() + period;\n\t\twhile (slot <= after.getTime()) slot += period;\n\t\treturn new Date(slot);\n\t}\n\tif (job.schedule.kind === \"cron\") {\n\t\treturn new Cron(job.schedule.expr!).nextRun(after);\n\t}\n\treturn null;\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\nlet workdirRoots: string[] = [process.cwd(), homedir()];\nlet deliverValidator: ((deliver: string, origin?: CronJobOrigin | null) => string | undefined) | undefined;\n\n/**\n * Configure the allowed absolute roots for cron job workdirs. Relative workdirs\n * are resolved against process.cwd() and must fall under one of these roots.\n * Default roots are process.cwd() and the user's home directory.\n */\nexport function setCronWorkdirRoots(roots: string[]): void {\n\tworkdirRoots = roots.map((r) => normalize(resolve(r)));\n}\n\n/**\n * Configure a deliver-target validator. When set, createJob/updateJob reject\n * deliver strings that the validator does not approve. The gateway uses this\n * to prevent delivery to arbitrary chats.\n */\nexport function setCronDeliverValidator(\n\tfn: ((deliver: string, origin?: CronJobOrigin | null) => string | undefined) | undefined,\n): void {\n\tdeliverValidator = fn;\n}\n\n/** Test seam: restore default validation state. */\nexport function resetCronValidators(): void {\n\tworkdirRoots = [process.cwd(), homedir()];\n\tdeliverValidator = undefined;\n}\n\nfunction isPathUnderRoot(absPath: string, root: string): boolean {\n\tconst normRoot = normalize(root).replace(/\\\\$/g, \"\");\n\tconst normPath = normalize(absPath).replace(/\\\\$/g, \"\");\n\treturn normPath === normRoot || normPath.startsWith(`${normRoot}/`) || normPath.startsWith(`${normRoot}\\\\`);\n}\n\nfunction validateWorkdir(workdir: string): string | undefined {\n\tconst candidate = resolve(workdir);\n\tif (isAbsolute(workdir) && !workdirRoots.some((root) => isPathUnderRoot(candidate, root))) {\n\t\treturn `workdir ${workdir} is outside allowed roots`;\n\t}\n\tif (!workdirRoots.some((root) => isPathUnderRoot(candidate, root))) {\n\t\treturn `workdir ${workdir} resolves outside allowed roots`;\n\t}\n\treturn undefined;\n}\n\nfunction runDeliverValidation(deliver: string, origin?: CronJobOrigin | null): string | undefined {\n\tif (deliverMentionsChatPlatform(deliver) && !isFeatureEnabled(\"chat-platforms\")) {\n\t\treturn chatPlatformDeliverBlockedMessage();\n\t}\n\treturn deliverValidator?.(deliver, origin);\n}\n\nfunction deriveName(prompt: string): string {\n\tconst first = prompt.split(\"\\n\")[0].replace(/\\s+/g, \" \").trim();\n\treturn (first || \"cron job\").slice(0, MAX_NAME_LEN);\n}\n\nexport async function createJob(input: CreateJobInput): Promise<CronJob> {\n\tconst prompt = input.prompt.trim();\n\tif (!prompt) throw new Error(\"createJob: prompt is empty\");\n\tif (input.workdir) {\n\t\tconst err = validateWorkdir(input.workdir);\n\t\tif (err) throw new Error(`createJob: ${err}`);\n\t}\n\tif (input.deliver) {\n\t\tconst err = runDeliverValidation(input.deliver, input.origin);\n\t\tif (err) throw new Error(`createJob: ${err}`);\n\t}\n\tconst now = new Date();\n\tconst parsed = parseSchedule(input.schedule, now);\n\tconst isOneShot = parsed.schedule.kind === \"once\";\n\tconst times = isOneShot ? 1 : (input.times ?? null);\n\tif (times !== null && (!Number.isInteger(times) || times < 1)) {\n\t\tthrow new Error(`createJob: times must be a positive integer or null, got ${times}`);\n\t}\n\tconst job: CronJob = {\n\t\tid: randomUUID().replaceAll(\"-\", \"\").slice(0, 12),\n\t\tname: (input.name?.trim() || deriveName(prompt)).slice(0, MAX_NAME_LEN),\n\t\tprompt,\n\t\tschedule: parsed.schedule,\n\t\tscheduleDisplay: parsed.scheduleDisplay,\n\t\trepeat: { times, completed: 0 },\n\t\tenabled: true,\n\t\tstate: \"scheduled\",\n\t\tcreatedAt: now.toISOString(),\n\t\tnextRunAt: null,\n\t\tlastRunAt: null,\n\t\tlastStatus: null,\n\t\tlastError: null,\n\t\tlastDeliveryError: null,\n\t\tdeliver: input.deliver?.trim() || \"local\",\n\t\torigin: input.origin ?? null,\n\t\tcontextFrom: input.contextFrom,\n\t\tworkdir: input.workdir,\n\t};\n\tjob.nextRunAt = computeNextRun(job, now)?.toISOString() ?? null;\n\tloadJobs().push(job);\n\tawait persist();\n\treturn job;\n}\n\n/** Look up a job by id, then by unique name. Throws when not found or when the name is ambiguous. */\nexport function getJob(idOrName: string): CronJob {\n\tconst jobs = loadJobs();\n\tconst byId = jobs.find((j) => j.id === idOrName);\n\tif (byId) return byId;\n\tconst byName = jobs.filter((j) => j.name === idOrName);\n\tif (byName.length === 1) return byName[0];\n\tif (byName.length > 1) {\n\t\tthrow new Error(\n\t\t\t`cron job name \"${idOrName}\" is ambiguous (${byName.length} matches: ${byName.map((j) => j.id).join(\", \")})`,\n\t\t);\n\t}\n\tthrow new Error(`no cron job matches \"${idOrName}\"`);\n}\n\nexport function listJobs(): CronJob[] {\n\treturn [...loadJobs()];\n}\n\nexport async function updateJob(idOrName: string, patch: JobPatch): Promise<CronJob> {\n\tconst job = getJob(idOrName);\n\tif (patch.name !== undefined) job.name = patch.name.trim().slice(0, MAX_NAME_LEN) || job.name;\n\tif (patch.workdir !== undefined) {\n\t\tif (patch.workdir) {\n\t\t\tconst err = validateWorkdir(patch.workdir);\n\t\t\tif (err) throw new Error(`updateJob: ${err}`);\n\t\t}\n\t\tjob.workdir = patch.workdir;\n\t}\n\tif (patch.deliver !== undefined) {\n\t\tconst err = runDeliverValidation(patch.deliver, patch.origin ?? job.origin);\n\t\tif (err) throw new Error(`updateJob: ${err}`);\n\t\tjob.deliver = patch.deliver.trim() || \"local\";\n\t}\n\tif (patch.prompt !== undefined) {\n\t\tconst prompt = patch.prompt.trim();\n\t\tif (!prompt) throw new Error(\"updateJob: prompt is empty\");\n\t\tjob.prompt = prompt;\n\t}\n\tif (patch.schedule !== undefined) {\n\t\tconst parsed = parseSchedule(patch.schedule);\n\t\tjob.schedule = parsed.schedule;\n\t\tjob.scheduleDisplay = parsed.scheduleDisplay;\n\t\tif (parsed.schedule.kind === \"once\") job.repeat.times = 1;\n\t\tjob.nextRunAt = computeNextRun(job)?.toISOString() ?? null;\n\t}\n\tif (patch.enabled !== undefined) job.enabled = patch.enabled;\n\tif (patch.times !== undefined) {\n\t\tif (patch.times !== null && (!Number.isInteger(patch.times) || patch.times < 1)) {\n\t\t\tthrow new Error(`updateJob: times must be a positive integer or null, got ${patch.times}`);\n\t\t}\n\t\tif (job.schedule.kind !== \"once\") job.repeat.times = patch.times;\n\t}\n\tif (patch.contextFrom !== undefined) job.contextFrom = patch.contextFrom;\n\tif (patch.origin !== undefined) job.origin = patch.origin;\n\tif (patch.nextRunAt !== undefined) job.nextRunAt = patch.nextRunAt;\n\tif (patch.lastDeliveryError !== undefined) job.lastDeliveryError = patch.lastDeliveryError;\n\tawait persist();\n\treturn job;\n}\n\nexport async function pauseJob(idOrName: string): Promise<CronJob> {\n\tconst job = getJob(idOrName);\n\tif (job.state !== \"completed\") job.state = \"paused\";\n\tawait persist();\n\treturn job;\n}\n\nexport async function resumeJob(idOrName: string): Promise<CronJob> {\n\tconst job = getJob(idOrName);\n\tif (job.state === \"paused\") {\n\t\tjob.state = \"scheduled\";\n\t\tjob.nextRunAt = computeNextRun(job)?.toISOString() ?? null;\n\t}\n\tawait persist();\n\treturn job;\n}\n\nexport async function removeJob(idOrName: string): Promise<CronJob> {\n\tconst job = getJob(idOrName);\n\tconst jobs = loadJobs();\n\tjobs.splice(jobs.indexOf(job), 1);\n\tawait persist();\n\treturn job;\n}\n\n// ---------------------------------------------------------------------------\n// Scheduling\n// ---------------------------------------------------------------------------\n\n/**\n * Jobs due to fire now. Skips disabled/paused/completed jobs and jobs without a\n * nextRunAt. One-shots fire up to 120s late (flat recovery grace); beyond that\n * they are marked state \"error\" and skipped. Recurring jobs whose nextRunAt is\n * older than the grace window — min(max(period/2, 120s), 2h) — are fast-forwarded\n * to their next future slot but still fire ONCE now (collapse backlog, no burst).\n */\nexport async function getDueJobs(now: Date = new Date()): Promise<CronJob[]> {\n\tconst due: CronJob[] = [];\n\tlet changed = false;\n\tfor (const job of loadJobs()) {\n\t\tif (!job.enabled || job.state === \"paused\" || job.state === \"completed\") continue;\n\t\tif (!job.nextRunAt) continue;\n\t\tconst next = new Date(job.nextRunAt).getTime();\n\t\tif (Number.isNaN(next) || now.getTime() < next) continue;\n\n\t\tif (job.schedule.kind === \"once\") {\n\t\t\tif (now.getTime() - next <= ONE_SHOT_GRACE_MS) {\n\t\t\t\tdue.push(job);\n\t\t\t} else {\n\t\t\t\tjob.state = \"error\";\n\t\t\t\tjob.lastStatus = \"error\";\n\t\t\t\tjob.lastError = \"missed one-shot schedule beyond the 120s recovery grace\";\n\t\t\t\tjob.nextRunAt = null;\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst grace = Math.min(Math.max(periodMs(job, now) / 2, MIN_GRACE_MS), MAX_GRACE_MS);\n\t\tif (now.getTime() - next > grace) {\n\t\t\tjob.nextRunAt = nextSlotAfter(job, now)?.toISOString() ?? null;\n\t\t\tchanged = true;\n\t\t}\n\t\tdue.push(job);\n\t}\n\tif (changed) await persist();\n\treturn due;\n}\n\n/**\n * Advance a recurring job to its next slot. Called by the scheduler BEFORE\n * execution so a crash mid-run loses at most that run (at-most-once).\n */\nexport async function advanceNextRun(jobId: string): Promise<CronJob> {\n\tconst job = getJob(jobId);\n\tif (job.schedule.kind !== \"once\") {\n\t\t// Advance to the first slot strictly after NOW: the job fires once for the\n\t\t// current slot, and the next fire is the next future slot (no catch-up burst).\n\t\tjob.nextRunAt = nextSlotAfter(job, new Date())?.toISOString() ?? computeNextRun(job)?.toISOString() ?? null;\n\t\tawait persist();\n\t}\n\treturn job;\n}\n\n/**\n * Record a finished run: lastRunAt/lastStatus/lastError, repeat.completed++,\n * then either complete the job (finite repeats exhausted, one-shots included)\n * or re-anchor nextRunAt off the previous scheduled slot (no drift).\n */\nexport async function markJobRun(jobId: string, result: { status: CronJobStatus; error?: string }): Promise<CronJob> {\n\tconst job = getJob(jobId);\n\tconst now = new Date();\n\tjob.lastRunAt = now.toISOString();\n\tjob.lastStatus = result.status;\n\tjob.lastError = result.error ?? null;\n\tjob.repeat.completed += 1;\n\tif (job.repeat.times !== null && job.repeat.completed >= job.repeat.times) {\n\t\tjob.state = \"completed\";\n\t\tjob.nextRunAt = null;\n\t} else if (job.schedule.kind === \"interval\") {\n\t\t// Anchor to the previous scheduled slot + period to avoid cumulative drift.\n\t\t// If advanceNextRun already moved nextRunAt into the future (scheduler path),\n\t\t// keep it; otherwise (manual run) step forward from now.\n\t\tconst current = job.nextRunAt ? new Date(job.nextRunAt) : now;\n\t\tif (current.getTime() > now.getTime()) {\n\t\t\t// Already advanced by the scheduler — keep the scheduled slot.\n\t\t\tjob.nextRunAt = current.toISOString();\n\t\t} else {\n\t\t\tjob.nextRunAt = nextSlotAfter(job, now)?.toISOString() ?? null;\n\t\t}\n\t} else if (job.schedule.kind === \"cron\") {\n\t\tjob.nextRunAt = new Cron(job.schedule.expr!).nextRun(now)?.toISOString() ?? null;\n\t}\n\tawait persist();\n\treturn job;\n}\n\n// ---------------------------------------------------------------------------\n// Per-run output\n// ---------------------------------------------------------------------------\n\nfunction formatStamp(d: Date): string {\n\tconst p = (n: number) => String(n).padStart(2, \"0\");\n\treturn `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}_${p(d.getHours())}-${p(d.getMinutes())}-${p(d.getSeconds())}`;\n}\n\nfunction parseStamp(stamp: string): Date {\n\tconst m = /^(\\d{4})-(\\d{2})-(\\d{2})_(\\d{2})-(\\d{2})-(\\d{2})/.exec(stamp);\n\tif (!m) return new Date();\n\treturn new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]), Number(m[4]), Number(m[5]), Number(m[6]));\n}\n\nlet lastOutputStamp = \"\";\n\n/** Monotonic timestamp stamp: never collides within the process, keeps lexicographic = chronological order. */\nfunction nextOutputStamp(): string {\n\tlet d = new Date();\n\tlet stamp = formatStamp(d);\n\tif (stamp <= lastOutputStamp) {\n\t\td = new Date(parseStamp(lastOutputStamp).getTime() + 1000);\n\t\tstamp = formatStamp(d);\n\t}\n\tlastOutputStamp = stamp;\n\treturn stamp;\n}\n\nfunction listOutputFiles(jobId: string): string[] {\n\tconst dir = outputDir(jobId);\n\tif (!existsSync(dir)) return [];\n\treturn readdirSync(dir)\n\t\t.filter((f) => f.endsWith(\".md\"))\n\t\t.sort();\n}\n\n/** Save a run's output and prune to the newest OUTPUT_RETENTION files. Returns the file path. */\nexport async function saveJobOutput(jobId: string, content: string): Promise<string> {\n\tconst dir = outputDir(jobId);\n\tmkdirSync(dir, { recursive: true });\n\tconst file = join(dir, `${nextOutputStamp()}.md`);\n\twriteFileSync(file, content, \"utf-8\");\n\tconst files = listOutputFiles(jobId);\n\twhile (files.length > OUTPUT_RETENTION) {\n\t\tconst oldest = files.shift();\n\t\tif (oldest) rmSync(join(dir, oldest), { force: true });\n\t}\n\treturn file;\n}\n\n/** Content of the newest output file for a job, or null when none exists. */\nexport function getLatestJobOutput(jobId: string): string | null {\n\tconst files = listOutputFiles(jobId);\n\tconst latest = files[files.length - 1];\n\tif (!latest) return null;\n\ttry {\n\t\treturn readFileSync(join(outputDir(jobId), latest), \"utf-8\");\n\t} catch {\n\t\treturn null;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../../../src/core/cron/jobs.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * lunR: cron job model + persistent store (Phase 1 of the cron/gateway roadmap).\n *\n * Jobs persist at `<agentDir>/cron/jobs.json` (`{ jobs: [...], updated_at }`),\n * agentDir resolved via getAgentDir() (honors PI_CODING_AGENT_DIR, defaults\n * ~/.lunr/agent). Writes are atomic (tmp file in the same dir + rename) and\n * serialized with a cross-process read-modify-write lock over fresh data.\n *\n * Per-run output goes to `<agentDir>/cron/output/<jobId>/<YYYY-MM-DD_HH-MM-SS>.md`\n * with a retention cap of the newest 50 files per job.\n *\n * Tests inject a base dir via setCronBaseDir() so no real agent dir is touched.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport {\n\texistsSync,\n\tmkdirSync,\n\treaddirSync,\n\treadFileSync,\n\trealpathSync,\n\trenameSync,\n\trmSync,\n\tstatSync,\n\twriteFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { isAbsolute, join, normalize, relative, resolve, sep } from \"node:path\";\nimport { Cron } from \"croner\";\nimport lockfile from \"proper-lockfile\";\nimport { getAgentDir } from \"../../config.ts\";\nimport { loadGatewayConfig } from \"../../gateway/config.ts\";\nimport {\n\tchatPlatformDeliverBlockedMessage,\n\tdeliverMentionsChatPlatform,\n\tisFeatureEnabled,\n} from \"../install-features.ts\";\n\n// ---------------------------------------------------------------------------\n// Model\n// ---------------------------------------------------------------------------\n\nexport type CronScheduleKind = \"once\" | \"interval\" | \"cron\";\n\nexport interface CronSchedule {\n\tkind: CronScheduleKind;\n\t/** ISO timestamp, one-shots only. */\n\trunAt?: string;\n\t/** Interval length in minutes, interval kind only. */\n\tminutes?: number;\n\t/** 5-field cron expression, cron kind only. */\n\texpr?: string;\n}\n\nexport interface CronJobOrigin {\n\t/** Requester identity, absent on legacy jobs. Never persist adapter role grants. */\n\tuserId?: string;\n\tplatform: string;\n\tchatId: string;\n\tthreadId?: string;\n\tchatType?: string;\n}\n\nexport type CronJobState = \"scheduled\" | \"paused\" | \"completed\" | \"error\";\nexport type CronJobStatus = \"ok\" | \"error\";\n\nexport interface CronJob {\n\tid: string;\n\tname: string;\n\tprompt: string;\n\tschedule: CronSchedule;\n\tscheduleDisplay: string;\n\trepeat: { times: number | null; completed: number };\n\tenabled: boolean;\n\tstate: CronJobState;\n\tcreatedAt: string;\n\tnextRunAt: string | null;\n\tlastRunAt: string | null;\n\tlastStatus: CronJobStatus | null;\n\tlastError: string | null;\n\tlastDeliveryError: string | null;\n\t/** \"local\" | \"origin\" | \"telegram[:chatId]\" | \"discord[:chatId]\" (comma-combinable). v1 TUI only uses \"local\". */\n\tdeliver: string;\n\torigin?: CronJobOrigin | null;\n\t/** Job IDs whose latest output (8K chars cap each) is prepended to the prompt. */\n\tcontextFrom?: string[];\n\tworkdir?: string;\n\t/** Unknown interrupted effects require an explicit run, rather than ordinary resume. */\n\tinterrupted?: boolean;\n\t/** Durable claim written before dispatch. Interrupted claims require explicit retry. */\n\tactiveRun?: { id: string; scheduledAt: string | null; startedAt: string; advancedTo?: string | null };\n}\n\nexport interface CreateJobInput {\n\tprompt: string;\n\t/** Raw schedule input, parsed by parseSchedule(). */\n\tschedule: string;\n\tname?: string;\n\t/** Repetition cap; null = forever. One-shots are always times=1. */\n\ttimes?: number | null;\n\tdeliver?: string;\n\tcontextFrom?: string[];\n\tworkdir?: string;\n\torigin?: CronJobOrigin | null;\n}\n\nexport interface JobPatch {\n\tname?: string;\n\tprompt?: string;\n\t/** Raw schedule input; reparsed and re-anchors nextRunAt. */\n\tschedule?: string;\n\tdeliver?: string;\n\tenabled?: boolean;\n\ttimes?: number | null;\n\tcontextFrom?: string[];\n\tworkdir?: string;\n\torigin?: CronJobOrigin | null;\n\t/** Internal: manual-run trigger and delivery-error bookkeeping. */\n\tnextRunAt?: string | null;\n\tlastDeliveryError?: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Flat recovery grace for one-shots: fire up to 120s late. */\nexport const ONE_SHOT_GRACE_MS = 120_000;\n/** Per-job output retention. */\nexport const OUTPUT_RETENTION = 50;\n/** Cap per upstream job output injected via contextFrom. */\nexport const CONTEXT_OUTPUT_CAP = 8000;\n\nconst MAX_NAME_LEN = 50;\n\n// ---------------------------------------------------------------------------\n// Paths + store state\n// ---------------------------------------------------------------------------\n\nlet baseDirOverride: string | undefined;\nlet transactionJobs: CronJob[] | undefined;\nlet writeQueue: Promise<void> = Promise.resolve();\n\n/**\n * Override the base dir (defaults to the agent dir) and reset the in-memory\n * transaction queue. Passing undefined restores the default. For tests.\n */\nexport function setCronBaseDir(dir: string | undefined): void {\n\tbaseDirOverride = dir;\n\ttransactionJobs = undefined;\n\twriteQueue = Promise.resolve();\n}\n\nfunction cronDir(): string {\n\treturn join(baseDirOverride ?? getAgentDir(), \"cron\");\n}\n\nfunction jobsFile(): string {\n\treturn join(cronDir(), \"jobs.json\");\n}\n\nfunction outputDir(jobId: string): string {\n\treturn join(cronDir(), \"output\", jobId);\n}\n\nfunction loadJobs(): CronJob[] {\n\tif (transactionJobs) return transactionJobs;\n\tconst file = jobsFile();\n\tif (!existsSync(file)) return [];\n\tconst parsed = JSON.parse(readFileSync(file, \"utf-8\"));\n\tif (!Array.isArray(parsed?.jobs)) throw new Error(\"invalid cron job store\");\n\treturn parsed.jobs as CronJob[];\n}\n\n/** Each mutation reads the latest snapshot while holding the profile store lock. */\nfunction mutateJobs<T>(fn: () => T): Promise<T> {\n\tconst dir = cronDir();\n\tconst file = join(dir, \"jobs.json\");\n\tconst operation = writeQueue.then(async () => {\n\t\tmkdirSync(dir, { recursive: true });\n\t\tconst release = await lockfile.lock(file, {\n\t\t\trealpath: false,\n\t\t\tretries: { retries: 100, minTimeout: 10, maxTimeout: 100 },\n\t\t});\n\t\ttry {\n\t\t\ttransactionJobs = loadJobs();\n\t\t\tconst result = fn();\n\t\t\tconst tmp = join(dir, `.jobs.json.${randomUUID()}.tmp`);\n\t\t\ttry {\n\t\t\t\twriteFileSync(\n\t\t\t\t\ttmp,\n\t\t\t\t\tJSON.stringify({ jobs: transactionJobs, updated_at: new Date().toISOString() }, null, 2),\n\t\t\t\t);\n\t\t\t\trenameSync(tmp, file);\n\t\t\t} finally {\n\t\t\t\trmSync(tmp, { force: true });\n\t\t\t}\n\t\t\treturn structuredClone(result);\n\t\t} finally {\n\t\t\ttransactionJobs = undefined;\n\t\t\tawait release();\n\t\t}\n\t});\n\twriteQueue = operation.then(\n\t\t() => undefined,\n\t\t() => undefined,\n\t);\n\treturn operation;\n}\n\n/** Acquire the non-preemptive profile scheduler lease. A live PID is never displaced. */\nexport async function acquireSchedulerLease(): Promise<(() => Promise<void>) | null> {\n\tconst dir = cronDir();\n\tmkdirSync(dir, { recursive: true });\n\tconst file = join(dir, \"scheduler\");\n\tconst ownerFile = `${file}.owner.json`;\n\tconst staleMs = 120_000;\n\tif (existsSync(`${file}.lock`)) {\n\t\tlet owner: unknown;\n\t\ttry {\n\t\t\towner = JSON.parse(readFileSync(ownerFile, \"utf-8\"));\n\t\t\tif (\n\t\t\t\t!owner ||\n\t\t\t\ttypeof owner !== \"object\" ||\n\t\t\t\t!(\"pid\" in owner) ||\n\t\t\t\ttypeof owner.pid !== \"number\" ||\n\t\t\t\t!Number.isInteger(owner.pid) ||\n\t\t\t\towner.pid <= 0 ||\n\t\t\t\towner.pid > 2_147_483_647\n\t\t\t)\n\t\t\t\tthrow new Error(\"invalid scheduler owner PID\");\n\t\t} catch (error) {\n\t\t\t// A competing operator may still be publishing its owner record. Missing\n\t\t\t// or malformed metadata never proves that an existing owner is dead.\n\t\t\tif (!existsSync(`${file}.lock`)) return acquireSchedulerLease();\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n\t\t\t\ttry {\n\t\t\t\t\tif (Date.now() - statSync(`${file}.lock`).mtimeMs < staleMs) return null;\n\t\t\t\t} catch (lockError) {\n\t\t\t\t\tif ((lockError as NodeJS.ErrnoException).code === \"ENOENT\") return acquireSchedulerLease();\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new Error(\n\t\t\t\t`Cron scheduler ownership cannot be verified. Before repairing it, confirm every operator using this profile has stopped. ` +\n\t\t\t\t\t`Then remove ${file}.lock and ${ownerFile}, and restart scheduling. Never remove them while an operator may be running.`,\n\t\t\t\t{ cause: error },\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\tprocess.kill(owner.pid, 0);\n\t\t\treturn null;\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code !== \"ESRCH\") return null;\n\t\t}\n\t}\n\tlet release: () => Promise<void>;\n\ttry {\n\t\trelease = await lockfile.lock(file, { realpath: false, stale: staleMs });\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ELOCKED\") return null;\n\t\tthrow error;\n\t}\n\tconst ownerTmp = join(dir, `.scheduler.owner.json.${randomUUID()}.tmp`);\n\ttry {\n\t\twriteFileSync(ownerTmp, JSON.stringify({ pid: process.pid }));\n\t\trenameSync(ownerTmp, ownerFile);\n\t} catch (error) {\n\t\tawait release();\n\t\tthrow error;\n\t} finally {\n\t\trmSync(ownerTmp, { force: true });\n\t}\n\treturn async () => {\n\t\ttry {\n\t\t\trmSync(ownerFile, { force: true });\n\t\t} finally {\n\t\t\tawait release();\n\t\t}\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Schedule parsing\n// ---------------------------------------------------------------------------\n\nexport interface ParsedSchedule {\n\tschedule: CronSchedule;\n\tscheduleDisplay: string;\n}\n\nconst INTERVAL_RE = /^every\\s+(\\d+)\\s*([mhd])$/i;\nconst DURATION_RE = /^(\\d+)\\s*([mhd])$/i;\n\nfunction toMinutes(value: number, unit: string): number {\n\tconst u = unit.toLowerCase();\n\tconst factor = u === \"d\" ? 1440 : u === \"h\" ? 60 : 1;\n\treturn value * factor;\n}\n\n/**\n * Parse a schedule input:\n * - `every 30m` / `every 2h` / `every 1d` → interval (minutes; d = 1440)\n * - bare `30m` / `2h` / `1d` → one-shot at now + duration\n * - ISO timestamp → one-shot at that time\n * - 5-field cron expression (validated via croner; throws on invalid)\n */\nexport function parseSchedule(input: string, now: Date = new Date()): ParsedSchedule {\n\tconst text = input.trim().replace(/\\s+/g, \" \");\n\tif (!text) throw new Error(\"schedule is empty\");\n\n\tconst interval = INTERVAL_RE.exec(text);\n\tif (interval) {\n\t\tconst minutes = toMinutes(Number(interval[1]), interval[2]);\n\t\tif (minutes <= 0) throw new Error(`invalid interval: \"${text}\"`);\n\t\treturn {\n\t\t\tschedule: { kind: \"interval\", minutes },\n\t\t\tscheduleDisplay: `every ${Number(interval[1])}${interval[2].toLowerCase()}`,\n\t\t};\n\t}\n\n\tconst duration = DURATION_RE.exec(text);\n\tif (duration) {\n\t\tconst minutes = toMinutes(Number(duration[1]), duration[2]);\n\t\tif (minutes <= 0) throw new Error(`invalid duration: \"${text}\"`);\n\t\tconst runAt = new Date(now.getTime() + minutes * 60_000).toISOString();\n\t\treturn { schedule: { kind: \"once\", runAt }, scheduleDisplay: text };\n\t}\n\n\tif (/^\\d{4}-\\d{2}-\\d{2}/.test(text)) {\n\t\tconst ts = Date.parse(text);\n\t\tif (!Number.isNaN(ts)) {\n\t\t\tconst runAt = new Date(ts).toISOString();\n\t\t\treturn { schedule: { kind: \"once\", runAt }, scheduleDisplay: runAt };\n\t\t}\n\t}\n\n\tif (text.split(\" \").length === 5) {\n\t\ttry {\n\t\t\tnew Cron(text);\n\t\t} catch (err) {\n\t\t\tthrow new Error(`invalid cron expression \"${text}\": ${err instanceof Error ? err.message : String(err)}`);\n\t\t}\n\t\treturn { schedule: { kind: \"cron\", expr: text }, scheduleDisplay: text };\n\t}\n\n\tthrow new Error(\n\t\t`unrecognized schedule: \"${input}\" (expected \"every 30m\", \"2h\", an ISO timestamp, or a 5-field cron expression)`,\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// Next-run computation\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the next run time for a job:\n * - once: the stored runAt, recoverable within a 120s grace if never run; null after that or once run.\n * - interval: (lastRunAt ?? createdAt) + minutes.\n * - cron: croner nextRun after (lastRunAt ?? now).\n */\nexport function computeNextRun(job: CronJob, now: Date = new Date()): Date | null {\n\tconst s = job.schedule;\n\tif (s.kind === \"once\") {\n\t\tif (job.repeat.completed > 0) return null;\n\t\tif (!s.runAt) return null;\n\t\tconst runAt = new Date(s.runAt);\n\t\tif (Number.isNaN(runAt.getTime())) return null;\n\t\treturn now.getTime() - runAt.getTime() <= ONE_SHOT_GRACE_MS ? runAt : null;\n\t}\n\tif (s.kind === \"interval\") {\n\t\tconst base = job.lastRunAt ? new Date(job.lastRunAt) : new Date(job.createdAt);\n\t\treturn new Date(base.getTime() + (s.minutes ?? 0) * 60_000);\n\t}\n\tconst cron = new Cron(s.expr!);\n\treturn cron.nextRun(job.lastRunAt ? new Date(job.lastRunAt) : now);\n}\n\n/** Next slot strictly after `after` for a recurring job. */\nfunction nextSlotAfter(job: CronJob, after: Date): Date | null {\n\tif (job.schedule.kind === \"interval\") {\n\t\tconst period = (job.schedule.minutes ?? 0) * 60_000;\n\t\tif (period <= 0) return null;\n\t\t// Step forward from the stored nextRunAt (or now) until strictly in the future of `after`.\n\t\tlet slot = job.nextRunAt ? new Date(job.nextRunAt).getTime() : new Date(job.createdAt).getTime() + period;\n\t\twhile (slot <= after.getTime()) slot += period;\n\t\treturn new Date(slot);\n\t}\n\tif (job.schedule.kind === \"cron\") {\n\t\treturn new Cron(job.schedule.expr!).nextRun(after);\n\t}\n\treturn null;\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\nlet workdirRoots: string[] = [process.cwd(), homedir()];\nlet deliverValidator: ((deliver: string, origin?: CronJobOrigin | null) => string | undefined) | undefined;\n\n/**\n * Configure the allowed absolute roots for cron job workdirs. Relative workdirs\n * are resolved against process.cwd() and must fall under one of these roots.\n * Default roots are process.cwd() and the user's home directory.\n */\nexport function setCronWorkdirRoots(roots: string[]): void {\n\tworkdirRoots = roots.map((r) => normalize(resolve(r)));\n}\n\n/**\n * Configure a deliver-target validator. When set, createJob/updateJob reject\n * deliver strings that the validator does not approve. The gateway uses this\n * to prevent delivery to arbitrary chats.\n */\nexport function setCronDeliverValidator(\n\tfn: ((deliver: string, origin?: CronJobOrigin | null) => string | undefined) | undefined,\n): void {\n\tdeliverValidator = fn;\n}\n\n/** Test seam: restore default validation state. */\nexport function resetCronValidators(): void {\n\tworkdirRoots = [process.cwd(), homedir()];\n\tdeliverValidator = undefined;\n}\n\nfunction isPathUnderRoot(absPath: string, root: string): boolean {\n\tconst rel = relative(root, absPath);\n\treturn rel === \"\" || (!rel.startsWith(`..${sep}`) && rel !== \"..\" && !isAbsolute(rel));\n}\n\nfunction validateWorkdir(workdir: string, origin?: CronJobOrigin | null): string | undefined {\n\tconst candidate = origin ? realpathSync(resolve(workdir)) : resolve(workdir);\n\tconst roots = origin\n\t\t? (loadGatewayConfig().projectRoots ?? []).flatMap((root) => {\n\t\t\t\ttry {\n\t\t\t\t\treturn [realpathSync(root)];\n\t\t\t\t} catch {\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t})\n\t\t: workdirRoots;\n\tif (isAbsolute(workdir) && !roots.some((root) => isPathUnderRoot(candidate, root))) {\n\t\treturn `workdir ${workdir} is outside allowed roots`;\n\t}\n\tif (!roots.some((root) => isPathUnderRoot(candidate, root))) {\n\t\treturn `workdir ${workdir} resolves outside allowed roots`;\n\t}\n\treturn undefined;\n}\n\nfunction runDeliverValidation(deliver: string, origin?: CronJobOrigin | null): string | undefined {\n\tif (deliverMentionsChatPlatform(deliver) && !isFeatureEnabled(\"chat-platforms\")) {\n\t\treturn chatPlatformDeliverBlockedMessage();\n\t}\n\treturn deliverValidator?.(deliver, origin);\n}\n\nfunction deriveName(prompt: string): string {\n\tconst first = prompt.split(\"\\n\")[0].replace(/\\s+/g, \" \").trim();\n\treturn (first || \"cron job\").slice(0, MAX_NAME_LEN);\n}\n\nexport async function createJob(input: CreateJobInput): Promise<CronJob> {\n\treturn mutateJobs(() => {\n\t\tconst prompt = input.prompt.trim();\n\t\tif (!prompt) throw new Error(\"createJob: prompt is empty\");\n\t\tif (input.workdir) {\n\t\t\tconst err = validateWorkdir(input.workdir, input.origin);\n\t\t\tif (err) throw new Error(`createJob: ${err}`);\n\t\t}\n\t\tif (input.deliver) {\n\t\t\tconst err = runDeliverValidation(input.deliver, input.origin);\n\t\t\tif (err) throw new Error(`createJob: ${err}`);\n\t\t}\n\t\tconst now = new Date();\n\t\tconst parsed = parseSchedule(input.schedule, now);\n\t\tconst isOneShot = parsed.schedule.kind === \"once\";\n\t\tconst times = isOneShot ? 1 : (input.times ?? null);\n\t\tif (times !== null && (!Number.isInteger(times) || times < 1)) {\n\t\t\tthrow new Error(`createJob: times must be a positive integer or null, got ${times}`);\n\t\t}\n\t\tconst job: CronJob = {\n\t\t\tid: randomUUID().replaceAll(\"-\", \"\").slice(0, 12),\n\t\t\tname: (input.name?.trim() || deriveName(prompt)).slice(0, MAX_NAME_LEN),\n\t\t\tprompt,\n\t\t\tschedule: parsed.schedule,\n\t\t\tscheduleDisplay: parsed.scheduleDisplay,\n\t\t\trepeat: { times, completed: 0 },\n\t\t\tenabled: true,\n\t\t\tstate: \"scheduled\",\n\t\t\tcreatedAt: now.toISOString(),\n\t\t\tnextRunAt: null,\n\t\t\tlastRunAt: null,\n\t\t\tlastStatus: null,\n\t\t\tlastError: null,\n\t\t\tlastDeliveryError: null,\n\t\t\tdeliver: input.deliver?.trim() || \"local\",\n\t\t\torigin: input.origin ?? null,\n\t\t\tcontextFrom: input.contextFrom,\n\t\t\tworkdir: input.workdir,\n\t\t};\n\t\tjob.nextRunAt = computeNextRun(job, now)?.toISOString() ?? null;\n\t\tloadJobs().push(job);\n\t\treturn job;\n\t});\n}\n\n/** Look up a job by id, then by unique name. Throws when not found or when the name is ambiguous. */\nexport function getJob(idOrName: string): CronJob {\n\tconst jobs = loadJobs();\n\tconst byId = jobs.find((j) => j.id === idOrName);\n\tif (byId) return byId;\n\tconst byName = jobs.filter((j) => j.name === idOrName);\n\tif (byName.length === 1) return byName[0];\n\tif (byName.length > 1) {\n\t\tthrow new Error(\n\t\t\t`cron job name \"${idOrName}\" is ambiguous (${byName.length} matches: ${byName.map((j) => j.id).join(\", \")})`,\n\t\t);\n\t}\n\tthrow new Error(`no cron job matches \"${idOrName}\"`);\n}\n\nexport function listJobs(): CronJob[] {\n\treturn [...loadJobs()];\n}\n\nexport async function updateJob(idOrName: string, patch: JobPatch): Promise<CronJob> {\n\treturn mutateJobs(() => {\n\t\tconst job = getJob(idOrName);\n\t\tif (patch.name !== undefined) job.name = patch.name.trim().slice(0, MAX_NAME_LEN) || job.name;\n\t\tif (patch.workdir !== undefined) {\n\t\t\tif (patch.workdir) {\n\t\t\t\tconst err = validateWorkdir(patch.workdir, patch.origin ?? job.origin);\n\t\t\t\tif (err) throw new Error(`updateJob: ${err}`);\n\t\t\t}\n\t\t\tjob.workdir = patch.workdir;\n\t\t}\n\t\tif (patch.deliver !== undefined) {\n\t\t\tconst err = runDeliverValidation(patch.deliver, patch.origin ?? job.origin);\n\t\t\tif (err) throw new Error(`updateJob: ${err}`);\n\t\t\tjob.deliver = patch.deliver.trim() || \"local\";\n\t\t}\n\t\tif (patch.prompt !== undefined) {\n\t\t\tconst prompt = patch.prompt.trim();\n\t\t\tif (!prompt) throw new Error(\"updateJob: prompt is empty\");\n\t\t\tjob.prompt = prompt;\n\t\t}\n\t\tif (patch.schedule !== undefined) {\n\t\t\tconst parsed = parseSchedule(patch.schedule);\n\t\t\tjob.schedule = parsed.schedule;\n\t\t\tjob.scheduleDisplay = parsed.scheduleDisplay;\n\t\t\tif (parsed.schedule.kind === \"once\") job.repeat.times = 1;\n\t\t\tjob.nextRunAt = computeNextRun(job)?.toISOString() ?? null;\n\t\t}\n\t\tif (patch.enabled !== undefined) job.enabled = patch.enabled;\n\t\tif (patch.times !== undefined) {\n\t\t\tif (patch.times !== null && (!Number.isInteger(patch.times) || patch.times < 1)) {\n\t\t\t\tthrow new Error(`updateJob: times must be a positive integer or null, got ${patch.times}`);\n\t\t\t}\n\t\t\tif (job.schedule.kind !== \"once\") job.repeat.times = patch.times;\n\t\t}\n\t\tif (patch.contextFrom !== undefined) job.contextFrom = patch.contextFrom;\n\t\tif (patch.origin !== undefined) job.origin = patch.origin;\n\t\tif (patch.nextRunAt !== undefined) job.nextRunAt = patch.nextRunAt;\n\t\tif (patch.lastDeliveryError !== undefined) job.lastDeliveryError = patch.lastDeliveryError;\n\t\treturn job;\n\t});\n}\n\nexport async function pauseJob(idOrName: string): Promise<CronJob> {\n\treturn mutateJobs(() => {\n\t\tconst job = getJob(idOrName);\n\t\tif (job.state !== \"completed\") job.state = \"paused\";\n\t\treturn job;\n\t});\n}\n\nexport async function resumeJob(idOrName: string): Promise<CronJob> {\n\treturn mutateJobs(() => {\n\t\tconst job = getJob(idOrName);\n\t\tif (job.interrupted)\n\t\t\tthrow new Error(\"interrupted run has unknown effects; inspect them and use cron run for a deliberate retry\");\n\t\tif (job.state === \"paused\") {\n\t\t\tjob.state = \"scheduled\";\n\t\t\tjob.nextRunAt = computeNextRun(job)?.toISOString() ?? null;\n\t\t}\n\t\treturn job;\n\t});\n}\n\nexport async function removeJob(idOrName: string): Promise<CronJob> {\n\treturn mutateJobs(() => {\n\t\tconst job = getJob(idOrName);\n\t\tconst jobs = loadJobs();\n\t\tjobs.splice(jobs.indexOf(job), 1);\n\t\treturn job;\n\t});\n}\n\n// ---------------------------------------------------------------------------\n// Scheduling\n// ---------------------------------------------------------------------------\n\n/**\n * Jobs due to fire now. Skips disabled/paused/completed jobs and jobs without a\n * nextRunAt. One-shots fire up to 120s late (flat recovery grace); beyond that\n * they are marked state \"error\" and skipped. Recurring backlog fires once;\n * claiming the occurrence advances it to the next future slot without a burst.\n */\nexport async function getDueJobs(now: Date = new Date()): Promise<CronJob[]> {\n\treturn mutateJobs(() => {\n\t\tconst due: CronJob[] = [];\n\t\tfor (const job of loadJobs()) {\n\t\t\tif (!job.enabled || job.state !== \"scheduled\" || job.activeRun) continue;\n\t\t\tif (!job.nextRunAt) continue;\n\t\t\tconst next = new Date(job.nextRunAt).getTime();\n\t\t\tif (Number.isNaN(next) || now.getTime() < next) continue;\n\n\t\t\tif (job.schedule.kind === \"once\") {\n\t\t\t\tif (now.getTime() - next <= ONE_SHOT_GRACE_MS) {\n\t\t\t\t\tdue.push(job);\n\t\t\t\t} else {\n\t\t\t\t\tjob.state = \"error\";\n\t\t\t\t\tjob.lastStatus = \"error\";\n\t\t\t\t\tjob.lastError = \"missed one-shot schedule beyond the 120s recovery grace\";\n\t\t\t\t\tjob.nextRunAt = null;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tdue.push(job);\n\t\t}\n\t\treturn due;\n\t});\n}\n\n/**\n * Advance a recurring job to its next slot. Scheduler dispatch uses claimJobRun\n * instead so one-shots and recurring work both retain a durable claim.\n */\nexport async function advanceNextRun(jobId: string): Promise<CronJob> {\n\treturn mutateJobs(() => {\n\t\tconst job = getJob(jobId);\n\t\tif (job.schedule.kind !== \"once\") {\n\t\t\t// Advance to the first slot strictly after NOW: the job fires once for the\n\t\t\t// current slot, and the next fire is the next future slot (no catch-up burst).\n\t\t\tjob.nextRunAt = nextSlotAfter(job, new Date())?.toISOString() ?? computeNextRun(job)?.toISOString() ?? null;\n\t\t}\n\t\treturn job;\n\t});\n}\n\n/**\n * Record a finished run: lastRunAt/lastStatus/lastError, repeat.completed++,\n * then either complete the job (finite repeats exhausted, one-shots included)\n * or re-anchor nextRunAt off the previous scheduled slot (no drift).\n */\nexport async function markJobRun(\n\tjobId: string,\n\tresult: { status: CronJobStatus; error?: string; runId?: string },\n): Promise<CronJob | null> {\n\treturn mutateJobs(() => {\n\t\tconst job = loadJobs().find((job) => job.id === jobId);\n\t\tif (!job || (result.runId && job.activeRun?.id !== result.runId)) return null;\n\t\tdelete job.activeRun;\n\t\tdelete job.interrupted;\n\t\tconst now = new Date();\n\t\tjob.lastRunAt = now.toISOString();\n\t\tjob.lastStatus = result.status;\n\t\tjob.lastError = result.error ?? null;\n\t\tjob.repeat.completed += 1;\n\t\tif (job.repeat.times !== null && job.repeat.completed >= job.repeat.times) {\n\t\t\tjob.state = \"completed\";\n\t\t\tjob.nextRunAt = null;\n\t\t} else if (!result.runId && job.schedule.kind === \"interval\") {\n\t\t\t// Anchor to the previous scheduled slot + period to avoid cumulative drift.\n\t\t\t// If advanceNextRun already moved nextRunAt into the future (scheduler path),\n\t\t\t// keep it; otherwise (manual run) step forward from now.\n\t\t\tconst current = job.nextRunAt ? new Date(job.nextRunAt) : now;\n\t\t\tif (current.getTime() > now.getTime()) {\n\t\t\t\t// Already advanced by the scheduler — keep the scheduled slot.\n\t\t\t\tjob.nextRunAt = current.toISOString();\n\t\t\t} else {\n\t\t\t\tjob.nextRunAt = nextSlotAfter(job, now)?.toISOString() ?? null;\n\t\t\t}\n\t\t} else if (!result.runId && job.schedule.kind === \"cron\") {\n\t\t\tjob.nextRunAt = new Cron(job.schedule.expr!).nextRun(now)?.toISOString() ?? null;\n\t\t}\n\t\treturn job;\n\t});\n}\n\n/** Claim only a still-due, enabled occurrence from the fresh store. */\nexport async function claimJobRun(jobId: string, now: Date, manual = false): Promise<CronJob | null> {\n\treturn mutateJobs(() => {\n\t\tconst job = loadJobs().find((job) => job.id === jobId);\n\t\tif (!job || job.activeRun) return null;\n\t\tif (!manual && (!job.enabled || job.state !== \"scheduled\" || !job.nextRunAt || new Date(job.nextRunAt) > now))\n\t\t\treturn null;\n\t\tjob.activeRun = { id: randomUUID(), scheduledAt: job.nextRunAt, startedAt: now.toISOString() };\n\t\tjob.nextRunAt = job.schedule.kind === \"once\" ? null : (nextSlotAfter(job, now)?.toISOString() ?? null);\n\t\tjob.activeRun.advancedTo = job.nextRunAt;\n\t\treturn job;\n\t});\n}\n\n/** Recover uncertain interrupted work without replaying its external effects. */\nexport async function recoverInterruptedRuns(): Promise<void> {\n\tawait mutateJobs(() => {\n\t\tfor (const job of loadJobs()) {\n\t\t\tif (!job.activeRun) continue;\n\t\t\tjob.state = \"paused\";\n\t\t\tjob.lastStatus = \"error\";\n\t\t\tjob.lastError = \"interrupted run has unknown effects; use cron run to retry deliberately\";\n\t\t\tjob.interrupted = true;\n\t\t\tdelete job.activeRun;\n\t\t}\n\t});\n}\n\nexport async function deferJobRun(jobId: string, runId: string): Promise<void> {\n\tawait mutateJobs(() => {\n\t\tconst job = loadJobs().find((job) => job.id === jobId);\n\t\tif (job?.activeRun?.id !== runId) return;\n\t\tif (job.nextRunAt === job.activeRun.advancedTo) job.nextRunAt = job.activeRun.scheduledAt;\n\t\tdelete job.activeRun;\n\t});\n}\n\n// ---------------------------------------------------------------------------\n// Per-run output\n// ---------------------------------------------------------------------------\n\nfunction formatStamp(d: Date): string {\n\tconst p = (n: number) => String(n).padStart(2, \"0\");\n\treturn `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}_${p(d.getHours())}-${p(d.getMinutes())}-${p(d.getSeconds())}`;\n}\n\nfunction parseStamp(stamp: string): Date {\n\tconst m = /^(\\d{4})-(\\d{2})-(\\d{2})_(\\d{2})-(\\d{2})-(\\d{2})/.exec(stamp);\n\tif (!m) return new Date();\n\treturn new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]), Number(m[4]), Number(m[5]), Number(m[6]));\n}\n\nlet lastOutputStamp = \"\";\n\n/** Monotonic timestamp stamp: never collides within the process, keeps lexicographic = chronological order. */\nfunction nextOutputStamp(): string {\n\tlet d = new Date();\n\tlet stamp = formatStamp(d);\n\tif (stamp <= lastOutputStamp) {\n\t\td = new Date(parseStamp(lastOutputStamp).getTime() + 1000);\n\t\tstamp = formatStamp(d);\n\t}\n\tlastOutputStamp = stamp;\n\treturn stamp;\n}\n\nfunction listOutputFiles(jobId: string): string[] {\n\tconst dir = outputDir(jobId);\n\tif (!existsSync(dir)) return [];\n\treturn readdirSync(dir)\n\t\t.filter((f) => f.endsWith(\".md\"))\n\t\t.sort();\n}\n\n/** Save a run's output and prune to the newest OUTPUT_RETENTION files. Returns the file path. */\nexport async function saveJobOutput(jobId: string, content: string): Promise<string> {\n\tconst dir = outputDir(jobId);\n\tmkdirSync(dir, { recursive: true });\n\tconst file = join(dir, `${nextOutputStamp()}.md`);\n\twriteFileSync(file, content, \"utf-8\");\n\tconst files = listOutputFiles(jobId);\n\twhile (files.length > OUTPUT_RETENTION) {\n\t\tconst oldest = files.shift();\n\t\tif (oldest) rmSync(join(dir, oldest), { force: true });\n\t}\n\treturn file;\n}\n\n/** Content of the newest output file for a job, or null when none exists. */\nexport function getLatestJobOutput(jobId: string): string | null {\n\tconst files = listOutputFiles(jobId);\n\tconst latest = files[files.length - 1];\n\tif (!latest) return null;\n\ttry {\n\t\treturn readFileSync(join(outputDir(jobId), latest), \"utf-8\");\n\t} catch {\n\t\treturn null;\n\t}\n}\n"]}
|