@xyit/wellspring 0.0.0-stage → 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/LICENSE +21 -0
- package/README.md +829 -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 +45 -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 +188 -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 +12 -0
- package/dist/plugin/install.js +114 -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 +265 -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/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 +126 -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/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 +55 -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 +218 -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 +149 -0
- package/src/plugin/loader.ts +952 -0
- package/src/plugin/manage.ts +329 -0
- package/src/plugin/models-service.ts +383 -0
- package/src/plugin/network-service.ts +102 -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 +152 -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,155 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* 服务进程控制:pid 文件 + 跨进程停止。
|
|
3
|
+
* 只有 wellspring start 会写服务记录;wellspring stop 读取后发送 SIGTERM。
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { join } from "node:path"
|
|
7
|
+
|
|
8
|
+
import { readJsonIfExists, removePath, statIfExists, writeJsonAtomic } from "../platform/file.ts"
|
|
9
|
+
import { getPaths, type ResolvedPaths } from "../platform/path.ts"
|
|
10
|
+
|
|
11
|
+
export interface ServiceRecord {
|
|
12
|
+
readonly version: 1
|
|
13
|
+
readonly pid: number
|
|
14
|
+
readonly startedAt: string
|
|
15
|
+
readonly cwd: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class ServiceNotRunningError extends Error {
|
|
19
|
+
constructor() {
|
|
20
|
+
super("没有正在运行的 Wellspring 服务")
|
|
21
|
+
this.name = "ServiceNotRunningError"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class ServiceAlreadyRunningError extends Error {
|
|
26
|
+
readonly pid: number
|
|
27
|
+
|
|
28
|
+
constructor(pid: number) {
|
|
29
|
+
super(`Wellspring 服务已在运行(pid ${pid})`)
|
|
30
|
+
this.name = "ServiceAlreadyRunningError"
|
|
31
|
+
this.pid = pid
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class ServiceStopTimeoutError extends Error {
|
|
36
|
+
readonly pid: number
|
|
37
|
+
|
|
38
|
+
constructor(pid: number) {
|
|
39
|
+
super(`等待服务退出超时(pid ${pid})`)
|
|
40
|
+
this.name = "ServiceStopTimeoutError"
|
|
41
|
+
this.pid = pid
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function serviceRecordFile(paths: ResolvedPaths = getPaths()): string {
|
|
46
|
+
return join(paths.dataDir, "service.json")
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function readServiceRecord(
|
|
50
|
+
paths: ResolvedPaths = getPaths(),
|
|
51
|
+
): Promise<ServiceRecord | null> {
|
|
52
|
+
const value = await readJsonIfExists<Partial<ServiceRecord>>(serviceRecordFile(paths))
|
|
53
|
+
if (
|
|
54
|
+
value === null ||
|
|
55
|
+
typeof value.pid !== "number" ||
|
|
56
|
+
!Number.isInteger(value.pid) ||
|
|
57
|
+
value.pid <= 0
|
|
58
|
+
) {
|
|
59
|
+
return null
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
version: 1,
|
|
63
|
+
pid: value.pid,
|
|
64
|
+
startedAt: typeof value.startedAt === "string" ? value.startedAt : "",
|
|
65
|
+
cwd: typeof value.cwd === "string" ? value.cwd : "",
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export async function writeServiceRecord(
|
|
70
|
+
record: Omit<ServiceRecord, "version">,
|
|
71
|
+
paths: ResolvedPaths = getPaths(),
|
|
72
|
+
): Promise<void> {
|
|
73
|
+
await writeJsonAtomic(serviceRecordFile(paths), { version: 1, ...record })
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** 只清理属于指定 pid 的记录,避免误删后来的服务 */
|
|
77
|
+
export async function clearServiceRecord(
|
|
78
|
+
pid: number,
|
|
79
|
+
paths: ResolvedPaths = getPaths(),
|
|
80
|
+
): Promise<void> {
|
|
81
|
+
const current = await readServiceRecord(paths)
|
|
82
|
+
if (current !== null && current.pid !== pid) {
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
await removePath(serviceRecordFile(paths))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function isProcessAlive(pid: number): boolean {
|
|
89
|
+
try {
|
|
90
|
+
process.kill(pid, 0)
|
|
91
|
+
return true
|
|
92
|
+
} catch (error) {
|
|
93
|
+
if (error instanceof Error && "code" in error && error.code === "ESRCH") {
|
|
94
|
+
return false
|
|
95
|
+
}
|
|
96
|
+
return true
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface StopServiceOptions {
|
|
101
|
+
readonly timeoutMs?: number
|
|
102
|
+
readonly pollMs?: number
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** 停止当前服务:SIGTERM → 轮询等待退出 → 清理 pid 文件 */
|
|
106
|
+
export async function stopService(
|
|
107
|
+
paths: ResolvedPaths = getPaths(),
|
|
108
|
+
options: StopServiceOptions = {},
|
|
109
|
+
): Promise<number> {
|
|
110
|
+
const record = await readServiceRecord(paths)
|
|
111
|
+
if (record === null) {
|
|
112
|
+
throw new ServiceNotRunningError()
|
|
113
|
+
}
|
|
114
|
+
if (!isProcessAlive(record.pid)) {
|
|
115
|
+
await clearServiceRecord(record.pid, paths)
|
|
116
|
+
throw new ServiceNotRunningError()
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
process.kill(record.pid, "SIGTERM")
|
|
121
|
+
} catch (error) {
|
|
122
|
+
if (error instanceof Error && "code" in error && error.code === "ESRCH") {
|
|
123
|
+
await clearServiceRecord(record.pid, paths)
|
|
124
|
+
throw new ServiceNotRunningError()
|
|
125
|
+
}
|
|
126
|
+
throw error
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const timeoutMs = options.timeoutMs ?? 5_000
|
|
130
|
+
const pollMs = options.pollMs ?? 100
|
|
131
|
+
const deadline = Date.now() + timeoutMs
|
|
132
|
+
while (Date.now() < deadline) {
|
|
133
|
+
await new Promise((resolve) => setTimeout(resolve, pollMs))
|
|
134
|
+
if (!isProcessAlive(record.pid)) {
|
|
135
|
+
await clearServiceRecord(record.pid, paths)
|
|
136
|
+
return record.pid
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
throw new ServiceStopTimeoutError(record.pid)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** start 前检查:已有存活服务则报错,残留记录直接清掉 */
|
|
143
|
+
export async function assertServiceStartable(paths: ResolvedPaths = getPaths()): Promise<void> {
|
|
144
|
+
const record = await readServiceRecord(paths)
|
|
145
|
+
if (record === null) {
|
|
146
|
+
return
|
|
147
|
+
}
|
|
148
|
+
if (isProcessAlive(record.pid)) {
|
|
149
|
+
throw new ServiceAlreadyRunningError(record.pid)
|
|
150
|
+
}
|
|
151
|
+
const shown = await statIfExists(serviceRecordFile(paths))
|
|
152
|
+
if (shown !== null) {
|
|
153
|
+
await clearServiceRecord(record.pid, paths)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* 会话段编解码。
|
|
3
|
+
* 每轮一个 zstd frame:解压后是 JSONL 事件流,一行一个事件。
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { zstdCompressSync, zstdDecompressSync } from "node:zlib"
|
|
7
|
+
|
|
8
|
+
import type { SessionEvent } from "./types.ts"
|
|
9
|
+
|
|
10
|
+
export function encodeEvents(events: readonly SessionEvent[]): Buffer {
|
|
11
|
+
const text = `${events.map((event) => JSON.stringify(event)).join("\n")}\n`
|
|
12
|
+
return zstdCompressSync(Buffer.from(text, "utf8"))
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function decodeEvents(data: Buffer): SessionEvent[] {
|
|
16
|
+
let text: string
|
|
17
|
+
try {
|
|
18
|
+
text = zstdDecompressSync(data).toString("utf8")
|
|
19
|
+
} catch (error) {
|
|
20
|
+
throw new Error("会话段解压失败", { cause: error })
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const events: SessionEvent[] = []
|
|
24
|
+
for (const line of text.split("\n")) {
|
|
25
|
+
const trimmed = line.trim()
|
|
26
|
+
if (trimmed === "") {
|
|
27
|
+
continue
|
|
28
|
+
}
|
|
29
|
+
let parsed: unknown
|
|
30
|
+
try {
|
|
31
|
+
parsed = JSON.parse(trimmed)
|
|
32
|
+
} catch (error) {
|
|
33
|
+
throw new Error("会话段包含无法解析的行", { cause: error })
|
|
34
|
+
}
|
|
35
|
+
if (
|
|
36
|
+
typeof parsed !== "object" ||
|
|
37
|
+
parsed === null ||
|
|
38
|
+
typeof (parsed as { type?: unknown }).type !== "string" ||
|
|
39
|
+
typeof (parsed as { seq?: unknown }).seq !== "number" ||
|
|
40
|
+
typeof (parsed as { time?: unknown }).time !== "number"
|
|
41
|
+
) {
|
|
42
|
+
throw new Error("会话事件缺少 type/seq/time")
|
|
43
|
+
}
|
|
44
|
+
events.push(parsed as SessionEvent)
|
|
45
|
+
}
|
|
46
|
+
return events
|
|
47
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// 活跃会话注册表
|
|
2
|
+
|
|
3
|
+
import type { Session } from "./session.ts"
|
|
4
|
+
|
|
5
|
+
const sessions = new Map<string, Session>()
|
|
6
|
+
|
|
7
|
+
export function registerSession(session: Session): void {
|
|
8
|
+
sessions.set(session.id, session)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function unregisterSession(id: string): void {
|
|
12
|
+
sessions.delete(id)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getSession(id: string): Session | null {
|
|
16
|
+
return sessions.get(id) ?? null
|
|
17
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* 会话回放:把事件流还原成对话轮次与 Chat Completions 消息。
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ChatCompletionMessageParam } from "openai/resources/chat/completions"
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
ContentPart,
|
|
9
|
+
SessionEvent,
|
|
10
|
+
SessionMessageRecord,
|
|
11
|
+
SessionMode,
|
|
12
|
+
SessionTurn,
|
|
13
|
+
} from "./types.ts"
|
|
14
|
+
|
|
15
|
+
export function contentText(parts: readonly ContentPart[] | undefined): string {
|
|
16
|
+
if (parts === undefined) {
|
|
17
|
+
return ""
|
|
18
|
+
}
|
|
19
|
+
let text = ""
|
|
20
|
+
for (const part of parts) {
|
|
21
|
+
if (part.type === "text") {
|
|
22
|
+
text += part.text
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return text
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function messageOf(event: SessionEvent): SessionMessageRecord | null {
|
|
29
|
+
const message = event.data["message"]
|
|
30
|
+
if (typeof message !== "object" || message === null) {
|
|
31
|
+
return null
|
|
32
|
+
}
|
|
33
|
+
return message as SessionMessageRecord
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** 按 turn/start 分组;没有 turn 边界的事件归到当前组 */
|
|
37
|
+
export function groupTurns(events: readonly SessionEvent[]): SessionTurn[] {
|
|
38
|
+
const turns: SessionTurn[] = []
|
|
39
|
+
let current: SessionTurn | null = null
|
|
40
|
+
|
|
41
|
+
for (const event of events) {
|
|
42
|
+
if (event.type === "turn/start") {
|
|
43
|
+
const turn =
|
|
44
|
+
typeof event.data["turn"] === "number" ? event.data["turn"] : turns.length + 1
|
|
45
|
+
const mode =
|
|
46
|
+
event.data["mode"] === "run" ? "run" : event.data["mode"] === "chat" ? "chat" : null
|
|
47
|
+
current = { turn, mode, events: [] }
|
|
48
|
+
turns.push(current)
|
|
49
|
+
}
|
|
50
|
+
if (current === null) {
|
|
51
|
+
const turn = typeof event.data["turn"] === "number" ? event.data["turn"] : 1
|
|
52
|
+
const mode =
|
|
53
|
+
event.data["mode"] === "run" ? "run" : event.data["mode"] === "chat" ? "chat" : null
|
|
54
|
+
current = { turn, mode, events: [] }
|
|
55
|
+
turns.push(current)
|
|
56
|
+
}
|
|
57
|
+
current.events.push(event)
|
|
58
|
+
}
|
|
59
|
+
return turns
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function lastTurnNumber(events: readonly SessionEvent[]): number {
|
|
63
|
+
let max = 0
|
|
64
|
+
for (const event of events) {
|
|
65
|
+
const turn = event.data["turn"]
|
|
66
|
+
if (typeof turn === "number" && turn > max) {
|
|
67
|
+
max = turn
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return max
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function lastSeq(events: readonly SessionEvent[]): number {
|
|
74
|
+
let max = -1
|
|
75
|
+
for (const event of events) {
|
|
76
|
+
if (event.seq > max) {
|
|
77
|
+
max = event.seq
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return max
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** 历史事件 → 模型消息;保留 assistant tool_calls 与 tool 结果 */
|
|
84
|
+
export function toChatMessages(events: readonly SessionEvent[]): ChatCompletionMessageParam[] {
|
|
85
|
+
const messages: ChatCompletionMessageParam[] = []
|
|
86
|
+
for (const event of events) {
|
|
87
|
+
if (event.type === "tool/result") {
|
|
88
|
+
const callId = event.data["callId"]
|
|
89
|
+
const content = event.data["content"]
|
|
90
|
+
if (typeof callId === "string" && typeof content === "string") {
|
|
91
|
+
messages.push({ role: "tool", tool_call_id: callId, content })
|
|
92
|
+
}
|
|
93
|
+
continue
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const message = messageOf(event)
|
|
97
|
+
if (message === null) {
|
|
98
|
+
continue
|
|
99
|
+
}
|
|
100
|
+
const text = contentText(message.content)
|
|
101
|
+
if (event.type === "user/message" && message.role === "user") {
|
|
102
|
+
if (text !== "") {
|
|
103
|
+
messages.push({ role: "user", content: text })
|
|
104
|
+
}
|
|
105
|
+
continue
|
|
106
|
+
}
|
|
107
|
+
if (event.type === "assistant/message" && message.role === "assistant") {
|
|
108
|
+
const toolCalls = message.content.filter(
|
|
109
|
+
(part): part is Extract<ContentPart, { type: "tool-call" }> =>
|
|
110
|
+
part.type === "tool-call",
|
|
111
|
+
)
|
|
112
|
+
if (toolCalls.length > 0) {
|
|
113
|
+
messages.push({
|
|
114
|
+
role: "assistant",
|
|
115
|
+
content: text === "" ? null : text,
|
|
116
|
+
tool_calls: toolCalls.map((call) => ({
|
|
117
|
+
id: call.id,
|
|
118
|
+
type: "function" as const,
|
|
119
|
+
function: { name: call.name, arguments: call.arguments },
|
|
120
|
+
})),
|
|
121
|
+
})
|
|
122
|
+
} else if (text !== "") {
|
|
123
|
+
messages.push({ role: "assistant", content: text })
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return messages
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function turnModeLabel(mode: SessionMode | null): string {
|
|
131
|
+
return mode === "run" ? "run" : "chat"
|
|
132
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// 会话门面:插件与宿主使用的 Session / SessionMessage
|
|
2
|
+
|
|
3
|
+
import { randomUUID } from "node:crypto"
|
|
4
|
+
|
|
5
|
+
import { emitOnMessage } from "../api/host/hooks.ts"
|
|
6
|
+
import type { SessionStore, SessionData } from "./store.ts"
|
|
7
|
+
import type { SessionMessageRecord } from "./types.ts"
|
|
8
|
+
import { lastSeq, lastTurnNumber } from "./replay.ts"
|
|
9
|
+
import { Workspace } from "../workspace/index.ts"
|
|
10
|
+
|
|
11
|
+
export interface SessionMessageInput {
|
|
12
|
+
readonly sessionId: string
|
|
13
|
+
readonly content: string | readonly string[]
|
|
14
|
+
readonly type?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class SessionMessage {
|
|
18
|
+
readonly sessionId: string
|
|
19
|
+
readonly content: string[]
|
|
20
|
+
readonly type: string
|
|
21
|
+
|
|
22
|
+
constructor(input: SessionMessageInput) {
|
|
23
|
+
this.sessionId = input.sessionId
|
|
24
|
+
this.content = typeof input.content === "string" ? [input.content] : [...input.content]
|
|
25
|
+
this.type = input.type ?? "message"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class Session {
|
|
30
|
+
readonly id: string
|
|
31
|
+
readonly type: string
|
|
32
|
+
readonly metadata: Record<string, unknown>
|
|
33
|
+
readonly workspace: Workspace
|
|
34
|
+
readonly data: SessionData
|
|
35
|
+
readonly #store: SessionStore | null
|
|
36
|
+
readonly #queue: SessionMessage[] = []
|
|
37
|
+
#active = false
|
|
38
|
+
#stopRequested = false
|
|
39
|
+
|
|
40
|
+
constructor(data: SessionData, store: SessionStore | null = null) {
|
|
41
|
+
this.data = data
|
|
42
|
+
this.#store = store
|
|
43
|
+
this.id = data.meta.id
|
|
44
|
+
this.type = data.meta.type
|
|
45
|
+
this.metadata = data.meta.metadata
|
|
46
|
+
this.workspace = new Workspace(data.meta.workspace)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Agent 循环开始后,消息进入队列而不是直接落盘 */
|
|
50
|
+
begin(): void {
|
|
51
|
+
this.#active = true
|
|
52
|
+
this.#stopRequested = false
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** 请求停止本轮:循环在下一步之前收尾,不再调用模型 */
|
|
56
|
+
requestStop(): void {
|
|
57
|
+
this.#stopRequested = true
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** 本轮是否被要求停止 */
|
|
61
|
+
get stopRequested(): boolean {
|
|
62
|
+
return this.#stopRequested
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
end(): void {
|
|
66
|
+
this.#active = false
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** 是否有一轮正在跑;插话只在这个窗口内有效 */
|
|
70
|
+
get active(): boolean {
|
|
71
|
+
return this.#active
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** 取走运行期排队的消息 */
|
|
75
|
+
take(): SessionMessage[] {
|
|
76
|
+
return this.#queue.splice(0)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
get events() {
|
|
80
|
+
return this.data.events
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get turns() {
|
|
84
|
+
return this.data.turns
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** 发送消息并触发 onMessage */
|
|
88
|
+
async message(content: string | readonly string[], type = "message"): Promise<SessionMessage> {
|
|
89
|
+
const message = new SessionMessage({ sessionId: this.id, content, type })
|
|
90
|
+
await emitOnMessage({
|
|
91
|
+
sessionId: this.id,
|
|
92
|
+
mode: "chat",
|
|
93
|
+
turn: lastTurnNumber(this.data.events) + 1,
|
|
94
|
+
role: "user",
|
|
95
|
+
phase: "before",
|
|
96
|
+
content: message.content.join(""),
|
|
97
|
+
prompt: [],
|
|
98
|
+
})
|
|
99
|
+
if (this.#active || this.#store === null) {
|
|
100
|
+
this.#queue.push(message)
|
|
101
|
+
return message
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const turn = lastTurnNumber(this.data.events) + 1
|
|
105
|
+
await this.#store.appendTurn(this.data, [
|
|
106
|
+
{
|
|
107
|
+
type: "user/message",
|
|
108
|
+
seq: lastSeq(this.data.events) + 1,
|
|
109
|
+
time: Date.now(),
|
|
110
|
+
data: {
|
|
111
|
+
turn,
|
|
112
|
+
message: {
|
|
113
|
+
role: "user",
|
|
114
|
+
content: [{ type: "text", text: message.content.join("") }],
|
|
115
|
+
source: { kind: "plugin", type: message.type },
|
|
116
|
+
id: randomUUID(),
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
])
|
|
121
|
+
return message
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
toJSON(): Record<string, unknown> {
|
|
125
|
+
return {
|
|
126
|
+
id: this.id,
|
|
127
|
+
type: this.type,
|
|
128
|
+
metadata: this.metadata,
|
|
129
|
+
workspace: this.workspace.root,
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export type { SessionStore, SessionData, SessionMessageRecord }
|