@xyit/wellspring 0.0.0-stage → 1.1.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/LICENSE +21 -0
- package/README.md +853 -2
- package/dist/agent/pending-asks.d.ts +20 -0
- package/dist/agent/pending-asks.js +70 -0
- package/dist/agent/pending-asks.js.map +1 -0
- package/dist/agent/task-registry.d.ts +14 -0
- package/dist/agent/task-registry.js +80 -0
- package/dist/agent/task-registry.js.map +1 -0
- package/dist/agent/tool-context.d.ts +30 -0
- package/dist/agent/tool-context.js +10 -0
- package/dist/agent/tool-context.js.map +1 -0
- package/dist/agent/usage.d.ts +40 -0
- package/dist/agent/usage.js +122 -0
- package/dist/agent/usage.js.map +1 -0
- package/dist/api/host/agent.d.ts +165 -0
- package/dist/api/host/agent.js +5 -0
- package/dist/api/host/agent.js.map +1 -0
- package/dist/api/host/events.d.ts +2 -0
- package/dist/api/host/events.js +6 -0
- package/dist/api/host/events.js.map +1 -0
- package/dist/api/host/exec.d.ts +36 -0
- package/dist/api/host/exec.js +10 -0
- package/dist/api/host/exec.js.map +1 -0
- package/dist/api/host/fs.d.ts +24 -0
- package/dist/api/host/fs.js +7 -0
- package/dist/api/host/fs.js.map +1 -0
- package/dist/api/host/hooks.d.ts +210 -0
- package/dist/api/host/hooks.js +401 -0
- package/dist/api/host/hooks.js.map +1 -0
- package/dist/api/host/host.d.ts +36 -0
- package/dist/api/host/host.js +53 -0
- package/dist/api/host/host.js.map +1 -0
- package/dist/api/host/http.d.ts +58 -0
- package/dist/api/host/http.js +6 -0
- package/dist/api/host/http.js.map +1 -0
- package/dist/api/host/index.d.ts +15 -0
- package/dist/api/host/index.js +20 -0
- package/dist/api/host/index.js.map +1 -0
- package/dist/api/host/models.d.ts +65 -0
- package/dist/api/host/models.js +8 -0
- package/dist/api/host/models.js.map +1 -0
- package/dist/api/host/network.d.ts +22 -0
- package/dist/api/host/network.js +7 -0
- package/dist/api/host/network.js.map +1 -0
- package/dist/api/host/plugin.d.ts +138 -0
- package/dist/api/host/plugin.js +6 -0
- package/dist/api/host/plugin.js.map +1 -0
- package/dist/api/host/plugins.d.ts +49 -0
- package/dist/api/host/plugins.js +6 -0
- package/dist/api/host/plugins.js.map +1 -0
- package/dist/api/host/pty.d.ts +55 -0
- package/dist/api/host/pty.js +21 -0
- package/dist/api/host/pty.js.map +1 -0
- package/dist/api/host/session.d.ts +5 -0
- package/dist/api/host/session.js +52 -0
- package/dist/api/host/session.js.map +1 -0
- package/dist/api/host/version.d.ts +2 -0
- package/dist/api/host/version.js +3 -0
- package/dist/api/host/version.js.map +1 -0
- package/dist/api/host/workspace.d.ts +38 -0
- package/dist/api/host/workspace.js +9 -0
- package/dist/api/host/workspace.js.map +1 -0
- package/dist/api/plugin/http-client.d.ts +42 -0
- package/dist/api/plugin/http-client.js +364 -0
- package/dist/api/plugin/http-client.js.map +1 -0
- package/dist/api/plugin/http-protocol.d.ts +152 -0
- package/dist/api/plugin/http-protocol.js +49 -0
- package/dist/api/plugin/http-protocol.js.map +1 -0
- package/dist/api/result/result.d.ts +16 -0
- package/dist/api/result/result.js +43 -0
- package/dist/api/result/result.js.map +1 -0
- package/dist/commands/agent-turn.d.ts +63 -0
- package/dist/commands/agent-turn.js +687 -0
- package/dist/commands/agent-turn.js.map +1 -0
- package/dist/commands/ask-prompt.d.ts +6 -0
- package/dist/commands/ask-prompt.js +49 -0
- package/dist/commands/ask-prompt.js.map +1 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +283 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/conversation.d.ts +51 -0
- package/dist/commands/conversation.js +630 -0
- package/dist/commands/conversation.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +77 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/exec-approval.d.ts +3 -0
- package/dist/commands/exec-approval.js +80 -0
- package/dist/commands/exec-approval.js.map +1 -0
- package/dist/commands/help.d.ts +2 -0
- package/dist/commands/help.js +35 -0
- package/dist/commands/help.js.map +1 -0
- package/dist/commands/key.d.ts +2 -0
- package/dist/commands/key.js +226 -0
- package/dist/commands/key.js.map +1 -0
- package/dist/commands/plugin.d.ts +2 -0
- package/dist/commands/plugin.js +190 -0
- package/dist/commands/plugin.js.map +1 -0
- package/dist/commands/session.d.ts +2 -0
- package/dist/commands/session.js +167 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/shared.d.ts +35 -0
- package/dist/commands/shared.js +66 -0
- package/dist/commands/shared.js.map +1 -0
- package/dist/commands/start.d.ts +2 -0
- package/dist/commands/start.js +75 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/stop.d.ts +2 -0
- package/dist/commands/stop.js +24 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/commands/version.d.ts +2 -0
- package/dist/commands/version.js +33 -0
- package/dist/commands/version.js.map +1 -0
- package/dist/config/codes.d.ts +13 -0
- package/dist/config/codes.js +15 -0
- package/dist/config/codes.js.map +1 -0
- package/dist/config/credentials.d.ts +67 -0
- package/dist/config/credentials.js +214 -0
- package/dist/config/credentials.js.map +1 -0
- package/dist/config/defaults.d.ts +5 -0
- package/dist/config/defaults.js +31 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.js +10 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +10 -0
- package/dist/config/loader.js +68 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/providers.d.ts +30 -0
- package/dist/config/providers.js +97 -0
- package/dist/config/providers.js.map +1 -0
- package/dist/config/types.d.ts +75 -0
- package/dist/config/types.js +4 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/validate.d.ts +4 -0
- package/dist/config/validate.js +391 -0
- package/dist/config/validate.js.map +1 -0
- package/dist/display/markdown.d.ts +7 -0
- package/dist/display/markdown.js +116 -0
- package/dist/display/markdown.js.map +1 -0
- package/dist/display/tool-label.d.ts +6 -0
- package/dist/display/tool-label.js +81 -0
- package/dist/display/tool-label.js.map +1 -0
- package/dist/event/event.d.ts +27 -0
- package/dist/event/event.js +152 -0
- package/dist/event/event.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +308 -0
- package/dist/index.js.map +1 -0
- package/dist/input/codes.d.ts +15 -0
- package/dist/input/codes.js +20 -0
- package/dist/input/codes.js.map +1 -0
- package/dist/input/commands.d.ts +10 -0
- package/dist/input/commands.js +65 -0
- package/dist/input/commands.js.map +1 -0
- package/dist/input/help.d.ts +8 -0
- package/dist/input/help.js +51 -0
- package/dist/input/help.js.map +1 -0
- package/dist/input/index.d.ts +6 -0
- package/dist/input/index.js +10 -0
- package/dist/input/index.js.map +1 -0
- package/dist/input/parse-options.d.ts +11 -0
- package/dist/input/parse-options.js +51 -0
- package/dist/input/parse-options.js.map +1 -0
- package/dist/input/parse.d.ts +3 -0
- package/dist/input/parse.js +119 -0
- package/dist/input/parse.js.map +1 -0
- package/dist/input/types.d.ts +17 -0
- package/dist/input/types.js +2 -0
- package/dist/input/types.js.map +1 -0
- package/dist/logger/elog4js.d.ts +65 -0
- package/dist/logger/elog4js.js +305 -0
- package/dist/logger/elog4js.js.map +1 -0
- package/dist/logger/logger.d.ts +37 -0
- package/dist/logger/logger.js +196 -0
- package/dist/logger/logger.js.map +1 -0
- package/dist/network/index.d.ts +2 -0
- package/dist/network/index.js +6 -0
- package/dist/network/index.js.map +1 -0
- package/dist/network/openai.d.ts +117 -0
- package/dist/network/openai.js +443 -0
- package/dist/network/openai.js.map +1 -0
- package/dist/network/proxy.d.ts +9 -0
- package/dist/network/proxy.js +72 -0
- package/dist/network/proxy.js.map +1 -0
- package/dist/network/web.d.ts +34 -0
- package/dist/network/web.js +152 -0
- package/dist/network/web.js.map +1 -0
- package/dist/platform/clipboard.d.ts +15 -0
- package/dist/platform/clipboard.js +82 -0
- package/dist/platform/clipboard.js.map +1 -0
- package/dist/platform/exec.d.ts +28 -0
- package/dist/platform/exec.js +95 -0
- package/dist/platform/exec.js.map +1 -0
- package/dist/platform/file.d.ts +38 -0
- package/dist/platform/file.js +197 -0
- package/dist/platform/file.js.map +1 -0
- package/dist/platform/index.d.ts +7 -0
- package/dist/platform/index.js +12 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/notification.d.ts +14 -0
- package/dist/platform/notification.js +82 -0
- package/dist/platform/notification.js.map +1 -0
- package/dist/platform/open-external.d.ts +10 -0
- package/dist/platform/open-external.js +105 -0
- package/dist/platform/open-external.js.map +1 -0
- package/dist/platform/os.d.ts +20 -0
- package/dist/platform/os.js +86 -0
- package/dist/platform/os.js.map +1 -0
- package/dist/platform/path.d.ts +32 -0
- package/dist/platform/path.js +154 -0
- package/dist/platform/path.js.map +1 -0
- package/dist/plugin/access-guard.d.ts +1 -0
- package/dist/plugin/access-guard.js +40 -0
- package/dist/plugin/access-guard.js.map +1 -0
- package/dist/plugin/agent-service.d.ts +25 -0
- package/dist/plugin/agent-service.js +809 -0
- package/dist/plugin/agent-service.js.map +1 -0
- package/dist/plugin/agent-tools.d.ts +12 -0
- package/dist/plugin/agent-tools.js +31 -0
- package/dist/plugin/agent-tools.js.map +1 -0
- package/dist/plugin/capabilities.d.ts +26 -0
- package/dist/plugin/capabilities.js +192 -0
- package/dist/plugin/capabilities.js.map +1 -0
- package/dist/plugin/console-guard.d.ts +2 -0
- package/dist/plugin/console-guard.js +52 -0
- package/dist/plugin/console-guard.js.map +1 -0
- package/dist/plugin/data-access.d.ts +15 -0
- package/dist/plugin/data-access.js +57 -0
- package/dist/plugin/data-access.js.map +1 -0
- package/dist/plugin/fs.d.ts +3 -0
- package/dist/plugin/fs.js +93 -0
- package/dist/plugin/fs.js.map +1 -0
- package/dist/plugin/host-alias.d.ts +2 -0
- package/dist/plugin/host-alias.js +57 -0
- package/dist/plugin/host-alias.js.map +1 -0
- package/dist/plugin/index.d.ts +7 -0
- package/dist/plugin/index.js +11 -0
- package/dist/plugin/index.js.map +1 -0
- package/dist/plugin/install.d.ts +17 -0
- package/dist/plugin/install.js +163 -0
- package/dist/plugin/install.js.map +1 -0
- package/dist/plugin/loader.d.ts +45 -0
- package/dist/plugin/loader.js +739 -0
- package/dist/plugin/loader.js.map +1 -0
- package/dist/plugin/manage.d.ts +31 -0
- package/dist/plugin/manage.js +271 -0
- package/dist/plugin/manage.js.map +1 -0
- package/dist/plugin/models-service.d.ts +15 -0
- package/dist/plugin/models-service.js +317 -0
- package/dist/plugin/models-service.js.map +1 -0
- package/dist/plugin/network-service.d.ts +10 -0
- package/dist/plugin/network-service.js +87 -0
- package/dist/plugin/network-service.js.map +1 -0
- package/dist/plugin/package-manager.d.ts +46 -0
- package/dist/plugin/package-manager.js +148 -0
- package/dist/plugin/package-manager.js.map +1 -0
- package/dist/plugin/paths.d.ts +6 -0
- package/dist/plugin/paths.js +15 -0
- package/dist/plugin/paths.js.map +1 -0
- package/dist/plugin/registry.d.ts +17 -0
- package/dist/plugin/registry.js +82 -0
- package/dist/plugin/registry.js.map +1 -0
- package/dist/plugin/runtime.d.ts +9 -0
- package/dist/plugin/runtime.js +43 -0
- package/dist/plugin/runtime.js.map +1 -0
- package/dist/plugin/scaffold.d.ts +13 -0
- package/dist/plugin/scaffold.js +132 -0
- package/dist/plugin/scaffold.js.map +1 -0
- package/dist/plugin/state.d.ts +6 -0
- package/dist/plugin/state.js +38 -0
- package/dist/plugin/state.js.map +1 -0
- package/dist/plugin/zip.d.ts +7 -0
- package/dist/plugin/zip.js +138 -0
- package/dist/plugin/zip.js.map +1 -0
- package/dist/sandbox/audit.d.ts +12 -0
- package/dist/sandbox/audit.js +20 -0
- package/dist/sandbox/audit.js.map +1 -0
- package/dist/sandbox/backends/bwrap.d.ts +28 -0
- package/dist/sandbox/backends/bwrap.js +197 -0
- package/dist/sandbox/backends/bwrap.js.map +1 -0
- package/dist/sandbox/backends/direct.d.ts +7 -0
- package/dist/sandbox/backends/direct.js +32 -0
- package/dist/sandbox/backends/direct.js.map +1 -0
- package/dist/sandbox/bridge-state.d.ts +13 -0
- package/dist/sandbox/bridge-state.js +12 -0
- package/dist/sandbox/bridge-state.js.map +1 -0
- package/dist/sandbox/index.d.ts +5 -0
- package/dist/sandbox/index.js +6 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/sandbox/manager.d.ts +8 -0
- package/dist/sandbox/manager.js +325 -0
- package/dist/sandbox/manager.js.map +1 -0
- package/dist/sandbox/memory-limit.d.ts +44 -0
- package/dist/sandbox/memory-limit.js +193 -0
- package/dist/sandbox/memory-limit.js.map +1 -0
- package/dist/sandbox/plugin-client.d.ts +80 -0
- package/dist/sandbox/plugin-client.js +1601 -0
- package/dist/sandbox/plugin-client.js.map +1 -0
- package/dist/sandbox/plugin-host.d.ts +1 -0
- package/dist/sandbox/plugin-host.js +1001 -0
- package/dist/sandbox/plugin-host.js.map +1 -0
- package/dist/sandbox/protocol.d.ts +43 -0
- package/dist/sandbox/protocol.js +96 -0
- package/dist/sandbox/protocol.js.map +1 -0
- package/dist/sandbox/rpc-timeouts.d.ts +28 -0
- package/dist/sandbox/rpc-timeouts.js +15 -0
- package/dist/sandbox/rpc-timeouts.js.map +1 -0
- package/dist/sandbox/supervisor.d.ts +31 -0
- package/dist/sandbox/supervisor.js +114 -0
- package/dist/sandbox/supervisor.js.map +1 -0
- package/dist/sandbox/types.d.ts +124 -0
- package/dist/sandbox/types.js +17 -0
- package/dist/sandbox/types.js.map +1 -0
- package/dist/service/control.d.ts +32 -0
- package/dist/service/control.js +117 -0
- package/dist/service/control.js.map +1 -0
- package/dist/session/compress.d.ts +3 -0
- package/dist/session/compress.js +42 -0
- package/dist/session/compress.js.map +1 -0
- package/dist/session/index.d.ts +4 -0
- package/dist/session/index.js +8 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/registry.d.ts +4 -0
- package/dist/session/registry.js +12 -0
- package/dist/session/registry.js.map +1 -0
- package/dist/session/replay.d.ts +10 -0
- package/dist/session/replay.js +109 -0
- package/dist/session/replay.js.map +1 -0
- package/dist/session/session.d.ts +40 -0
- package/dist/session/session.js +108 -0
- package/dist/session/session.js.map +1 -0
- package/dist/session/store.d.ts +58 -0
- package/dist/session/store.js +382 -0
- package/dist/session/store.js.map +1 -0
- package/dist/session/types.d.ts +56 -0
- package/dist/session/types.js +3 -0
- package/dist/session/types.js.map +1 -0
- package/dist/workspace/index.d.ts +7 -0
- package/dist/workspace/index.js +17 -0
- package/dist/workspace/index.js.map +1 -0
- package/dist/workspace/registry.d.ts +25 -0
- package/dist/workspace/registry.js +293 -0
- package/dist/workspace/registry.js.map +1 -0
- package/package.json +73 -5
- package/scripts/build-node-pty.mjs +55 -0
- package/scripts/rewrite-dts.mjs +36 -0
- package/scripts/run-tests.mjs +41 -0
- package/scripts/verify-sandbox.ts +98 -0
- package/src/agent/pending-asks.ts +88 -0
- package/src/agent/task-registry.ts +108 -0
- package/src/agent/tool-context.ts +47 -0
- package/src/agent/usage.ts +170 -0
- package/src/api/host/agent.ts +162 -0
- package/src/api/host/events.ts +7 -0
- package/src/api/host/exec.ts +47 -0
- package/src/api/host/fs.ts +33 -0
- package/src/api/host/hooks.ts +635 -0
- package/src/api/host/host.ts +99 -0
- package/src/api/host/http.ts +79 -0
- package/src/api/host/index.ts +20 -0
- package/src/api/host/models.ts +81 -0
- package/src/api/host/network.ts +32 -0
- package/src/api/host/plugin.ts +158 -0
- package/src/api/host/plugins.ts +59 -0
- package/src/api/host/pty.ts +73 -0
- package/src/api/host/session.ts +61 -0
- package/src/api/host/version.ts +2 -0
- package/src/api/host/workspace.ts +51 -0
- package/src/api/plugin/http-client.ts +492 -0
- package/src/api/plugin/http-protocol.ts +231 -0
- package/src/api/result/result.ts +52 -0
- package/src/commands/agent-turn.ts +817 -0
- package/src/commands/ask-prompt.ts +52 -0
- package/src/commands/config.ts +306 -0
- package/src/commands/conversation.ts +777 -0
- package/src/commands/doctor.ts +92 -0
- package/src/commands/exec-approval.ts +91 -0
- package/src/commands/help.ts +41 -0
- package/src/commands/key.ts +281 -0
- package/src/commands/plugin.ts +222 -0
- package/src/commands/session.ts +179 -0
- package/src/commands/shared.ts +103 -0
- package/src/commands/start.ts +88 -0
- package/src/commands/stop.ts +24 -0
- package/src/commands/version.ts +40 -0
- package/src/config/codes.ts +17 -0
- package/src/config/credentials.ts +302 -0
- package/src/config/defaults.ts +32 -0
- package/src/config/index.ts +10 -0
- package/src/config/loader.ts +80 -0
- package/src/config/providers.ts +133 -0
- package/src/config/types.ts +88 -0
- package/src/config/validate.ts +458 -0
- package/src/display/markdown.ts +137 -0
- package/src/display/tool-label.ts +87 -0
- package/src/event/event.ts +171 -0
- package/src/index.ts +344 -0
- package/src/input/codes.ts +21 -0
- package/src/input/commands.ts +76 -0
- package/src/input/help.ts +60 -0
- package/src/input/index.ts +10 -0
- package/src/input/parse-options.ts +66 -0
- package/src/input/parse.ts +138 -0
- package/src/input/types.ts +19 -0
- package/src/logger/elog4js.ts +366 -0
- package/src/logger/logger.ts +251 -0
- package/src/network/index.ts +6 -0
- package/src/network/openai.ts +571 -0
- package/src/network/proxy.ts +80 -0
- package/src/network/web.ts +206 -0
- package/src/platform/clipboard.ts +107 -0
- package/src/platform/exec.ts +128 -0
- package/src/platform/file.ts +235 -0
- package/src/platform/index.ts +12 -0
- package/src/platform/notification.ts +108 -0
- package/src/platform/open-external.ts +132 -0
- package/src/platform/os.ts +101 -0
- package/src/platform/path.ts +214 -0
- package/src/plugin/access-guard.ts +46 -0
- package/src/plugin/agent-service.ts +969 -0
- package/src/plugin/agent-tools.ts +43 -0
- package/src/plugin/capabilities.ts +240 -0
- package/src/plugin/console-guard.ts +66 -0
- package/src/plugin/data-access.ts +70 -0
- package/src/plugin/fs.ts +109 -0
- package/src/plugin/host-alias.ts +61 -0
- package/src/plugin/index.ts +11 -0
- package/src/plugin/install.ts +213 -0
- package/src/plugin/loader.ts +952 -0
- package/src/plugin/manage.ts +338 -0
- package/src/plugin/models-service.ts +383 -0
- package/src/plugin/network-service.ts +102 -0
- package/src/plugin/package-manager.ts +214 -0
- package/src/plugin/paths.ts +19 -0
- package/src/plugin/registry.ts +103 -0
- package/src/plugin/runtime.ts +57 -0
- package/src/plugin/scaffold.ts +158 -0
- package/src/plugin/state.ts +52 -0
- package/src/plugin/zip.ts +156 -0
- package/src/sandbox/audit.ts +38 -0
- package/src/sandbox/backends/bwrap.ts +251 -0
- package/src/sandbox/backends/direct.ts +43 -0
- package/src/sandbox/bridge-state.ts +29 -0
- package/src/sandbox/index.ts +5 -0
- package/src/sandbox/manager.ts +406 -0
- package/src/sandbox/memory-limit.ts +245 -0
- package/src/sandbox/plugin-client.ts +1881 -0
- package/src/sandbox/plugin-host.ts +1282 -0
- package/src/sandbox/protocol.ts +142 -0
- package/src/sandbox/pty-bridge.py +154 -0
- package/src/sandbox/rpc-timeouts.ts +43 -0
- package/src/sandbox/supervisor.ts +172 -0
- package/src/sandbox/types.ts +149 -0
- package/src/service/control.ts +155 -0
- package/src/session/compress.ts +47 -0
- package/src/session/index.ts +8 -0
- package/src/session/registry.ts +17 -0
- package/src/session/replay.ts +132 -0
- package/src/session/session.ts +134 -0
- package/src/session/store.ts +468 -0
- package/src/session/types.ts +61 -0
- package/src/workspace/index.ts +21 -0
- package/src/workspace/registry.ts +356 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* EventEntity / EventBus
|
|
3
|
+
*
|
|
4
|
+
* EventEntity 的负载只读,取消状态可变:监听器对事件实例调 cancel 后
|
|
5
|
+
* isCancelled 立即为 true,EventBus 据此终止后续传播
|
|
6
|
+
* 取消不回滚已完成的投递
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export class EventEntity<T> {
|
|
10
|
+
private readonly data: T
|
|
11
|
+
private cancelled: boolean
|
|
12
|
+
private cancelReason: string
|
|
13
|
+
|
|
14
|
+
private constructor(data: T, cancelled = false, cancelReason = "") {
|
|
15
|
+
this.data = data
|
|
16
|
+
this.cancelled = cancelled
|
|
17
|
+
this.cancelReason = cancelReason
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public static create<T>(data: T, cancelled = false, cancelReason = ""): EventEntity<T> {
|
|
21
|
+
return new EventEntity(data, cancelled, cancelReason)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public cancel(reason = ""): this {
|
|
25
|
+
this.cancelled = true
|
|
26
|
+
this.cancelReason = reason
|
|
27
|
+
return this
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public getData(): T {
|
|
31
|
+
return this.data
|
|
32
|
+
}
|
|
33
|
+
public isCancelled(): boolean {
|
|
34
|
+
return this.cancelled
|
|
35
|
+
}
|
|
36
|
+
public getCancelReason(): string {
|
|
37
|
+
return this.cancelReason
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
import { getHostBridge } from "../sandbox/bridge-state.ts"
|
|
42
|
+
|
|
43
|
+
export type EventListener<T = unknown> = (event: EventEntity<T>) => void
|
|
44
|
+
|
|
45
|
+
// 存储层擦除负载类型:同一总线容纳各事件名的监听器
|
|
46
|
+
type ListenerRecord = {
|
|
47
|
+
readonly fn: EventListener<any>
|
|
48
|
+
active: boolean
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export class EventBus {
|
|
52
|
+
private readonly listeners = new Map<string, ListenerRecord[]>()
|
|
53
|
+
private readonly bridgeSubscriptions = new Set<string>()
|
|
54
|
+
|
|
55
|
+
subscribe<T>(eventName: string, listener: EventListener<T>): () => void {
|
|
56
|
+
if (typeof listener !== "function") {
|
|
57
|
+
throw new TypeError(`监听器不是函数:${eventName}`)
|
|
58
|
+
}
|
|
59
|
+
const record: ListenerRecord = { fn: listener, active: true }
|
|
60
|
+
const bridge = getHostBridge()
|
|
61
|
+
if (bridge !== null && !this.bridgeSubscriptions.has(eventName)) {
|
|
62
|
+
this.bridgeSubscriptions.add(eventName)
|
|
63
|
+
void bridge.request("host.event.subscribe", { name: eventName }).catch(() => undefined)
|
|
64
|
+
}
|
|
65
|
+
const handlers = this.listeners.get(eventName)
|
|
66
|
+
if (handlers) {
|
|
67
|
+
handlers.push(record)
|
|
68
|
+
} else {
|
|
69
|
+
this.listeners.set(eventName, [record])
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return () => this.remove(eventName, record)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
publish<T>(eventName: string, event: EventEntity<T>): void {
|
|
76
|
+
const bridge = getHostBridge()
|
|
77
|
+
if (bridge !== null) {
|
|
78
|
+
bridge.notify("host.event.publish", { name: eventName, data: event.getData() })
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
this.deliverLocal(eventName, event)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** sandbox bridge 收到宿主事件后在本进程投递 */
|
|
85
|
+
receive<T>(eventName: string, data: T): void {
|
|
86
|
+
this.deliverLocal(eventName, EventEntity.create(data))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private deliverLocal<T>(eventName: string, event: EventEntity<T>): void {
|
|
90
|
+
const handlers = this.listeners.get(eventName)
|
|
91
|
+
if (!handlers || handlers.length === 0) {
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let firstError: unknown
|
|
96
|
+
let failed = false
|
|
97
|
+
// 快照后校验存活状态:本轮回调内的退订对后续监听器生效
|
|
98
|
+
for (const record of handlers.slice()) {
|
|
99
|
+
if (!record.active) continue
|
|
100
|
+
if (event.isCancelled()) break
|
|
101
|
+
try {
|
|
102
|
+
record.fn(event)
|
|
103
|
+
} catch (error) {
|
|
104
|
+
// 单监听器异常不中断其余监听器,循环结束后抛出首个异常
|
|
105
|
+
if (!failed) {
|
|
106
|
+
firstError = error
|
|
107
|
+
failed = true
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (failed) {
|
|
112
|
+
throw firstError
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
once<T>(eventName: string, listener: EventListener<T>): () => void {
|
|
117
|
+
const unsubscribe = this.subscribe<T>(eventName, (event) => {
|
|
118
|
+
// 先退订再回调:回调内重入发布不会二次触发,回调抛错也不残留订阅
|
|
119
|
+
unsubscribe()
|
|
120
|
+
listener(event)
|
|
121
|
+
})
|
|
122
|
+
return unsubscribe
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
clear(eventName: string): void {
|
|
126
|
+
this.unsubscribeBridge(eventName)
|
|
127
|
+
const handlers = this.listeners.get(eventName)
|
|
128
|
+
if (!handlers) return
|
|
129
|
+
for (const record of handlers) {
|
|
130
|
+
record.active = false
|
|
131
|
+
}
|
|
132
|
+
this.listeners.delete(eventName)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
clearAll(): void {
|
|
136
|
+
for (const eventName of [...this.bridgeSubscriptions]) {
|
|
137
|
+
this.unsubscribeBridge(eventName)
|
|
138
|
+
}
|
|
139
|
+
for (const handlers of this.listeners.values()) {
|
|
140
|
+
for (const record of handlers) {
|
|
141
|
+
record.active = false
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
this.listeners.clear()
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
private remove(eventName: string, record: ListenerRecord): void {
|
|
148
|
+
if (!record.active) return
|
|
149
|
+
record.active = false
|
|
150
|
+
const handlers = this.listeners.get(eventName)
|
|
151
|
+
if (!handlers) return
|
|
152
|
+
const index = handlers.indexOf(record)
|
|
153
|
+
if (index !== -1) {
|
|
154
|
+
handlers.splice(index, 1)
|
|
155
|
+
}
|
|
156
|
+
if (handlers.length === 0) {
|
|
157
|
+
this.listeners.delete(eventName)
|
|
158
|
+
this.unsubscribeBridge(eventName)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private unsubscribeBridge(eventName: string): void {
|
|
163
|
+
if (!this.bridgeSubscriptions.delete(eventName)) {
|
|
164
|
+
return
|
|
165
|
+
}
|
|
166
|
+
const bridge = getHostBridge()
|
|
167
|
+
bridge?.notify("host.event.unsubscribe", { name: eventName })
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export const eventBus = new EventBus()
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/*
|
|
3
|
+
* Wellspring CLI 入口。
|
|
4
|
+
* 解析全局参数 → 应用目录/日志覆盖 → 加载配置与插件 → 分发命令。
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { resolve } from "node:path"
|
|
8
|
+
|
|
9
|
+
import type { HostOutput, PluginCommandContext } from "./api/host/plugin.ts"
|
|
10
|
+
import { configureHost, setHostStatus } from "./api/host/host.ts"
|
|
11
|
+
import { setHookErrorHandler, setHookGuard, withHookOwner } from "./api/host/hooks.ts"
|
|
12
|
+
import { runConfigCommand } from "./commands/config.ts"
|
|
13
|
+
import { runConversationCommand } from "./commands/conversation.ts"
|
|
14
|
+
import { runDoctorCommand } from "./commands/doctor.ts"
|
|
15
|
+
import { runHelpCommand } from "./commands/help.ts"
|
|
16
|
+
import { runKeyCommand } from "./commands/key.ts"
|
|
17
|
+
import { runPluginCommand } from "./commands/plugin.ts"
|
|
18
|
+
import {
|
|
19
|
+
errorMessage,
|
|
20
|
+
exitCodeFor,
|
|
21
|
+
failure,
|
|
22
|
+
type CommandContext,
|
|
23
|
+
type CommandOutcome,
|
|
24
|
+
} from "./commands/shared.ts"
|
|
25
|
+
import { runSessionCommand } from "./commands/session.ts"
|
|
26
|
+
import { runStartCommand } from "./commands/start.ts"
|
|
27
|
+
import { runStopCommand } from "./commands/stop.ts"
|
|
28
|
+
import { runVersionCommand } from "./commands/version.ts"
|
|
29
|
+
import { credentialsFile } from "./config/credentials.ts"
|
|
30
|
+
import {
|
|
31
|
+
activeModelProvider,
|
|
32
|
+
effectiveModel,
|
|
33
|
+
effectiveReasoning,
|
|
34
|
+
providerApiKey,
|
|
35
|
+
providerOpenAISettings,
|
|
36
|
+
} from "./config/providers.ts"
|
|
37
|
+
import { DEFAULT_SETTINGS } from "./config/defaults.ts"
|
|
38
|
+
import { loadSettings, SETTING_FILE_NAME } from "./config/loader.ts"
|
|
39
|
+
import type { AppSetting } from "./config/types.ts"
|
|
40
|
+
import { BUILTIN_NAMES, findBuiltin } from "./input/commands.ts"
|
|
41
|
+
import { parseGlobal } from "./input/parse.ts"
|
|
42
|
+
import type { GlobalOptions } from "./input/types.ts"
|
|
43
|
+
import { getElog, initElog } from "./logger/elog4js.ts"
|
|
44
|
+
import { closeLogger, initLogger } from "./logger/logger.ts"
|
|
45
|
+
import { initOpenAIClient, type OpenAIClient } from "./network/openai.ts"
|
|
46
|
+
import { createProxyFetch } from "./network/proxy.ts"
|
|
47
|
+
import { getPaths } from "./platform/path.ts"
|
|
48
|
+
import { withConsoleGuard } from "./plugin/console-guard.ts"
|
|
49
|
+
import { loadPlugins, type LoadedPlugin } from "./plugin/loader.ts"
|
|
50
|
+
import { createPluginFileApi } from "./plugin/fs.ts"
|
|
51
|
+
import { ensurePluginDataDir, loadPluginConfig } from "./plugin/runtime.ts"
|
|
52
|
+
import { shutdownAllSandboxPlugins } from "./sandbox/plugin-client.ts"
|
|
53
|
+
import { AgentToolRegistry } from "./plugin/agent-tools.ts"
|
|
54
|
+
import { PluginRegistry } from "./plugin/registry.ts"
|
|
55
|
+
|
|
56
|
+
function printParseError(code: string): void {
|
|
57
|
+
const elog = getElog()
|
|
58
|
+
elog.error(errorMessage(code))
|
|
59
|
+
elog.notice("运行 wellspring --help 查看用法")
|
|
60
|
+
process.exitCode = 2
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function emitOutcome(outcome: CommandOutcome, json: boolean): void {
|
|
64
|
+
const code = outcome.result.getCode()
|
|
65
|
+
if (json) {
|
|
66
|
+
const payload = {
|
|
67
|
+
success: outcome.result.isSuccess(),
|
|
68
|
+
code: outcome.result.isSuccess() ? null : code,
|
|
69
|
+
data: outcome.result.isSuccess() ? outcome.result.getData() : null,
|
|
70
|
+
}
|
|
71
|
+
process.stdout.write(`${JSON.stringify(payload)}\n`)
|
|
72
|
+
} else if (!outcome.result.isSuccess() && code !== null) {
|
|
73
|
+
getElog().error(errorMessage(code))
|
|
74
|
+
}
|
|
75
|
+
process.exitCode = outcome.result.isSuccess() ? 0 : exitCodeFor(code)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function stripJsonFlag(argv: readonly string[]): { argv: string[]; json: boolean } {
|
|
79
|
+
const next = [...argv]
|
|
80
|
+
const marker = next.indexOf("--")
|
|
81
|
+
const limit = marker === -1 ? next.length : marker
|
|
82
|
+
for (let index = 0; index < limit; index += 1) {
|
|
83
|
+
if (next[index] === "--json") {
|
|
84
|
+
next.splice(index, 1)
|
|
85
|
+
return { argv: next, json: true }
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return { argv: next, json: false }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function createPluginOutput(pluginName: string): HostOutput {
|
|
92
|
+
const elog = getElog()
|
|
93
|
+
return {
|
|
94
|
+
info: (text) => elog.plugin("info", pluginName, text),
|
|
95
|
+
warn: (text) => elog.plugin("warn", pluginName, text),
|
|
96
|
+
error: (text) => elog.plugin("error", pluginName, text),
|
|
97
|
+
print: (text = "") => elog.plugin("info", pluginName, text),
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function main(argv: readonly string[]): Promise<void> {
|
|
102
|
+
const parsed = parseGlobal(argv)
|
|
103
|
+
if (!parsed.isSuccess()) {
|
|
104
|
+
printParseError(parsed.getCode() ?? "usage.invalid-value")
|
|
105
|
+
return
|
|
106
|
+
}
|
|
107
|
+
const parsedGlobal = parsed.getData()
|
|
108
|
+
if (parsedGlobal === null) {
|
|
109
|
+
printParseError("usage.invalid-value")
|
|
110
|
+
return
|
|
111
|
+
}
|
|
112
|
+
const { options: globalOptions } = parsedGlobal
|
|
113
|
+
let command = parsedGlobal.command
|
|
114
|
+
let commandArgv = [...parsedGlobal.commandArgv]
|
|
115
|
+
|
|
116
|
+
if (globalOptions.version) {
|
|
117
|
+
command = "version"
|
|
118
|
+
commandArgv = []
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const builtin = command === null ? undefined : findBuiltin(command)
|
|
122
|
+
const builtinName = builtin?.name ?? null
|
|
123
|
+
let jsonMode = globalOptions.json
|
|
124
|
+
if (builtinName !== null) {
|
|
125
|
+
const stripped = stripJsonFlag(commandArgv)
|
|
126
|
+
commandArgv = stripped.argv
|
|
127
|
+
jsonMode = jsonMode || stripped.json
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const options: GlobalOptions = { ...globalOptions, json: jsonMode }
|
|
131
|
+
|
|
132
|
+
if (globalOptions.home !== undefined) {
|
|
133
|
+
process.env["WELLSPRING_HOME"] = globalOptions.home
|
|
134
|
+
}
|
|
135
|
+
const paths = getPaths()
|
|
136
|
+
configureHost({ paths })
|
|
137
|
+
setHostStatus("starting")
|
|
138
|
+
const settingsFile = resolve(globalOptions.config ?? `${paths.configDir}/${SETTING_FILE_NAME}`)
|
|
139
|
+
|
|
140
|
+
const loaded = await loadSettings(settingsFile)
|
|
141
|
+
const settings: AppSetting = loaded.getData() ?? DEFAULT_SETTINGS
|
|
142
|
+
const configCode = loaded.isSuccess() ? null : loaded.getCode()
|
|
143
|
+
|
|
144
|
+
initElog({ json: jsonMode })
|
|
145
|
+
const elog = getElog()
|
|
146
|
+
|
|
147
|
+
const logger = await initLogger({
|
|
148
|
+
settings,
|
|
149
|
+
level: globalOptions.logLevel ?? (globalOptions.quiet ? "silent" : undefined),
|
|
150
|
+
json: jsonMode,
|
|
151
|
+
stdout: false,
|
|
152
|
+
})
|
|
153
|
+
if (configCode !== null) {
|
|
154
|
+
logger.warn({ code: configCode }, "配置加载失败,使用默认配置")
|
|
155
|
+
elog.warn(`配置加载失败,使用默认配置:${errorMessage(configCode)}`)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
setHookGuard(async (owner, task) => {
|
|
159
|
+
await withHookOwner(owner, async () => {
|
|
160
|
+
await withConsoleGuard(owner, logger.child({ plugin: owner }), task)
|
|
161
|
+
})
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
setHookErrorHandler(({ hook, owner, error }) => {
|
|
165
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
166
|
+
logger.warn({ hook, owner, message }, "插件钩子执行失败")
|
|
167
|
+
elog.warn(`插件钩子执行失败:${hook}(${owner ?? "-"}):${message}`)
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
let openai: OpenAIClient | null = null
|
|
171
|
+
let proxyFetch: ReturnType<typeof createProxyFetch>
|
|
172
|
+
try {
|
|
173
|
+
proxyFetch = createProxyFetch(settings.network.proxy)
|
|
174
|
+
} catch (error) {
|
|
175
|
+
const reason = error instanceof Error ? error.message : String(error)
|
|
176
|
+
logger.warn({ reason }, "代理初始化失败")
|
|
177
|
+
elog.warn(`代理初始化失败:${reason}`)
|
|
178
|
+
proxyFetch = undefined
|
|
179
|
+
}
|
|
180
|
+
// 当前供应商/模型:启动时解析一次,CLI 单轮命令直接用
|
|
181
|
+
const provider = activeModelProvider(settings)
|
|
182
|
+
const activeModel = effectiveModel(settings, provider)
|
|
183
|
+
const activeReasoning = effectiveReasoning(settings, provider)
|
|
184
|
+
const providerApiKeyValue = providerApiKey(provider, paths.configDir)
|
|
185
|
+
const openaiResult = initOpenAIClient({
|
|
186
|
+
settings: providerOpenAISettings(settings, provider),
|
|
187
|
+
apiKey: providerApiKeyValue ?? "",
|
|
188
|
+
credentialsFile: credentialsFile(paths.configDir),
|
|
189
|
+
logger: logger.child({ module: "openai" }),
|
|
190
|
+
fetch: proxyFetch,
|
|
191
|
+
})
|
|
192
|
+
if (openaiResult.isSuccess()) {
|
|
193
|
+
openai = openaiResult.getData()
|
|
194
|
+
} else {
|
|
195
|
+
logger.warn({ code: openaiResult.getCode() }, "OpenAI 客户端不可用")
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const registry = new PluginRegistry()
|
|
199
|
+
const agentTools = new AgentToolRegistry()
|
|
200
|
+
let pluginsCache: readonly LoadedPlugin[] | null = null
|
|
201
|
+
const ensurePlugins = async (): Promise<readonly LoadedPlugin[]> => {
|
|
202
|
+
if (pluginsCache !== null) {
|
|
203
|
+
return pluginsCache
|
|
204
|
+
}
|
|
205
|
+
pluginsCache = await loadPlugins({
|
|
206
|
+
paths,
|
|
207
|
+
config: settings,
|
|
208
|
+
logger,
|
|
209
|
+
registry,
|
|
210
|
+
agentTools,
|
|
211
|
+
sandbox: settings.sandbox,
|
|
212
|
+
})
|
|
213
|
+
setHostStatus("running")
|
|
214
|
+
for (const plugin of pluginsCache) {
|
|
215
|
+
if (plugin.status === "failed") {
|
|
216
|
+
logger.warn({ plugin: plugin.name, error: plugin.error }, "插件加载失败")
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return pluginsCache
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const commandHelpRequested =
|
|
223
|
+
builtinName !== null && commandArgv.some((token) => token === "--help" || token === "-h")
|
|
224
|
+
const requested = commandHelpRequested ? builtinName : command
|
|
225
|
+
let commandName: string
|
|
226
|
+
if ((globalOptions.help || commandHelpRequested) && requested !== null) {
|
|
227
|
+
commandName = "help"
|
|
228
|
+
commandArgv = [requested]
|
|
229
|
+
} else {
|
|
230
|
+
commandName = requested ?? "help"
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const ctx: CommandContext = {
|
|
234
|
+
global: options,
|
|
235
|
+
settings,
|
|
236
|
+
settingsFile,
|
|
237
|
+
configCode,
|
|
238
|
+
paths,
|
|
239
|
+
logger,
|
|
240
|
+
elog,
|
|
241
|
+
registry,
|
|
242
|
+
agentTools,
|
|
243
|
+
openai,
|
|
244
|
+
activeProvider: provider.id,
|
|
245
|
+
activeModel,
|
|
246
|
+
activeReasoning,
|
|
247
|
+
loadPlugins: ensurePlugins,
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
try {
|
|
251
|
+
// 钩子与插件命令都可能在任意命令里用到;version / key / plugin 不启动插件
|
|
252
|
+
// plugin 子命令只改文件,插件是否加载由下次运行决定
|
|
253
|
+
if (commandName !== "version" && commandName !== "key" && commandName !== "plugin") {
|
|
254
|
+
await ensurePlugins()
|
|
255
|
+
}
|
|
256
|
+
setHostStatus("running")
|
|
257
|
+
|
|
258
|
+
let outcome: CommandOutcome
|
|
259
|
+
switch (commandName) {
|
|
260
|
+
case "chat":
|
|
261
|
+
outcome = await runConversationCommand(ctx, commandArgv, "chat")
|
|
262
|
+
break
|
|
263
|
+
case "run":
|
|
264
|
+
outcome = await runConversationCommand(ctx, commandArgv, "run")
|
|
265
|
+
break
|
|
266
|
+
case "start":
|
|
267
|
+
outcome = await runStartCommand(ctx)
|
|
268
|
+
break
|
|
269
|
+
case "stop":
|
|
270
|
+
outcome = await runStopCommand(ctx)
|
|
271
|
+
break
|
|
272
|
+
case "session":
|
|
273
|
+
outcome = await runSessionCommand(ctx, commandArgv)
|
|
274
|
+
break
|
|
275
|
+
case "config":
|
|
276
|
+
outcome = await runConfigCommand(ctx, commandArgv)
|
|
277
|
+
break
|
|
278
|
+
case "plugin":
|
|
279
|
+
outcome = await runPluginCommand(ctx, commandArgv)
|
|
280
|
+
break
|
|
281
|
+
case "doctor":
|
|
282
|
+
outcome = await runDoctorCommand(ctx)
|
|
283
|
+
break
|
|
284
|
+
case "key":
|
|
285
|
+
outcome = await runKeyCommand(ctx, commandArgv)
|
|
286
|
+
break
|
|
287
|
+
case "version":
|
|
288
|
+
outcome = await runVersionCommand(ctx)
|
|
289
|
+
break
|
|
290
|
+
case "help":
|
|
291
|
+
outcome = await runHelpCommand(ctx, commandArgv)
|
|
292
|
+
break
|
|
293
|
+
default: {
|
|
294
|
+
const record = registry.resolve(commandName)
|
|
295
|
+
if (record === undefined) {
|
|
296
|
+
outcome = failure(`usage.unknown-command:${commandName}`)
|
|
297
|
+
break
|
|
298
|
+
}
|
|
299
|
+
const pluginLogger = logger.child({ plugin: record.pluginName })
|
|
300
|
+
try {
|
|
301
|
+
const pluginDataDir = await ensurePluginDataDir(record.pluginName, paths)
|
|
302
|
+
const pluginConfig = await loadPluginConfig(record.pluginName, paths)
|
|
303
|
+
const pluginFs = createPluginFileApi(pluginDataDir)
|
|
304
|
+
const workspaceFs = createPluginFileApi(process.cwd())
|
|
305
|
+
const pluginContext: PluginCommandContext = {
|
|
306
|
+
argv: commandArgv,
|
|
307
|
+
env: process.env,
|
|
308
|
+
paths,
|
|
309
|
+
config: settings,
|
|
310
|
+
logger: pluginLogger,
|
|
311
|
+
output: createPluginOutput(record.pluginName),
|
|
312
|
+
pluginDataDir,
|
|
313
|
+
pluginConfig,
|
|
314
|
+
fs: pluginFs,
|
|
315
|
+
workspaceFs,
|
|
316
|
+
cwd: process.cwd(),
|
|
317
|
+
json: jsonMode,
|
|
318
|
+
stdin: process.stdin,
|
|
319
|
+
stdout: process.stdout,
|
|
320
|
+
stderr: process.stderr,
|
|
321
|
+
}
|
|
322
|
+
const code = await withHookOwner(record.pluginName, async () =>
|
|
323
|
+
withConsoleGuard(record.pluginName, pluginLogger, async () =>
|
|
324
|
+
record.command.run(pluginContext),
|
|
325
|
+
),
|
|
326
|
+
)
|
|
327
|
+
process.exitCode = typeof code === "number" ? code : 0
|
|
328
|
+
return
|
|
329
|
+
} catch (error) {
|
|
330
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
331
|
+
logger.error({ plugin: record.pluginName, message }, "插件命令执行失败")
|
|
332
|
+
outcome = failure(`plugin.command-failed:${message}`)
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
emitOutcome(outcome, jsonMode)
|
|
337
|
+
} finally {
|
|
338
|
+
setHostStatus("stopped")
|
|
339
|
+
await shutdownAllSandboxPlugins()
|
|
340
|
+
await closeLogger()
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
await main(process.argv.slice(2))
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** 入参错误码,退出码统一为 2 */
|
|
2
|
+
export const USAGE_CODES = {
|
|
3
|
+
unknownCommand: "usage.unknown-command",
|
|
4
|
+
unknownOption: "usage.unknown-option",
|
|
5
|
+
unknownSubcommand: "usage.unknown-subcommand",
|
|
6
|
+
missingValue: "usage.missing-value",
|
|
7
|
+
invalidValue: "usage.invalid-value",
|
|
8
|
+
missingContext: "usage.missing-context",
|
|
9
|
+
invalidSessionId: "usage.invalid-session-id",
|
|
10
|
+
unknownConfigKey: "usage.unknown-config-key",
|
|
11
|
+
conflictingOptions: "usage.conflicting-options",
|
|
12
|
+
missingConfirmation: "usage.missing-confirmation",
|
|
13
|
+
} as const
|
|
14
|
+
|
|
15
|
+
export function usageCode(code: string, detail?: string): string {
|
|
16
|
+
return detail === undefined || detail === "" ? code : `${code}:${detail}`
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function isUsageCode(code: string | null): boolean {
|
|
20
|
+
return code !== null && code.startsWith("usage.")
|
|
21
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/** 内置命令元数据,帮助文本与命令校验共用这一份 */
|
|
2
|
+
|
|
3
|
+
export interface BuiltinCommandSpec {
|
|
4
|
+
readonly name: string
|
|
5
|
+
readonly summary: string
|
|
6
|
+
readonly usage: string
|
|
7
|
+
readonly aliases?: readonly string[]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const BUILTIN_COMMANDS: readonly BuiltinCommandSpec[] = [
|
|
11
|
+
{
|
|
12
|
+
name: "chat",
|
|
13
|
+
summary: "对话模式,单轮对话或进入交互式会话",
|
|
14
|
+
usage: "wellspring chat [--session-id <id>] [--new] [--model <name>] [--reasoning off|low|high|max] [--system <text>] <context...>",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: "run",
|
|
18
|
+
summary: "Agent 模式,单轮执行或进入交互式会话",
|
|
19
|
+
usage: "wellspring run [--session-id <id>] [--new] [--agent <name>] [--model <name>] [--reasoning off|low|high|max] [--permission read-only|workspace-write|danger-full-access] [--allow-exec] [--max-steps <n>] <context...>",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: "start",
|
|
23
|
+
summary: "以服务进程启动,加载插件并触发 onInit",
|
|
24
|
+
usage: "wellspring start",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: "stop",
|
|
28
|
+
summary: "停止正在运行的 Wellspring 服务",
|
|
29
|
+
usage: "wellspring stop",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: "session",
|
|
33
|
+
summary: "查看、切换与删除会话",
|
|
34
|
+
usage: "wellspring session <list|show|delete> [args]",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "config",
|
|
38
|
+
summary: "配置路径、查看与读写配置项",
|
|
39
|
+
usage: "wellspring config <path|show|get|set> [args]",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "key",
|
|
43
|
+
summary: "查看、设置、清除与测试 OpenAI API Key",
|
|
44
|
+
usage: "wellspring key <status|set|clear|test|path> [--provider <id>] [args]",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "plugin",
|
|
48
|
+
summary: "插件列表、安装与删除",
|
|
49
|
+
usage: "wellspring plugin <list|new|install|link|enable|disable|remove> [args]",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "doctor",
|
|
53
|
+
summary: "环境与配置诊断",
|
|
54
|
+
usage: "wellspring doctor [--json]",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: "version",
|
|
58
|
+
summary: "显示版本与运行环境",
|
|
59
|
+
usage: "wellspring version [--json]",
|
|
60
|
+
aliases: ["-v"],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: "help",
|
|
64
|
+
summary: "显示帮助",
|
|
65
|
+
usage: "wellspring help [command]",
|
|
66
|
+
aliases: ["-h"],
|
|
67
|
+
},
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
export const BUILTIN_NAMES: ReadonlySet<string> = new Set(BUILTIN_COMMANDS.map((spec) => spec.name))
|
|
71
|
+
|
|
72
|
+
export function findBuiltin(name: string): BuiltinCommandSpec | undefined {
|
|
73
|
+
return BUILTIN_COMMANDS.find(
|
|
74
|
+
(spec) => spec.name === name || (spec.aliases ?? []).includes(name),
|
|
75
|
+
)
|
|
76
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* 帮助文本生成。内置命令来自命令表,插件命令来自注册表。
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { BUILTIN_COMMANDS, findBuiltin } from "./commands.ts"
|
|
6
|
+
|
|
7
|
+
export interface HelpPluginCommand {
|
|
8
|
+
readonly name: string
|
|
9
|
+
readonly summary: string
|
|
10
|
+
readonly usage: string
|
|
11
|
+
readonly plugin: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function formatGlobalHelp(pluginCommands: readonly HelpPluginCommand[]): string {
|
|
15
|
+
const lines: string[] = []
|
|
16
|
+
lines.push("Wellspring 源泉 —— 聚合式 Agent 平台")
|
|
17
|
+
lines.push("")
|
|
18
|
+
lines.push("用法:wellspring <command> [args] [options]")
|
|
19
|
+
lines.push("")
|
|
20
|
+
lines.push("命令:")
|
|
21
|
+
for (const spec of BUILTIN_COMMANDS) {
|
|
22
|
+
lines.push(` ${spec.name.padEnd(9)} ${spec.summary}`)
|
|
23
|
+
}
|
|
24
|
+
if (pluginCommands.length > 0) {
|
|
25
|
+
lines.push("")
|
|
26
|
+
lines.push("插件命令:")
|
|
27
|
+
for (const command of pluginCommands) {
|
|
28
|
+
lines.push(` ${command.name.padEnd(9)} ${command.summary}(来自 ${command.plugin})`)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
lines.push("")
|
|
32
|
+
lines.push("全局参数:")
|
|
33
|
+
lines.push(" -c, --config <file> 指定配置文件")
|
|
34
|
+
lines.push(" --home <dir> 便携模式根目录")
|
|
35
|
+
lines.push(" -l, --log-level <level> 日志级别")
|
|
36
|
+
lines.push(" --json 机器可读输出")
|
|
37
|
+
lines.push(" -q, --quiet 静默")
|
|
38
|
+
lines.push(" -h, --help 帮助")
|
|
39
|
+
lines.push(" -v, --version 版本")
|
|
40
|
+
lines.push("")
|
|
41
|
+
lines.push('示例:wellspring chat "解释一下 EventBus"')
|
|
42
|
+
lines.push(' wellspring run --session-id 20261021-173000-ab12 "读取 package.json"')
|
|
43
|
+
return lines.join("\n")
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function formatCommandHelp(name: string, pluginCommand?: HelpPluginCommand): string | null {
|
|
47
|
+
const spec = findBuiltin(name)
|
|
48
|
+
if (spec !== undefined) {
|
|
49
|
+
return [`用法:${spec.usage}`, "", spec.summary].join("\n")
|
|
50
|
+
}
|
|
51
|
+
if (pluginCommand !== undefined) {
|
|
52
|
+
return [
|
|
53
|
+
`用法:${pluginCommand.usage}`,
|
|
54
|
+
"",
|
|
55
|
+
pluginCommand.summary,
|
|
56
|
+
`来自插件:${pluginCommand.plugin}`,
|
|
57
|
+
].join("\n")
|
|
58
|
+
}
|
|
59
|
+
return null
|
|
60
|
+
}
|