@earendil-works/pi-coding-agent 0.84.4 → 0.85.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/CHANGELOG.md +57 -5
- package/README.md +3 -1
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js +10 -7
- package/dist/bun/cli.js.map +1 -1
- package/dist/bun/runtime-setup.d.ts +2 -0
- package/dist/bun/runtime-setup.d.ts.map +1 -0
- package/dist/bun/runtime-setup.js +9 -0
- package/dist/bun/runtime-setup.js.map +1 -0
- package/dist/bundle/chunks/anthropic-messages-QAQLEQIY.js +6 -0
- package/dist/bundle/chunks/{azure-openai-responses-5ENVCQ7U.js → azure-openai-responses-Q7MJBRE6.js} +1 -1
- package/dist/bundle/chunks/bedrock-converse-stream.js +1 -1
- package/dist/bundle/chunks/chunk-7ZC4UXSL.js +2 -0
- package/dist/bundle/chunks/chunk-EQ6DR6XK.js +5 -0
- package/dist/bundle/chunks/{chunk-MNAIPA3J.js → chunk-IDDQWTHI.js} +1 -1
- package/dist/bundle/chunks/chunk-LZKJTKCT.js +2 -0
- package/dist/bundle/chunks/{chunk-NBBFIJUL.js → chunk-OUXLLA64.js} +2 -2
- package/dist/bundle/chunks/chunk-R7UUJ4C2.js +42 -0
- package/dist/bundle/chunks/chunk-USJZMAIR.js +2 -0
- package/dist/bundle/chunks/chunk-WBE4J4AU.js +9 -0
- package/dist/bundle/chunks/chunk-WZB2R5YO.js +1558 -0
- package/dist/bundle/chunks/github-copilot.js +1 -1
- package/dist/bundle/chunks/{google-generative-ai-YMUPJBKR.js → google-generative-ai-BSMTYDAM.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-MPWMV4OF.js → google-vertex-5C3HASOJ.js} +1 -1
- package/dist/bundle/chunks/image-resize-worker.js +1 -1
- package/dist/bundle/chunks/{mistral-conversations-Q3AWZJAZ.js → mistral-conversations-4M6BZBX6.js} +1 -1
- package/dist/bundle/chunks/node-EM5FIVUN.js +16 -0
- package/dist/bundle/chunks/node-TWVVAGPO.js +2 -0
- package/dist/bundle/chunks/openai-codex-responses-YJOO52RW.js +10 -0
- package/dist/bundle/chunks/{openai-completions-ERMU2SS7.js → openai-completions-QOT3QX7D.js} +3 -3
- package/dist/bundle/chunks/openai-responses-U7LNPQN4.js +2 -0
- package/dist/bundle/chunks/{pi-messages-TPFH44NP.js → pi-messages-EGZIFQGG.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/client.js +1 -1
- package/dist/bundle/coordinator.js +3 -0
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +2 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +2 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/experimental/cli.d.ts +7 -3
- package/dist/cli/experimental/cli.d.ts.map +1 -1
- package/dist/cli/experimental/cli.js +6 -2
- package/dist/cli/experimental/cli.js.map +1 -1
- package/dist/cli/experimental/command-options.d.ts +23 -12
- package/dist/cli/experimental/command-options.d.ts.map +1 -1
- package/dist/cli/experimental/command-options.js +69 -20
- package/dist/cli/experimental/command-options.js.map +1 -1
- package/dist/cli/experimental/command.d.ts +10 -3
- package/dist/cli/experimental/command.d.ts.map +1 -1
- package/dist/cli/experimental/command.js +28 -14
- package/dist/cli/experimental/command.js.map +1 -1
- package/dist/cli/experimental/commands/client.d.ts +8 -2
- package/dist/cli/experimental/commands/client.d.ts.map +1 -1
- package/dist/cli/experimental/commands/client.js +43 -5
- package/dist/cli/experimental/commands/client.js.map +1 -1
- package/dist/cli/experimental/commands/server.d.ts +7 -3
- package/dist/cli/experimental/commands/server.d.ts.map +1 -1
- package/dist/cli/experimental/commands/server.js +27 -8
- package/dist/cli/experimental/commands/server.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +23 -14
- package/dist/cli.js.map +1 -1
- package/dist/client/index.d.ts +1 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -2
- package/dist/client/index.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +15 -7
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts +2 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +14 -6
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +2 -1
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +1 -2
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/types.d.ts +8 -2
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +2 -0
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/messages.d.ts +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-config.d.ts +15 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +3 -0
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-runtime.d.ts +1 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +5 -2
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +8 -2
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/session-manager.d.ts +3 -2
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +40 -13
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +4 -2
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +8 -9
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +3 -117
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts +1 -12
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +5 -163
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +4 -55
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +4 -60
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +4 -49
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +4 -120
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/renderers/bash.d.ts +12 -0
- package/dist/core/tools/renderers/bash.d.ts.map +1 -0
- package/dist/core/tools/renderers/bash.js +130 -0
- package/dist/core/tools/renderers/bash.js.map +1 -0
- package/dist/core/tools/renderers/edit.d.ts +23 -0
- package/dist/core/tools/renderers/edit.d.ts.map +1 -0
- package/dist/core/tools/renderers/edit.js +167 -0
- package/dist/core/tools/renderers/edit.js.map +1 -0
- package/dist/core/tools/renderers/find.d.ts +10 -0
- package/dist/core/tools/renderers/find.d.ts.map +1 -0
- package/dist/core/tools/renderers/find.js +64 -0
- package/dist/core/tools/renderers/find.js.map +1 -0
- package/dist/core/tools/renderers/grep.d.ts +10 -0
- package/dist/core/tools/renderers/grep.d.ts.map +1 -0
- package/dist/core/tools/renderers/grep.js +69 -0
- package/dist/core/tools/renderers/grep.js.map +1 -0
- package/dist/core/tools/renderers/index.d.ts +28 -0
- package/dist/core/tools/renderers/index.d.ts.map +1 -0
- package/dist/core/tools/renderers/index.js +47 -0
- package/dist/core/tools/renderers/index.js.map +1 -0
- package/dist/core/tools/renderers/ls.d.ts +10 -0
- package/dist/core/tools/renderers/ls.d.ts.map +1 -0
- package/dist/core/tools/renderers/ls.js +58 -0
- package/dist/core/tools/renderers/ls.js.map +1 -0
- package/dist/core/tools/renderers/read.d.ts +11 -0
- package/dist/core/tools/renderers/read.d.ts.map +1 -0
- package/dist/core/tools/renderers/read.js +129 -0
- package/dist/core/tools/renderers/read.js.map +1 -0
- package/dist/core/tools/renderers/write.d.ts +10 -0
- package/dist/core/tools/renderers/write.d.ts.map +1 -0
- package/dist/core/tools/renderers/write.js +153 -0
- package/dist/core/tools/renderers/write.js.map +1 -0
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +5 -146
- package/dist/core/tools/write.js.map +1 -1
- package/dist/experimental/client-runtime.d.ts +43 -0
- package/dist/experimental/client-runtime.d.ts.map +1 -0
- package/dist/experimental/client-runtime.js +183 -0
- package/dist/experimental/client-runtime.js.map +1 -0
- package/dist/experimental/client-tui-chat.d.ts +14 -0
- package/dist/experimental/client-tui-chat.d.ts.map +1 -0
- package/dist/experimental/client-tui-chat.js +171 -0
- package/dist/experimental/client-tui-chat.js.map +1 -0
- package/dist/experimental/client-tui.d.ts +37 -0
- package/dist/experimental/client-tui.d.ts.map +1 -0
- package/dist/experimental/client-tui.js +702 -0
- package/dist/experimental/client-tui.js.map +1 -0
- package/dist/experimental/client.d.ts +25 -0
- package/dist/experimental/client.d.ts.map +1 -0
- package/dist/experimental/client.js +99 -0
- package/dist/experimental/client.js.map +1 -0
- package/dist/experimental/coordinator-entry.d.ts +3 -0
- package/dist/experimental/coordinator-entry.d.ts.map +1 -0
- package/dist/experimental/coordinator-entry.js +11 -0
- package/dist/experimental/coordinator-entry.js.map +1 -0
- package/dist/experimental/coordinator.d.ts +38 -0
- package/dist/experimental/coordinator.d.ts.map +1 -0
- package/dist/experimental/coordinator.js +570 -0
- package/dist/experimental/coordinator.js.map +1 -0
- package/dist/experimental/mini/main.d.ts +7 -0
- package/dist/experimental/mini/main.d.ts.map +1 -0
- package/dist/experimental/mini/main.js +21 -0
- package/dist/experimental/mini/main.js.map +1 -0
- package/dist/experimental/mini/server/entry.d.ts +3 -0
- package/dist/experimental/mini/server/entry.d.ts.map +1 -0
- package/dist/experimental/mini/server/entry.js +11 -0
- package/dist/experimental/mini/server/entry.js.map +1 -0
- package/dist/experimental/mini/server/run.d.ts +13 -0
- package/dist/experimental/mini/server/run.d.ts.map +1 -0
- package/dist/experimental/mini/server/run.js +150 -0
- package/dist/experimental/mini/server/run.js.map +1 -0
- package/dist/experimental/mini/shared/protocol.d.ts +127 -0
- package/dist/experimental/mini/shared/protocol.d.ts.map +1 -0
- package/dist/experimental/mini/shared/protocol.js +13 -0
- package/dist/experimental/mini/shared/protocol.js.map +1 -0
- package/dist/experimental/mini/shared/rpc.d.ts +49 -0
- package/dist/experimental/mini/shared/rpc.d.ts.map +1 -0
- package/dist/experimental/mini/shared/rpc.js +171 -0
- package/dist/experimental/mini/shared/rpc.js.map +1 -0
- package/dist/experimental/mini/shared/transport.d.ts +35 -0
- package/dist/experimental/mini/shared/transport.d.ts.map +1 -0
- package/dist/experimental/mini/shared/transport.js +94 -0
- package/dist/experimental/mini/shared/transport.js.map +1 -0
- package/dist/experimental/mini/tui/run.d.ts +9 -0
- package/dist/experimental/mini/tui/run.d.ts.map +1 -0
- package/dist/experimental/mini/tui/run.js +62 -0
- package/dist/experimental/mini/tui/run.js.map +1 -0
- package/dist/experimental/mini/tui/session.d.ts +26 -0
- package/dist/experimental/mini/tui/session.d.ts.map +1 -0
- package/dist/experimental/mini/tui/session.js +94 -0
- package/dist/experimental/mini/tui/session.js.map +1 -0
- package/dist/experimental/mini/tui/view.d.ts +10 -0
- package/dist/experimental/mini/tui/view.d.ts.map +1 -0
- package/dist/experimental/mini/tui/view.js +459 -0
- package/dist/experimental/mini/tui/view.js.map +1 -0
- package/dist/experimental/mini/worker/entry.d.ts +3 -0
- package/dist/experimental/mini/worker/entry.d.ts.map +1 -0
- package/dist/experimental/mini/worker/entry.js +10 -0
- package/dist/experimental/mini/worker/entry.js.map +1 -0
- package/dist/experimental/mini/worker/lane-service.d.ts +44 -0
- package/dist/experimental/mini/worker/lane-service.d.ts.map +1 -0
- package/dist/experimental/mini/worker/lane-service.js +97 -0
- package/dist/experimental/mini/worker/lane-service.js.map +1 -0
- package/dist/experimental/mini/worker/models-service.d.ts +19 -0
- package/dist/experimental/mini/worker/models-service.d.ts.map +1 -0
- package/dist/experimental/mini/worker/models-service.js +136 -0
- package/dist/experimental/mini/worker/models-service.js.map +1 -0
- package/dist/experimental/mini/worker/run.d.ts +14 -0
- package/dist/experimental/mini/worker/run.d.ts.map +1 -0
- package/dist/experimental/mini/worker/run.js +88 -0
- package/dist/experimental/mini/worker/run.js.map +1 -0
- package/dist/experimental/plugin.d.ts +4 -0
- package/dist/experimental/plugin.d.ts.map +1 -0
- package/dist/experimental/plugin.js +4 -0
- package/dist/experimental/plugin.js.map +1 -0
- package/dist/experimental/plugins/bundled.d.ts +7 -0
- package/dist/experimental/plugins/bundled.d.ts.map +1 -0
- package/dist/experimental/plugins/bundled.js +48 -0
- package/dist/experimental/plugins/bundled.js.map +1 -0
- package/dist/experimental/plugins/package.d.ts +18 -0
- package/dist/experimental/plugins/package.d.ts.map +1 -0
- package/dist/experimental/plugins/package.js +113 -0
- package/dist/experimental/plugins/package.js.map +1 -0
- package/dist/experimental/process.d.ts +20 -0
- package/dist/experimental/process.d.ts.map +1 -0
- package/dist/experimental/process.js +85 -0
- package/dist/experimental/process.js.map +1 -0
- package/dist/experimental/radius-auth.d.ts +17 -0
- package/dist/experimental/radius-auth.d.ts.map +1 -0
- package/dist/experimental/radius-auth.js +52 -0
- package/dist/experimental/radius-auth.js.map +1 -0
- package/dist/experimental/radius-relay.d.ts +90 -0
- package/dist/experimental/radius-relay.d.ts.map +1 -0
- package/dist/experimental/radius-relay.js +582 -0
- package/dist/experimental/radius-relay.js.map +1 -0
- package/dist/experimental/server.d.ts +75 -0
- package/dist/experimental/server.d.ts.map +1 -0
- package/dist/experimental/server.js +682 -0
- package/dist/experimental/server.js.map +1 -0
- package/dist/experimental/services/agent-controller-provider.d.ts +4 -0
- package/dist/experimental/services/agent-controller-provider.d.ts.map +1 -0
- package/dist/experimental/services/agent-controller-provider.js +84 -0
- package/dist/experimental/services/agent-controller-provider.js.map +1 -0
- package/dist/experimental/services/agent-controller.d.ts +57 -0
- package/dist/experimental/services/agent-controller.d.ts.map +1 -0
- package/dist/experimental/services/agent-controller.js +3 -0
- package/dist/experimental/services/agent-controller.js.map +1 -0
- package/dist/experimental/services/connection.d.ts +40 -0
- package/dist/experimental/services/connection.d.ts.map +1 -0
- package/dist/experimental/services/connection.js +300 -0
- package/dist/experimental/services/connection.js.map +1 -0
- package/dist/experimental/services/models-provider.d.ts +16 -0
- package/dist/experimental/services/models-provider.d.ts.map +1 -0
- package/dist/experimental/services/models-provider.js +116 -0
- package/dist/experimental/services/models-provider.js.map +1 -0
- package/dist/experimental/services/models.d.ts +36 -0
- package/dist/experimental/services/models.d.ts.map +1 -0
- package/dist/experimental/services/models.js +3 -0
- package/dist/experimental/services/models.js.map +1 -0
- package/dist/experimental/services/plugins.d.ts +16 -0
- package/dist/experimental/services/plugins.d.ts.map +1 -0
- package/dist/experimental/services/plugins.js +4 -0
- package/dist/experimental/services/plugins.js.map +1 -0
- package/dist/experimental/services/presentation-ui.d.ts +13 -0
- package/dist/experimental/services/presentation-ui.d.ts.map +1 -0
- package/dist/experimental/services/presentation-ui.js +3 -0
- package/dist/experimental/services/presentation-ui.js.map +1 -0
- package/dist/experimental/services/server.d.ts +19 -0
- package/dist/experimental/services/server.d.ts.map +1 -0
- package/dist/experimental/services/server.js +104 -0
- package/dist/experimental/services/server.js.map +1 -0
- package/dist/experimental/services/sessions.d.ts +28 -0
- package/dist/experimental/services/sessions.d.ts.map +1 -0
- package/dist/experimental/services/sessions.js +4 -0
- package/dist/experimental/services/sessions.js.map +1 -0
- package/dist/experimental/services/slash-commands-provider.d.ts +14 -0
- package/dist/experimental/services/slash-commands-provider.d.ts.map +1 -0
- package/dist/experimental/services/slash-commands-provider.js +200 -0
- package/dist/experimental/services/slash-commands-provider.js.map +1 -0
- package/dist/experimental/services/slash-commands.d.ts +24 -0
- package/dist/experimental/services/slash-commands.d.ts.map +1 -0
- package/dist/experimental/services/slash-commands.js +3 -0
- package/dist/experimental/services/slash-commands.js.map +1 -0
- package/dist/experimental/services/transcript-provider.d.ts +12 -0
- package/dist/experimental/services/transcript-provider.d.ts.map +1 -0
- package/dist/experimental/services/transcript-provider.js +109 -0
- package/dist/experimental/services/transcript-provider.js.map +1 -0
- package/dist/experimental/services/transcript.d.ts +13 -0
- package/dist/experimental/services/transcript.d.ts.map +1 -0
- package/dist/experimental/services/transcript.js +3 -0
- package/dist/experimental/services/transcript.js.map +1 -0
- package/dist/experimental/services/worker.d.ts +28 -0
- package/dist/experimental/services/worker.d.ts.map +1 -0
- package/dist/experimental/services/worker.js +107 -0
- package/dist/experimental/services/worker.js.map +1 -0
- package/dist/experimental/session-worker-manager.d.ts +24 -0
- package/dist/experimental/session-worker-manager.d.ts.map +1 -0
- package/dist/experimental/session-worker-manager.js +691 -0
- package/dist/experimental/session-worker-manager.js.map +1 -0
- package/dist/experimental/session-worker.d.ts +188 -0
- package/dist/experimental/session-worker.d.ts.map +1 -0
- package/dist/experimental/session-worker.js +785 -0
- package/dist/experimental/session-worker.js.map +1 -0
- package/dist/experimental/source-resolver.d.ts +2 -0
- package/dist/experimental/source-resolver.d.ts.map +1 -0
- package/dist/experimental/source-resolver.js +71 -0
- package/dist/experimental/source-resolver.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +126 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/chat-viewport.d.ts +20 -0
- package/dist/modes/interactive/chat-viewport.d.ts.map +1 -0
- package/dist/modes/interactive/chat-viewport.js +28 -0
- package/dist/modes/interactive/chat-viewport.js.map +1 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +1 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +18 -10
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +10 -1
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +39 -1
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +5 -14
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +13 -15
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +14 -10
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts +3 -1
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +10 -3
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +2 -2
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +21 -4
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +35 -33
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/trust-selector.js +2 -2
- package/dist/modes/interactive/components/trust-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +8 -15
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +95 -80
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/session-share.d.ts.map +1 -1
- package/dist/modes/interactive/session-share.js +8 -12
- package/dist/modes/interactive/session-share.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +2 -1
- package/dist/modes/interactive/theme/light.json +2 -1
- package/dist/modes/interactive/theme/theme-controller.d.ts +1 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +5 -0
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme-json.d.ts +84 -0
- package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme-json.js +130 -0
- package/dist/modes/interactive/theme/theme-json.js.map +1 -0
- package/dist/modes/interactive/theme/theme-schema.json +6 -2
- package/dist/modes/interactive/theme/theme.d.ts +14 -5
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +18 -119
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/interactive/tui-renderer.d.ts +21 -0
- package/dist/modes/interactive/tui-renderer.d.ts.map +1 -0
- package/dist/modes/interactive/tui-renderer.js +66 -0
- package/dist/modes/interactive/tui-renderer.js.map +1 -0
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js +2 -3
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/tools-manager.d.ts +1 -0
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +41 -19
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/environment-variables.md +2 -0
- package/docs/extensions.md +5 -2
- package/docs/keybindings.md +3 -1
- package/docs/models.md +3 -0
- package/docs/rpc.md +1 -1
- package/docs/sdk.md +5 -0
- package/docs/settings.md +5 -5
- package/docs/skills.md +1 -1
- package/docs/terminal-setup.md +15 -0
- package/docs/themes.md +8 -6
- package/docs/tui.md +20 -1
- package/examples/README.md +3 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/dynamic-resources/dynamic.json +2 -0
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/plugins/pi-example-plugin/README.md +38 -0
- package/examples/plugins/pi-example-plugin/package.json +10 -0
- package/examples/plugins/pi-example-plugin/src/contract.ts +13 -0
- package/examples/plugins/pi-example-plugin/src/session.ts +23 -0
- package/examples/plugins/pi-example-plugin/src/tui.ts +31 -0
- package/npm-shrinkwrap.json +523 -28
- package/package.json +12 -6
- package/dist/bun/register-bedrock.d.ts +0 -2
- package/dist/bun/register-bedrock.d.ts.map +0 -1
- package/dist/bun/register-bedrock.js +0 -4
- package/dist/bun/register-bedrock.js.map +0 -1
- package/dist/bundle/chunks/anthropic-messages-JWX2WP65.js +0 -45
- package/dist/bundle/chunks/chunk-JUUC5AZY.js +0 -2
- package/dist/bundle/chunks/chunk-OMWWHBTG.js +0 -1548
- package/dist/bundle/chunks/openai-codex-responses-GJVBJXLB.js +0 -8
- package/dist/bundle/chunks/openai-responses-BSOJMSEV.js +0 -2
- package/dist/cli/experimental/auth.d.ts +0 -16
- package/dist/cli/experimental/auth.d.ts.map +0 -1
- package/dist/cli/experimental/auth.js +0 -13
- package/dist/cli/experimental/auth.js.map +0 -1
- package/dist/cli/experimental/commands/pi.d.ts +0 -15
- package/dist/cli/experimental/commands/pi.d.ts.map +0 -1
- package/dist/cli/experimental/commands/pi.js +0 -28
- package/dist/cli/experimental/commands/pi.js.map +0 -1
- package/dist/cli/experimental/transport-address.d.ts +0 -10
- package/dist/cli/experimental/transport-address.d.ts.map +0 -1
- package/dist/cli/experimental/transport-address.js +0 -38
- package/dist/cli/experimental/transport-address.js.map +0 -1
- package/dist/client/remote-session.d.ts +0 -53
- package/dist/client/remote-session.d.ts.map +0 -1
- package/dist/client/remote-session.js +0 -340
- package/dist/client/remote-session.js.map +0 -1
- package/dist/client/transcript.d.ts +0 -12
- package/dist/client/transcript.d.ts.map +0 -1
- package/dist/client/transcript.js +0 -98
- package/dist/client/transcript.js.map +0 -1
- package/dist/server/create-harness.d.ts +0 -26
- package/dist/server/create-harness.d.ts.map +0 -1
- package/dist/server/create-harness.js +0 -106
- package/dist/server/create-harness.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"radius-relay.js","sourceRoot":"","sources":["../../src/experimental/radius-relay.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ByteTransport, ByteTransportFactory, ByteTransportHandlers, Client } from \"@earendil-works/pi-client\";\nimport { DEFAULT_MAX_FRAME_LENGTH, type ServerId } from \"@earendil-works/pi-protocol\";\nimport type { Server } from \"@earendil-works/pi-server\";\nimport { WebSocket } from \"undici\";\nimport type { RadiusRelayAuthResolver } from \"./radius-auth.ts\";\n\nexport const RADIUS_RELAY_HOST_SUBPROTOCOL = \"pi-session-relay.host.v1\";\nexport const RADIUS_RELAY_CLIENT_SUBPROTOCOL = \"pi-session-relay.client.v1\";\n\nconst RELAY_DATA_HEADER_BYTES = 18;\nconst RELAY_DATA_FRAME_VERSION = 1;\nconst RELAY_DATA_FRAME_TYPE = 1;\nconst CONNECTION_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u;\nconst MAX_PENDING_BYTES = DEFAULT_MAX_FRAME_LENGTH * 4;\nconst DRAIN_THRESHOLD_BYTES = 1024 * 1024;\nconst HOST_RETRY_INITIAL_MS = 1_000;\nconst HOST_RETRY_MAX_MS = 30_000;\nconst MISSING_AUTH_RETRY_MS = 30_000;\nconst CLIENT_RETRY_INITIAL_MS = 1_000;\nconst CLIENT_RETRY_MAX_MS = 30_000;\n// Undici implements the browser WebSocket API, which permits callers to send\n// only code 1000 or application codes from 3000 through 4999. RFC protocol\n// codes such as 1002 and 1011 may be received but cannot be passed to close().\nconst LOCAL_PROTOCOL_ERROR_CLOSE_CODE = 4000;\nconst LOCAL_TRANSPORT_ERROR_CLOSE_CODE = 4001;\n\ninterface RadiusRelayMessageEvent extends Event {\n\treadonly data: unknown;\n}\n\ninterface RadiusRelayCloseEvent extends Event {\n\treadonly code: number;\n\treadonly reason: string;\n}\n\ninterface RadiusRelayErrorEvent extends Event {\n\treadonly error?: unknown;\n\treadonly message?: string;\n}\n\nexport interface RadiusRelayWebSocket {\n\tbinaryType: \"arraybuffer\" | \"blob\";\n\treadonly bufferedAmount: number;\n\treadonly protocol: string;\n\treadonly readyState: number;\n\treadonly OPEN: number;\n\tsend(data: string | ArrayBuffer): void;\n\tclose(code?: number, reason?: string): void;\n\taddEventListener(type: \"open\", listener: (event: Event) => void, options?: { once?: boolean }): void;\n\taddEventListener(\n\t\ttype: \"message\",\n\t\tlistener: (event: RadiusRelayMessageEvent) => void,\n\t\toptions?: { once?: boolean },\n\t): void;\n\taddEventListener(\n\t\ttype: \"close\",\n\t\tlistener: (event: RadiusRelayCloseEvent) => void,\n\t\toptions?: { once?: boolean },\n\t): void;\n\taddEventListener(\n\t\ttype: \"error\",\n\t\tlistener: (event: RadiusRelayErrorEvent) => void,\n\t\toptions?: { once?: boolean },\n\t): void;\n\tremoveEventListener(type: \"open\", listener: (event: Event) => void): void;\n\tremoveEventListener(type: \"message\", listener: (event: RadiusRelayMessageEvent) => void): void;\n\tremoveEventListener(type: \"close\", listener: (event: RadiusRelayCloseEvent) => void): void;\n\tremoveEventListener(type: \"error\", listener: (event: RadiusRelayErrorEvent) => void): void;\n}\n\nexport type RadiusRelayWebSocketFactory = (options: {\n\treadonly url: string;\n\treadonly protocol: string;\n\treadonly authorization: string;\n}) => RadiusRelayWebSocket;\n\ninterface RelayByteConnection {\n\treadonly closed: boolean;\n\tsend(chunk: Uint8Array): Promise<void>;\n\tclose(finalChunk?: Uint8Array): Promise<void>;\n}\n\ninterface RelayByteConnectionHandler {\n\tonData(chunk: Uint8Array): void;\n\tonClose(): void;\n\tonError(error: Error): void;\n}\n\nexport type RadiusRelayHostStatus =\n\t| { readonly status: \"not_authenticated\" }\n\t| { readonly status: \"connecting\" }\n\t| { readonly status: \"connected\" }\n\t| { readonly status: \"retrying\"; readonly error: string };\n\nexport interface RadiusRelayHostOptions {\n\treadonly serverId: ServerId;\n\treadonly server: Pick<Server, \"accept\">;\n\treadonly auth: RadiusRelayAuthResolver;\n\treadonly webSocketFactory?: RadiusRelayWebSocketFactory;\n\treadonly onStatus?: (status: RadiusRelayHostStatus) => void;\n}\n\n/** Maintain the experimental server's multiplexed, authenticated Radius host connection. */\nexport class RadiusRelayHost {\n\treadonly #options: RadiusRelayHostOptions;\n\treadonly #abortController = new AbortController();\n\treadonly #connections = new Map<\n\t\tstring,\n\t\t{ connection: RelayServerByteConnection; handler: RelayByteConnectionHandler }\n\t>();\n\t#socket: RadiusRelayWebSocket | undefined;\n\t#writer: OrderedWebSocketWriter | undefined;\n\t#loop: Promise<void> | undefined;\n\t#closed = false;\n\n\tconstructor(options: RadiusRelayHostOptions) {\n\t\tthis.#options = options;\n\t}\n\n\tstart(): void {\n\t\tif (this.#loop !== undefined) return;\n\t\tthis.#loop = this.#run();\n\t}\n\n\tasync close(): Promise<void> {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tthis.#abortController.abort();\n\t\tthis.#writer?.close();\n\t\tthis.#socket?.close(1000, \"Pi server stopped\");\n\t\tthis.#dropConnections();\n\t\tawait this.#loop;\n\t}\n\n\tasync #run(): Promise<void> {\n\t\tlet retryMs = HOST_RETRY_INITIAL_MS;\n\t\twhile (!this.#closed) {\n\t\t\ttry {\n\t\t\t\tconst auth = await this.#options.auth.resolve({\n\t\t\t\t\trequired: false,\n\t\t\t\t\tsignal: this.#abortController.signal,\n\t\t\t\t});\n\t\t\t\tif (auth === undefined) {\n\t\t\t\t\tthis.#options.onStatus?.({ status: \"not_authenticated\" });\n\t\t\t\t\tawait delay(MISSING_AUTH_RETRY_MS, this.#abortController.signal, true);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tthis.#options.onStatus?.({ status: \"connecting\" });\n\t\t\t\tconst socket = await openRadiusRelayWebSocket(\n\t\t\t\t\trelayWebSocketUrl(auth.gateway, this.#options.serverId),\n\t\t\t\t\tRADIUS_RELAY_HOST_SUBPROTOCOL,\n\t\t\t\t\tauth.token,\n\t\t\t\t\tthis.#options.webSocketFactory ?? defaultWebSocketFactory,\n\t\t\t\t\tthis.#abortController.signal,\n\t\t\t\t);\n\t\t\t\tretryMs = HOST_RETRY_INITIAL_MS;\n\t\t\t\tthis.#options.onStatus?.({ status: \"connected\" });\n\t\t\t\tawait this.#serve(socket);\n\t\t\t\tif (!this.#closed) throw new Error(\"Radius relay host disconnected\");\n\t\t\t} catch (error) {\n\t\t\t\tif (this.#closed || this.#abortController.signal.aborted) break;\n\t\t\t\tthis.#options.onStatus?.({ status: \"retrying\", error: errorMessage(error) });\n\t\t\t\ttry {\n\t\t\t\t\tawait delay(retryMs, this.#abortController.signal, true);\n\t\t\t\t} catch {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tretryMs = Math.min(retryMs * 2, HOST_RETRY_MAX_MS);\n\t\t\t}\n\t\t}\n\t}\n\n\t#serve(socket: RadiusRelayWebSocket): Promise<void> {\n\t\tthis.#socket = socket;\n\t\tthis.#writer = new OrderedWebSocketWriter(socket);\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\tlet terminal = false;\n\t\t\tconst cleanup = (): void => {\n\t\t\t\tsocket.removeEventListener(\"message\", onMessage);\n\t\t\t\tsocket.removeEventListener(\"close\", onClose);\n\t\t\t\tsocket.removeEventListener(\"error\", onError);\n\t\t\t\tthis.#writer?.close();\n\t\t\t\tif (this.#socket === socket) {\n\t\t\t\t\tthis.#socket = undefined;\n\t\t\t\t\tthis.#writer = undefined;\n\t\t\t\t}\n\t\t\t};\n\t\t\tconst finish = (error?: Error): void => {\n\t\t\t\tif (terminal) return;\n\t\t\t\tterminal = true;\n\t\t\t\tcleanup();\n\t\t\t\tthis.#dropConnections(error);\n\t\t\t\tif (error) reject(error);\n\t\t\t\telse resolve();\n\t\t\t};\n\t\t\tconst onMessage = (event: RadiusRelayMessageEvent): void => {\n\t\t\t\ttry {\n\t\t\t\t\tthis.#handleHostMessage(event.data);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcloseWebSocket(socket, LOCAL_PROTOCOL_ERROR_CLOSE_CODE, \"Radius relay protocol error\");\n\t\t\t\t\tfinish(toError(error));\n\t\t\t\t}\n\t\t\t};\n\t\t\tconst onClose = (event: RadiusRelayCloseEvent): void => {\n\t\t\t\tfinish(\n\t\t\t\t\tevent.code === 1000\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: new Error(`Radius relay host closed (${event.code}${event.reason ? `: ${event.reason}` : \"\"})`),\n\t\t\t\t);\n\t\t\t};\n\t\t\tconst onError = (event: RadiusRelayErrorEvent): void => finish(webSocketError(event));\n\t\t\tsocket.addEventListener(\"message\", onMessage);\n\t\t\tsocket.addEventListener(\"close\", onClose);\n\t\t\tsocket.addEventListener(\"error\", onError);\n\t\t});\n\t}\n\n\t#handleHostMessage(value: unknown): void {\n\t\tif (typeof value === \"string\") {\n\t\t\tconst control = parseHostControlMessage(value);\n\t\t\tswitch (control.type) {\n\t\t\t\tcase \"ping\":\n\t\t\t\t\tvoid this.#sendControl({ version: 1, type: \"pong\" }).catch(() => {\n\t\t\t\t\t\tif (this.#socket !== undefined) {\n\t\t\t\t\t\t\tcloseWebSocket(this.#socket, LOCAL_TRANSPORT_ERROR_CLOSE_CODE, \"Radius relay send failed\");\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\tcase \"pong\":\n\t\t\t\t\treturn;\n\t\t\t\tcase \"connection_open\":\n\t\t\t\t\tthis.#openConnection(control.connection_id);\n\t\t\t\t\treturn;\n\t\t\t\tcase \"connection_close\":\n\t\t\t\t\tthis.#remoteCloseConnection(control.connection_id);\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (!(value instanceof ArrayBuffer)) throw new Error(\"Radius relay data message must be binary\");\n\t\tconst frame = parseRelayDataFrame(value);\n\t\tif (!frame) throw new Error(\"Invalid Radius relay data frame\");\n\t\tconst active = this.#connections.get(frame.connectionId);\n\t\tif (!active) {\n\t\t\tvoid this.#sendControl({\n\t\t\t\tversion: 1,\n\t\t\t\ttype: \"connection_close\",\n\t\t\t\tconnection_id: frame.connectionId,\n\t\t\t\tcode: 1000,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tactive.handler.onData(new Uint8Array(frame.payload));\n\t}\n\n\t#openConnection(connectionId: string): void {\n\t\tif (this.#connections.has(connectionId)) throw new Error(\"Radius relay reused a connection ID\");\n\t\tconst connection = new RelayServerByteConnection(\n\t\t\t(chunk) => this.#sendData(connectionId, chunk),\n\t\t\t(finalChunk) => this.#serverCloseConnection(connectionId, finalChunk),\n\t\t);\n\t\tconst handler = this.#options.server.accept(connection);\n\t\tif (connection.closed) {\n\t\t\tvoid this.#sendControl({ version: 1, type: \"connection_close\", connection_id: connectionId, code: 1012 });\n\t\t} else {\n\t\t\tthis.#connections.set(connectionId, { connection, handler });\n\t\t}\n\t}\n\n\t#remoteCloseConnection(connectionId: string): void {\n\t\tconst active = this.#connections.get(connectionId);\n\t\tif (!active) return;\n\t\tthis.#connections.delete(connectionId);\n\t\tactive.connection.markClosed();\n\t\tactive.handler.onClose();\n\t}\n\n\tasync #serverCloseConnection(connectionId: string, finalChunk?: Uint8Array): Promise<void> {\n\t\tif (!this.#connections.delete(connectionId)) return;\n\t\tif (finalChunk !== undefined) await this.#requireWriter().send(encodeRelayDataFrame(connectionId, finalChunk));\n\t\tawait this.#sendControl({\n\t\t\tversion: 1,\n\t\t\ttype: \"connection_close\",\n\t\t\tconnection_id: connectionId,\n\t\t\tcode: 1000,\n\t\t});\n\t}\n\n\t#sendData(connectionId: string, chunk: Uint8Array): Promise<void> {\n\t\tif (!this.#connections.has(connectionId)) return Promise.reject(new Error(\"Radius relay connection is closed\"));\n\t\treturn this.#requireWriter().send(encodeRelayDataFrame(connectionId, chunk));\n\t}\n\n\t#sendControl(message: HostOutputControlMessage): Promise<void> {\n\t\treturn this.#requireWriter().send(JSON.stringify(message));\n\t}\n\n\t#requireWriter(): OrderedWebSocketWriter {\n\t\tif (!this.#writer) throw new Error(\"Radius relay host is disconnected\");\n\t\treturn this.#writer;\n\t}\n\n\t#dropConnections(error?: Error): void {\n\t\tconst connections = [...this.#connections.values()];\n\t\tthis.#connections.clear();\n\t\tfor (const active of connections) {\n\t\t\tactive.connection.markClosed();\n\t\t\tif (error) active.handler.onError(error);\n\t\t\telse active.handler.onClose();\n\t\t}\n\t}\n}\n\nexport function createRadiusClientTransportFactory(options: {\n\treadonly serverId: ServerId;\n\treadonly auth: RadiusRelayAuthResolver;\n\treadonly webSocketFactory?: RadiusRelayWebSocketFactory;\n}): ByteTransportFactory {\n\treturn async (handlers) => {\n\t\tconst auth = await options.auth.resolve({ required: true });\n\t\tif (!auth) throw new Error(\"Radius authentication is required\");\n\t\tconst socket = await openRadiusRelayWebSocket(\n\t\t\trelayWebSocketUrl(auth.gateway, options.serverId),\n\t\t\tRADIUS_RELAY_CLIENT_SUBPROTOCOL,\n\t\t\tauth.token,\n\t\t\toptions.webSocketFactory ?? defaultWebSocketFactory,\n\t\t);\n\t\treturn new RadiusClientByteTransport(socket, handlers);\n\t};\n}\n\ntype RadiusReconnectClient = Pick<\n\tClient,\n\t| \"attachment\"\n\t| \"connected\"\n\t| \"connectionState\"\n\t| \"disconnect\"\n\t| \"onAttachmentChange\"\n\t| \"onConnectionStateChange\"\n\t| \"reconnect\"\n>;\n\n/** Reconnect one established Radius client and restore its last selected Session. */\nexport class RadiusClientReconnect {\n\treadonly #client: RadiusReconnectClient;\n\treadonly #reattach: (sessionId: string) => Promise<void>;\n\treadonly #abortController = new AbortController();\n\treadonly #removeConnectionListener: () => void;\n\treadonly #removeAttachmentListener: () => void;\n\t#desiredSessionId: string | undefined;\n\t#reconnecting: Promise<void> | undefined;\n\t#disposed = false;\n\n\tconstructor(client: RadiusReconnectClient, reattach: (sessionId: string) => Promise<void>) {\n\t\tthis.#client = client;\n\t\tthis.#reattach = reattach;\n\t\tthis.#desiredSessionId = client.attachment?.sessionId;\n\t\tthis.#removeAttachmentListener = client.onAttachmentChange((attachment) => {\n\t\t\tif (attachment !== undefined) this.#desiredSessionId = attachment.sessionId;\n\t\t\telse if (client.connected) this.#desiredSessionId = undefined;\n\t\t});\n\t\tthis.#removeConnectionListener = client.onConnectionStateChange(({ state }) => {\n\t\t\tif (state === \"disconnected\" && !this.#disposed) this.#startReconnect();\n\t\t});\n\t}\n\n\tasync dispose(): Promise<void> {\n\t\tif (this.#disposed) return;\n\t\tthis.#disposed = true;\n\t\tthis.#removeConnectionListener();\n\t\tthis.#removeAttachmentListener();\n\t\tthis.#abortController.abort();\n\t\tif (this.#client.connectionState !== \"disconnected\") {\n\t\t\tthis.#client.disconnect(\"Radius reconnect stopped\");\n\t\t}\n\t\tawait this.#reconnecting;\n\t}\n\n\t#startReconnect(): void {\n\t\tif (this.#reconnecting !== undefined) return;\n\t\tthis.#reconnecting = this.#runReconnect().finally(() => {\n\t\t\tthis.#reconnecting = undefined;\n\t\t});\n\t}\n\n\tasync #runReconnect(): Promise<void> {\n\t\tlet retryMs = CLIENT_RETRY_INITIAL_MS;\n\t\twhile (!this.#disposed && !this.#client.connected) {\n\t\t\ttry {\n\t\t\t\tawait delay(retryMs, this.#abortController.signal, false);\n\t\t\t\tawait this.#client.reconnect();\n\t\t\t\tconst sessionId = this.#desiredSessionId;\n\t\t\t\tif (sessionId !== undefined) await this.#reattach(sessionId);\n\t\t\t\treturn;\n\t\t\t} catch (error) {\n\t\t\t\tif (this.#disposed || this.#abortController.signal.aborted) return;\n\t\t\t\tif (this.#client.connected) this.#client.disconnect(errorMessage(error));\n\t\t\t\tretryMs = Math.min(retryMs * 2, CLIENT_RETRY_MAX_MS);\n\t\t\t}\n\t\t}\n\t}\n}\n\nclass RelayServerByteConnection implements RelayByteConnection {\n\treadonly #sendChunk: (chunk: Uint8Array) => Promise<void>;\n\treadonly #closeConnection: (finalChunk?: Uint8Array) => Promise<void>;\n\t#closed = false;\n\n\tconstructor(\n\t\tsendChunk: (chunk: Uint8Array) => Promise<void>,\n\t\tcloseConnection: (finalChunk?: Uint8Array) => Promise<void>,\n\t) {\n\t\tthis.#sendChunk = sendChunk;\n\t\tthis.#closeConnection = closeConnection;\n\t}\n\n\tget closed(): boolean {\n\t\treturn this.#closed;\n\t}\n\n\tsend(chunk: Uint8Array): Promise<void> {\n\t\tif (this.#closed) return Promise.reject(new Error(\"Radius relay connection is closed\"));\n\t\treturn this.#sendChunk(chunk);\n\t}\n\n\tasync close(finalChunk?: Uint8Array): Promise<void> {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tawait this.#closeConnection(finalChunk);\n\t}\n\n\tmarkClosed(): void {\n\t\tthis.#closed = true;\n\t}\n}\n\nclass RadiusClientByteTransport implements ByteTransport {\n\treadonly #socket: RadiusRelayWebSocket;\n\treadonly #handlers: ByteTransportHandlers;\n\treadonly #writer: OrderedWebSocketWriter;\n\treadonly #onMessage: (event: RadiusRelayMessageEvent) => void;\n\treadonly #onClose: (event: RadiusRelayCloseEvent) => void;\n\treadonly #onError: (event: RadiusRelayErrorEvent) => void;\n\t#closed = false;\n\n\tconstructor(socket: RadiusRelayWebSocket, handlers: ByteTransportHandlers) {\n\t\tthis.#socket = socket;\n\t\tthis.#handlers = handlers;\n\t\tthis.#writer = new OrderedWebSocketWriter(socket);\n\t\tthis.#onMessage = (event) => {\n\t\t\tif (this.#closed) return;\n\t\t\tif (!(event.data instanceof ArrayBuffer)) {\n\t\t\t\tthis.#fail(new Error(\"Radius relay client received a non-binary message\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.#handlers.onData(new Uint8Array(event.data));\n\t\t};\n\t\tthis.#onClose = () => {\n\t\t\tif (this.#markClosed()) this.#handlers.onClose();\n\t\t};\n\t\tthis.#onError = (event) => this.#fail(webSocketError(event));\n\t\tsocket.addEventListener(\"message\", this.#onMessage);\n\t\tsocket.addEventListener(\"close\", this.#onClose);\n\t\tsocket.addEventListener(\"error\", this.#onError);\n\t}\n\n\tsend(chunk: Uint8Array): Promise<void> {\n\t\tif (!(chunk instanceof Uint8Array))\n\t\t\treturn Promise.reject(new TypeError(\"Radius relay chunks must be Uint8Array\"));\n\t\tif (this.#closed) return Promise.reject(new Error(\"Radius relay client is closed\"));\n\t\treturn this.#writer.send(chunk.slice().buffer);\n\t}\n\n\tclose(): void {\n\t\tif (!this.#markClosed()) return;\n\t\tthis.#socket.close(1000, \"Pi client closed\");\n\t}\n\n\t#fail(error: Error): void {\n\t\tif (!this.#markClosed()) return;\n\t\tcloseWebSocket(this.#socket, LOCAL_TRANSPORT_ERROR_CLOSE_CODE, \"Radius relay transport error\");\n\t\tthis.#handlers.onError(error);\n\t}\n\n\t#markClosed(): boolean {\n\t\tif (this.#closed) return false;\n\t\tthis.#closed = true;\n\t\tthis.#writer.close();\n\t\tthis.#socket.removeEventListener(\"message\", this.#onMessage);\n\t\tthis.#socket.removeEventListener(\"close\", this.#onClose);\n\t\tthis.#socket.removeEventListener(\"error\", this.#onError);\n\t\treturn true;\n\t}\n}\n\nclass OrderedWebSocketWriter {\n\treadonly #socket: RadiusRelayWebSocket;\n\t#tail: Promise<void> = Promise.resolve();\n\t#pendingBytes = 0;\n\t#closed = false;\n\n\tconstructor(socket: RadiusRelayWebSocket) {\n\t\tthis.#socket = socket;\n\t}\n\n\tsend(value: string | ArrayBuffer): Promise<void> {\n\t\tif (this.#closed) return Promise.reject(new Error(\"Radius relay WebSocket is closed\"));\n\t\tconst copied = typeof value === \"string\" ? value : value.slice(0);\n\t\tconst byteLength = typeof copied === \"string\" ? Buffer.byteLength(copied) : copied.byteLength;\n\t\tif (this.#pendingBytes + byteLength > MAX_PENDING_BYTES) {\n\t\t\treturn Promise.reject(new Error(\"Radius relay exceeded its pending byte limit\"));\n\t\t}\n\t\tthis.#pendingBytes += byteLength;\n\t\tconst operation = this.#tail.then(async () => {\n\t\t\tif (this.#closed || this.#socket.readyState !== this.#socket.OPEN) {\n\t\t\t\tthrow new Error(\"Radius relay WebSocket is closed\");\n\t\t\t}\n\t\t\tthis.#socket.send(copied);\n\t\t\twhile (this.#socket.bufferedAmount > DRAIN_THRESHOLD_BYTES) {\n\t\t\t\tif (this.#closed || this.#socket.readyState !== this.#socket.OPEN) {\n\t\t\t\t\tthrow new Error(\"Radius relay WebSocket closed during write\");\n\t\t\t\t}\n\t\t\t\tawait delay(5, undefined, false);\n\t\t\t}\n\t\t});\n\t\tconst tracked = operation.finally(() => {\n\t\t\tthis.#pendingBytes -= byteLength;\n\t\t});\n\t\tthis.#tail = tracked.catch(() => {});\n\t\treturn tracked;\n\t}\n\n\tclose(): void {\n\t\tthis.#closed = true;\n\t}\n}\n\ntype HostInputControlMessage =\n\t| { readonly version: 1; readonly type: \"ping\" | \"pong\" }\n\t| { readonly version: 1; readonly type: \"connection_open\"; readonly connection_id: string }\n\t| {\n\t\t\treadonly version: 1;\n\t\t\treadonly type: \"connection_close\";\n\t\t\treadonly connection_id: string;\n\t\t\treadonly code?: number;\n\t };\n\ntype HostOutputControlMessage =\n\t| { readonly version: 1; readonly type: \"pong\" }\n\t| {\n\t\t\treadonly version: 1;\n\t\t\treadonly type: \"connection_close\";\n\t\t\treadonly connection_id: string;\n\t\t\treadonly code?: number;\n\t };\n\nfunction parseHostControlMessage(value: string): HostInputControlMessage {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(value);\n\t} catch {\n\t\tthrow new Error(\"Invalid Radius relay control message\");\n\t}\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tthrow new Error(\"Invalid Radius relay control message\");\n\t}\n\tconst message = parsed as { version?: unknown; type?: unknown; connection_id?: unknown; code?: unknown };\n\tif (message.version !== 1) throw new Error(\"Unsupported Radius relay control version\");\n\tif (message.type === \"ping\" || message.type === \"pong\") return { version: 1, type: message.type };\n\tif (\n\t\t(message.type === \"connection_open\" || message.type === \"connection_close\") &&\n\t\ttypeof message.connection_id === \"string\" &&\n\t\tCONNECTION_ID_PATTERN.test(message.connection_id) &&\n\t\t(message.code === undefined ||\n\t\t\t(typeof message.code === \"number\" &&\n\t\t\t\tNumber.isInteger(message.code) &&\n\t\t\t\tmessage.code >= 1000 &&\n\t\t\t\tmessage.code <= 4999))\n\t) {\n\t\treturn message.type === \"connection_open\"\n\t\t\t? { version: 1, type: \"connection_open\", connection_id: message.connection_id }\n\t\t\t: {\n\t\t\t\t\tversion: 1,\n\t\t\t\t\ttype: \"connection_close\",\n\t\t\t\t\tconnection_id: message.connection_id,\n\t\t\t\t\t...(message.code === undefined ? {} : { code: message.code }),\n\t\t\t\t};\n\t}\n\tthrow new Error(\"Invalid Radius relay control message\");\n}\n\nexport function encodeRelayDataFrame(connectionId: string, payload: Uint8Array): ArrayBuffer {\n\tif (!CONNECTION_ID_PATTERN.test(connectionId)) throw new TypeError(\"Invalid Radius relay connection ID\");\n\tconst frame = new Uint8Array(RELAY_DATA_HEADER_BYTES + payload.byteLength);\n\tframe[0] = RELAY_DATA_FRAME_VERSION;\n\tframe[1] = RELAY_DATA_FRAME_TYPE;\n\tconst hex = connectionId.replaceAll(\"-\", \"\");\n\tfor (let index = 0; index < 16; index++) {\n\t\tframe[index + 2] = Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16);\n\t}\n\tframe.set(payload, RELAY_DATA_HEADER_BYTES);\n\treturn frame.buffer;\n}\n\nexport function parseRelayDataFrame(\n\tframe: ArrayBuffer,\n): { readonly connectionId: string; readonly payload: ArrayBuffer } | undefined {\n\tif (frame.byteLength < RELAY_DATA_HEADER_BYTES) return undefined;\n\tconst bytes = new Uint8Array(frame);\n\tif (bytes[0] !== RELAY_DATA_FRAME_VERSION || bytes[1] !== RELAY_DATA_FRAME_TYPE) return undefined;\n\tlet hex = \"\";\n\tfor (const byte of bytes.subarray(2, RELAY_DATA_HEADER_BYTES)) hex += byte.toString(16).padStart(2, \"0\");\n\tconst connectionId = `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n\tif (!CONNECTION_ID_PATTERN.test(connectionId)) return undefined;\n\treturn { connectionId, payload: frame.slice(RELAY_DATA_HEADER_BYTES) };\n}\n\nfunction relayWebSocketUrl(gateway: string, serverId: ServerId): string {\n\tconst url = new URL(`/v1/session-relays/${serverId}/connect`, gateway);\n\tif (url.protocol === \"https:\") url.protocol = \"wss:\";\n\telse if (url.protocol === \"http:\") url.protocol = \"ws:\";\n\telse throw new Error(`Unsupported Radius gateway protocol: ${url.protocol}`);\n\treturn url.toString();\n}\n\nfunction defaultWebSocketFactory(options: {\n\treadonly url: string;\n\treadonly protocol: string;\n\treadonly authorization: string;\n}): RadiusRelayWebSocket {\n\treturn new WebSocket(options.url, {\n\t\tprotocols: [options.protocol],\n\t\theaders: { authorization: options.authorization },\n\t}) as unknown as RadiusRelayWebSocket;\n}\n\nfunction openRadiusRelayWebSocket(\n\turl: string,\n\tprotocol: string,\n\ttoken: string,\n\tfactory: RadiusRelayWebSocketFactory,\n\tsignal?: AbortSignal,\n): Promise<RadiusRelayWebSocket> {\n\tsignal?.throwIfAborted();\n\treturn new Promise((resolve, reject) => {\n\t\tconst socket = factory({ url, protocol, authorization: `Bearer ${token}` });\n\t\tsocket.binaryType = \"arraybuffer\";\n\t\tlet settled = false;\n\t\tconst cleanup = (): void => {\n\t\t\tsocket.removeEventListener(\"open\", onOpen);\n\t\t\tsocket.removeEventListener(\"close\", onClose);\n\t\t\tsocket.removeEventListener(\"error\", onError);\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t};\n\t\tconst fail = (error: Error): void => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tcleanup();\n\t\t\tcloseWebSocket(socket, 1000, \"Radius relay connection failed\");\n\t\t\treject(error);\n\t\t};\n\t\tconst onOpen = (): void => {\n\t\t\tif (settled) return;\n\t\t\tif (socket.protocol !== protocol) {\n\t\t\t\tfail(new Error(`Radius relay selected unexpected WebSocket protocol ${JSON.stringify(socket.protocol)}`));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsettled = true;\n\t\t\tcleanup();\n\t\t\tresolve(socket);\n\t\t};\n\t\tconst onClose = (event: RadiusRelayCloseEvent): void =>\n\t\t\tfail(new Error(`Radius relay closed before connecting (${event.code})`));\n\t\tconst onError = (event: RadiusRelayErrorEvent): void => fail(webSocketError(event));\n\t\tconst onAbort = (): void => fail(new Error(\"Radius relay connection cancelled\"));\n\t\tsocket.addEventListener(\"open\", onOpen, { once: true });\n\t\tsocket.addEventListener(\"close\", onClose, { once: true });\n\t\tsocket.addEventListener(\"error\", onError, { once: true });\n\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t});\n}\n\nfunction closeWebSocket(socket: RadiusRelayWebSocket, code: number, reason: string): void {\n\ttry {\n\t\tsocket.close(code, reason);\n\t} catch {\n\t\t// A WebSocket can reject close() while its opening handshake is still pending.\n\t}\n}\n\nfunction webSocketError(event: RadiusRelayErrorEvent): Error {\n\tif (event.error instanceof Error && event.error.message.trim().length > 0) return event.error;\n\treturn new Error(event.message?.trim() || \"Radius WebSocket connection failed\");\n}\n\nfunction delay(milliseconds: number, signal: AbortSignal | undefined, unref: boolean): Promise<void> {\n\tsignal?.throwIfAborted();\n\treturn new Promise((resolve, reject) => {\n\t\tconst timer = setTimeout(() => {\n\t\t\tcleanup();\n\t\t\tresolve();\n\t\t}, milliseconds);\n\t\tif (unref) timer.unref();\n\t\tconst onAbort = (): void => {\n\t\t\tclearTimeout(timer);\n\t\t\tcleanup();\n\t\t\ttry {\n\t\t\t\tsignal?.throwIfAborted();\n\t\t\t} catch (error) {\n\t\t\t\treject(error);\n\t\t\t}\n\t\t};\n\t\tconst cleanup = (): void => signal?.removeEventListener(\"abort\", onAbort);\n\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\t});\n}\n\nfunction toError(error: unknown): Error {\n\treturn error instanceof Error ? error : new Error(String(error));\n}\n\nfunction errorMessage(error: unknown): string {\n\treturn toError(error).message;\n}\n"]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Client } from "@earendil-works/pi-client";
|
|
2
|
+
import { type UnixServerRoute } from "@earendil-works/pi-client/unix";
|
|
3
|
+
import { type ServerId } from "@earendil-works/pi-protocol";
|
|
4
|
+
import { type Server } from "@earendil-works/pi-server";
|
|
5
|
+
import type { AuthInput } from "../cli/experimental/command-options.ts";
|
|
6
|
+
import { type RadiusRelayHostStatus } from "./radius-relay.ts";
|
|
7
|
+
export declare const ENV_SERVER_DIR = "PI_SERVER_DIR";
|
|
8
|
+
export declare const ENV_SERVER_ID = "PI_SERVER_ID";
|
|
9
|
+
export declare function resolveServerDirectory(directory?: string): string;
|
|
10
|
+
export declare function ensurePrivateServerDirectory(directory: string): Promise<void>;
|
|
11
|
+
export declare function resolveSessionDirectory(sessionDir?: string): string;
|
|
12
|
+
export interface ServerProfile {
|
|
13
|
+
readonly serverId: ServerId;
|
|
14
|
+
release(): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
/** Lock one logical server ID in a shared experimental server directory. */
|
|
17
|
+
export declare function acquireServerProfile(directory: string, requestedServerId?: string): Promise<ServerProfile>;
|
|
18
|
+
export interface ActivatedServer {
|
|
19
|
+
readonly client: Client;
|
|
20
|
+
readonly route: UnixServerRoute;
|
|
21
|
+
}
|
|
22
|
+
export interface ActivateServerOptions {
|
|
23
|
+
readonly directory: string;
|
|
24
|
+
readonly requestedServerId?: ServerId | string;
|
|
25
|
+
readonly sessionDir: string;
|
|
26
|
+
readonly provider?: string;
|
|
27
|
+
readonly model?: string;
|
|
28
|
+
}
|
|
29
|
+
/** Ensure the selected logical server is reachable, launching the current Pi installation if needed. */
|
|
30
|
+
export declare function activateServer(options: ActivateServerOptions): Promise<ActivatedServer>;
|
|
31
|
+
export declare function acquireServerActivation(directory: string, serverId: ServerId): Promise<() => Promise<void>>;
|
|
32
|
+
/** Reconcile operator, startup, client, and worker holds for one server generation. */
|
|
33
|
+
export declare class ServerLifetime {
|
|
34
|
+
#private;
|
|
35
|
+
constructor(keepAlive: boolean);
|
|
36
|
+
start(retire: () => void): void;
|
|
37
|
+
setConnectionCount(count: number): void;
|
|
38
|
+
setWorkerCount(count: number): void;
|
|
39
|
+
stop(): void;
|
|
40
|
+
}
|
|
41
|
+
export interface RunningServer {
|
|
42
|
+
readonly serverId: string;
|
|
43
|
+
readonly sessionDir: string;
|
|
44
|
+
readonly socketPath: string;
|
|
45
|
+
readonly server: Server;
|
|
46
|
+
readonly workerPids: ReadonlyMap<string, number>;
|
|
47
|
+
readonly closed: Promise<void>;
|
|
48
|
+
close(): Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
export interface StartServerOptions {
|
|
51
|
+
/** Server profile and socket directory. Defaults to PI_SERVER_DIR or ~/.pi/server. */
|
|
52
|
+
readonly directory?: string;
|
|
53
|
+
/** Logical service ID. Defaults to PI_SERVER_ID or the directory's default-server-id. */
|
|
54
|
+
readonly serverId?: ServerId;
|
|
55
|
+
/** Durable session directory. Defaults to the experimental directory under the configured agent directory. */
|
|
56
|
+
readonly sessionDir?: string;
|
|
57
|
+
/** Optional provider for an explicitly selected Session worker model. */
|
|
58
|
+
readonly provider?: string;
|
|
59
|
+
/** Optional model override for newly started Session workers. */
|
|
60
|
+
readonly model?: string;
|
|
61
|
+
/** Hold the server open without client or Session demand. Defaults to true for foreground servers. */
|
|
62
|
+
readonly keepAlive?: boolean;
|
|
63
|
+
/** Optional explicit Radius credential. Stored Radius auth is used when omitted. */
|
|
64
|
+
readonly relayAuth?: AuthInput;
|
|
65
|
+
/** Explicit plugin packages. Undefined restores the logical server profile; an empty list clears it. */
|
|
66
|
+
readonly pluginPackages?: readonly string[];
|
|
67
|
+
readonly onRelayStatus?: (status: RadiusRelayHostStatus) => void;
|
|
68
|
+
}
|
|
69
|
+
/** Start a replaceable experimental server behind the stable coordinator endpoint. */
|
|
70
|
+
export declare function startServer(options?: StartServerOptions): Promise<RunningServer>;
|
|
71
|
+
/** Start an operator-held server while serializing against automatic cold activation. */
|
|
72
|
+
export declare function startForegroundServer(options?: Omit<StartServerOptions, "keepAlive">): Promise<RunningServer>;
|
|
73
|
+
/** Run an automatically activated server until its client and Session demand disappears. */
|
|
74
|
+
export declare function runServerProcess(args: readonly string[]): Promise<void>;
|
|
75
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/experimental/server.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { chmod, lstat, mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { isAbsolute, join } from \"node:path\";\nimport type { Context } from \"@earendil-works/chord\";\nimport type { FacetBundleArtifact } from \"@earendil-works/chord/node\";\nimport {\n\tBACKGROUND_CONTEXT,\n\ttype JsonlSessionMetadata,\n\tJsonlSessionRepo,\n\tTODO_CONTEXT,\n} from \"@earendil-works/pi-agent-core\";\nimport { NodeExecutionEnv } from \"@earendil-works/pi-agent-core/node\";\nimport { Client, ServerError as ClientServerError, DisconnectedError } from \"@earendil-works/pi-client\";\nimport { createUnixTransportFactory, type UnixServerRoute } from \"@earendil-works/pi-client/unix\";\nimport { isServerId, type ServerId } from \"@earendil-works/pi-protocol\";\nimport {\n\tServerError as RoutedServerError,\n\ttype Server,\n\ttype ServerHost,\n\tSessionAmbiguousError,\n\tSessionNotFoundError,\n} from \"@earendil-works/pi-server\";\nimport { createUnixServer, getUnixSocketPath } from \"@earendil-works/pi-server/unix\";\nimport lockfile from \"proper-lockfile\";\nimport type { AuthInput } from \"../cli/experimental/command-options.ts\";\nimport { getAgentDir } from \"../config.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { CoordinatorConnection, type CoordinatorStartupLease, ensureCoordinator } from \"./coordinator.ts\";\nimport { createPresentationFacetData } from \"./plugins/bundled.ts\";\nimport {\n\tcreateServerPluginPackage,\n\tnormalizePluginPackagePaths,\n\treadSessionPluginPackageProfile,\n\tremoveSessionPluginPackageProfile,\n\trestoreServerPluginPackageProfile,\n\twriteSessionPluginPackageProfile,\n} from \"./plugins/package.ts\";\nimport {\n\tconsumeInternalProcessRole,\n\tisDirectInternalProcessEntry,\n\tspawnInternalProcess,\n\tterminateInternalProcess,\n} from \"./process.ts\";\nimport { RadiusRelayAuthResolver } from \"./radius-auth.ts\";\nimport { RadiusRelayHost, type RadiusRelayHostStatus } from \"./radius-relay.ts\";\nimport { createExperimentalServerServices } from \"./services/server.ts\";\nimport type { SessionCreateOptions, SessionSummary } from \"./services/sessions.ts\";\nimport { SessionPluginSelectionConflictError, SessionWorkerManager } from \"./session-worker-manager.ts\";\n\nexport const ENV_SERVER_DIR = \"PI_SERVER_DIR\";\nexport const ENV_SERVER_ID = \"PI_SERVER_ID\";\n\nexport function resolveServerDirectory(directory?: string): string {\n\treturn resolvePath(directory ?? process.env[ENV_SERVER_DIR] ?? join(homedir(), \".pi\", \"server\"));\n}\n\nexport async function ensurePrivateServerDirectory(directory: string): Promise<void> {\n\tif (typeof process.getuid !== \"function\") throw new Error(\"Unix socket directory requires a POSIX user ID\");\n\tawait mkdir(directory, { recursive: true, mode: 0o700 });\n\tconst stats = await lstat(directory);\n\tif (!stats.isDirectory()) throw new Error(`Unix socket directory is not a directory: ${directory}`);\n\tif (stats.uid !== process.getuid()) {\n\t\tthrow new Error(`Unix socket directory is not owned by the current user: ${directory}`);\n\t}\n\tawait chmod(directory, 0o700);\n}\n\nexport function resolveSessionDirectory(sessionDir?: string): string {\n\treturn resolvePath(sessionDir ?? join(getAgentDir(), \"experimental\", \"sessions\"));\n}\n\nconst LOCK_STALE_MS = 30_000;\nconst LOCK_RETRY_MS = 25;\nconst LOCK_WAIT_MS = 30_000;\nconst DEFAULT_SERVER_ID_FILE = \"default-server-id\";\n\nexport interface ServerProfile {\n\treadonly serverId: ServerId;\n\trelease(): Promise<void>;\n}\n\n/** Lock one logical server ID in a shared experimental server directory. */\nexport async function acquireServerProfile(directory: string, requestedServerId?: string): Promise<ServerProfile> {\n\tawait mkdir(directory, { recursive: true, mode: 0o700 });\n\tlet serverId: ServerId;\n\tif (requestedServerId !== undefined) {\n\t\tif (!isServerId(requestedServerId)) throw new Error(`Invalid experimental server ID: ${requestedServerId}`);\n\t\tserverId = requestedServerId;\n\t} else {\n\t\tconst path = join(directory, DEFAULT_SERVER_ID_FILE);\n\t\ttry {\n\t\t\tconst value = (await readFile(path, \"utf8\")).trim();\n\t\t\tif (!isServerId(value)) throw new Error(`Invalid default experimental server identity in ${path}`);\n\t\t\tserverId = value;\n\t\t} catch (error) {\n\t\t\tconst code = error instanceof Error && \"code\" in error ? error.code : undefined;\n\t\t\tif (code !== \"ENOENT\") throw error;\n\t\t\tconst candidate = randomUUID();\n\t\t\ttry {\n\t\t\t\tawait writeFile(path, candidate, { encoding: \"utf8\", mode: 0o600, flag: \"wx\" });\n\t\t\t\tserverId = candidate;\n\t\t\t} catch (writeError) {\n\t\t\t\tconst writeCode = writeError instanceof Error && \"code\" in writeError ? writeError.code : undefined;\n\t\t\t\tif (writeCode !== \"EEXIST\") throw writeError;\n\t\t\t\tconst value = (await readFile(path, \"utf8\")).trim();\n\t\t\t\tif (!isServerId(value)) throw new Error(`Invalid default experimental server identity in ${path}`);\n\t\t\t\tserverId = value;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst release = await lockfile.lock(join(directory, `launcher-${serverId}`), {\n\t\trealpath: false,\n\t\tstale: LOCK_STALE_MS,\n\t\tupdate: LOCK_STALE_MS / 3,\n\t\tretries: {\n\t\t\tretries: Math.ceil(LOCK_WAIT_MS / LOCK_RETRY_MS),\n\t\t\tfactor: 1,\n\t\t\tminTimeout: LOCK_RETRY_MS,\n\t\t\tmaxTimeout: LOCK_RETRY_MS,\n\t\t\tmaxRetryTime: LOCK_WAIT_MS,\n\t\t},\n\t});\n\treturn { serverId, release };\n}\n\nconst ACTIVATION_TIMEOUT_MS = 10_000;\nconst ACTIVATION_RETRY_MS = 10;\n\nexport interface ActivatedServer {\n\treadonly client: Client;\n\treadonly route: UnixServerRoute;\n}\n\nexport interface ActivateServerOptions {\n\treadonly directory: string;\n\treadonly requestedServerId?: ServerId | string;\n\treadonly sessionDir: string;\n\treadonly provider?: string;\n\treadonly model?: string;\n}\n\n/** Ensure the selected logical server is reachable, launching the current Pi installation if needed. */\nexport async function activateServer(options: ActivateServerOptions): Promise<ActivatedServer> {\n\tif (options.provider !== undefined && options.model === undefined) {\n\t\tthrow new Error(\"Server model provider requires a model\");\n\t}\n\tawait ensurePrivateServerDirectory(options.directory);\n\tconst profile = await acquireServerProfile(options.directory, options.requestedServerId);\n\tconst serverId = profile.serverId;\n\tawait profile.release();\n\tconst route = { serverId, path: getUnixSocketPath(serverId, options.directory) };\n\tconst release = await acquireServerActivation(options.directory, serverId);\n\ttry {\n\t\tconst existing = await connect(route);\n\t\tif (existing) {\n\t\t\t// Another activator won the race, so startup-only selections can no longer be applied.\n\t\t\tif (options.model !== undefined) {\n\t\t\t\tawait existing.dispose();\n\t\t\t\tthrow new Error(\"Model selection is only valid when automatically activating a new server\");\n\t\t\t}\n\t\t\treturn { client: existing, route };\n\t\t}\n\t\tconst modelArgs =\n\t\t\toptions.model === undefined\n\t\t\t\t? []\n\t\t\t\t: [\n\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\t...(options.provider === undefined ? {} : { provider: options.provider }),\n\t\t\t\t\t\t\tmodel: options.model,\n\t\t\t\t\t\t}),\n\t\t\t\t\t];\n\t\tconst child = spawnInternalProcess(\"server\", [options.directory, serverId, options.sessionDir, ...modelArgs]);\n\t\tlet spawnError: Error | undefined;\n\t\tchild.once(\"error\", (error) => {\n\t\t\tspawnError = error;\n\t\t});\n\t\ttry {\n\t\t\tconst deadline = Date.now() + ACTIVATION_TIMEOUT_MS;\n\t\t\twhile (true) {\n\t\t\t\tconst client = await connect(route);\n\t\t\t\tif (client) return { client, route };\n\t\t\t\tif (spawnError) throw new Error(\"Failed to automatically activate server\", { cause: spawnError });\n\t\t\t\tif (child.exitCode !== null || child.signalCode !== null) {\n\t\t\t\t\tthrow new Error(\"Automatically activated server exited during startup\");\n\t\t\t\t}\n\t\t\t\tif (Date.now() >= deadline) throw new Error(\"Timed out waiting for automatically activated server\");\n\t\t\t\tawait new Promise<void>((resolve) => setTimeout(resolve, ACTIVATION_RETRY_MS));\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait terminateInternalProcess(child);\n\t\t\tthrow error;\n\t\t}\n\t} finally {\n\t\tawait release();\n\t}\n}\n\nexport function acquireServerActivation(directory: string, serverId: ServerId): Promise<() => Promise<void>> {\n\treturn lockfile.lock(join(directory, `activation-${serverId}`), {\n\t\trealpath: false,\n\t\tstale: ACTIVATION_TIMEOUT_MS * 2,\n\t\tupdate: ACTIVATION_TIMEOUT_MS,\n\t\tretries: {\n\t\t\tretries: Math.ceil(ACTIVATION_TIMEOUT_MS / 25),\n\t\t\tfactor: 1,\n\t\t\tminTimeout: 25,\n\t\t\tmaxTimeout: 25,\n\t\t\tmaxRetryTime: ACTIVATION_TIMEOUT_MS,\n\t\t},\n\t});\n}\n\nasync function connect(route: UnixServerRoute): Promise<Client | undefined> {\n\tconst client = new Client({\n\t\tserverId: route.serverId,\n\t\ttransportFactory: createUnixTransportFactory({ path: route.path }),\n\t});\n\ttry {\n\t\tawait client.connect();\n\t\treturn client;\n\t} catch (error) {\n\t\tawait client.dispose();\n\t\tif (error instanceof DisconnectedError || (error instanceof ClientServerError && error.code === \"version\")) {\n\t\t\treturn undefined;\n\t\t}\n\t\tlet current = error;\n\t\tconst seen = new Set<unknown>();\n\t\twhile (current instanceof Error && !seen.has(current)) {\n\t\t\tseen.add(current);\n\t\t\tif (\n\t\t\t\t\"code\" in current &&\n\t\t\t\t[\"ENOENT\", \"ECONNREFUSED\", \"ECONNRESET\", \"EPIPE\", \"ETIMEDOUT\"].includes(String(current.code))\n\t\t\t) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tcurrent = current.cause;\n\t\t}\n\t\tthrow error;\n\t}\n}\n\nconst AUTO_SERVER_STARTUP_GRACE_MS = 10_000;\nconst AUTO_SERVER_IDLE_GRACE_MS = 1_000;\n\n/** Reconcile operator, startup, client, and worker holds for one server generation. */\nexport class ServerLifetime {\n\treadonly #keepAlive: boolean;\n\t#connectionCount = 0;\n\t#workerCount = 0;\n\t#startupHeld: boolean;\n\t#startupTimer: NodeJS.Timeout | undefined;\n\t#retirementTimer: NodeJS.Timeout | undefined;\n\t#retire: (() => void) | undefined;\n\t#stopped = false;\n\n\tconstructor(keepAlive: boolean) {\n\t\tthis.#keepAlive = keepAlive;\n\t\tthis.#startupHeld = !keepAlive;\n\t}\n\n\tstart(retire: () => void): void {\n\t\tthis.#retire = retire;\n\t\tif (this.#startupHeld) {\n\t\t\tthis.#startupTimer = setTimeout(() => {\n\t\t\t\tthis.#startupTimer = undefined;\n\t\t\t\tthis.#startupHeld = false;\n\t\t\t\tthis.#reconcile();\n\t\t\t}, AUTO_SERVER_STARTUP_GRACE_MS);\n\t\t\tthis.#startupTimer.unref();\n\t\t}\n\t\tthis.#reconcile();\n\t}\n\n\tsetConnectionCount(count: number): void {\n\t\tthis.#connectionCount = count;\n\t\tif (count > 0 && this.#startupHeld) {\n\t\t\tthis.#startupHeld = false;\n\t\t\tif (this.#startupTimer) clearTimeout(this.#startupTimer);\n\t\t\tthis.#startupTimer = undefined;\n\t\t}\n\t\tthis.#reconcile();\n\t}\n\n\tsetWorkerCount(count: number): void {\n\t\tthis.#workerCount = count;\n\t\tthis.#reconcile();\n\t}\n\n\tstop(): void {\n\t\tthis.#stopped = true;\n\t\tif (this.#startupTimer) clearTimeout(this.#startupTimer);\n\t\tif (this.#retirementTimer) clearTimeout(this.#retirementTimer);\n\t\tthis.#startupTimer = undefined;\n\t\tthis.#retirementTimer = undefined;\n\t}\n\n\t#reconcile(): void {\n\t\tif (\n\t\t\tthis.#stopped ||\n\t\t\tthis.#keepAlive ||\n\t\t\tthis.#startupHeld ||\n\t\t\tthis.#connectionCount !== 0 ||\n\t\t\tthis.#workerCount !== 0\n\t\t) {\n\t\t\tif (this.#retirementTimer) clearTimeout(this.#retirementTimer);\n\t\t\tthis.#retirementTimer = undefined;\n\t\t\treturn;\n\t\t}\n\t\tconst retire = this.#retire;\n\t\tif (this.#retirementTimer || !retire) return;\n\t\tthis.#retirementTimer = setTimeout(() => {\n\t\t\tthis.#retirementTimer = undefined;\n\t\t\tif (!this.#stopped && !this.#startupHeld && this.#connectionCount === 0 && this.#workerCount === 0) {\n\t\t\t\tretire();\n\t\t\t}\n\t\t}, AUTO_SERVER_IDLE_GRACE_MS);\n\t\tthis.#retirementTimer.unref();\n\t}\n}\n\nexport interface RunningServer {\n\treadonly serverId: string;\n\treadonly sessionDir: string;\n\treadonly socketPath: string;\n\treadonly server: Server;\n\treadonly workerPids: ReadonlyMap<string, number>;\n\treadonly closed: Promise<void>;\n\tclose(): Promise<void>;\n}\n\nexport interface StartServerOptions {\n\t/** Server profile and socket directory. Defaults to PI_SERVER_DIR or ~/.pi/server. */\n\treadonly directory?: string;\n\t/** Logical service ID. Defaults to PI_SERVER_ID or the directory's default-server-id. */\n\treadonly serverId?: ServerId;\n\t/** Durable session directory. Defaults to the experimental directory under the configured agent directory. */\n\treadonly sessionDir?: string;\n\t/** Optional provider for an explicitly selected Session worker model. */\n\treadonly provider?: string;\n\t/** Optional model override for newly started Session workers. */\n\treadonly model?: string;\n\t/** Hold the server open without client or Session demand. Defaults to true for foreground servers. */\n\treadonly keepAlive?: boolean;\n\t/** Optional explicit Radius credential. Stored Radius auth is used when omitted. */\n\treadonly relayAuth?: AuthInput;\n\t/** Explicit plugin packages. Undefined restores the logical server profile; an empty list clears it. */\n\treadonly pluginPackages?: readonly string[];\n\treadonly onRelayStatus?: (status: RadiusRelayHostStatus) => void;\n}\n\ninterface ResolvedSessionPlugins {\n\treadonly packagePaths: readonly string[];\n\treadonly manifestPaths: readonly string[];\n\treadonly presentationArtifacts: readonly FacetBundleArtifact[];\n}\n\ninterface StartServerBackendOptions {\n\treadonly path: string;\n\treadonly serverId: ServerId;\n\treadonly sessionDir?: string;\n\tresolveSessionPlugins(\n\t\tmetadata: JsonlSessionMetadata,\n\t\tpackagePaths: readonly string[] | undefined,\n\t\tcontext: Context,\n\t): Promise<ResolvedSessionPlugins>;\n\tremoveSessionPlugins(metadata: JsonlSessionMetadata): Promise<void>;\n\treloadPresentationFacetBundles(packagePaths: readonly string[]): Promise<readonly FacetBundleArtifact[]>;\n}\n\ninterface RunningServerBackend extends RunningServer {\n\trefreshSessions(): Promise<void>;\n}\n\nasync function startServerBackend(\n\toptions: StartServerBackendOptions,\n\tworkers: SessionWorkerManager,\n\tonConnectionCountChanged?: (count: number) => void,\n): Promise<RunningServerBackend> {\n\tconst serverId = options.serverId;\n\tconst sessionDir = resolveSessionDirectory(options.sessionDir);\n\tconst executionEnv = new NodeExecutionEnv({ cwd: process.cwd() });\n\tconst repo = new JsonlSessionRepo({ fileSystem: executionEnv, sessionsRoot: sessionDir });\n\tconst listSessions = async (context: Context): Promise<JsonlSessionMetadata[]> => {\n\t\tconst sessions = new Map((await repo.list(undefined, context)).map((metadata) => [metadata.path, metadata]));\n\t\tfor (const metadata of workers.trackedSessions) sessions.set(metadata.path, metadata);\n\t\treturn [...sessions.values()];\n\t};\n\tconst resolveSession = async (sessionId: string, context: Context): Promise<JsonlSessionMetadata> => {\n\t\tconst matches = (await listSessions(context)).filter((metadata) => metadata.id === sessionId);\n\t\tif (matches.length === 0) throw new SessionNotFoundError(`Unknown session: ${sessionId}`);\n\t\tif (matches.length > 1) throw new SessionAmbiguousError();\n\t\treturn matches[0]!;\n\t};\n\tconst createSession = async (\n\t\tcreateOptions: SessionCreateOptions,\n\t\tcontext: Context,\n\t): Promise<JsonlSessionMetadata> => {\n\t\tconst session = await repo.create({ ...createOptions, cwd: process.cwd() }, context);\n\t\ttry {\n\t\t\treturn session.metadata;\n\t\t} finally {\n\t\t\tawait session.close(context);\n\t\t}\n\t};\n\tconst summarize = (metadata: JsonlSessionMetadata): SessionSummary => ({\n\t\tserverId,\n\t\tsessionId: metadata.id,\n\t\tcreatedAt: metadata.createdAt,\n\t});\n\tconst closeStorage = async (): Promise<void> => {\n\t\tconst cleanup = await Promise.allSettled([repo.close(TODO_CONTEXT), executionEnv.cleanup(TODO_CONTEXT)]);\n\t\tconst errors = cleanup.flatMap((result) => (result.status === \"rejected\" ? [result.reason] : []));\n\t\tif (errors.length === 1) throw errors[0];\n\t\tif (errors.length > 1) throw new AggregateError(errors, \"Experimental session storage cleanup failed\");\n\t};\n\tconst serverServices = await createExperimentalServerServices({\n\t\tlist: async (context) =>\n\t\t\t(await listSessions(context))\n\t\t\t\t.map(summarize)\n\t\t\t\t.sort((left, right) => left.sessionId.localeCompare(right.sessionId) || left.createdAt - right.createdAt),\n\t\tcreate: async (createOptions, context) => summarize(await createSession(createOptions, context)),\n\t\tremove: async (sessionId, context) => {\n\t\t\tconst metadata = await resolveSession(sessionId, context);\n\t\t\tawait workers.closeSession(metadata, context);\n\t\t\tawait repo.delete(metadata, context);\n\t\t\tawait options.removeSessionPlugins(metadata);\n\t\t},\n\t\tasync prepareSessionPlugins(sessionId, packagePaths, context) {\n\t\t\tconst metadata = await resolveSession(sessionId, context);\n\t\t\tlet selected: ResolvedSessionPlugins;\n\t\t\ttry {\n\t\t\t\tselected = await options.resolveSessionPlugins(metadata, packagePaths, context);\n\t\t\t\tworkers.assertSessionPluginManifestPaths(metadata, selected.manifestPaths);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof SessionPluginSelectionConflictError) {\n\t\t\t\t\tthrow new RoutedServerError(\"service_invalid_value\", error.message);\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tpackagePaths: selected.packagePaths,\n\t\t\t\tpresentationPlugins: createPresentationFacetData(selected.presentationArtifacts),\n\t\t\t};\n\t\t},\n\t\tasync reloadPresentationPlugins(packagePaths) {\n\t\t\treturn createPresentationFacetData(await options.reloadPresentationFacetBundles(packagePaths));\n\t\t},\n\t}).catch(async (error: unknown) => {\n\t\ttry {\n\t\t\tawait closeStorage();\n\t\t} catch (cleanupError) {\n\t\t\tthrow new AggregateError([error, cleanupError], \"Server service startup and cleanup failed\");\n\t\t}\n\t\tthrow error;\n\t});\n\tconst host: ServerHost<JsonlSessionMetadata> = {\n\t\tserverServices: serverServices.host,\n\t\tresolveSession,\n\t\topenSession: async (metadata, context) => {\n\t\t\tconst selected = await options.resolveSessionPlugins(metadata, undefined, context);\n\t\t\treturn workers.openSession(metadata, context, selected.manifestPaths);\n\t\t},\n\t};\n\tconst socketPath = options.path;\n\tconst closeCatalog = async (): Promise<void> => {\n\t\tconst cleanup = await Promise.allSettled([serverServices.dispose(), closeStorage()]);\n\t\tconst errors = cleanup.flatMap((result) => (result.status === \"rejected\" ? [result.reason] : []));\n\t\tif (errors.length === 1) throw errors[0];\n\t\tif (errors.length > 1) throw new AggregateError(errors, \"Experimental session catalog cleanup failed\");\n\t};\n\tconst server = createUnixServer(host, {\n\t\tserverId,\n\t\tpath: socketPath,\n\t\tmode: 0o600,\n\t\tonConnectionCountChanged,\n\t});\n\ttry {\n\t\tawait server.start();\n\t} catch (error) {\n\t\tconst cleanup = await Promise.allSettled([server.close(), closeCatalog()]);\n\t\tconst cleanupErrors = cleanup.flatMap((result) => (result.status === \"rejected\" ? [result.reason] : []));\n\t\tif (cleanupErrors.length > 0) {\n\t\t\tthrow new AggregateError([error, ...cleanupErrors], \"Experimental server startup and cleanup failed\");\n\t\t}\n\t\tthrow error;\n\t}\n\n\tlet closePromise: Promise<void> | undefined;\n\tconst closed = server.closed.then(\n\t\t() => closeCatalog(),\n\t\tasync (serverError: unknown) => {\n\t\t\ttry {\n\t\t\t\tawait closeCatalog();\n\t\t\t} catch (repoError) {\n\t\t\t\tthrow new AggregateError([serverError, repoError], \"Server and repository shutdown failed\");\n\t\t\t}\n\t\t\tthrow serverError;\n\t\t},\n\t);\n\treturn {\n\t\tserverId,\n\t\tsessionDir,\n\t\tsocketPath,\n\t\tserver,\n\t\tworkerPids: workers.workerPids,\n\t\tclosed,\n\t\trefreshSessions: () => serverServices.refresh(BACKGROUND_CONTEXT),\n\t\tclose() {\n\t\t\tclosePromise ??= server.close().then(\n\t\t\t\t() => closed,\n\t\t\t\t() => closed,\n\t\t\t);\n\t\t\treturn closePromise;\n\t\t},\n\t};\n}\n\n/** Start a replaceable experimental server behind the stable coordinator endpoint. */\nexport async function startServer(options: StartServerOptions = {}): Promise<RunningServer> {\n\tif (options.provider !== undefined && options.model === undefined) {\n\t\tthrow new Error(\"Server model provider requires a model\");\n\t}\n\tconst workerModel =\n\t\toptions.model === undefined\n\t\t\t? undefined\n\t\t\t: { ...(options.provider === undefined ? {} : { provider: options.provider }), model: options.model };\n\tconst directory = resolveServerDirectory(options.directory);\n\tconst { serverId, release } = await acquireServerProfile(directory, options.serverId ?? process.env[ENV_SERVER_ID]);\n\tconst lifetime = new ServerLifetime(options.keepAlive ?? true);\n\tlet backend: RunningServerBackend | undefined;\n\tlet coordinator: CoordinatorConnection | undefined;\n\tlet startupLease: CoordinatorStartupLease | undefined;\n\tlet workers: SessionWorkerManager | undefined;\n\tlet relay: RadiusRelayHost | undefined;\n\tlet released = false;\n\ttry {\n\t\tawait ensurePrivateServerDirectory(directory);\n\t\tconst pluginPackagePaths = await restoreServerPluginPackageProfile(directory, serverId, options.pluginPackages);\n\t\tconst pluginPackages = new Map<string, ReturnType<typeof createServerPluginPackage>>();\n\t\tconst getPluginPackage = (packagePath: string): ReturnType<typeof createServerPluginPackage> => {\n\t\t\tlet plugin = pluginPackages.get(packagePath);\n\t\t\tif (plugin === undefined) {\n\t\t\t\tplugin = createServerPluginPackage(directory, serverId, packagePath);\n\t\t\t\tpluginPackages.set(packagePath, plugin);\n\t\t\t}\n\t\t\treturn plugin;\n\t\t};\n\t\tconst buildPluginSelection = async (packagePaths: readonly string[]): Promise<ResolvedSessionPlugins> => {\n\t\t\tconst normalizedPackagePaths = normalizePluginPackagePaths(packagePaths);\n\t\t\tconst plugins = normalizedPackagePaths.map(getPluginPackage);\n\t\t\tconst built = (await Promise.all(plugins.map((plugin) => plugin.build()))).flat();\n\t\t\treturn {\n\t\t\t\tpackagePaths: normalizedPackagePaths,\n\t\t\t\tmanifestPaths: plugins.map((plugin) => plugin.manifestPath),\n\t\t\t\tpresentationArtifacts: built,\n\t\t\t};\n\t\t};\n\t\tlet defaultPluginSelection = await buildPluginSelection(pluginPackagePaths);\n\t\tconst sessionPluginSelections = new Map<string, ResolvedSessionPlugins>();\n\t\tconst resolveSessionPlugins = async (\n\t\t\tmetadata: JsonlSessionMetadata,\n\t\t\trequestedPackagePaths: readonly string[] | undefined,\n\t\t\t_context: Context,\n\t\t): Promise<ResolvedSessionPlugins> => {\n\t\t\tif (requestedPackagePaths !== undefined) {\n\t\t\t\tconst normalizedPackagePaths = normalizePluginPackagePaths(requestedPackagePaths);\n\t\t\t\tconst current = sessionPluginSelections.get(metadata.path);\n\t\t\t\tif (current !== undefined && sameStrings(current.packagePaths, normalizedPackagePaths)) return current;\n\t\t\t\tconst requestedManifestPaths = normalizedPackagePaths.map(\n\t\t\t\t\t(packagePath) => getPluginPackage(packagePath).manifestPath,\n\t\t\t\t);\n\t\t\t\tworkers?.assertSessionPluginManifestPaths(metadata, requestedManifestPaths);\n\t\t\t\tconst candidate = await buildPluginSelection(normalizedPackagePaths);\n\t\t\t\tworkers?.assertSessionPluginManifestPaths(metadata, candidate.manifestPaths);\n\t\t\t\tawait writeSessionPluginPackageProfile(directory, serverId, metadata.path, candidate.packagePaths);\n\t\t\t\tsessionPluginSelections.set(metadata.path, candidate);\n\t\t\t\treturn candidate;\n\t\t\t}\n\t\t\tconst cached = sessionPluginSelections.get(metadata.path);\n\t\t\tif (cached !== undefined) return cached;\n\t\t\tconst storedPackagePaths = await readSessionPluginPackageProfile(directory, serverId, metadata.path);\n\t\t\tconst selected =\n\t\t\t\tstoredPackagePaths === undefined ? defaultPluginSelection : await buildPluginSelection(storedPackagePaths);\n\t\t\tif (storedPackagePaths === undefined) {\n\t\t\t\tawait writeSessionPluginPackageProfile(directory, serverId, metadata.path, selected.packagePaths);\n\t\t\t}\n\t\t\tsessionPluginSelections.set(metadata.path, selected);\n\t\t\treturn selected;\n\t\t};\n\t\tconst removeSessionPlugins = async (metadata: JsonlSessionMetadata): Promise<void> => {\n\t\t\tsessionPluginSelections.delete(metadata.path);\n\t\t\tawait removeSessionPluginPackageProfile(directory, serverId, metadata.path);\n\t\t};\n\t\tconst reloadPresentationFacetBundles = async (\n\t\t\tpackagePaths: readonly string[],\n\t\t): Promise<readonly FacetBundleArtifact[]> => {\n\t\t\tconst reloaded = await buildPluginSelection(packagePaths);\n\t\t\tif (sameStrings(defaultPluginSelection.packagePaths, reloaded.packagePaths)) {\n\t\t\t\tdefaultPluginSelection = reloaded;\n\t\t\t}\n\t\t\tfor (const [sessionPath, selected] of sessionPluginSelections) {\n\t\t\t\tif (sameStrings(selected.packagePaths, reloaded.packagePaths)) {\n\t\t\t\t\tsessionPluginSelections.set(sessionPath, reloaded);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn reloaded.presentationArtifacts;\n\t\t};\n\t\tconst socketPath = getUnixSocketPath(serverId, directory);\n\t\tconst controlPath = join(directory, `control-${serverId}.sock`);\n\t\tconst serverNonce = randomUUID().replaceAll(\"-\", \"\").slice(0, 12);\n\t\tconst serverPath = join(directory, `server-${serverId}-${serverNonce}.sock`);\n\t\tstartupLease = await ensureCoordinator(socketPath, controlPath);\n\t\tcoordinator = new CoordinatorConnection({ controlPath, endpoint: serverPath });\n\t\tconst sessionDir = resolveSessionDirectory(options.sessionDir);\n\t\tworkers = new SessionWorkerManager(coordinator, sessionDir, workerModel, (count) =>\n\t\t\tlifetime.setWorkerCount(count),\n\t\t);\n\t\tbackend = await startServerBackend(\n\t\t\t{\n\t\t\t\tpath: serverPath,\n\t\t\t\tserverId,\n\t\t\t\tsessionDir: options.sessionDir,\n\t\t\t\tresolveSessionPlugins,\n\t\t\t\tremoveSessionPlugins,\n\t\t\t\treloadPresentationFacetBundles,\n\t\t\t},\n\t\t\tworkers,\n\t\t\t(count) => lifetime.setConnectionCount(count),\n\t\t);\n\t\tawait coordinator.connect();\n\t\tstartupLease.close();\n\t\tstartupLease = undefined;\n\t\tawait workers.discover(coordinator.peerIds);\n\t\tawait backend.refreshSessions();\n\t\trelay = new RadiusRelayHost({\n\t\t\tserverId,\n\t\t\tserver: backend.server,\n\t\t\tauth: new RadiusRelayAuthResolver(options.relayAuth),\n\t\t\tonStatus: options.onRelayStatus,\n\t\t});\n\t\trelay.start();\n\n\t\tconst activeBackend = backend;\n\t\tconst activeCoordinator = coordinator;\n\t\tconst activeWorkers = workers;\n\t\tconst activeRelay = relay;\n\t\tvoid activeCoordinator.replaced\n\t\t\t.then(async () => {\n\t\t\t\tlifetime.stop();\n\t\t\t\tactiveWorkers.detach();\n\t\t\t\tawait activeRelay.close();\n\t\t\t\tawait activeBackend.close();\n\t\t\t})\n\t\t\t.finally(() => activeCoordinator.close())\n\t\t\t.catch(() => {});\n\t\tlet closePromise: Promise<void> | undefined;\n\t\tconst runtime: RunningServer = {\n\t\t\tserverId,\n\t\t\tsessionDir: activeBackend.sessionDir,\n\t\t\tsocketPath,\n\t\t\tserver: activeBackend.server,\n\t\t\tworkerPids: activeWorkers.workerPids,\n\t\t\tclosed: activeBackend.closed.finally(() => activeRelay.close()),\n\t\t\tclose() {\n\t\t\t\tlifetime.stop();\n\t\t\t\tclosePromise ??= (async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait activeRelay.close();\n\t\t\t\t\t\tawait activeBackend.close();\n\t\t\t\t\t} finally {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif (activeCoordinator.wasReplaced) activeWorkers.detach();\n\t\t\t\t\t\t\telse await activeWorkers.shutdown();\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tactiveCoordinator.close();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t\treturn closePromise;\n\t\t\t},\n\t\t};\n\t\tlifetime.start(() => {\n\t\t\tvoid runtime.close().catch(() => {});\n\t\t});\n\t\treleased = true;\n\t\tawait release();\n\t\treturn runtime;\n\t} catch (error) {\n\t\tlifetime.stop();\n\t\tstartupLease?.close();\n\t\tif (coordinator?.wasReplaced) workers?.detach();\n\t\tconst cleanup = await Promise.allSettled([\n\t\t\trelay?.close(),\n\t\t\tbackend?.close(),\n\t\t\tcoordinator?.wasReplaced ? undefined : workers?.shutdown(),\n\t\t\tPromise.resolve(coordinator?.close()),\n\t\t\treleased ? undefined : release(),\n\t\t]);\n\t\tconst cleanupErrors = cleanup.flatMap((result) => (result.status === \"rejected\" ? [result.reason] : []));\n\t\tif (cleanupErrors.length > 0) {\n\t\t\tthrow new AggregateError([error, ...cleanupErrors], \"Server runtime startup and cleanup failed\");\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/** Start an operator-held server while serializing against automatic cold activation. */\nexport async function startForegroundServer(\n\toptions: Omit<StartServerOptions, \"keepAlive\"> = {},\n): Promise<RunningServer> {\n\tconst directory = resolveServerDirectory(options.directory);\n\tawait ensurePrivateServerDirectory(directory);\n\tconst profile = await acquireServerProfile(directory, options.serverId ?? process.env[ENV_SERVER_ID]);\n\tconst serverId = profile.serverId;\n\tawait profile.release();\n\tconst release = await acquireServerActivation(directory, serverId);\n\ttry {\n\t\treturn await startServer({\n\t\t\t...options,\n\t\t\tdirectory,\n\t\t\tserverId,\n\t\t\tkeepAlive: true,\n\t\t});\n\t} finally {\n\t\tawait release();\n\t}\n}\n\nfunction parseServerModelOptions(value: string | undefined): { provider?: string; model: string } | undefined {\n\tif (value === undefined) return undefined;\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(value);\n\t} catch (error) {\n\t\tthrow new Error(\"Internal server received invalid model options\", { cause: error });\n\t}\n\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\tthrow new Error(\"Internal server received invalid model options\");\n\t}\n\tconst keys = Object.keys(parsed);\n\tconst model = \"model\" in parsed ? parsed.model : undefined;\n\tconst provider = \"provider\" in parsed ? parsed.provider : undefined;\n\tif (\n\t\tkeys.some((key) => key !== \"provider\" && key !== \"model\") ||\n\t\ttypeof model !== \"string\" ||\n\t\tmodel.length === 0 ||\n\t\t(provider !== undefined && (typeof provider !== \"string\" || provider.length === 0))\n\t) {\n\t\tthrow new Error(\"Internal server received invalid model options\");\n\t}\n\treturn provider === undefined ? { model } : { provider, model };\n}\n\n/** Run an automatically activated server until its client and Session demand disappears. */\nexport async function runServerProcess(args: readonly string[]): Promise<void> {\n\tconst [directory, serverId, sessionDir, serializedModel] = args;\n\tif (args.length > 4) throw new Error(\"Internal server received unexpected arguments\");\n\tif (!directory || !isAbsolute(directory)) throw new Error(\"Internal server requires an absolute server directory\");\n\tif (!isServerId(serverId)) throw new Error(\"Internal server requires a canonical server ID\");\n\tif (!sessionDir || !isAbsolute(sessionDir))\n\t\tthrow new Error(\"Internal server requires an absolute Session directory\");\n\tconst workerModel = parseServerModelOptions(serializedModel);\n\n\tconst runtime = await startServer({\n\t\tdirectory,\n\t\tserverId,\n\t\tsessionDir,\n\t\tkeepAlive: false,\n\t\t...workerModel,\n\t});\n\tconst close = (): void => {\n\t\tvoid runtime.close().catch(() => {});\n\t};\n\tprocess.once(\"SIGINT\", close);\n\tprocess.once(\"SIGTERM\", close);\n\ttry {\n\t\tawait runtime.closed;\n\t} finally {\n\t\tprocess.off(\"SIGINT\", close);\n\t\tprocess.off(\"SIGTERM\", close);\n\t\tawait runtime.close();\n\t}\n}\n\nfunction sameStrings(left: readonly string[], right: readonly string[]): boolean {\n\treturn left.length === right.length && left.every((value, index) => value === right[index]);\n}\n\nif (isDirectInternalProcessEntry(import.meta.url)) {\n\tconst role = consumeInternalProcessRole();\n\tif (role !== \"server\") throw new Error(\"Server entrypoint requires an internal server invocation\");\n\tvoid runServerProcess(process.argv.slice(2)).catch((error: unknown) => {\n\t\tconsole.error(error);\n\t\tprocess.exit(1);\n\t});\n}\n"]}
|