@zhijiewang/openharness 0.12.0 → 1.0.0
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 +56 -0
- package/dist/agents/roles.js +42 -0
- package/dist/commands/index.js +127 -8
- package/dist/components/InitWizard.js +84 -5
- package/dist/harness/session.d.ts +19 -0
- package/dist/harness/session.js +53 -0
- package/dist/mcp/registry.d.ts +31 -0
- package/dist/mcp/registry.js +180 -0
- package/dist/renderer/index.d.ts +7 -0
- package/dist/renderer/index.js +33 -5
- package/dist/repl.js +13 -0
- package/dist/tools/AgentTool/index.js +1 -1
- package/package.json +5 -2
- package/dist/DeferredTool.d.ts.map +0 -1
- package/dist/DeferredTool.js.map +0 -1
- package/dist/DeferredTool.test.d.ts +0 -2
- package/dist/DeferredTool.test.d.ts.map +0 -1
- package/dist/DeferredTool.test.js +0 -79
- package/dist/DeferredTool.test.js.map +0 -1
- 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 -62
- 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-consolidation.test.d.ts +0 -2
- package/dist/harness/memory-consolidation.test.d.ts.map +0 -1
- package/dist/harness/memory-consolidation.test.js +0 -152
- package/dist/harness/memory-consolidation.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 -107
- 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 -73
- 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/harness/verification.d.ts.map +0 -1
- package/dist/harness/verification.js.map +0 -1
- package/dist/harness/verification.test.d.ts +0 -2
- package/dist/harness/verification.test.d.ts.map +0 -1
- package/dist/harness/verification.test.js +0 -181
- package/dist/harness/verification.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/CronExecutor.d.ts.map +0 -1
- package/dist/services/CronExecutor.js.map +0 -1
- package/dist/services/CronExecutor.test.d.ts +0 -2
- package/dist/services/CronExecutor.test.d.ts.map +0 -1
- package/dist/services/CronExecutor.test.js +0 -128
- package/dist/services/CronExecutor.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
package/README.md
CHANGED
|
@@ -366,6 +366,16 @@ mcpServers:
|
|
|
366
366
|
|
|
367
367
|
MCP tools appear alongside built-in tools. `/status` shows connected servers.
|
|
368
368
|
|
|
369
|
+
**MCP Server Registry** — browse and install from a curated catalog:
|
|
370
|
+
|
|
371
|
+
```
|
|
372
|
+
/mcp-registry # browse all available servers
|
|
373
|
+
/mcp-registry github # show install config for a specific server
|
|
374
|
+
/mcp-registry database # search by category
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Categories: filesystem, git, database, api, search, productivity, dev-tools, ai.
|
|
378
|
+
|
|
369
379
|
## Git Integration
|
|
370
380
|
|
|
371
381
|
OpenHarness auto-commits AI edits in git repos:
|
|
@@ -460,6 +470,9 @@ Dispatch specialized sub-agents for focused tasks:
|
|
|
460
470
|
| `refactorer` | Simplify code without changing behavior | All file tools + Bash |
|
|
461
471
|
| `security-auditor` | OWASP, injection, secrets, CVE scanning | Read-only + Bash |
|
|
462
472
|
| `evaluator` | Evaluate code quality and run tests (read-only) | Read-only + Bash + Diagnostics |
|
|
473
|
+
| `planner` | Design step-by-step implementation plans | Read-only + Bash |
|
|
474
|
+
| `architect` | Analyze architecture and design structural changes | Read-only |
|
|
475
|
+
| `migrator` | Systematic codebase migrations and upgrades | All file tools + Bash |
|
|
463
476
|
|
|
464
477
|
Each role restricts the sub-agent to only its suggested tools. You can also pass `allowed_tools` explicitly:
|
|
465
478
|
|
|
@@ -598,6 +611,49 @@ Create `.oh/RULES.md` in any repo (or run `oh init`):
|
|
|
598
611
|
|
|
599
612
|
Rules load automatically into every session.
|
|
600
613
|
|
|
614
|
+
## Skills & Plugins
|
|
615
|
+
|
|
616
|
+
### Skills
|
|
617
|
+
|
|
618
|
+
Skills are markdown files with YAML frontmatter that add reusable behaviors:
|
|
619
|
+
|
|
620
|
+
```markdown
|
|
621
|
+
---
|
|
622
|
+
name: deploy
|
|
623
|
+
description: Deploy the application to production
|
|
624
|
+
trigger: deploy
|
|
625
|
+
tools: [Bash, Read]
|
|
626
|
+
---
|
|
627
|
+
|
|
628
|
+
Run the deploy script with health checks...
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
**Locations** (searched in order):
|
|
632
|
+
1. `.oh/skills/` — project-level skills
|
|
633
|
+
2. `~/.oh/skills/` — global skills (available in all projects)
|
|
634
|
+
|
|
635
|
+
Skills auto-trigger when the user's message contains the trigger keyword, or can be invoked explicitly with `/skill deploy`.
|
|
636
|
+
|
|
637
|
+
### Plugins
|
|
638
|
+
|
|
639
|
+
Plugins are npm packages that bundle skills, hooks, and MCP servers:
|
|
640
|
+
|
|
641
|
+
```json
|
|
642
|
+
{
|
|
643
|
+
"name": "my-openharness-plugin",
|
|
644
|
+
"version": "1.0.0",
|
|
645
|
+
"skills": ["skills/deploy.md", "skills/review.md"],
|
|
646
|
+
"hooks": {
|
|
647
|
+
"sessionStart": "scripts/setup.sh"
|
|
648
|
+
},
|
|
649
|
+
"mcpServers": [
|
|
650
|
+
{ "name": "my-api", "command": "npx", "args": ["-y", "@my-org/mcp-server"] }
|
|
651
|
+
]
|
|
652
|
+
}
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
Save as `openharness-plugin.json` in your npm package root. Install with `npm install`, and openHarness discovers it automatically from `node_modules/`.
|
|
656
|
+
|
|
601
657
|
## How It Works
|
|
602
658
|
|
|
603
659
|
```mermaid
|
package/dist/agents/roles.js
CHANGED
|
@@ -114,6 +114,48 @@ Report findings with severity (Critical/High/Medium/Low), affected file:line, an
|
|
|
114
114
|
You CANNOT modify files. Only read, search, and run test/lint commands to evaluate.`,
|
|
115
115
|
suggestedTools: ['Read', 'Glob', 'Grep', 'LS', 'Bash', 'Diagnostics'],
|
|
116
116
|
},
|
|
117
|
+
{
|
|
118
|
+
id: 'planner',
|
|
119
|
+
name: 'Planner',
|
|
120
|
+
description: 'Designs step-by-step implementation plans from requirements',
|
|
121
|
+
systemPromptSupplement: `You are a planning agent. Your job is to:
|
|
122
|
+
- Read the codebase to understand architecture, patterns, and conventions
|
|
123
|
+
- Design a detailed step-by-step implementation plan for the given task
|
|
124
|
+
- Identify files to create, modify, or delete with specific change descriptions
|
|
125
|
+
- Flag risks, dependencies, and the recommended implementation order
|
|
126
|
+
- Estimate scope (number of files, complexity)
|
|
127
|
+
|
|
128
|
+
Do NOT implement anything. Your output is a plan document, not code. Read widely before planning.`,
|
|
129
|
+
suggestedTools: ['Read', 'Glob', 'Grep', 'LS', 'Bash'],
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
id: 'architect',
|
|
133
|
+
name: 'Architect',
|
|
134
|
+
description: 'Analyzes system architecture and designs structural changes',
|
|
135
|
+
systemPromptSupplement: `You are an architecture agent. Your job is to:
|
|
136
|
+
- Map the current system architecture (modules, dependencies, data flow)
|
|
137
|
+
- Identify architectural patterns and conventions in use
|
|
138
|
+
- Design structural changes that preserve existing patterns
|
|
139
|
+
- Evaluate trade-offs between approaches (performance, maintainability, complexity)
|
|
140
|
+
- Document interfaces, contracts, and integration points
|
|
141
|
+
|
|
142
|
+
Focus on the big picture: module boundaries, data flow, dependency graphs. Leave implementation details to other agents.`,
|
|
143
|
+
suggestedTools: ['Read', 'Glob', 'Grep', 'LS'],
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
id: 'migrator',
|
|
147
|
+
name: 'Migrator',
|
|
148
|
+
description: 'Performs codebase migrations (API upgrades, framework changes, renames)',
|
|
149
|
+
systemPromptSupplement: `You are a migration agent. Your job is to:
|
|
150
|
+
- Identify all occurrences of the pattern/API/convention being migrated
|
|
151
|
+
- Apply changes systematically across all affected files
|
|
152
|
+
- Preserve behavior while updating the implementation
|
|
153
|
+
- Run tests after each batch of changes to catch regressions
|
|
154
|
+
- Handle edge cases and conditional patterns that need manual review
|
|
155
|
+
|
|
156
|
+
Work methodically: search exhaustively, change incrementally, test after each batch. Never leave a migration half-done.`,
|
|
157
|
+
suggestedTools: ['Read', 'Write', 'Edit', 'Glob', 'Grep', 'Bash'],
|
|
158
|
+
},
|
|
117
159
|
];
|
|
118
160
|
/** Get a role by ID */
|
|
119
161
|
export function getRole(id) {
|
package/dist/commands/index.js
CHANGED
|
@@ -27,7 +27,7 @@ register("help", "Show available commands", () => {
|
|
|
27
27
|
const categories = {
|
|
28
28
|
'Session': ['clear', 'compact', 'export', 'history', 'browse', 'resume', 'fork', 'pin', 'unpin'],
|
|
29
29
|
'Git': ['diff', 'undo', 'rewind', 'commit', 'log'],
|
|
30
|
-
'Info': ['help', 'cost', 'status', 'config', 'files', 'model', 'memory', 'doctor', 'context', 'mcp'],
|
|
30
|
+
'Info': ['help', 'cost', 'status', 'config', 'files', 'model', 'memory', 'doctor', 'context', 'mcp', 'mcp-registry'],
|
|
31
31
|
'Settings': ['theme', 'vim', 'companion', 'fast', 'keys'],
|
|
32
32
|
'AI': ['plan', 'review', 'roles'],
|
|
33
33
|
'Pet': ['cybergotchi'],
|
|
@@ -473,18 +473,61 @@ register("doctor", "Run diagnostic health checks", (_args, ctx) => {
|
|
|
473
473
|
lines.push(` Session: ${ctx.sessionId}`);
|
|
474
474
|
lines.push(` Messages: ${ctx.messages.length}`);
|
|
475
475
|
lines.push(` Cost: $${ctx.totalCost.toFixed(4)}`);
|
|
476
|
-
// Disk space
|
|
476
|
+
// Disk space & storage
|
|
477
477
|
try {
|
|
478
|
-
const { statSync } = require("node:fs");
|
|
479
478
|
const ohDir = join(homedir(), ".oh");
|
|
480
479
|
if (existsSync(ohDir)) {
|
|
481
|
-
const
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
480
|
+
const sessionsDir = join(ohDir, "sessions");
|
|
481
|
+
const sessCount = existsSync(sessionsDir) ? readdirSync(sessionsDir).filter(f => f.endsWith('.json')).length : 0;
|
|
482
|
+
lines.push(` Sessions: ${sessCount} saved`);
|
|
483
|
+
if (sessCount > 80)
|
|
484
|
+
issues.push(`${sessCount} saved sessions. Consider cleaning old ones.`);
|
|
485
|
+
// Memory stats
|
|
486
|
+
const memDir = join(ohDir, "memory");
|
|
487
|
+
const memCount = existsSync(memDir) ? readdirSync(memDir).filter(f => f.endsWith('.md')).length : 0;
|
|
488
|
+
lines.push(` Memories: ${memCount} global`);
|
|
489
|
+
// Cron stats
|
|
490
|
+
const cronDir = join(ohDir, "crons");
|
|
491
|
+
const cronCount = existsSync(cronDir) ? readdirSync(cronDir).filter(f => f.endsWith('.json')).length : 0;
|
|
492
|
+
lines.push(` Cron tasks: ${cronCount}`);
|
|
485
493
|
}
|
|
486
494
|
}
|
|
487
495
|
catch { /* ignore */ }
|
|
496
|
+
// Project-level stats
|
|
497
|
+
try {
|
|
498
|
+
const projMemDir = join(".oh", "memory");
|
|
499
|
+
const projMemCount = existsSync(projMemDir) ? readdirSync(projMemDir).filter(f => f.endsWith('.md')).length : 0;
|
|
500
|
+
if (projMemCount > 0)
|
|
501
|
+
lines.push(` Project mems: ${projMemCount}`);
|
|
502
|
+
const skillsDir = join(".oh", "skills");
|
|
503
|
+
const skillCount = existsSync(skillsDir) ? readdirSync(skillsDir).filter(f => f.endsWith('.md')).length : 0;
|
|
504
|
+
if (skillCount > 0)
|
|
505
|
+
lines.push(` Skills: ${skillCount}`);
|
|
506
|
+
}
|
|
507
|
+
catch { /* ignore */ }
|
|
508
|
+
// Global config
|
|
509
|
+
const globalCfg = existsSync(join(homedir(), ".oh", "config.yaml"));
|
|
510
|
+
lines.push(` Global config: ${globalCfg ? "~/.oh/config.yaml ✓" : "not set (optional)"}`);
|
|
511
|
+
// Verification config
|
|
512
|
+
try {
|
|
513
|
+
const { getVerificationConfig } = require('../harness/verification.js');
|
|
514
|
+
const vCfg = getVerificationConfig();
|
|
515
|
+
if (vCfg?.enabled) {
|
|
516
|
+
lines.push(` Verification: ✓ (${vCfg.rules.length} rules, mode: ${vCfg.mode})`);
|
|
517
|
+
}
|
|
518
|
+
else {
|
|
519
|
+
lines.push(` Verification: off (no rules detected)`);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
catch { /* ignore */ }
|
|
523
|
+
// Tools
|
|
524
|
+
lines.push("");
|
|
525
|
+
lines.push(` Tools: ${ctx.messages.length > 0 ? 'ready' : 'loaded'}`);
|
|
526
|
+
// Node.js version
|
|
527
|
+
lines.push(` Node.js: ${process.version}`);
|
|
528
|
+
const [major] = process.version.slice(1).split('.').map(Number);
|
|
529
|
+
if (major && major < 18)
|
|
530
|
+
issues.push(`Node.js ${process.version} is below minimum (18+). Upgrade Node.js.`);
|
|
488
531
|
// Issues summary
|
|
489
532
|
if (issues.length > 0) {
|
|
490
533
|
lines.push("");
|
|
@@ -519,14 +562,43 @@ register("context", "Show context window usage breakdown", (_args, ctx) => {
|
|
|
519
562
|
register("mcp", "Show MCP server status", () => {
|
|
520
563
|
const mcp = connectedMcpServers();
|
|
521
564
|
if (mcp.length === 0) {
|
|
522
|
-
return { output: "No MCP servers connected.\nConfigure in .oh/config.yaml under mcpServers.", handled: true };
|
|
565
|
+
return { output: "No MCP servers connected.\nConfigure in .oh/config.yaml under mcpServers.\nRun /mcp-registry to browse available servers.", handled: true };
|
|
523
566
|
}
|
|
524
567
|
const lines = [`MCP Servers (${mcp.length} connected):\n`];
|
|
525
568
|
for (const name of mcp) {
|
|
526
569
|
lines.push(` ✓ ${name}`);
|
|
527
570
|
}
|
|
571
|
+
lines.push("\nRun /mcp-registry to browse and add more servers.");
|
|
528
572
|
return { output: lines.join("\n"), handled: true };
|
|
529
573
|
});
|
|
574
|
+
register("mcp-registry", "Browse and add MCP servers from the curated registry", (args) => {
|
|
575
|
+
const { searchRegistry, formatRegistry, generateConfigBlock, MCP_REGISTRY } = require('../mcp/registry.js');
|
|
576
|
+
const query = args.trim();
|
|
577
|
+
if (!query) {
|
|
578
|
+
// Show full registry
|
|
579
|
+
const output = `MCP Server Registry (${MCP_REGISTRY.length} servers)\n${'─'.repeat(50)}\n\n${formatRegistry()}\n\nUsage:\n /mcp-registry <name> Show install config for a server\n /mcp-registry <keyword> Search by name, description, or category`;
|
|
580
|
+
return { output, handled: true };
|
|
581
|
+
}
|
|
582
|
+
// Search or show specific server
|
|
583
|
+
const results = searchRegistry(query);
|
|
584
|
+
if (results.length === 0) {
|
|
585
|
+
return { output: `No MCP servers found matching "${query}".`, handled: true };
|
|
586
|
+
}
|
|
587
|
+
if (results.length === 1) {
|
|
588
|
+
// Show install instructions
|
|
589
|
+
const entry = results[0];
|
|
590
|
+
const config = generateConfigBlock(entry);
|
|
591
|
+
const envNote = entry.envVars?.length
|
|
592
|
+
? `\n\nRequired environment variables:\n${entry.envVars.map((v) => ` - ${v}`).join('\n')}`
|
|
593
|
+
: '';
|
|
594
|
+
return {
|
|
595
|
+
output: `${entry.name} — ${entry.description}\nPackage: ${entry.package}\nRisk: ${entry.riskLevel ?? 'medium'}${envNote}\n\nAdd to .oh/config.yaml under mcpServers:\n\n${config}`,
|
|
596
|
+
handled: true,
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
// Multiple results
|
|
600
|
+
return { output: `Found ${results.length} servers:\n\n${formatRegistry(results)}`, handled: true };
|
|
601
|
+
});
|
|
530
602
|
function setPinned(args, ctx, pinned) {
|
|
531
603
|
const idx = parseInt(args.trim(), 10);
|
|
532
604
|
if (isNaN(idx) || idx < 1 || idx > ctx.messages.length) {
|
|
@@ -542,6 +614,53 @@ function setPinned(args, ctx, pinned) {
|
|
|
542
614
|
}
|
|
543
615
|
register("pin", "Pin a message (survives /compact)", (args, ctx) => setPinned(args, ctx, true));
|
|
544
616
|
register("unpin", "Unpin a message", (args, ctx) => setPinned(args, ctx, false));
|
|
617
|
+
register("plugins", "List installed plugins and discover new ones", (args) => {
|
|
618
|
+
const { discoverPlugins, discoverSkills } = require('../harness/plugins.js');
|
|
619
|
+
const query = args.trim();
|
|
620
|
+
if (query === 'search' || query.startsWith('search ')) {
|
|
621
|
+
// npm registry search
|
|
622
|
+
const keyword = query.replace(/^search\s*/, '').trim() || 'openharness-plugin';
|
|
623
|
+
return {
|
|
624
|
+
output: `To discover plugins, search npm:\n\n npm search openharness-plugin${keyword !== 'openharness-plugin' ? ' ' + keyword : ''}\n\nInstall with:\n npm install <package-name>\n\nPlugins are auto-discovered from node_modules/ if they contain openharness-plugin.json.`,
|
|
625
|
+
handled: true,
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
// List installed
|
|
629
|
+
const plugins = discoverPlugins();
|
|
630
|
+
const skills = discoverSkills();
|
|
631
|
+
const lines = [];
|
|
632
|
+
if (plugins.length > 0) {
|
|
633
|
+
lines.push(`Installed Plugins (${plugins.length}):`);
|
|
634
|
+
for (const p of plugins) {
|
|
635
|
+
lines.push(` ${p.name}@${p.version} — ${p.description || 'no description'}`);
|
|
636
|
+
if (p.skills?.length)
|
|
637
|
+
lines.push(` Skills: ${p.skills.length}`);
|
|
638
|
+
if (p.mcpServers?.length)
|
|
639
|
+
lines.push(` MCP servers: ${p.mcpServers.map((s) => s.name).join(', ')}`);
|
|
640
|
+
}
|
|
641
|
+
lines.push('');
|
|
642
|
+
}
|
|
643
|
+
if (skills.length > 0) {
|
|
644
|
+
lines.push(`Available Skills (${skills.length}):`);
|
|
645
|
+
const bySource = {};
|
|
646
|
+
for (const s of skills) {
|
|
647
|
+
(bySource[s.source] ??= []).push(s);
|
|
648
|
+
}
|
|
649
|
+
for (const [source, sourceSkills] of Object.entries(bySource)) {
|
|
650
|
+
lines.push(` ${source}:`);
|
|
651
|
+
for (const s of sourceSkills) {
|
|
652
|
+
lines.push(` ${s.name} — ${s.description}${s.trigger ? ` (trigger: "${s.trigger}")` : ''}`);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
else if (plugins.length === 0) {
|
|
657
|
+
lines.push('No plugins or skills installed.');
|
|
658
|
+
lines.push('');
|
|
659
|
+
lines.push('Create skills in .oh/skills/ or ~/.oh/skills/');
|
|
660
|
+
lines.push('Run /plugins search to find npm packages.');
|
|
661
|
+
}
|
|
662
|
+
return { output: lines.join('\n'), handled: true };
|
|
663
|
+
});
|
|
545
664
|
// ── Command Parser ──
|
|
546
665
|
/**
|
|
547
666
|
* Check if input is a slash command. If so, execute it.
|
|
@@ -30,9 +30,30 @@ const PERMISSION_MODES = [
|
|
|
30
30
|
{ key: "trust", label: "trust — auto-approve everything" },
|
|
31
31
|
{ key: "deny", label: "deny — read-only, block write/run tools" },
|
|
32
32
|
];
|
|
33
|
+
/** Auto-detect provider from environment variables */
|
|
34
|
+
function detectProviderFromEnv() {
|
|
35
|
+
if (process.env.ANTHROPIC_API_KEY)
|
|
36
|
+
return PROVIDERS.findIndex(p => p.key === "anthropic");
|
|
37
|
+
if (process.env.OPENAI_API_KEY)
|
|
38
|
+
return PROVIDERS.findIndex(p => p.key === "openai");
|
|
39
|
+
if (process.env.OPENROUTER_API_KEY)
|
|
40
|
+
return PROVIDERS.findIndex(p => p.key === "openrouter");
|
|
41
|
+
return 0; // Default to Ollama
|
|
42
|
+
}
|
|
43
|
+
/** Get the detected API key for a provider */
|
|
44
|
+
function getEnvApiKey(providerKey) {
|
|
45
|
+
const envMap = {
|
|
46
|
+
anthropic: 'ANTHROPIC_API_KEY',
|
|
47
|
+
openai: 'OPENAI_API_KEY',
|
|
48
|
+
openrouter: 'OPENROUTER_API_KEY',
|
|
49
|
+
};
|
|
50
|
+
const envVar = envMap[providerKey];
|
|
51
|
+
return envVar ? (process.env[envVar] ?? '') : '';
|
|
52
|
+
}
|
|
33
53
|
export default function InitWizard({ onDone }) {
|
|
54
|
+
const detectedIdx = detectProviderFromEnv();
|
|
34
55
|
const [step, setStep] = useState("provider");
|
|
35
|
-
const [providerIdx, setProviderIdx] = useState(
|
|
56
|
+
const [providerIdx, setProviderIdx] = useState(detectedIdx);
|
|
36
57
|
const [apiKey, setApiKey] = useState("");
|
|
37
58
|
const [baseUrl, setBaseUrl] = useState("");
|
|
38
59
|
const [model, setModel] = useState("");
|
|
@@ -43,6 +64,9 @@ export default function InitWizard({ onDone }) {
|
|
|
43
64
|
const [permIdx, setPermIdx] = useState(0);
|
|
44
65
|
const [hatchGotchi, setHatchGotchi] = useState(false);
|
|
45
66
|
const [showSetup, setShowSetup] = useState(false);
|
|
67
|
+
const [suggestedMcp, setSuggestedMcp] = useState([]);
|
|
68
|
+
const [selectedMcp, setSelectedMcp] = useState(new Set());
|
|
69
|
+
const [mcpIdx, setMcpIdx] = useState(0);
|
|
46
70
|
const provider = PROVIDERS[providerIdx];
|
|
47
71
|
// ── Keyboard navigation ──
|
|
48
72
|
useInput(useCallback((input, key) => {
|
|
@@ -54,11 +78,19 @@ export default function InitWizard({ onDone }) {
|
|
|
54
78
|
if (key.return) {
|
|
55
79
|
setBaseUrl(provider.defaultBaseUrl ?? "");
|
|
56
80
|
setModel(provider.defaultModel);
|
|
81
|
+
// Auto-fill API key from environment if available
|
|
82
|
+
const envKey = getEnvApiKey(provider.key);
|
|
83
|
+
if (envKey)
|
|
84
|
+
setApiKey(envKey);
|
|
57
85
|
if (!provider.needsApiKey) {
|
|
58
|
-
// Skip API key, go straight to testing
|
|
59
86
|
runTest(provider, "", provider.defaultBaseUrl ?? "");
|
|
60
87
|
setStep("testing");
|
|
61
88
|
}
|
|
89
|
+
else if (envKey) {
|
|
90
|
+
// Have env API key — skip manual entry, go to testing
|
|
91
|
+
runTest(provider, envKey, provider.defaultBaseUrl ?? "");
|
|
92
|
+
setStep("testing");
|
|
93
|
+
}
|
|
62
94
|
else {
|
|
63
95
|
setStep("apikey");
|
|
64
96
|
}
|
|
@@ -69,8 +101,37 @@ export default function InitWizard({ onDone }) {
|
|
|
69
101
|
setPermIdx(i => Math.max(0, i - 1));
|
|
70
102
|
if (key.downArrow)
|
|
71
103
|
setPermIdx(i => Math.min(PERMISSION_MODES.length - 1, i + 1));
|
|
104
|
+
if (key.return) {
|
|
105
|
+
// Suggest popular MCP servers
|
|
106
|
+
setSuggestedMcp(['github', 'memory', 'fetch', 'sequential-thinking', 'brave-search']);
|
|
107
|
+
setMcpIdx(0);
|
|
108
|
+
setSelectedMcp(new Set());
|
|
109
|
+
setStep("mcp");
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (step === "mcp") {
|
|
113
|
+
if (key.upArrow)
|
|
114
|
+
setMcpIdx(i => Math.max(0, i - 1));
|
|
115
|
+
if (key.downArrow)
|
|
116
|
+
setMcpIdx(i => Math.min(suggestedMcp.length - 1, i + 1));
|
|
117
|
+
if (input === " ") {
|
|
118
|
+
// Toggle selection
|
|
119
|
+
const name = suggestedMcp[mcpIdx];
|
|
120
|
+
if (name) {
|
|
121
|
+
setSelectedMcp(prev => {
|
|
122
|
+
const next = new Set(prev);
|
|
123
|
+
if (next.has(name))
|
|
124
|
+
next.delete(name);
|
|
125
|
+
else
|
|
126
|
+
next.add(name);
|
|
127
|
+
return next;
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
72
131
|
if (key.return)
|
|
73
132
|
setStep("gotchi");
|
|
133
|
+
if (input === "s" || input === "S")
|
|
134
|
+
setStep("gotchi"); // Skip
|
|
74
135
|
}
|
|
75
136
|
if (step === "model" && availableModels.length > 0) {
|
|
76
137
|
if (key.upArrow)
|
|
@@ -120,16 +181,34 @@ export default function InitWizard({ onDone }) {
|
|
|
120
181
|
// ── Write final config ──
|
|
121
182
|
const writeFinal = useCallback(() => {
|
|
122
183
|
const selectedModel = availableModels.length > 0 ? (availableModels[modelIdx] ?? model) : model;
|
|
184
|
+
// Build MCP server configs from selected registry entries
|
|
185
|
+
let mcpServers;
|
|
186
|
+
if (selectedMcp.size > 0) {
|
|
187
|
+
try {
|
|
188
|
+
const { MCP_REGISTRY } = require('../mcp/registry.js');
|
|
189
|
+
mcpServers = [...selectedMcp]
|
|
190
|
+
.map(name => MCP_REGISTRY.find((e) => e.name === name))
|
|
191
|
+
.filter(Boolean)
|
|
192
|
+
.map((e) => ({
|
|
193
|
+
name: e.name,
|
|
194
|
+
command: 'npx',
|
|
195
|
+
args: ['-y', e.package, ...(e.args ?? [])],
|
|
196
|
+
...(e.envVars?.length ? { env: Object.fromEntries(e.envVars.map((v) => [v, `YOUR_${v}`])) } : {}),
|
|
197
|
+
}));
|
|
198
|
+
}
|
|
199
|
+
catch { /* ignore */ }
|
|
200
|
+
}
|
|
123
201
|
writeOhConfig({
|
|
124
202
|
provider: provider.key,
|
|
125
203
|
model: selectedModel || provider.defaultModel,
|
|
126
204
|
permissionMode: PERMISSION_MODES[permIdx].key,
|
|
127
205
|
...(apiKey ? { apiKey } : {}),
|
|
128
206
|
...(baseUrl ? { baseUrl } : {}),
|
|
207
|
+
...(mcpServers?.length ? { mcpServers } : {}),
|
|
129
208
|
});
|
|
130
209
|
setStep("done");
|
|
131
210
|
setTimeout(() => onDone?.(), 1500);
|
|
132
|
-
}, [provider, model, availableModels, modelIdx, permIdx, apiKey, baseUrl]);
|
|
211
|
+
}, [provider, model, availableModels, modelIdx, permIdx, apiKey, baseUrl, selectedMcp]);
|
|
133
212
|
// ── Render ──
|
|
134
213
|
if (showSetup) {
|
|
135
214
|
return _jsx(CybergotchiSetup, { onComplete: () => { setShowSetup(false); writeFinal(); }, onSkip: () => { setShowSetup(false); writeFinal(); } });
|
|
@@ -137,7 +216,7 @@ export default function InitWizard({ onDone }) {
|
|
|
137
216
|
if (step === "done") {
|
|
138
217
|
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { color: "green", children: "\u2713 OpenHarness configured!" }), _jsx(Text, { dimColor: true, children: "Config saved to .oh/config.yaml" }), _jsx(Text, { dimColor: true, children: "Run: oh" })] }));
|
|
139
218
|
}
|
|
140
|
-
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "OpenHarness Setup" }), _jsx(Text, { children: " " }), step === "provider" && (_jsxs(Box, { flexDirection: "column", children: [
|
|
219
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { bold: true, color: "cyan", children: "OpenHarness Setup" }), _jsx(Text, { children: " " }), step === "provider" && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: ["Select provider:", detectedIdx > 0 ? _jsx(Text, { dimColor: true, children: " (auto-detected from env)" }) : ''] }), PROVIDERS.map((p, i) => (_jsxs(Text, { color: i === providerIdx ? "cyan" : undefined, children: [i === providerIdx ? "▶ " : " ", p.label] }, p.key))), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: "\u2191\u2193 navigate Enter select" })] })), step === "apikey" && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: ["API key for ", _jsx(Text, { color: "cyan", children: provider.label }), ":"] }), _jsx(TextInput, { value: apiKey, onChange: setApiKey, mask: "*", onSubmit: (val) => {
|
|
141
220
|
if (!val.trim())
|
|
142
221
|
return;
|
|
143
222
|
if (provider.key === "custom") {
|
|
@@ -158,6 +237,6 @@ export default function InitWizard({ onDone }) {
|
|
|
158
237
|
const gi = start + vi;
|
|
159
238
|
return (_jsxs(Text, { color: gi === modelIdx ? "cyan" : undefined, children: [gi === modelIdx ? "▶ " : " ", m] }, m));
|
|
160
239
|
}), start + WINDOW < availableModels.length && (_jsxs(Text, { dimColor: true, children: [" \u2193 ", availableModels.length - start - WINDOW, " more"] }))] }));
|
|
161
|
-
})() : (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "Could not fetch model list. Enter model name:" }), _jsx(TextInput, { value: model, onChange: setModel, onSubmit: () => setStep("permission") })] })), availableModels.length > 0 && _jsx(Text, { dimColor: true, children: "\u2191\u2193 navigate Enter select" })] })), step === "permission" && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Permission mode:" }), PERMISSION_MODES.map((p, i) => (_jsxs(Text, { color: i === permIdx ? "cyan" : undefined, children: [i === permIdx ? "▶ " : " ", p.label] }, p.key))), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: "\u2191\u2193 navigate Enter select" })] })), step === "gotchi" && (_jsx(Box, { flexDirection: "column", children: _jsxs(Text, { children: ["Hatch a cybergotchi companion? ", _jsx(Text, { dimColor: true, children: "(Y/n)" })] }) }))] }));
|
|
240
|
+
})() : (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "Could not fetch model list. Enter model name:" }), _jsx(TextInput, { value: model, onChange: setModel, onSubmit: () => setStep("permission") })] })), availableModels.length > 0 && _jsx(Text, { dimColor: true, children: "\u2191\u2193 navigate Enter select" })] })), step === "permission" && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Permission mode:" }), PERMISSION_MODES.map((p, i) => (_jsxs(Text, { color: i === permIdx ? "cyan" : undefined, children: [i === permIdx ? "▶ " : " ", p.label] }, p.key))), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: "\u2191\u2193 navigate Enter select" })] })), step === "mcp" && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: ["Add MCP servers? ", _jsx(Text, { dimColor: true, children: "(Space to toggle, Enter to confirm, S to skip)" })] }), _jsx(Text, { children: " " }), suggestedMcp.map((name, i) => (_jsxs(Text, { color: i === mcpIdx ? "cyan" : undefined, children: [i === mcpIdx ? "▶ " : " ", selectedMcp.has(name) ? "[✓] " : "[ ] ", name] }, name))), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: "\u2191\u2193 navigate Space toggle Enter confirm S skip" })] })), step === "gotchi" && (_jsx(Box, { flexDirection: "column", children: _jsxs(Text, { children: ["Hatch a cybergotchi companion? ", _jsx(Text, { dimColor: true, children: "(Y/n)" })] }) }))] }));
|
|
162
241
|
}
|
|
163
242
|
//# sourceMappingURL=InitWizard.js.map
|
|
@@ -13,6 +13,14 @@ export type Session = {
|
|
|
13
13
|
gitBranch?: string;
|
|
14
14
|
workingDir?: string;
|
|
15
15
|
tools?: string[];
|
|
16
|
+
/** Hibernate state — saved on exit for wake reconstruction */
|
|
17
|
+
hibernate?: {
|
|
18
|
+
summary?: string;
|
|
19
|
+
lastUserMessage?: string;
|
|
20
|
+
pendingTask?: string;
|
|
21
|
+
totalInputTokens?: number;
|
|
22
|
+
totalOutputTokens?: number;
|
|
23
|
+
};
|
|
16
24
|
};
|
|
17
25
|
export declare function createSession(provider: string, model: string, extras?: {
|
|
18
26
|
gitBranch?: string;
|
|
@@ -30,6 +38,17 @@ export declare function listSessions(dir?: string): Array<{
|
|
|
30
38
|
}>;
|
|
31
39
|
/** Returns the ID of the most recently updated session, or null if none exist. */
|
|
32
40
|
export declare function getLastSessionId(dir?: string): string | null;
|
|
41
|
+
/**
|
|
42
|
+
* Build hibernate state from the current session.
|
|
43
|
+
* Captures the last user message, recent assistant activity,
|
|
44
|
+
* and a brief summary for context reconstruction on wake.
|
|
45
|
+
*/
|
|
46
|
+
export declare function buildHibernateState(messages: Message[]): Session['hibernate'];
|
|
47
|
+
/**
|
|
48
|
+
* Generate a wake-up context message for a resumed session.
|
|
49
|
+
* Tells the LLM what happened in the previous session.
|
|
50
|
+
*/
|
|
51
|
+
export declare function buildWakeContext(session: Session): string;
|
|
33
52
|
/**
|
|
34
53
|
* Evict oldest sessions when count exceeds MAX_SESSIONS.
|
|
35
54
|
* Called automatically by saveSession.
|
package/dist/harness/session.js
CHANGED
|
@@ -72,6 +72,59 @@ export function getLastSessionId(dir) {
|
|
|
72
72
|
const sessions = listSessions(dir);
|
|
73
73
|
return sessions.length > 0 ? sessions[0].id : null;
|
|
74
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Build hibernate state from the current session.
|
|
77
|
+
* Captures the last user message, recent assistant activity,
|
|
78
|
+
* and a brief summary for context reconstruction on wake.
|
|
79
|
+
*/
|
|
80
|
+
export function buildHibernateState(messages) {
|
|
81
|
+
if (messages.length === 0)
|
|
82
|
+
return undefined;
|
|
83
|
+
// Find last user message
|
|
84
|
+
const lastUser = [...messages].reverse().find(m => m.role === 'user');
|
|
85
|
+
const lastAssistant = [...messages].reverse().find(m => m.role === 'assistant');
|
|
86
|
+
// Build a brief summary from the last few exchanges
|
|
87
|
+
const recentMsgs = messages.slice(-6);
|
|
88
|
+
const summaryParts = [];
|
|
89
|
+
for (const m of recentMsgs) {
|
|
90
|
+
if (m.role === 'user') {
|
|
91
|
+
summaryParts.push(`User: ${m.content.slice(0, 100)}`);
|
|
92
|
+
}
|
|
93
|
+
else if (m.role === 'assistant' && m.content) {
|
|
94
|
+
summaryParts.push(`Assistant: ${m.content.slice(0, 100)}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
lastUserMessage: lastUser?.content.slice(0, 200),
|
|
99
|
+
pendingTask: lastAssistant?.content.slice(0, 200),
|
|
100
|
+
summary: summaryParts.join('\n'),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Generate a wake-up context message for a resumed session.
|
|
105
|
+
* Tells the LLM what happened in the previous session.
|
|
106
|
+
*/
|
|
107
|
+
export function buildWakeContext(session) {
|
|
108
|
+
const parts = ['[Session Resumed]'];
|
|
109
|
+
if (session.workingDir) {
|
|
110
|
+
parts.push(`Previous working directory: ${session.workingDir}`);
|
|
111
|
+
if (session.workingDir !== process.cwd()) {
|
|
112
|
+
parts.push(`WARNING: Working directory changed! Was: ${session.workingDir}, Now: ${process.cwd()}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (session.gitBranch) {
|
|
116
|
+
parts.push(`Previous git branch: ${session.gitBranch}`);
|
|
117
|
+
}
|
|
118
|
+
if (session.hibernate?.summary) {
|
|
119
|
+
parts.push(`\nPrevious session context:\n${session.hibernate.summary}`);
|
|
120
|
+
}
|
|
121
|
+
if (session.hibernate?.lastUserMessage) {
|
|
122
|
+
parts.push(`\nLast user request: ${session.hibernate.lastUserMessage}`);
|
|
123
|
+
}
|
|
124
|
+
parts.push(`\nSession has ${session.messages.length} messages and cost $${session.totalCost.toFixed(4)} so far.`);
|
|
125
|
+
parts.push('Continue where you left off. If the user\'s last request was incomplete, acknowledge that and ask how to proceed.');
|
|
126
|
+
return parts.join('\n');
|
|
127
|
+
}
|
|
75
128
|
/** Maximum number of sessions to keep on disk. */
|
|
76
129
|
const MAX_SESSIONS = 100;
|
|
77
130
|
/**
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
export type McpRegistryEntry = {
|
|
8
|
+
name: string;
|
|
9
|
+
package: string;
|
|
10
|
+
description: string;
|
|
11
|
+
category: 'filesystem' | 'git' | 'database' | 'api' | 'search' | 'productivity' | 'dev-tools' | 'ai';
|
|
12
|
+
args?: string[];
|
|
13
|
+
envVars?: string[];
|
|
14
|
+
riskLevel?: 'low' | 'medium' | 'high';
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Curated registry of popular MCP servers.
|
|
18
|
+
* Each entry has enough info to generate the config.yaml block.
|
|
19
|
+
*/
|
|
20
|
+
export declare const MCP_REGISTRY: McpRegistryEntry[];
|
|
21
|
+
/** Search the registry by name or keyword */
|
|
22
|
+
export declare function searchRegistry(query: string): McpRegistryEntry[];
|
|
23
|
+
/** Get all entries in a category */
|
|
24
|
+
export declare function getByCategory(category: McpRegistryEntry['category']): McpRegistryEntry[];
|
|
25
|
+
/** Get all unique categories */
|
|
26
|
+
export declare function getCategories(): string[];
|
|
27
|
+
/** Generate the config.yaml block for a registry entry */
|
|
28
|
+
export declare function generateConfigBlock(entry: McpRegistryEntry): string;
|
|
29
|
+
/** Format registry as a browsable list */
|
|
30
|
+
export declare function formatRegistry(entries?: McpRegistryEntry[]): string;
|
|
31
|
+
//# sourceMappingURL=registry.d.ts.map
|