@zhijiewang/openharness 0.11.1 → 0.12.1
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/README.md +212 -23
- package/dist/DeferredTool.d.ts +34 -0
- package/dist/DeferredTool.js +62 -0
- package/dist/agents/roles.js +62 -6
- package/dist/commands/index.js +31 -2
- package/dist/harness/config.d.ts +15 -0
- package/dist/harness/config.js +45 -23
- package/dist/harness/memory.d.ts +12 -0
- package/dist/harness/memory.js +53 -2
- package/dist/harness/session.d.ts +19 -0
- package/dist/harness/session.js +53 -0
- package/dist/harness/verification.d.ts +41 -0
- package/dist/harness/verification.js +197 -0
- package/dist/mcp/registry.d.ts +31 -0
- package/dist/mcp/registry.js +180 -0
- package/dist/query/index.js +9 -1
- package/dist/query/tools.js +30 -4
- package/dist/repl.js +34 -0
- package/dist/services/AgentDispatcher.d.ts +1 -0
- package/dist/services/AgentDispatcher.js +10 -1
- package/dist/services/CronExecutor.d.ts +38 -0
- package/dist/services/CronExecutor.js +130 -0
- package/dist/services/StreamingToolExecutor.js +28 -0
- package/dist/services/cron.d.ts +4 -0
- package/dist/services/cron.js +27 -0
- package/dist/tools/AgentTool/index.d.ts +3 -0
- package/dist/tools/AgentTool/index.js +17 -4
- package/dist/tools/MemoryTool/index.d.ts +2 -2
- package/dist/tools/ToolSearchTool/index.js +7 -0
- package/dist/tools.d.ts +8 -0
- package/dist/tools.js +40 -41
- package/package.json +5 -2
- package/dist/Tool.d.ts.map +0 -1
- package/dist/Tool.js.map +0 -1
- package/dist/Tool.test.d.ts +0 -2
- package/dist/Tool.test.d.ts.map +0 -1
- package/dist/Tool.test.js +0 -48
- package/dist/Tool.test.js.map +0 -1
- package/dist/agents/roles.d.ts.map +0 -1
- package/dist/agents/roles.js.map +0 -1
- package/dist/agents/roles.test.d.ts +0 -2
- package/dist/agents/roles.test.d.ts.map +0 -1
- package/dist/agents/roles.test.js +0 -38
- package/dist/agents/roles.test.js.map +0 -1
- package/dist/commands/commands-new.test.d.ts +0 -5
- package/dist/commands/commands-new.test.d.ts.map +0 -1
- package/dist/commands/commands-new.test.js +0 -132
- package/dist/commands/commands-new.test.js.map +0 -1
- package/dist/commands/commands.test.d.ts +0 -2
- package/dist/commands/commands.test.d.ts.map +0 -1
- package/dist/commands/commands.test.js +0 -98
- package/dist/commands/commands.test.js.map +0 -1
- package/dist/commands/cybergotchi.d.ts.map +0 -1
- package/dist/commands/cybergotchi.js.map +0 -1
- package/dist/commands/index.d.ts.map +0 -1
- package/dist/commands/index.js.map +0 -1
- package/dist/components/App.d.ts.map +0 -1
- package/dist/components/App.js.map +0 -1
- package/dist/components/CompanionFooter.d.ts.map +0 -1
- package/dist/components/CompanionFooter.js.map +0 -1
- package/dist/components/CybergotchiBubble.d.ts.map +0 -1
- package/dist/components/CybergotchiBubble.js.map +0 -1
- package/dist/components/CybergotchiPanel.d.ts.map +0 -1
- package/dist/components/CybergotchiPanel.js.map +0 -1
- package/dist/components/CybergotchiPanelConnected.d.ts.map +0 -1
- package/dist/components/CybergotchiPanelConnected.js.map +0 -1
- package/dist/components/CybergotchiSetup.d.ts.map +0 -1
- package/dist/components/CybergotchiSetup.js.map +0 -1
- package/dist/components/CybergotchiSprite.d.ts.map +0 -1
- package/dist/components/CybergotchiSprite.js.map +0 -1
- package/dist/components/DiffView.d.ts.map +0 -1
- package/dist/components/DiffView.js.map +0 -1
- package/dist/components/ErrorBoundary.d.ts.map +0 -1
- package/dist/components/ErrorBoundary.js.map +0 -1
- package/dist/components/InitWizard.d.ts.map +0 -1
- package/dist/components/InitWizard.js.map +0 -1
- package/dist/components/Markdown.d.ts.map +0 -1
- package/dist/components/Markdown.js.map +0 -1
- package/dist/components/Messages.d.ts.map +0 -1
- package/dist/components/Messages.js.map +0 -1
- package/dist/components/PermissionPrompt.d.ts.map +0 -1
- package/dist/components/PermissionPrompt.js.map +0 -1
- package/dist/components/REPL.d.ts.map +0 -1
- package/dist/components/REPL.js.map +0 -1
- package/dist/components/Spinner.d.ts.map +0 -1
- package/dist/components/Spinner.js.map +0 -1
- package/dist/components/TextInput.d.ts.map +0 -1
- package/dist/components/TextInput.js.map +0 -1
- package/dist/components/ToolCallDisplay.d.ts.map +0 -1
- package/dist/components/ToolCallDisplay.js.map +0 -1
- package/dist/cybergotchi/bones.d.ts.map +0 -1
- package/dist/cybergotchi/bones.js.map +0 -1
- package/dist/cybergotchi/bones.test.d.ts +0 -2
- package/dist/cybergotchi/bones.test.d.ts.map +0 -1
- package/dist/cybergotchi/bones.test.js +0 -100
- package/dist/cybergotchi/bones.test.js.map +0 -1
- package/dist/cybergotchi/config.d.ts.map +0 -1
- package/dist/cybergotchi/config.js.map +0 -1
- package/dist/cybergotchi/events.d.ts.map +0 -1
- package/dist/cybergotchi/events.js.map +0 -1
- package/dist/cybergotchi/needs.d.ts.map +0 -1
- package/dist/cybergotchi/needs.js.map +0 -1
- package/dist/cybergotchi/needs.test.d.ts +0 -2
- package/dist/cybergotchi/needs.test.d.ts.map +0 -1
- package/dist/cybergotchi/needs.test.js +0 -150
- package/dist/cybergotchi/needs.test.js.map +0 -1
- package/dist/cybergotchi/personality.d.ts.map +0 -1
- package/dist/cybergotchi/personality.js.map +0 -1
- package/dist/cybergotchi/species.d.ts.map +0 -1
- package/dist/cybergotchi/species.js.map +0 -1
- package/dist/cybergotchi/speech.d.ts.map +0 -1
- package/dist/cybergotchi/speech.js.map +0 -1
- package/dist/cybergotchi/types.d.ts.map +0 -1
- package/dist/cybergotchi/types.js.map +0 -1
- package/dist/cybergotchi/useCybergotchi.d.ts.map +0 -1
- package/dist/cybergotchi/useCybergotchi.js.map +0 -1
- package/dist/git/git.test.d.ts +0 -2
- package/dist/git/git.test.d.ts.map +0 -1
- package/dist/git/git.test.js +0 -141
- package/dist/git/git.test.js.map +0 -1
- package/dist/git/index.d.ts.map +0 -1
- package/dist/git/index.js.map +0 -1
- package/dist/harness/checkpoints.d.ts.map +0 -1
- package/dist/harness/checkpoints.js.map +0 -1
- package/dist/harness/config.d.ts.map +0 -1
- package/dist/harness/config.js.map +0 -1
- package/dist/harness/config.test.d.ts +0 -2
- package/dist/harness/config.test.d.ts.map +0 -1
- package/dist/harness/config.test.js +0 -107
- package/dist/harness/config.test.js.map +0 -1
- package/dist/harness/context-warning.d.ts.map +0 -1
- package/dist/harness/context-warning.js.map +0 -1
- package/dist/harness/context-warning.test.d.ts +0 -2
- package/dist/harness/context-warning.test.d.ts.map +0 -1
- package/dist/harness/context-warning.test.js +0 -72
- package/dist/harness/context-warning.test.js.map +0 -1
- package/dist/harness/cost.d.ts.map +0 -1
- package/dist/harness/cost.js.map +0 -1
- package/dist/harness/cost.test.d.ts +0 -2
- package/dist/harness/cost.test.d.ts.map +0 -1
- package/dist/harness/cost.test.js +0 -43
- package/dist/harness/cost.test.js.map +0 -1
- package/dist/harness/credentials.d.ts.map +0 -1
- package/dist/harness/credentials.js.map +0 -1
- package/dist/harness/credentials.test.d.ts +0 -2
- package/dist/harness/credentials.test.d.ts.map +0 -1
- package/dist/harness/credentials.test.js +0 -113
- package/dist/harness/credentials.test.js.map +0 -1
- package/dist/harness/hooks-env.test.d.ts +0 -5
- package/dist/harness/hooks-env.test.d.ts.map +0 -1
- package/dist/harness/hooks-env.test.js +0 -41
- package/dist/harness/hooks-env.test.js.map +0 -1
- package/dist/harness/hooks.d.ts.map +0 -1
- package/dist/harness/hooks.js.map +0 -1
- package/dist/harness/hooks.test.d.ts +0 -2
- package/dist/harness/hooks.test.d.ts.map +0 -1
- package/dist/harness/hooks.test.js +0 -24
- package/dist/harness/hooks.test.js.map +0 -1
- package/dist/harness/keybindings.d.ts.map +0 -1
- package/dist/harness/keybindings.js.map +0 -1
- package/dist/harness/keybindings.test.d.ts +0 -2
- package/dist/harness/keybindings.test.d.ts.map +0 -1
- package/dist/harness/keybindings.test.js +0 -38
- package/dist/harness/keybindings.test.js.map +0 -1
- package/dist/harness/memory.d.ts.map +0 -1
- package/dist/harness/memory.js.map +0 -1
- package/dist/harness/memory.test.d.ts +0 -2
- package/dist/harness/memory.test.d.ts.map +0 -1
- package/dist/harness/memory.test.js +0 -65
- package/dist/harness/memory.test.js.map +0 -1
- package/dist/harness/onboarding.d.ts.map +0 -1
- package/dist/harness/onboarding.js.map +0 -1
- package/dist/harness/onboarding.test.d.ts +0 -5
- package/dist/harness/onboarding.test.d.ts.map +0 -1
- package/dist/harness/onboarding.test.js +0 -93
- package/dist/harness/onboarding.test.js.map +0 -1
- package/dist/harness/plugins.d.ts.map +0 -1
- package/dist/harness/plugins.js.map +0 -1
- package/dist/harness/plugins.test.d.ts +0 -2
- package/dist/harness/plugins.test.d.ts.map +0 -1
- package/dist/harness/plugins.test.js +0 -97
- package/dist/harness/plugins.test.js.map +0 -1
- package/dist/harness/rules.d.ts.map +0 -1
- package/dist/harness/rules.js.map +0 -1
- package/dist/harness/rules.test.d.ts +0 -2
- package/dist/harness/rules.test.d.ts.map +0 -1
- package/dist/harness/rules.test.js +0 -54
- package/dist/harness/rules.test.js.map +0 -1
- package/dist/harness/session.d.ts.map +0 -1
- package/dist/harness/session.js.map +0 -1
- package/dist/harness/session.test.d.ts +0 -2
- package/dist/harness/session.test.d.ts.map +0 -1
- package/dist/harness/session.test.js +0 -37
- package/dist/harness/session.test.js.map +0 -1
- package/dist/harness/store.d.ts.map +0 -1
- package/dist/harness/store.js.map +0 -1
- package/dist/harness/store.test.d.ts +0 -2
- package/dist/harness/store.test.d.ts.map +0 -1
- package/dist/harness/store.test.js +0 -71
- package/dist/harness/store.test.js.map +0 -1
- package/dist/harness/submit-handler.d.ts.map +0 -1
- package/dist/harness/submit-handler.js.map +0 -1
- package/dist/harness/submit-handler.test.d.ts +0 -2
- package/dist/harness/submit-handler.test.d.ts.map +0 -1
- package/dist/harness/submit-handler.test.js +0 -62
- package/dist/harness/submit-handler.test.js.map +0 -1
- package/dist/lsp/client.d.ts.map +0 -1
- package/dist/lsp/client.js.map +0 -1
- package/dist/lsp/client.test.d.ts +0 -2
- package/dist/lsp/client.test.d.ts.map +0 -1
- package/dist/lsp/client.test.js +0 -44
- package/dist/lsp/client.test.js.map +0 -1
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js.map +0 -1
- package/dist/mcp/DeferredMcpTool.d.ts.map +0 -1
- package/dist/mcp/DeferredMcpTool.js.map +0 -1
- package/dist/mcp/McpTool.d.ts.map +0 -1
- package/dist/mcp/McpTool.js.map +0 -1
- package/dist/mcp/McpTool.test.d.ts +0 -2
- package/dist/mcp/McpTool.test.d.ts.map +0 -1
- package/dist/mcp/McpTool.test.js +0 -53
- package/dist/mcp/McpTool.test.js.map +0 -1
- package/dist/mcp/client.d.ts.map +0 -1
- package/dist/mcp/client.js.map +0 -1
- package/dist/mcp/loader.d.ts.map +0 -1
- package/dist/mcp/loader.js.map +0 -1
- package/dist/mcp/loader.test.d.ts +0 -7
- package/dist/mcp/loader.test.d.ts.map +0 -1
- package/dist/mcp/loader.test.js +0 -25
- package/dist/mcp/loader.test.js.map +0 -1
- package/dist/mcp/schema.d.ts.map +0 -1
- package/dist/mcp/schema.js.map +0 -1
- package/dist/mcp/schema.test.d.ts +0 -2
- package/dist/mcp/schema.test.d.ts.map +0 -1
- package/dist/mcp/schema.test.js +0 -33
- package/dist/mcp/schema.test.js.map +0 -1
- package/dist/mcp/server.d.ts.map +0 -1
- package/dist/mcp/server.js.map +0 -1
- package/dist/mcp/server.test.d.ts +0 -2
- package/dist/mcp/server.test.d.ts.map +0 -1
- package/dist/mcp/server.test.js +0 -54
- package/dist/mcp/server.test.js.map +0 -1
- package/dist/mcp/types.d.ts.map +0 -1
- package/dist/mcp/types.js.map +0 -1
- package/dist/providers/anthropic-convert.test.d.ts +0 -5
- package/dist/providers/anthropic-convert.test.d.ts.map +0 -1
- package/dist/providers/anthropic-convert.test.js +0 -98
- package/dist/providers/anthropic-convert.test.js.map +0 -1
- package/dist/providers/anthropic.d.ts.map +0 -1
- package/dist/providers/anthropic.js.map +0 -1
- package/dist/providers/anthropic.test.d.ts +0 -2
- package/dist/providers/anthropic.test.d.ts.map +0 -1
- package/dist/providers/anthropic.test.js +0 -18
- package/dist/providers/anthropic.test.js.map +0 -1
- package/dist/providers/base.d.ts.map +0 -1
- package/dist/providers/base.js.map +0 -1
- package/dist/providers/index.d.ts.map +0 -1
- package/dist/providers/index.js.map +0 -1
- package/dist/providers/llamacpp.d.ts.map +0 -1
- package/dist/providers/llamacpp.js.map +0 -1
- package/dist/providers/llamacpp.test.d.ts +0 -2
- package/dist/providers/llamacpp.test.d.ts.map +0 -1
- package/dist/providers/llamacpp.test.js +0 -33
- package/dist/providers/llamacpp.test.js.map +0 -1
- package/dist/providers/message-format.test.d.ts +0 -2
- package/dist/providers/message-format.test.d.ts.map +0 -1
- package/dist/providers/message-format.test.js +0 -31
- package/dist/providers/message-format.test.js.map +0 -1
- package/dist/providers/ollama.d.ts.map +0 -1
- package/dist/providers/ollama.js.map +0 -1
- package/dist/providers/ollama.test.d.ts +0 -2
- package/dist/providers/ollama.test.d.ts.map +0 -1
- package/dist/providers/ollama.test.js +0 -40
- package/dist/providers/ollama.test.js.map +0 -1
- package/dist/providers/openai.d.ts.map +0 -1
- package/dist/providers/openai.js.map +0 -1
- package/dist/providers/openai.test.d.ts +0 -2
- package/dist/providers/openai.test.d.ts.map +0 -1
- package/dist/providers/openai.test.js +0 -23
- package/dist/providers/openai.test.js.map +0 -1
- package/dist/providers/openrouter.d.ts.map +0 -1
- package/dist/providers/openrouter.js.map +0 -1
- package/dist/providers/stream-parsing.test.d.ts +0 -6
- package/dist/providers/stream-parsing.test.d.ts.map +0 -1
- package/dist/providers/stream-parsing.test.js +0 -174
- package/dist/providers/stream-parsing.test.js.map +0 -1
- package/dist/query/compress.d.ts.map +0 -1
- package/dist/query/compress.js.map +0 -1
- package/dist/query/errors.d.ts.map +0 -1
- package/dist/query/errors.js.map +0 -1
- package/dist/query/index.d.ts.map +0 -1
- package/dist/query/index.js.map +0 -1
- package/dist/query/tools.d.ts.map +0 -1
- package/dist/query/tools.js.map +0 -1
- package/dist/query/types.d.ts.map +0 -1
- package/dist/query/types.js.map +0 -1
- package/dist/query.d.ts.map +0 -1
- package/dist/query.js.map +0 -1
- package/dist/query.test.d.ts +0 -2
- package/dist/query.test.d.ts.map +0 -1
- package/dist/query.test.js +0 -121
- package/dist/query.test.js.map +0 -1
- package/dist/remote/server.d.ts.map +0 -1
- package/dist/remote/server.js.map +0 -1
- package/dist/remote/server.test.d.ts +0 -2
- package/dist/remote/server.test.d.ts.map +0 -1
- package/dist/remote/server.test.js +0 -120
- package/dist/remote/server.test.js.map +0 -1
- package/dist/renderer/cells.d.ts.map +0 -1
- package/dist/renderer/cells.js.map +0 -1
- package/dist/renderer/cells.test.d.ts +0 -2
- package/dist/renderer/cells.test.d.ts.map +0 -1
- package/dist/renderer/cells.test.js +0 -69
- package/dist/renderer/cells.test.js.map +0 -1
- package/dist/renderer/colors.d.ts.map +0 -1
- package/dist/renderer/colors.js.map +0 -1
- package/dist/renderer/diff.d.ts.map +0 -1
- package/dist/renderer/diff.js.map +0 -1
- package/dist/renderer/diff.test.d.ts +0 -5
- package/dist/renderer/diff.test.d.ts.map +0 -1
- package/dist/renderer/diff.test.js +0 -140
- package/dist/renderer/diff.test.js.map +0 -1
- package/dist/renderer/differ.d.ts.map +0 -1
- package/dist/renderer/differ.js.map +0 -1
- package/dist/renderer/e2e.test.d.ts +0 -6
- package/dist/renderer/e2e.test.d.ts.map +0 -1
- package/dist/renderer/e2e.test.js +0 -702
- package/dist/renderer/e2e.test.js.map +0 -1
- package/dist/renderer/image.d.ts.map +0 -1
- package/dist/renderer/image.js.map +0 -1
- package/dist/renderer/image.test.d.ts +0 -5
- package/dist/renderer/image.test.d.ts.map +0 -1
- package/dist/renderer/image.test.js +0 -66
- package/dist/renderer/image.test.js.map +0 -1
- package/dist/renderer/index.d.ts.map +0 -1
- package/dist/renderer/index.js.map +0 -1
- package/dist/renderer/input.d.ts.map +0 -1
- package/dist/renderer/input.js.map +0 -1
- package/dist/renderer/input.test.d.ts +0 -5
- package/dist/renderer/input.test.d.ts.map +0 -1
- package/dist/renderer/input.test.js +0 -129
- package/dist/renderer/input.test.js.map +0 -1
- package/dist/renderer/layout.d.ts.map +0 -1
- package/dist/renderer/layout.js.map +0 -1
- package/dist/renderer/markdown.d.ts.map +0 -1
- package/dist/renderer/markdown.js.map +0 -1
- package/dist/renderer/markdown.test.d.ts +0 -2
- package/dist/renderer/markdown.test.d.ts.map +0 -1
- package/dist/renderer/markdown.test.js +0 -81
- package/dist/renderer/markdown.test.js.map +0 -1
- package/dist/renderer/perf.test.d.ts +0 -2
- package/dist/renderer/perf.test.d.ts.map +0 -1
- package/dist/renderer/perf.test.js +0 -128
- package/dist/renderer/perf.test.js.map +0 -1
- package/dist/renderer/session-browser.d.ts.map +0 -1
- package/dist/renderer/session-browser.js.map +0 -1
- package/dist/renderer/session-browser.test.d.ts +0 -6
- package/dist/renderer/session-browser.test.d.ts.map +0 -1
- package/dist/renderer/session-browser.test.js +0 -95
- package/dist/renderer/session-browser.test.js.map +0 -1
- package/dist/renderer/ui-ux.test.d.ts +0 -15
- package/dist/renderer/ui-ux.test.d.ts.map +0 -1
- package/dist/renderer/ui-ux.test.js +0 -470
- package/dist/renderer/ui-ux.test.js.map +0 -1
- package/dist/repl.d.ts.map +0 -1
- package/dist/repl.js.map +0 -1
- package/dist/services/AgentDispatcher.d.ts.map +0 -1
- package/dist/services/AgentDispatcher.js.map +0 -1
- package/dist/services/AgentDispatcher.test.d.ts +0 -2
- package/dist/services/AgentDispatcher.test.d.ts.map +0 -1
- package/dist/services/AgentDispatcher.test.js +0 -66
- package/dist/services/AgentDispatcher.test.js.map +0 -1
- package/dist/services/StreamingToolExecutor.d.ts.map +0 -1
- package/dist/services/StreamingToolExecutor.js.map +0 -1
- package/dist/services/StreamingToolExecutor.test.d.ts +0 -2
- package/dist/services/StreamingToolExecutor.test.d.ts.map +0 -1
- package/dist/services/StreamingToolExecutor.test.js +0 -103
- package/dist/services/StreamingToolExecutor.test.js.map +0 -1
- package/dist/services/agent-messaging.d.ts.map +0 -1
- package/dist/services/agent-messaging.js.map +0 -1
- package/dist/services/agent-messaging.test.d.ts +0 -2
- package/dist/services/agent-messaging.test.d.ts.map +0 -1
- package/dist/services/agent-messaging.test.js +0 -88
- package/dist/services/agent-messaging.test.js.map +0 -1
- package/dist/services/cron.d.ts.map +0 -1
- package/dist/services/cron.js.map +0 -1
- package/dist/services/cron.test.d.ts +0 -2
- package/dist/services/cron.test.d.ts.map +0 -1
- package/dist/services/cron.test.js +0 -49
- package/dist/services/cron.test.js.map +0 -1
- package/dist/test-helpers.d.ts +0 -31
- package/dist/test-helpers.d.ts.map +0 -1
- package/dist/test-helpers.js +0 -106
- package/dist/test-helpers.js.map +0 -1
- package/dist/tools/AgentTool/index.d.ts.map +0 -1
- package/dist/tools/AgentTool/index.js.map +0 -1
- package/dist/tools/AskUserTool/index.d.ts.map +0 -1
- package/dist/tools/AskUserTool/index.js.map +0 -1
- package/dist/tools/BashTool/index.d.ts.map +0 -1
- package/dist/tools/BashTool/index.js.map +0 -1
- package/dist/tools/CronTool/index.d.ts.map +0 -1
- package/dist/tools/CronTool/index.js.map +0 -1
- package/dist/tools/DiagnosticsTool/index.d.ts.map +0 -1
- package/dist/tools/DiagnosticsTool/index.js.map +0 -1
- package/dist/tools/EnterPlanModeTool/index.d.ts.map +0 -1
- package/dist/tools/EnterPlanModeTool/index.js.map +0 -1
- package/dist/tools/EnterWorktreeTool/index.d.ts.map +0 -1
- package/dist/tools/EnterWorktreeTool/index.js.map +0 -1
- package/dist/tools/ExitPlanModeTool/index.d.ts.map +0 -1
- package/dist/tools/ExitPlanModeTool/index.js.map +0 -1
- package/dist/tools/ExitWorktreeTool/index.d.ts.map +0 -1
- package/dist/tools/ExitWorktreeTool/index.js.map +0 -1
- package/dist/tools/FileEditTool/index.d.ts.map +0 -1
- package/dist/tools/FileEditTool/index.js.map +0 -1
- package/dist/tools/FileReadTool/index.d.ts.map +0 -1
- package/dist/tools/FileReadTool/index.js.map +0 -1
- package/dist/tools/FileWriteTool/index.d.ts.map +0 -1
- package/dist/tools/FileWriteTool/index.js.map +0 -1
- package/dist/tools/GlobTool/index.d.ts.map +0 -1
- package/dist/tools/GlobTool/index.js.map +0 -1
- package/dist/tools/GrepTool/index.d.ts.map +0 -1
- package/dist/tools/GrepTool/index.js.map +0 -1
- package/dist/tools/ImageReadTool/index.d.ts.map +0 -1
- package/dist/tools/ImageReadTool/index.js.map +0 -1
- package/dist/tools/KillProcessTool/index.d.ts.map +0 -1
- package/dist/tools/KillProcessTool/index.js.map +0 -1
- package/dist/tools/LSTool/index.d.ts.map +0 -1
- package/dist/tools/LSTool/index.js.map +0 -1
- package/dist/tools/MemoryTool/index.d.ts.map +0 -1
- package/dist/tools/MemoryTool/index.js.map +0 -1
- package/dist/tools/MultiEditTool/index.d.ts.map +0 -1
- package/dist/tools/MultiEditTool/index.js.map +0 -1
- package/dist/tools/NotebookEditTool/index.d.ts.map +0 -1
- package/dist/tools/NotebookEditTool/index.js.map +0 -1
- package/dist/tools/ParallelAgentTool/index.d.ts.map +0 -1
- package/dist/tools/ParallelAgentTool/index.js.map +0 -1
- package/dist/tools/RemoteTriggerTool/index.d.ts.map +0 -1
- package/dist/tools/RemoteTriggerTool/index.js.map +0 -1
- package/dist/tools/SendMessageTool/index.d.ts.map +0 -1
- package/dist/tools/SendMessageTool/index.js.map +0 -1
- package/dist/tools/SkillTool/index.d.ts.map +0 -1
- package/dist/tools/SkillTool/index.js.map +0 -1
- package/dist/tools/TaskCreateTool/index.d.ts.map +0 -1
- package/dist/tools/TaskCreateTool/index.js.map +0 -1
- package/dist/tools/TaskGetTool/index.d.ts.map +0 -1
- package/dist/tools/TaskGetTool/index.js.map +0 -1
- package/dist/tools/TaskListTool/index.d.ts.map +0 -1
- package/dist/tools/TaskListTool/index.js.map +0 -1
- package/dist/tools/TaskOutputTool/index.d.ts.map +0 -1
- package/dist/tools/TaskOutputTool/index.js.map +0 -1
- package/dist/tools/TaskStopTool/index.d.ts.map +0 -1
- package/dist/tools/TaskStopTool/index.js.map +0 -1
- package/dist/tools/TaskUpdateTool/index.d.ts.map +0 -1
- package/dist/tools/TaskUpdateTool/index.js.map +0 -1
- package/dist/tools/ToolSearchTool/index.d.ts.map +0 -1
- package/dist/tools/ToolSearchTool/index.js.map +0 -1
- package/dist/tools/WebFetchTool/index.d.ts.map +0 -1
- package/dist/tools/WebFetchTool/index.js.map +0 -1
- package/dist/tools/WebSearchTool/index.d.ts.map +0 -1
- package/dist/tools/WebSearchTool/index.js.map +0 -1
- package/dist/tools/file-edit.test.d.ts +0 -2
- package/dist/tools/file-edit.test.d.ts.map +0 -1
- package/dist/tools/file-edit.test.js +0 -35
- package/dist/tools/file-edit.test.js.map +0 -1
- package/dist/tools/tools-basic.test.d.ts +0 -6
- package/dist/tools/tools-basic.test.d.ts.map +0 -1
- package/dist/tools/tools-basic.test.js +0 -379
- package/dist/tools/tools-basic.test.js.map +0 -1
- package/dist/tools/web-fetch.test.d.ts +0 -2
- package/dist/tools/web-fetch.test.d.ts.map +0 -1
- package/dist/tools/web-fetch.test.js +0 -27
- package/dist/tools/web-fetch.test.js.map +0 -1
- package/dist/tools.d.ts.map +0 -1
- package/dist/tools.js.map +0 -1
- package/dist/types/events.d.ts.map +0 -1
- package/dist/types/events.js.map +0 -1
- package/dist/types/message.d.ts.map +0 -1
- package/dist/types/message.js.map +0 -1
- package/dist/types/message.test.d.ts +0 -2
- package/dist/types/message.test.d.ts.map +0 -1
- package/dist/types/message.test.js +0 -46
- package/dist/types/message.test.js.map +0 -1
- package/dist/types/permissions.d.ts.map +0 -1
- package/dist/types/permissions.js.map +0 -1
- package/dist/types/permissions.test.d.ts +0 -2
- package/dist/types/permissions.test.d.ts.map +0 -1
- package/dist/types/permissions.test.js +0 -127
- package/dist/types/permissions.test.js.map +0 -1
- package/dist/utils/bash-safety.d.ts.map +0 -1
- package/dist/utils/bash-safety.js.map +0 -1
- package/dist/utils/bash-safety.test.d.ts +0 -2
- package/dist/utils/bash-safety.test.d.ts.map +0 -1
- package/dist/utils/bash-safety.test.js +0 -112
- package/dist/utils/bash-safety.test.js.map +0 -1
- package/dist/utils/diff-algorithm.d.ts.map +0 -1
- package/dist/utils/diff-algorithm.js.map +0 -1
- package/dist/utils/diff-algorithm.test.d.ts +0 -2
- package/dist/utils/diff-algorithm.test.d.ts.map +0 -1
- package/dist/utils/diff-algorithm.test.js +0 -49
- package/dist/utils/diff-algorithm.test.js.map +0 -1
- package/dist/utils/format.d.ts.map +0 -1
- package/dist/utils/format.js.map +0 -1
- package/dist/utils/fs.d.ts.map +0 -1
- package/dist/utils/fs.js.map +0 -1
- package/dist/utils/fs.test.d.ts +0 -5
- package/dist/utils/fs.test.d.ts.map +0 -1
- package/dist/utils/fs.test.js +0 -82
- package/dist/utils/fs.test.js.map +0 -1
- package/dist/utils/safe-env.d.ts.map +0 -1
- package/dist/utils/safe-env.js.map +0 -1
- package/dist/utils/theme-data.d.ts.map +0 -1
- package/dist/utils/theme-data.js.map +0 -1
- package/dist/utils/theme.d.ts.map +0 -1
- package/dist/utils/theme.js.map +0 -1
- package/dist/utils/tool-summary.d.ts.map +0 -1
- package/dist/utils/tool-summary.js.map +0 -1
- package/dist/utils/tool-summary.test.d.ts +0 -2
- package/dist/utils/tool-summary.test.d.ts.map +0 -1
- package/dist/utils/tool-summary.test.js +0 -93
- package/dist/utils/tool-summary.test.js.map +0 -1
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server Registry — curated list of compatible MCP servers.
|
|
3
|
+
*
|
|
4
|
+
* Provides a browsable catalog of MCP servers that users can add
|
|
5
|
+
* to their .oh/config.yaml with a single command.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Curated registry of popular MCP servers.
|
|
9
|
+
* Each entry has enough info to generate the config.yaml block.
|
|
10
|
+
*/
|
|
11
|
+
export const MCP_REGISTRY = [
|
|
12
|
+
// ── Filesystem ──
|
|
13
|
+
{
|
|
14
|
+
name: 'filesystem',
|
|
15
|
+
package: '@modelcontextprotocol/server-filesystem',
|
|
16
|
+
description: 'Read, write, and manage files on the local filesystem',
|
|
17
|
+
category: 'filesystem',
|
|
18
|
+
args: ['/tmp'],
|
|
19
|
+
riskLevel: 'medium',
|
|
20
|
+
},
|
|
21
|
+
// ── Git & GitHub ──
|
|
22
|
+
{
|
|
23
|
+
name: 'github',
|
|
24
|
+
package: '@modelcontextprotocol/server-github',
|
|
25
|
+
description: 'GitHub API — issues, PRs, repos, code search',
|
|
26
|
+
category: 'git',
|
|
27
|
+
envVars: ['GITHUB_PERSONAL_ACCESS_TOKEN'],
|
|
28
|
+
riskLevel: 'medium',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'gitlab',
|
|
32
|
+
package: '@modelcontextprotocol/server-gitlab',
|
|
33
|
+
description: 'GitLab API — issues, merge requests, pipelines',
|
|
34
|
+
category: 'git',
|
|
35
|
+
envVars: ['GITLAB_PERSONAL_ACCESS_TOKEN', 'GITLAB_API_URL'],
|
|
36
|
+
riskLevel: 'medium',
|
|
37
|
+
},
|
|
38
|
+
// ── Database ──
|
|
39
|
+
{
|
|
40
|
+
name: 'sqlite',
|
|
41
|
+
package: '@modelcontextprotocol/server-sqlite',
|
|
42
|
+
description: 'Query and modify SQLite databases',
|
|
43
|
+
category: 'database',
|
|
44
|
+
args: ['./database.sqlite'],
|
|
45
|
+
riskLevel: 'medium',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'postgres',
|
|
49
|
+
package: '@modelcontextprotocol/server-postgres',
|
|
50
|
+
description: 'Query PostgreSQL databases (read-only by default)',
|
|
51
|
+
category: 'database',
|
|
52
|
+
envVars: ['POSTGRES_CONNECTION_STRING'],
|
|
53
|
+
riskLevel: 'medium',
|
|
54
|
+
},
|
|
55
|
+
// ── Search & Web ──
|
|
56
|
+
{
|
|
57
|
+
name: 'brave-search',
|
|
58
|
+
package: '@modelcontextprotocol/server-brave-search',
|
|
59
|
+
description: 'Web search via Brave Search API',
|
|
60
|
+
category: 'search',
|
|
61
|
+
envVars: ['BRAVE_API_KEY'],
|
|
62
|
+
riskLevel: 'low',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: 'fetch',
|
|
66
|
+
package: '@modelcontextprotocol/server-fetch',
|
|
67
|
+
description: 'Fetch and parse web pages, convert HTML to markdown',
|
|
68
|
+
category: 'search',
|
|
69
|
+
riskLevel: 'low',
|
|
70
|
+
},
|
|
71
|
+
// ── Productivity ──
|
|
72
|
+
{
|
|
73
|
+
name: 'slack',
|
|
74
|
+
package: '@modelcontextprotocol/server-slack',
|
|
75
|
+
description: 'Read and send Slack messages, list channels',
|
|
76
|
+
category: 'productivity',
|
|
77
|
+
envVars: ['SLACK_BOT_TOKEN'],
|
|
78
|
+
riskLevel: 'high',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'google-drive',
|
|
82
|
+
package: '@anthropic/mcp-server-google-drive',
|
|
83
|
+
description: 'Search and read Google Drive documents',
|
|
84
|
+
category: 'productivity',
|
|
85
|
+
envVars: ['GOOGLE_DRIVE_CREDENTIALS'],
|
|
86
|
+
riskLevel: 'medium',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'linear',
|
|
90
|
+
package: '@anthropic/mcp-server-linear',
|
|
91
|
+
description: 'Linear issue tracker — create, update, search issues',
|
|
92
|
+
category: 'productivity',
|
|
93
|
+
envVars: ['LINEAR_API_KEY'],
|
|
94
|
+
riskLevel: 'medium',
|
|
95
|
+
},
|
|
96
|
+
// ── Dev Tools ──
|
|
97
|
+
{
|
|
98
|
+
name: 'docker',
|
|
99
|
+
package: '@modelcontextprotocol/server-docker',
|
|
100
|
+
description: 'Manage Docker containers, images, and volumes',
|
|
101
|
+
category: 'dev-tools',
|
|
102
|
+
riskLevel: 'high',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
name: 'puppeteer',
|
|
106
|
+
package: '@modelcontextprotocol/server-puppeteer',
|
|
107
|
+
description: 'Browser automation — navigate, screenshot, interact with web pages',
|
|
108
|
+
category: 'dev-tools',
|
|
109
|
+
riskLevel: 'medium',
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: 'memory',
|
|
113
|
+
package: '@modelcontextprotocol/server-memory',
|
|
114
|
+
description: 'Persistent knowledge graph for long-term memory',
|
|
115
|
+
category: 'ai',
|
|
116
|
+
riskLevel: 'low',
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: 'sequential-thinking',
|
|
120
|
+
package: '@modelcontextprotocol/server-sequential-thinking',
|
|
121
|
+
description: 'Step-by-step reasoning and chain-of-thought tools',
|
|
122
|
+
category: 'ai',
|
|
123
|
+
riskLevel: 'low',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: 'context7',
|
|
127
|
+
package: '@anthropic/mcp-server-context7',
|
|
128
|
+
description: 'Fetch up-to-date library documentation for any framework',
|
|
129
|
+
category: 'dev-tools',
|
|
130
|
+
riskLevel: 'low',
|
|
131
|
+
},
|
|
132
|
+
];
|
|
133
|
+
/** Search the registry by name or keyword */
|
|
134
|
+
export function searchRegistry(query) {
|
|
135
|
+
const q = query.toLowerCase();
|
|
136
|
+
return MCP_REGISTRY.filter(e => e.name.includes(q) ||
|
|
137
|
+
e.description.toLowerCase().includes(q) ||
|
|
138
|
+
e.category.includes(q) ||
|
|
139
|
+
e.package.toLowerCase().includes(q));
|
|
140
|
+
}
|
|
141
|
+
/** Get all entries in a category */
|
|
142
|
+
export function getByCategory(category) {
|
|
143
|
+
return MCP_REGISTRY.filter(e => e.category === category);
|
|
144
|
+
}
|
|
145
|
+
/** Get all unique categories */
|
|
146
|
+
export function getCategories() {
|
|
147
|
+
return [...new Set(MCP_REGISTRY.map(e => e.category))];
|
|
148
|
+
}
|
|
149
|
+
/** Generate the config.yaml block for a registry entry */
|
|
150
|
+
export function generateConfigBlock(entry) {
|
|
151
|
+
const lines = [
|
|
152
|
+
` - name: ${entry.name}`,
|
|
153
|
+
` command: npx`,
|
|
154
|
+
` args: ["-y", "${entry.package}"${entry.args ? ', ' + entry.args.map(a => `"${a}"`).join(', ') : ''}]`,
|
|
155
|
+
];
|
|
156
|
+
if (entry.envVars && entry.envVars.length > 0) {
|
|
157
|
+
lines.push(' env:');
|
|
158
|
+
for (const v of entry.envVars) {
|
|
159
|
+
lines.push(` ${v}: "YOUR_${v}"`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (entry.riskLevel && entry.riskLevel !== 'medium') {
|
|
163
|
+
lines.push(` riskLevel: ${entry.riskLevel}`);
|
|
164
|
+
}
|
|
165
|
+
return lines.join('\n');
|
|
166
|
+
}
|
|
167
|
+
/** Format registry as a browsable list */
|
|
168
|
+
export function formatRegistry(entries) {
|
|
169
|
+
const list = entries ?? MCP_REGISTRY;
|
|
170
|
+
const categories = [...new Set(list.map(e => e.category))];
|
|
171
|
+
const sections = [];
|
|
172
|
+
for (const cat of categories) {
|
|
173
|
+
const catEntries = list.filter(e => e.category === cat);
|
|
174
|
+
const header = cat.charAt(0).toUpperCase() + cat.slice(1).replace('-', ' ');
|
|
175
|
+
const rows = catEntries.map(e => ` ${e.name.padEnd(20)} ${e.description}${e.envVars ? ' [requires: ' + e.envVars.join(', ') + ']' : ''}`);
|
|
176
|
+
sections.push(`${header}:\n${rows.join('\n')}`);
|
|
177
|
+
}
|
|
178
|
+
return sections.join('\n\n');
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=registry.js.map
|
package/dist/query/index.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* - types.ts — shared types
|
|
9
9
|
*/
|
|
10
10
|
import { toolToAPIFormat } from "../Tool.js";
|
|
11
|
+
import { DeferredTool } from "../DeferredTool.js";
|
|
11
12
|
import { createAssistantMessage, createUserMessage } from "../types/message.js";
|
|
12
13
|
import { StreamingToolExecutor } from "../services/StreamingToolExecutor.js";
|
|
13
14
|
import { getContextWindow } from "../harness/cost.js";
|
|
@@ -34,9 +35,16 @@ export async function* query(userMessage, config, existingMessages = []) {
|
|
|
34
35
|
const modelInfo = config.provider.getModelInfo?.(config.model ?? '');
|
|
35
36
|
const toolsSupported = !modelInfo || modelInfo.supportsTools;
|
|
36
37
|
const apiTools = toolsSupported ? config.tools.map(toolToAPIFormat) : undefined;
|
|
37
|
-
|
|
38
|
+
let toolPrompts = toolsSupported
|
|
38
39
|
? config.tools.map((t) => t.prompt()).join("\n\n")
|
|
39
40
|
: "";
|
|
41
|
+
// Hint about deferred tools available via ToolSearch
|
|
42
|
+
if (toolsSupported) {
|
|
43
|
+
const deferredCount = config.tools.filter(t => t instanceof DeferredTool && !t.activated).length;
|
|
44
|
+
if (deferredCount > 0) {
|
|
45
|
+
toolPrompts += `\n\n[${deferredCount} additional tools available — use ToolSearch to discover them]`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
40
48
|
const fullSystemPrompt = toolPrompts
|
|
41
49
|
? config.systemPrompt + "\n\n# Available Tools\n\n" + toolPrompts
|
|
42
50
|
: config.systemPrompt;
|
package/dist/query/tools.js
CHANGED
|
@@ -73,7 +73,7 @@ export async function executeSingleTool(toolCall, tools, context, permissionMode
|
|
|
73
73
|
try {
|
|
74
74
|
const toolAbort = AbortSignal.timeout(TOOL_TIMEOUT_MS);
|
|
75
75
|
const contextWithTimeout = { ...context, abortSignal: context.abortSignal ?? toolAbort };
|
|
76
|
-
|
|
76
|
+
let result = await Promise.race([
|
|
77
77
|
tool.call(parsed.data, contextWithTimeout),
|
|
78
78
|
new Promise((_, reject) => {
|
|
79
79
|
toolAbort.addEventListener("abort", () => reject(new Error(`Tool '${tool.name}' timed out after ${TOOL_TIMEOUT_MS / 1000}s`)));
|
|
@@ -85,11 +85,37 @@ export async function executeSingleTool(toolCall, tools, context, permissionMode
|
|
|
85
85
|
toolArgs: JSON.stringify(toolCall.arguments).slice(0, 1000),
|
|
86
86
|
toolOutput: result.output.slice(0, 1000),
|
|
87
87
|
});
|
|
88
|
-
//
|
|
89
|
-
let
|
|
88
|
+
// Verification loop: auto-run lint/typecheck after file-modifying tools
|
|
89
|
+
let verificationSuffix = '';
|
|
90
|
+
if (!result.isError && ['Edit', 'Write', 'MultiEdit'].includes(tool.name)) {
|
|
91
|
+
try {
|
|
92
|
+
const { runVerificationForFiles, getVerificationConfig, extractFilePaths } = await import('../harness/verification.js');
|
|
93
|
+
const vConfig = getVerificationConfig();
|
|
94
|
+
if (vConfig?.enabled) {
|
|
95
|
+
const filePaths = extractFilePaths(tool.name, parsed.data);
|
|
96
|
+
if (filePaths.length > 0) {
|
|
97
|
+
const vResult = await runVerificationForFiles(filePaths, vConfig);
|
|
98
|
+
if (vResult.ran) {
|
|
99
|
+
if (!vResult.passed) {
|
|
100
|
+
verificationSuffix = `\n\n[Verification FAILED]\n${vResult.summary}`;
|
|
101
|
+
if (vConfig.mode === 'block') {
|
|
102
|
+
result = { output: result.output, isError: true };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
verificationSuffix = '\n\n[Verification passed]';
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch { /* verification should never break tool execution */ }
|
|
113
|
+
}
|
|
114
|
+
// Strip ANSI and cap output, then append verification suffix
|
|
115
|
+
let output = result.output.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "") + verificationSuffix;
|
|
90
116
|
if (output.length > MAX_TOOL_RESULT_CHARS) {
|
|
91
117
|
output = output.slice(0, MAX_TOOL_RESULT_CHARS)
|
|
92
|
-
+ `\n\n[TRUNCATED: output was ${
|
|
118
|
+
+ `\n\n[TRUNCATED: output was ${output.length.toLocaleString()} chars, showing first ${MAX_TOOL_RESULT_CHARS.toLocaleString()}]`;
|
|
93
119
|
}
|
|
94
120
|
return { output, isError: result.isError };
|
|
95
121
|
}
|
package/dist/repl.js
CHANGED
|
@@ -48,9 +48,20 @@ export async function startREPL(config) {
|
|
|
48
48
|
catch {
|
|
49
49
|
session = createSession(config.provider.name, config.model ?? '', sessionExtras);
|
|
50
50
|
}
|
|
51
|
+
// Wake context: inject session summary when resuming
|
|
52
|
+
if (config.resumeSessionId && session.hibernate) {
|
|
53
|
+
const { buildWakeContext } = await import('./harness/session.js');
|
|
54
|
+
const wakeMsg = buildWakeContext(session);
|
|
55
|
+
const { createInfoMessage } = await import('./types/message.js');
|
|
56
|
+
session.messages.push(createInfoMessage(wakeMsg));
|
|
57
|
+
}
|
|
51
58
|
// Initialize checkpoints for file rewind
|
|
52
59
|
const { initCheckpoints } = await import('./harness/checkpoints.js');
|
|
53
60
|
initCheckpoints(session.id);
|
|
61
|
+
// Start background cron executor
|
|
62
|
+
const { CronExecutor } = await import('./services/CronExecutor.js');
|
|
63
|
+
const cronExecutor = new CronExecutor(config.provider, config.tools, config.systemPrompt, config.permissionMode, config.model);
|
|
64
|
+
cronExecutor.start();
|
|
54
65
|
const cost = new CostTracker();
|
|
55
66
|
let cachedConfig = readOhConfig();
|
|
56
67
|
// Centralized state store — all REPL state lives here
|
|
@@ -598,6 +609,28 @@ export async function startREPL(config) {
|
|
|
598
609
|
renderer.setError(null);
|
|
599
610
|
// Exit
|
|
600
611
|
if (input === 'exit' || input === 'quit' || input === '/exit' || input === '/quit' || input === '/q') {
|
|
612
|
+
// Hibernate: save session state for potential wake-up resume
|
|
613
|
+
try {
|
|
614
|
+
const { buildHibernateState } = await import('./harness/session.js');
|
|
615
|
+
session.hibernate = buildHibernateState(messages);
|
|
616
|
+
}
|
|
617
|
+
catch { /* ignore */ }
|
|
618
|
+
// Dream consolidation: prune stale memories before exit
|
|
619
|
+
try {
|
|
620
|
+
const { consolidateMemories } = await import('./harness/memory.js');
|
|
621
|
+
const { readOhConfig } = await import('./harness/config.js');
|
|
622
|
+
const ohCfg = readOhConfig();
|
|
623
|
+
if (ohCfg?.memory?.consolidateOnExit !== false) {
|
|
624
|
+
consolidateMemories();
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
catch { /* ignore */ }
|
|
628
|
+
// Emit sessionEnd hook
|
|
629
|
+
try {
|
|
630
|
+
const { emitHookAsync } = await import('./harness/hooks.js');
|
|
631
|
+
await emitHookAsync('sessionEnd', {});
|
|
632
|
+
}
|
|
633
|
+
catch { /* ignore */ }
|
|
601
634
|
cleanup();
|
|
602
635
|
process.exit(0);
|
|
603
636
|
}
|
|
@@ -890,6 +923,7 @@ export async function startREPL(config) {
|
|
|
890
923
|
if (cleanedUp)
|
|
891
924
|
return;
|
|
892
925
|
cleanedUp = true;
|
|
926
|
+
cronExecutor.stop();
|
|
893
927
|
renderer.stop();
|
|
894
928
|
session.messages = messages;
|
|
895
929
|
session.totalCost = cost.totalCost;
|
|
@@ -113,9 +113,18 @@ export class AgentDispatcher {
|
|
|
113
113
|
}
|
|
114
114
|
try {
|
|
115
115
|
const { query } = await import('../query.js');
|
|
116
|
+
// Filter tools if task specifies allowed tools
|
|
117
|
+
let taskTools = this.tools;
|
|
118
|
+
if (task.allowedTools && task.allowedTools.length > 0) {
|
|
119
|
+
const allowSet = new Set(task.allowedTools.map(n => n.toLowerCase()));
|
|
120
|
+
allowSet.add('askuser');
|
|
121
|
+
const filtered = this.tools.filter(t => allowSet.has(t.name.toLowerCase()));
|
|
122
|
+
if (filtered.length > 0)
|
|
123
|
+
taskTools = filtered;
|
|
124
|
+
}
|
|
116
125
|
const config = {
|
|
117
126
|
provider: this.provider,
|
|
118
|
-
tools:
|
|
127
|
+
tools: taskTools,
|
|
119
128
|
systemPrompt: this.systemPrompt,
|
|
120
129
|
permissionMode: this.permissionMode,
|
|
121
130
|
model: this.model,
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CronExecutor — background scheduler that runs due cron tasks.
|
|
3
|
+
*
|
|
4
|
+
* Checks every 60 seconds for crons that are due, then executes each
|
|
5
|
+
* by running the cron's prompt through a sub-query loop. Results are
|
|
6
|
+
* persisted to ~/.oh/crons/history/ for debugging and audit.
|
|
7
|
+
*
|
|
8
|
+
* Execution is non-blocking and failure-isolated — one failing cron
|
|
9
|
+
* does not affect others or the main REPL session.
|
|
10
|
+
*/
|
|
11
|
+
import type { Provider } from '../providers/base.js';
|
|
12
|
+
import type { Tools } from '../Tool.js';
|
|
13
|
+
import type { PermissionMode } from '../types/permissions.js';
|
|
14
|
+
import { type CronResult } from './cron.js';
|
|
15
|
+
export declare class CronExecutor {
|
|
16
|
+
private provider;
|
|
17
|
+
private tools;
|
|
18
|
+
private systemPrompt;
|
|
19
|
+
private permissionMode;
|
|
20
|
+
private model?;
|
|
21
|
+
private intervalId;
|
|
22
|
+
private running;
|
|
23
|
+
private _stopped;
|
|
24
|
+
constructor(provider: Provider, tools: Tools, systemPrompt: string, permissionMode: PermissionMode, model?: string | undefined);
|
|
25
|
+
/** Start the background scheduler */
|
|
26
|
+
start(): void;
|
|
27
|
+
/** Stop the scheduler */
|
|
28
|
+
stop(): void;
|
|
29
|
+
/** Check for due crons and execute them */
|
|
30
|
+
tick(): Promise<CronResult[]>;
|
|
31
|
+
/** Execute a single cron task */
|
|
32
|
+
private executeCron;
|
|
33
|
+
/** Whether the executor is currently running */
|
|
34
|
+
get isRunning(): boolean;
|
|
35
|
+
/** Get IDs of currently executing crons */
|
|
36
|
+
get activeIds(): string[];
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=CronExecutor.d.ts.map
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CronExecutor — background scheduler that runs due cron tasks.
|
|
3
|
+
*
|
|
4
|
+
* Checks every 60 seconds for crons that are due, then executes each
|
|
5
|
+
* by running the cron's prompt through a sub-query loop. Results are
|
|
6
|
+
* persisted to ~/.oh/crons/history/ for debugging and audit.
|
|
7
|
+
*
|
|
8
|
+
* Execution is non-blocking and failure-isolated — one failing cron
|
|
9
|
+
* does not affect others or the main REPL session.
|
|
10
|
+
*/
|
|
11
|
+
import { listCrons, getDueCrons, updateCron, saveCronResult, } from './cron.js';
|
|
12
|
+
const CHECK_INTERVAL_MS = 60_000; // Check every 60 seconds
|
|
13
|
+
const MAX_CRON_TURNS = 10; // Limit sub-query turns for cron tasks
|
|
14
|
+
export class CronExecutor {
|
|
15
|
+
provider;
|
|
16
|
+
tools;
|
|
17
|
+
systemPrompt;
|
|
18
|
+
permissionMode;
|
|
19
|
+
model;
|
|
20
|
+
intervalId = null;
|
|
21
|
+
running = new Set(); // Prevent overlapping executions
|
|
22
|
+
_stopped = false;
|
|
23
|
+
constructor(provider, tools, systemPrompt, permissionMode, model) {
|
|
24
|
+
this.provider = provider;
|
|
25
|
+
this.tools = tools;
|
|
26
|
+
this.systemPrompt = systemPrompt;
|
|
27
|
+
this.permissionMode = permissionMode;
|
|
28
|
+
this.model = model;
|
|
29
|
+
}
|
|
30
|
+
/** Start the background scheduler */
|
|
31
|
+
start() {
|
|
32
|
+
if (this.intervalId)
|
|
33
|
+
return;
|
|
34
|
+
this._stopped = false;
|
|
35
|
+
// Run first tick after a short delay (don't block startup)
|
|
36
|
+
setTimeout(() => {
|
|
37
|
+
if (!this._stopped)
|
|
38
|
+
this.tick().catch(() => { });
|
|
39
|
+
}, 5_000);
|
|
40
|
+
// Then check every 60 seconds
|
|
41
|
+
this.intervalId = setInterval(() => {
|
|
42
|
+
if (!this._stopped)
|
|
43
|
+
this.tick().catch(() => { });
|
|
44
|
+
}, CHECK_INTERVAL_MS);
|
|
45
|
+
}
|
|
46
|
+
/** Stop the scheduler */
|
|
47
|
+
stop() {
|
|
48
|
+
this._stopped = true;
|
|
49
|
+
if (this.intervalId) {
|
|
50
|
+
clearInterval(this.intervalId);
|
|
51
|
+
this.intervalId = null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Check for due crons and execute them */
|
|
55
|
+
async tick() {
|
|
56
|
+
const allCrons = listCrons();
|
|
57
|
+
const due = getDueCrons(allCrons);
|
|
58
|
+
const results = [];
|
|
59
|
+
for (const cron of due) {
|
|
60
|
+
// Skip if already running (prevent overlapping executions)
|
|
61
|
+
if (this.running.has(cron.id))
|
|
62
|
+
continue;
|
|
63
|
+
try {
|
|
64
|
+
const result = await this.executeCron(cron);
|
|
65
|
+
results.push(result);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
// Never let a single cron failure crash the scheduler
|
|
69
|
+
const result = {
|
|
70
|
+
cronId: cron.id,
|
|
71
|
+
timestamp: Date.now(),
|
|
72
|
+
output: '',
|
|
73
|
+
error: err instanceof Error ? err.message : String(err),
|
|
74
|
+
};
|
|
75
|
+
saveCronResult(result);
|
|
76
|
+
results.push(result);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return results;
|
|
80
|
+
}
|
|
81
|
+
/** Execute a single cron task */
|
|
82
|
+
async executeCron(cron) {
|
|
83
|
+
this.running.add(cron.id);
|
|
84
|
+
const timestamp = Date.now();
|
|
85
|
+
try {
|
|
86
|
+
const { query } = await import('../query.js');
|
|
87
|
+
const config = {
|
|
88
|
+
provider: this.provider,
|
|
89
|
+
tools: this.tools,
|
|
90
|
+
systemPrompt: `[Cron Task: ${cron.name}]\n\n${this.systemPrompt}`,
|
|
91
|
+
permissionMode: this.permissionMode,
|
|
92
|
+
model: this.model,
|
|
93
|
+
maxTurns: MAX_CRON_TURNS,
|
|
94
|
+
};
|
|
95
|
+
let output = '';
|
|
96
|
+
for await (const event of query(cron.prompt, config)) {
|
|
97
|
+
if (event.type === 'text_delta')
|
|
98
|
+
output += event.content;
|
|
99
|
+
if (event.type === 'error') {
|
|
100
|
+
const result = { cronId: cron.id, timestamp, output, error: event.message };
|
|
101
|
+
saveCronResult(result);
|
|
102
|
+
// Still update lastRun on error to prevent rapid retry loops
|
|
103
|
+
cron.lastRun = Date.now();
|
|
104
|
+
cron.runCount++;
|
|
105
|
+
updateCron(cron);
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Success: update cron metadata and save result
|
|
110
|
+
cron.lastRun = Date.now();
|
|
111
|
+
cron.runCount++;
|
|
112
|
+
updateCron(cron);
|
|
113
|
+
const result = { cronId: cron.id, timestamp, output };
|
|
114
|
+
saveCronResult(result);
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
this.running.delete(cron.id);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/** Whether the executor is currently running */
|
|
122
|
+
get isRunning() {
|
|
123
|
+
return this.intervalId !== null && !this._stopped;
|
|
124
|
+
}
|
|
125
|
+
/** Get IDs of currently executing crons */
|
|
126
|
+
get activeIds() {
|
|
127
|
+
return [...this.running];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=CronExecutor.js.map
|
|
@@ -94,6 +94,34 @@ export class StreamingToolExecutor {
|
|
|
94
94
|
};
|
|
95
95
|
try {
|
|
96
96
|
tracked.result = await tool.call(parsed.data, callContext);
|
|
97
|
+
// Verification loop: auto-run lint/typecheck after file-modifying tools
|
|
98
|
+
if (tracked.result && !tracked.result.isError && ['Edit', 'Write', 'MultiEdit'].includes(tool.name)) {
|
|
99
|
+
try {
|
|
100
|
+
const { runVerificationForFiles, getVerificationConfig, extractFilePaths } = await import('../harness/verification.js');
|
|
101
|
+
const vConfig = getVerificationConfig();
|
|
102
|
+
if (vConfig?.enabled) {
|
|
103
|
+
const filePaths = extractFilePaths(tool.name, tracked.toolCall.arguments);
|
|
104
|
+
if (filePaths.length > 0) {
|
|
105
|
+
const vResult = await runVerificationForFiles(filePaths, vConfig);
|
|
106
|
+
if (vResult.ran) {
|
|
107
|
+
if (!vResult.passed) {
|
|
108
|
+
tracked.result = {
|
|
109
|
+
output: tracked.result.output + `\n\n[Verification FAILED]\n${vResult.summary}`,
|
|
110
|
+
isError: vConfig.mode === 'block',
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
tracked.result = {
|
|
115
|
+
output: tracked.result.output + '\n\n[Verification passed]',
|
|
116
|
+
isError: false,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch { /* verification should never break tool execution */ }
|
|
124
|
+
}
|
|
97
125
|
}
|
|
98
126
|
catch (err) {
|
|
99
127
|
tracked.result = {
|
package/dist/services/cron.d.ts
CHANGED
|
@@ -33,6 +33,10 @@ export declare function deleteCron(id: string): boolean;
|
|
|
33
33
|
export declare function updateCron(cron: CronDefinition): void;
|
|
34
34
|
/** Parse a simplified schedule string into milliseconds interval */
|
|
35
35
|
export declare function parseScheduleMs(schedule: string): number | null;
|
|
36
|
+
/** Save a cron execution result to history */
|
|
37
|
+
export declare function saveCronResult(result: CronResult): void;
|
|
38
|
+
/** Get execution history for a cron (most recent first) */
|
|
39
|
+
export declare function getCronHistory(cronId: string, limit?: number): CronResult[];
|
|
36
40
|
/**
|
|
37
41
|
* Check which crons are due to run based on their schedule and lastRun.
|
|
38
42
|
*/
|
package/dist/services/cron.js
CHANGED
|
@@ -72,6 +72,33 @@ export function parseScheduleMs(schedule) {
|
|
|
72
72
|
return parseInt(dayMatch[1]) * 24 * 60 * 60 * 1000;
|
|
73
73
|
return null;
|
|
74
74
|
}
|
|
75
|
+
// ── Result Persistence ──
|
|
76
|
+
const HISTORY_DIR = join(CRON_DIR, 'history');
|
|
77
|
+
/** Save a cron execution result to history */
|
|
78
|
+
export function saveCronResult(result) {
|
|
79
|
+
mkdirSync(HISTORY_DIR, { recursive: true });
|
|
80
|
+
const filename = `${result.cronId}-${result.timestamp}.json`;
|
|
81
|
+
writeFileSync(join(HISTORY_DIR, filename), JSON.stringify(result, null, 2));
|
|
82
|
+
}
|
|
83
|
+
/** Get execution history for a cron (most recent first) */
|
|
84
|
+
export function getCronHistory(cronId, limit = 10) {
|
|
85
|
+
if (!existsSync(HISTORY_DIR))
|
|
86
|
+
return [];
|
|
87
|
+
return readdirSync(HISTORY_DIR)
|
|
88
|
+
.filter(f => f.startsWith(`${cronId}-`) && f.endsWith('.json'))
|
|
89
|
+
.sort()
|
|
90
|
+
.reverse()
|
|
91
|
+
.slice(0, limit)
|
|
92
|
+
.map(f => {
|
|
93
|
+
try {
|
|
94
|
+
return JSON.parse(readFileSync(join(HISTORY_DIR, f), 'utf-8'));
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
.filter((r) => r !== null);
|
|
101
|
+
}
|
|
75
102
|
/**
|
|
76
103
|
* Check which crons are due to run based on their schedule and lastRun.
|
|
77
104
|
*/
|
|
@@ -7,6 +7,7 @@ declare const inputSchema: z.ZodObject<{
|
|
|
7
7
|
run_in_background: z.ZodOptional<z.ZodBoolean>;
|
|
8
8
|
model: z.ZodOptional<z.ZodString>;
|
|
9
9
|
subagent_type: z.ZodOptional<z.ZodString>;
|
|
10
|
+
allowed_tools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
10
11
|
}, "strip", z.ZodTypeAny, {
|
|
11
12
|
prompt: string;
|
|
12
13
|
model?: string | undefined;
|
|
@@ -14,6 +15,7 @@ declare const inputSchema: z.ZodObject<{
|
|
|
14
15
|
run_in_background?: boolean | undefined;
|
|
15
16
|
isolated?: boolean | undefined;
|
|
16
17
|
subagent_type?: string | undefined;
|
|
18
|
+
allowed_tools?: string[] | undefined;
|
|
17
19
|
}, {
|
|
18
20
|
prompt: string;
|
|
19
21
|
model?: string | undefined;
|
|
@@ -21,6 +23,7 @@ declare const inputSchema: z.ZodObject<{
|
|
|
21
23
|
run_in_background?: boolean | undefined;
|
|
22
24
|
isolated?: boolean | undefined;
|
|
23
25
|
subagent_type?: string | undefined;
|
|
26
|
+
allowed_tools?: string[] | undefined;
|
|
24
27
|
}>;
|
|
25
28
|
export declare const AgentTool: Tool<typeof inputSchema>;
|
|
26
29
|
export {};
|