@earendil-works/pi-coding-agent 0.85.0 → 0.85.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +0 -2
  3. package/dist/bun/cli.d.ts +3 -1
  4. package/dist/bun/cli.d.ts.map +1 -1
  5. package/dist/bun/cli.js +3 -12
  6. package/dist/bun/cli.js.map +1 -1
  7. package/dist/bun/sandbox-env-setup.d.ts +2 -0
  8. package/dist/bun/sandbox-env-setup.d.ts.map +1 -0
  9. package/dist/bun/sandbox-env-setup.js +4 -0
  10. package/dist/bun/sandbox-env-setup.js.map +1 -0
  11. package/dist/bundle/chunks/{anthropic-messages-QAQLEQIY.js → anthropic-messages-VWZZOSJQ.js} +1 -1
  12. package/dist/bundle/chunks/{azure-openai-responses-Q7MJBRE6.js → azure-openai-responses-BJLAM6CD.js} +1 -1
  13. package/dist/bundle/chunks/{chunk-R7UUJ4C2.js → chunk-CLNPYIDP.js} +1 -1
  14. package/dist/bundle/chunks/chunk-JVUZSMYM.js +1547 -0
  15. package/dist/bundle/chunks/{chunk-2KVJKXS2.js → chunk-U6ZMQKGD.js} +1 -1
  16. package/dist/bundle/chunks/github-copilot.js +1 -1
  17. package/dist/bundle/chunks/{google-generative-ai-BSMTYDAM.js → google-generative-ai-Q2K7FBDI.js} +1 -1
  18. package/dist/bundle/chunks/{google-vertex-5C3HASOJ.js → google-vertex-7UJBF4S7.js} +1 -1
  19. package/dist/bundle/chunks/{node-EM5FIVUN.js → node-KG362ECQ.js} +1 -1
  20. package/dist/bundle/chunks/{openai-codex-responses-YJOO52RW.js → openai-codex-responses-R6VYZTVY.js} +1 -1
  21. package/dist/bundle/chunks/{openai-completions-QOT3QX7D.js → openai-completions-EKZT2IH2.js} +1 -1
  22. package/dist/bundle/chunks/openai-responses-TFDINO6W.js +2 -0
  23. package/dist/bundle/chunks/{pi-messages-EGZIFQGG.js → pi-messages-PML4SPVJ.js} +1 -1
  24. package/dist/bundle/cli.js +1 -1
  25. package/dist/bundle/index.js +1 -1
  26. package/dist/bundle/rpc-entry.js +1 -1
  27. package/dist/cli/args.d.ts.map +1 -1
  28. package/dist/cli/args.js +0 -2
  29. package/dist/cli/args.js.map +1 -1
  30. package/dist/cli/setup.d.ts +2 -0
  31. package/dist/cli/setup.d.ts.map +1 -0
  32. package/dist/cli/setup.js +12 -0
  33. package/dist/cli/setup.js.map +1 -0
  34. package/dist/cli.d.ts.map +1 -1
  35. package/dist/cli.js +3 -25
  36. package/dist/cli.js.map +1 -1
  37. package/dist/core/keybindings.d.ts +5 -0
  38. package/dist/core/keybindings.d.ts.map +1 -1
  39. package/dist/core/keybindings.js +4 -0
  40. package/dist/core/keybindings.js.map +1 -1
  41. package/dist/main.d.ts.map +1 -1
  42. package/dist/main.js +0 -122
  43. package/dist/main.js.map +1 -1
  44. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  45. package/dist/modes/interactive/components/model-selector.js +5 -5
  46. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  47. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  48. package/dist/modes/interactive/components/scoped-models-selector.js +8 -8
  49. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  50. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  51. package/dist/modes/interactive/components/thinking-selector.js +4 -4
  52. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  53. package/docs/containerization.md +45 -0
  54. package/docs/development.md +19 -0
  55. package/docs/environment-variables.md +2 -2
  56. package/docs/keybindings.md +2 -1
  57. package/docs/models.md +1 -1
  58. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  59. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  60. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  61. package/examples/extensions/gondolin/package-lock.json +2 -2
  62. package/examples/extensions/gondolin/package.json +1 -1
  63. package/examples/extensions/sandbox/package-lock.json +2 -2
  64. package/examples/extensions/sandbox/package.json +1 -1
  65. package/examples/extensions/with-deps/package-lock.json +2 -2
  66. package/examples/extensions/with-deps/package.json +1 -1
  67. package/npm-shrinkwrap.json +20 -46
  68. package/package.json +13 -12
  69. package/dist/bundle/chunks/chunk-EQ6DR6XK.js +0 -5
  70. package/dist/bundle/chunks/chunk-LZKJTKCT.js +0 -2
  71. package/dist/bundle/chunks/chunk-WBE4J4AU.js +0 -9
  72. package/dist/bundle/chunks/chunk-WZB2R5YO.js +0 -1558
  73. package/dist/bundle/chunks/openai-responses-U7LNPQN4.js +0 -2
  74. package/dist/bundle/client.js +0 -2
  75. package/dist/bundle/coordinator.js +0 -3
  76. package/dist/cli/experimental/cli.d.ts +0 -10
  77. package/dist/cli/experimental/cli.d.ts.map +0 -1
  78. package/dist/cli/experimental/cli.js +0 -9
  79. package/dist/cli/experimental/cli.js.map +0 -1
  80. package/dist/cli/experimental/command-options.d.ts +0 -28
  81. package/dist/cli/experimental/command-options.d.ts.map +0 -1
  82. package/dist/cli/experimental/command-options.js +0 -84
  83. package/dist/cli/experimental/command-options.js.map +0 -1
  84. package/dist/cli/experimental/command.d.ts +0 -70
  85. package/dist/cli/experimental/command.d.ts.map +0 -1
  86. package/dist/cli/experimental/command.js +0 -144
  87. package/dist/cli/experimental/command.js.map +0 -1
  88. package/dist/cli/experimental/commands/client.d.ts +0 -19
  89. package/dist/cli/experimental/commands/client.d.ts.map +0 -1
  90. package/dist/cli/experimental/commands/client.js +0 -63
  91. package/dist/cli/experimental/commands/client.js.map +0 -1
  92. package/dist/cli/experimental/commands/server.d.ts +0 -17
  93. package/dist/cli/experimental/commands/server.d.ts.map +0 -1
  94. package/dist/cli/experimental/commands/server.js +0 -44
  95. package/dist/cli/experimental/commands/server.js.map +0 -1
  96. package/dist/client/index.d.ts +0 -2
  97. package/dist/client/index.d.ts.map +0 -1
  98. package/dist/client/index.js +0 -2
  99. package/dist/client/index.js.map +0 -1
  100. package/dist/experimental/client-runtime.d.ts +0 -43
  101. package/dist/experimental/client-runtime.d.ts.map +0 -1
  102. package/dist/experimental/client-runtime.js +0 -183
  103. package/dist/experimental/client-runtime.js.map +0 -1
  104. package/dist/experimental/client-tui-chat.d.ts +0 -14
  105. package/dist/experimental/client-tui-chat.d.ts.map +0 -1
  106. package/dist/experimental/client-tui-chat.js +0 -171
  107. package/dist/experimental/client-tui-chat.js.map +0 -1
  108. package/dist/experimental/client-tui.d.ts +0 -37
  109. package/dist/experimental/client-tui.d.ts.map +0 -1
  110. package/dist/experimental/client-tui.js +0 -702
  111. package/dist/experimental/client-tui.js.map +0 -1
  112. package/dist/experimental/client.d.ts +0 -25
  113. package/dist/experimental/client.d.ts.map +0 -1
  114. package/dist/experimental/client.js +0 -99
  115. package/dist/experimental/client.js.map +0 -1
  116. package/dist/experimental/coordinator-entry.d.ts +0 -3
  117. package/dist/experimental/coordinator-entry.d.ts.map +0 -1
  118. package/dist/experimental/coordinator-entry.js +0 -11
  119. package/dist/experimental/coordinator-entry.js.map +0 -1
  120. package/dist/experimental/coordinator.d.ts +0 -38
  121. package/dist/experimental/coordinator.d.ts.map +0 -1
  122. package/dist/experimental/coordinator.js +0 -570
  123. package/dist/experimental/coordinator.js.map +0 -1
  124. package/dist/experimental/mini/main.d.ts +0 -7
  125. package/dist/experimental/mini/main.d.ts.map +0 -1
  126. package/dist/experimental/mini/main.js +0 -21
  127. package/dist/experimental/mini/main.js.map +0 -1
  128. package/dist/experimental/mini/server/entry.d.ts +0 -3
  129. package/dist/experimental/mini/server/entry.d.ts.map +0 -1
  130. package/dist/experimental/mini/server/entry.js +0 -11
  131. package/dist/experimental/mini/server/entry.js.map +0 -1
  132. package/dist/experimental/mini/server/run.d.ts +0 -13
  133. package/dist/experimental/mini/server/run.d.ts.map +0 -1
  134. package/dist/experimental/mini/server/run.js +0 -150
  135. package/dist/experimental/mini/server/run.js.map +0 -1
  136. package/dist/experimental/mini/shared/protocol.d.ts +0 -127
  137. package/dist/experimental/mini/shared/protocol.d.ts.map +0 -1
  138. package/dist/experimental/mini/shared/protocol.js +0 -13
  139. package/dist/experimental/mini/shared/protocol.js.map +0 -1
  140. package/dist/experimental/mini/shared/rpc.d.ts +0 -49
  141. package/dist/experimental/mini/shared/rpc.d.ts.map +0 -1
  142. package/dist/experimental/mini/shared/rpc.js +0 -171
  143. package/dist/experimental/mini/shared/rpc.js.map +0 -1
  144. package/dist/experimental/mini/shared/transport.d.ts +0 -35
  145. package/dist/experimental/mini/shared/transport.d.ts.map +0 -1
  146. package/dist/experimental/mini/shared/transport.js +0 -94
  147. package/dist/experimental/mini/shared/transport.js.map +0 -1
  148. package/dist/experimental/mini/tui/run.d.ts +0 -9
  149. package/dist/experimental/mini/tui/run.d.ts.map +0 -1
  150. package/dist/experimental/mini/tui/run.js +0 -62
  151. package/dist/experimental/mini/tui/run.js.map +0 -1
  152. package/dist/experimental/mini/tui/session.d.ts +0 -26
  153. package/dist/experimental/mini/tui/session.d.ts.map +0 -1
  154. package/dist/experimental/mini/tui/session.js +0 -94
  155. package/dist/experimental/mini/tui/session.js.map +0 -1
  156. package/dist/experimental/mini/tui/view.d.ts +0 -10
  157. package/dist/experimental/mini/tui/view.d.ts.map +0 -1
  158. package/dist/experimental/mini/tui/view.js +0 -459
  159. package/dist/experimental/mini/tui/view.js.map +0 -1
  160. package/dist/experimental/mini/worker/entry.d.ts +0 -3
  161. package/dist/experimental/mini/worker/entry.d.ts.map +0 -1
  162. package/dist/experimental/mini/worker/entry.js +0 -10
  163. package/dist/experimental/mini/worker/entry.js.map +0 -1
  164. package/dist/experimental/mini/worker/lane-service.d.ts +0 -44
  165. package/dist/experimental/mini/worker/lane-service.d.ts.map +0 -1
  166. package/dist/experimental/mini/worker/lane-service.js +0 -97
  167. package/dist/experimental/mini/worker/lane-service.js.map +0 -1
  168. package/dist/experimental/mini/worker/models-service.d.ts +0 -19
  169. package/dist/experimental/mini/worker/models-service.d.ts.map +0 -1
  170. package/dist/experimental/mini/worker/models-service.js +0 -136
  171. package/dist/experimental/mini/worker/models-service.js.map +0 -1
  172. package/dist/experimental/mini/worker/run.d.ts +0 -14
  173. package/dist/experimental/mini/worker/run.d.ts.map +0 -1
  174. package/dist/experimental/mini/worker/run.js +0 -88
  175. package/dist/experimental/mini/worker/run.js.map +0 -1
  176. package/dist/experimental/plugin.d.ts +0 -4
  177. package/dist/experimental/plugin.d.ts.map +0 -1
  178. package/dist/experimental/plugin.js +0 -4
  179. package/dist/experimental/plugin.js.map +0 -1
  180. package/dist/experimental/plugins/bundled.d.ts +0 -7
  181. package/dist/experimental/plugins/bundled.d.ts.map +0 -1
  182. package/dist/experimental/plugins/bundled.js +0 -48
  183. package/dist/experimental/plugins/bundled.js.map +0 -1
  184. package/dist/experimental/plugins/package.d.ts +0 -18
  185. package/dist/experimental/plugins/package.d.ts.map +0 -1
  186. package/dist/experimental/plugins/package.js +0 -113
  187. package/dist/experimental/plugins/package.js.map +0 -1
  188. package/dist/experimental/process.d.ts +0 -20
  189. package/dist/experimental/process.d.ts.map +0 -1
  190. package/dist/experimental/process.js +0 -85
  191. package/dist/experimental/process.js.map +0 -1
  192. package/dist/experimental/radius-auth.d.ts +0 -17
  193. package/dist/experimental/radius-auth.d.ts.map +0 -1
  194. package/dist/experimental/radius-auth.js +0 -52
  195. package/dist/experimental/radius-auth.js.map +0 -1
  196. package/dist/experimental/radius-relay.d.ts +0 -90
  197. package/dist/experimental/radius-relay.d.ts.map +0 -1
  198. package/dist/experimental/radius-relay.js +0 -582
  199. package/dist/experimental/radius-relay.js.map +0 -1
  200. package/dist/experimental/server.d.ts +0 -75
  201. package/dist/experimental/server.d.ts.map +0 -1
  202. package/dist/experimental/server.js +0 -682
  203. package/dist/experimental/server.js.map +0 -1
  204. package/dist/experimental/services/agent-controller-provider.d.ts +0 -4
  205. package/dist/experimental/services/agent-controller-provider.d.ts.map +0 -1
  206. package/dist/experimental/services/agent-controller-provider.js +0 -84
  207. package/dist/experimental/services/agent-controller-provider.js.map +0 -1
  208. package/dist/experimental/services/agent-controller.d.ts +0 -57
  209. package/dist/experimental/services/agent-controller.d.ts.map +0 -1
  210. package/dist/experimental/services/agent-controller.js +0 -3
  211. package/dist/experimental/services/agent-controller.js.map +0 -1
  212. package/dist/experimental/services/connection.d.ts +0 -40
  213. package/dist/experimental/services/connection.d.ts.map +0 -1
  214. package/dist/experimental/services/connection.js +0 -300
  215. package/dist/experimental/services/connection.js.map +0 -1
  216. package/dist/experimental/services/models-provider.d.ts +0 -16
  217. package/dist/experimental/services/models-provider.d.ts.map +0 -1
  218. package/dist/experimental/services/models-provider.js +0 -116
  219. package/dist/experimental/services/models-provider.js.map +0 -1
  220. package/dist/experimental/services/models.d.ts +0 -36
  221. package/dist/experimental/services/models.d.ts.map +0 -1
  222. package/dist/experimental/services/models.js +0 -3
  223. package/dist/experimental/services/models.js.map +0 -1
  224. package/dist/experimental/services/plugins.d.ts +0 -16
  225. package/dist/experimental/services/plugins.d.ts.map +0 -1
  226. package/dist/experimental/services/plugins.js +0 -4
  227. package/dist/experimental/services/plugins.js.map +0 -1
  228. package/dist/experimental/services/presentation-ui.d.ts +0 -13
  229. package/dist/experimental/services/presentation-ui.d.ts.map +0 -1
  230. package/dist/experimental/services/presentation-ui.js +0 -3
  231. package/dist/experimental/services/presentation-ui.js.map +0 -1
  232. package/dist/experimental/services/server.d.ts +0 -19
  233. package/dist/experimental/services/server.d.ts.map +0 -1
  234. package/dist/experimental/services/server.js +0 -104
  235. package/dist/experimental/services/server.js.map +0 -1
  236. package/dist/experimental/services/sessions.d.ts +0 -28
  237. package/dist/experimental/services/sessions.d.ts.map +0 -1
  238. package/dist/experimental/services/sessions.js +0 -4
  239. package/dist/experimental/services/sessions.js.map +0 -1
  240. package/dist/experimental/services/slash-commands-provider.d.ts +0 -14
  241. package/dist/experimental/services/slash-commands-provider.d.ts.map +0 -1
  242. package/dist/experimental/services/slash-commands-provider.js +0 -200
  243. package/dist/experimental/services/slash-commands-provider.js.map +0 -1
  244. package/dist/experimental/services/slash-commands.d.ts +0 -24
  245. package/dist/experimental/services/slash-commands.d.ts.map +0 -1
  246. package/dist/experimental/services/slash-commands.js +0 -3
  247. package/dist/experimental/services/slash-commands.js.map +0 -1
  248. package/dist/experimental/services/transcript-provider.d.ts +0 -12
  249. package/dist/experimental/services/transcript-provider.d.ts.map +0 -1
  250. package/dist/experimental/services/transcript-provider.js +0 -109
  251. package/dist/experimental/services/transcript-provider.js.map +0 -1
  252. package/dist/experimental/services/transcript.d.ts +0 -13
  253. package/dist/experimental/services/transcript.d.ts.map +0 -1
  254. package/dist/experimental/services/transcript.js +0 -3
  255. package/dist/experimental/services/transcript.js.map +0 -1
  256. package/dist/experimental/services/worker.d.ts +0 -28
  257. package/dist/experimental/services/worker.d.ts.map +0 -1
  258. package/dist/experimental/services/worker.js +0 -107
  259. package/dist/experimental/services/worker.js.map +0 -1
  260. package/dist/experimental/session-worker-manager.d.ts +0 -24
  261. package/dist/experimental/session-worker-manager.d.ts.map +0 -1
  262. package/dist/experimental/session-worker-manager.js +0 -691
  263. package/dist/experimental/session-worker-manager.js.map +0 -1
  264. package/dist/experimental/session-worker.d.ts +0 -188
  265. package/dist/experimental/session-worker.d.ts.map +0 -1
  266. package/dist/experimental/session-worker.js +0 -785
  267. package/dist/experimental/session-worker.js.map +0 -1
  268. package/dist/experimental/source-resolver.d.ts +0 -2
  269. package/dist/experimental/source-resolver.d.ts.map +0 -1
  270. package/dist/experimental/source-resolver.js +0 -71
  271. package/dist/experimental/source-resolver.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../src/cli/experimental/commands/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,OAAO,EAA6B,MAAM,eAAe,CAAC;AACnE,OAAO,EACN,KAAK,SAAS,EAKd,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACpC,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAYD,eAAO,MAAM,aAAa,6DA+BgC,CAAC","sourcesContent":["import { isServerId, type ServerId } from \"@earendil-works/pi-protocol\";\nimport { Command, stringOption, valueOption } from \"../command.ts\";\nimport {\n\ttype AuthInput,\n\tauthTokenFileOption,\n\tauthTokenOption,\n\tparseAuth,\n\tunsupportedOptions,\n} from \"../command-options.ts\";\n\nexport interface ServerCommand {\n\treadonly command: \"server\";\n\treadonly auth?: AuthInput;\n\treadonly provider?: string;\n\treadonly model?: string;\n\treadonly pluginPackages?: readonly string[];\n\treadonly serverId?: ServerId;\n\treadonly sessionDir?: string;\n}\n\nexport interface ServerCommandContext {\n\trunServer(command: ServerCommand): void | Promise<void>;\n}\n\nconst serverIdOption = valueOption(\"--server-id\", (value) =>\n\tisServerId(value)\n\t\t? { ok: true, value }\n\t\t: { ok: false, error: `Invalid --server-id \"${value}\"; expected a lowercase UUIDv4` },\n);\nconst sessionDirOption = stringOption(\"--session-dir\");\nconst providerOption = stringOption(\"--provider\");\nconst modelOption = stringOption(\"--model\");\nconst pluginPackageOption = stringOption(\"-e\", { repeatable: true });\n\nexport const serverCommand = new Command<ServerCommand, ServerCommandContext>(\"server\")\n\t.option(serverIdOption)\n\t.option(sessionDirOption)\n\t.option(providerOption)\n\t.option(modelOption)\n\t.option(pluginPackageOption)\n\t.option(authTokenOption)\n\t.option(authTokenFileOption)\n\t.build((input) => {\n\t\tconst { auth, errors: authErrors } = parseAuth(input);\n\t\tconst serverId = input.value(serverIdOption);\n\t\tconst sessionDir = input.value(sessionDirOption);\n\t\tconst provider = input.value(providerOption);\n\t\tconst model = input.value(modelOption);\n\t\tconst pluginPackages = input.values(pluginPackageOption);\n\t\tconst modelErrors = provider !== undefined && model === undefined ? [\"--provider requires --model\"] : [];\n\t\tconst errors = [...authErrors, ...modelErrors, ...unsupportedOptions(\"server\", input)];\n\t\tif (errors.length > 0) return { ok: false, errors };\n\t\treturn {\n\t\t\tok: true,\n\t\t\tcommand: {\n\t\t\t\tcommand: \"server\",\n\t\t\t\t...(auth === undefined ? {} : { auth }),\n\t\t\t\t...(provider === undefined ? {} : { provider }),\n\t\t\t\t...(model === undefined ? {} : { model }),\n\t\t\t\t...(pluginPackages.length === 0 ? {} : { pluginPackages }),\n\t\t\t\t...(serverId === undefined ? {} : { serverId }),\n\t\t\t\t...(sessionDir === undefined ? {} : { sessionDir }),\n\t\t\t},\n\t\t};\n\t})\n\t.action((command, context) => context.runServer(command));\n"]}
@@ -1,44 +0,0 @@
1
- import { isServerId } from "@earendil-works/pi-protocol";
2
- import { Command, stringOption, valueOption } from "../command.js";
3
- import { authTokenFileOption, authTokenOption, parseAuth, unsupportedOptions, } from "../command-options.js";
4
- const serverIdOption = valueOption("--server-id", (value) => isServerId(value)
5
- ? { ok: true, value }
6
- : { ok: false, error: `Invalid --server-id "${value}"; expected a lowercase UUIDv4` });
7
- const sessionDirOption = stringOption("--session-dir");
8
- const providerOption = stringOption("--provider");
9
- const modelOption = stringOption("--model");
10
- const pluginPackageOption = stringOption("-e", { repeatable: true });
11
- export const serverCommand = new Command("server")
12
- .option(serverIdOption)
13
- .option(sessionDirOption)
14
- .option(providerOption)
15
- .option(modelOption)
16
- .option(pluginPackageOption)
17
- .option(authTokenOption)
18
- .option(authTokenFileOption)
19
- .build((input) => {
20
- const { auth, errors: authErrors } = parseAuth(input);
21
- const serverId = input.value(serverIdOption);
22
- const sessionDir = input.value(sessionDirOption);
23
- const provider = input.value(providerOption);
24
- const model = input.value(modelOption);
25
- const pluginPackages = input.values(pluginPackageOption);
26
- const modelErrors = provider !== undefined && model === undefined ? ["--provider requires --model"] : [];
27
- const errors = [...authErrors, ...modelErrors, ...unsupportedOptions("server", input)];
28
- if (errors.length > 0)
29
- return { ok: false, errors };
30
- return {
31
- ok: true,
32
- command: {
33
- command: "server",
34
- ...(auth === undefined ? {} : { auth }),
35
- ...(provider === undefined ? {} : { provider }),
36
- ...(model === undefined ? {} : { model }),
37
- ...(pluginPackages.length === 0 ? {} : { pluginPackages }),
38
- ...(serverId === undefined ? {} : { serverId }),
39
- ...(sessionDir === undefined ? {} : { sessionDir }),
40
- },
41
- };
42
- })
43
- .action((command, context) => context.runServer(command));
44
- //# sourceMappingURL=server.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../../src/cli/experimental/commands/server.ts"],"names":[],"mappings":"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","sourcesContent":["import { isServerId, type ServerId } from \"@earendil-works/pi-protocol\";\nimport { Command, stringOption, valueOption } from \"../command.ts\";\nimport {\n\ttype AuthInput,\n\tauthTokenFileOption,\n\tauthTokenOption,\n\tparseAuth,\n\tunsupportedOptions,\n} from \"../command-options.ts\";\n\nexport interface ServerCommand {\n\treadonly command: \"server\";\n\treadonly auth?: AuthInput;\n\treadonly provider?: string;\n\treadonly model?: string;\n\treadonly pluginPackages?: readonly string[];\n\treadonly serverId?: ServerId;\n\treadonly sessionDir?: string;\n}\n\nexport interface ServerCommandContext {\n\trunServer(command: ServerCommand): void | Promise<void>;\n}\n\nconst serverIdOption = valueOption(\"--server-id\", (value) =>\n\tisServerId(value)\n\t\t? { ok: true, value }\n\t\t: { ok: false, error: `Invalid --server-id \"${value}\"; expected a lowercase UUIDv4` },\n);\nconst sessionDirOption = stringOption(\"--session-dir\");\nconst providerOption = stringOption(\"--provider\");\nconst modelOption = stringOption(\"--model\");\nconst pluginPackageOption = stringOption(\"-e\", { repeatable: true });\n\nexport const serverCommand = new Command<ServerCommand, ServerCommandContext>(\"server\")\n\t.option(serverIdOption)\n\t.option(sessionDirOption)\n\t.option(providerOption)\n\t.option(modelOption)\n\t.option(pluginPackageOption)\n\t.option(authTokenOption)\n\t.option(authTokenFileOption)\n\t.build((input) => {\n\t\tconst { auth, errors: authErrors } = parseAuth(input);\n\t\tconst serverId = input.value(serverIdOption);\n\t\tconst sessionDir = input.value(sessionDirOption);\n\t\tconst provider = input.value(providerOption);\n\t\tconst model = input.value(modelOption);\n\t\tconst pluginPackages = input.values(pluginPackageOption);\n\t\tconst modelErrors = provider !== undefined && model === undefined ? [\"--provider requires --model\"] : [];\n\t\tconst errors = [...authErrors, ...modelErrors, ...unsupportedOptions(\"server\", input)];\n\t\tif (errors.length > 0) return { ok: false, errors };\n\t\treturn {\n\t\t\tok: true,\n\t\t\tcommand: {\n\t\t\t\tcommand: \"server\",\n\t\t\t\t...(auth === undefined ? {} : { auth }),\n\t\t\t\t...(provider === undefined ? {} : { provider }),\n\t\t\t\t...(model === undefined ? {} : { model }),\n\t\t\t\t...(pluginPackages.length === 0 ? {} : { pluginPackages }),\n\t\t\t\t...(serverId === undefined ? {} : { serverId }),\n\t\t\t\t...(sessionDir === undefined ? {} : { sessionDir }),\n\t\t\t},\n\t\t};\n\t})\n\t.action((command, context) => context.runServer(command));\n"]}
@@ -1,2 +0,0 @@
1
- export * from "@earendil-works/pi-client";
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC","sourcesContent":["export * from \"@earendil-works/pi-client\";\n"]}
@@ -1,2 +0,0 @@
1
- export * from "@earendil-works/pi-client";
2
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,cAAc,2BAA2B,CAAC","sourcesContent":["export * from \"@earendil-works/pi-client\";\n"]}
@@ -1,43 +0,0 @@
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 { ClientCommand } from "../cli/experimental/commands/client.ts";
5
- import { AgentController } from "./services/agent-controller.ts";
6
- import { type ServerServiceSource, type SessionServiceSource } from "./services/connection.ts";
7
- import { Models } from "./services/models.ts";
8
- import { PresentationPlugins } from "./services/plugins.ts";
9
- import { SessionDirectory, SessionManagement } from "./services/sessions.ts";
10
- import { Transcript } from "./services/transcript.ts";
11
- export type ClientRuntimeRoute = ({
12
- readonly transport: "unix";
13
- } & UnixServerRoute) | {
14
- readonly transport: "radius";
15
- readonly serverId: ServerId;
16
- };
17
- export interface ClientRuntimeServer {
18
- readonly route: ClientRuntimeRoute;
19
- readonly client: Client;
20
- readonly server: ServerServiceSource;
21
- readonly session: SessionServiceSource;
22
- }
23
- export interface ActivatedClientRuntimeServer extends ClientRuntimeServer {
24
- readonly directory: SessionDirectory;
25
- readonly management: SessionManagement;
26
- readonly plugins: PresentationPlugins;
27
- readonly models: Models;
28
- readonly agent: AgentController;
29
- readonly transcript: Transcript;
30
- }
31
- export interface ClientRuntime {
32
- readonly servers: readonly ClientRuntimeServer[];
33
- dispose(): Promise<void>;
34
- }
35
- export interface OpenClientRuntimeOptions {
36
- /** Directory searched when --connect is omitted. Defaults to PI_SERVER_DIR or ~/.pi/server. */
37
- readonly directory?: string;
38
- }
39
- /** Open live server/session service namespaces for one experimental presentation. */
40
- export declare function openClientRuntime(command: ClientCommand, options?: OpenClientRuntimeOptions): Promise<ClientRuntime>;
41
- /** Acquire and connect the built-in service facades used by the non-interactive client. */
42
- export declare function activateBuiltinClientServices(server: ClientRuntimeServer): Promise<ActivatedClientRuntimeServer>;
43
- //# sourceMappingURL=client-runtime.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client-runtime.d.ts","sourceRoot":"","sources":["../../src/experimental/client-runtime.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAe,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAmD,KAAK,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACvH,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAI5E,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAGN,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,MAAM,MAAM,kBAAkB,GAC3B,CAAC;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,eAAe,CAAC,GAClD;IAAE,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEjE,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;CACvC;AAED,MAAM,WAAW,4BAA6B,SAAQ,mBAAmB;IACxE,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACjD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,wBAAwB;IACxC,+FAA+F;IAC/F,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,qFAAqF;AACrF,wBAAsB,iBAAiB,CACtC,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,wBAA6B,GACpC,OAAO,CAAC,aAAa,CAAC,CA+HxB;AAED,2FAA2F;AAC3F,wBAAsB,6BAA6B,CAClD,MAAM,EAAE,mBAAmB,GACzB,OAAO,CAAC,4BAA4B,CAAC,CAmCvC","sourcesContent":["import { basename } from \"node:path\";\nimport { BACKGROUND_CONTEXT } from \"@earendil-works/chord/context\";\nimport { Client, ServerError } from \"@earendil-works/pi-client\";\nimport { createUnixTransportFactory, discoverUnixServers, type UnixServerRoute } from \"@earendil-works/pi-client/unix\";\nimport { isServerId, type ServerId } from \"@earendil-works/pi-protocol\";\nimport type { ClientCommand } from \"../cli/experimental/commands/client.ts\";\nimport { RadiusRelayAuthResolver } from \"./radius-auth.ts\";\nimport { createRadiusClientTransportFactory, RadiusClientReconnect } from \"./radius-relay.ts\";\nimport { activateServer, ENV_SERVER_ID, resolveServerDirectory, resolveSessionDirectory } from \"./server.ts\";\nimport { AgentController } from \"./services/agent-controller.ts\";\nimport {\n\tcreateServerServiceSource,\n\tcreateSessionServiceSource,\n\ttype ServerServiceSource,\n\ttype SessionServiceSource,\n} from \"./services/connection.ts\";\nimport { Models } from \"./services/models.ts\";\nimport { PresentationPlugins } from \"./services/plugins.ts\";\nimport { SessionDirectory, SessionManagement } from \"./services/sessions.ts\";\nimport { Transcript } from \"./services/transcript.ts\";\n\nexport type ClientRuntimeRoute =\n\t| ({ readonly transport: \"unix\" } & UnixServerRoute)\n\t| { readonly transport: \"radius\"; readonly serverId: ServerId };\n\nexport interface ClientRuntimeServer {\n\treadonly route: ClientRuntimeRoute;\n\treadonly client: Client;\n\treadonly server: ServerServiceSource;\n\treadonly session: SessionServiceSource;\n}\n\nexport interface ActivatedClientRuntimeServer extends ClientRuntimeServer {\n\treadonly directory: SessionDirectory;\n\treadonly management: SessionManagement;\n\treadonly plugins: PresentationPlugins;\n\treadonly models: Models;\n\treadonly agent: AgentController;\n\treadonly transcript: Transcript;\n}\n\nexport interface ClientRuntime {\n\treadonly servers: readonly ClientRuntimeServer[];\n\tdispose(): Promise<void>;\n}\n\nexport interface OpenClientRuntimeOptions {\n\t/** Directory searched when --connect is omitted. Defaults to PI_SERVER_DIR or ~/.pi/server. */\n\treadonly directory?: string;\n}\n\n/** Open live server/session service namespaces for one experimental presentation. */\nexport async function openClientRuntime(\n\tcommand: ClientCommand,\n\toptions: OpenClientRuntimeOptions = {},\n): Promise<ClientRuntime> {\n\tif (command.auth !== undefined && command.connect?.transport !== \"radius\") {\n\t\tthrow new Error(\"Authentication is only supported for experimental Radius connections\");\n\t}\n\tif (command.provider !== undefined && command.model === undefined) {\n\t\tthrow new Error(\"Server model provider requires a model\");\n\t}\n\tif (command.connect && command.model !== undefined) {\n\t\tthrow new Error(\"Model selection is only valid when automatically activating a new server\");\n\t}\n\tif (command.connect?.transport === \"radius\" && command.pluginPackages !== undefined) {\n\t\tthrow new Error(\"Plugin package paths can only be configured on a local Unix server\");\n\t}\n\tconst directory = resolveServerDirectory(options.directory);\n\tlet routes: ClientRuntimeRoute[];\n\tlet activatedClient: Client | undefined;\n\tif (command.connect) {\n\t\troutes = [\n\t\t\tcommand.connect.transport === \"radius\"\n\t\t\t\t? { transport: \"radius\", serverId: command.connect.serverId }\n\t\t\t\t: { transport: \"unix\", ...routeFromExplicitPath(command.connect.path) },\n\t\t];\n\t} else {\n\t\troutes = (await discoverUnixServers({ directory })).map((route) => ({ transport: \"unix\", ...route }));\n\t\tif (routes.length > 0 && command.model !== undefined) {\n\t\t\tthrow new Error(\"Model selection is only valid when automatically activating a new server\");\n\t\t}\n\t\tif (routes.length === 0) {\n\t\t\tconst activated = await activateServer({\n\t\t\t\tdirectory,\n\t\t\t\trequestedServerId: process.env[ENV_SERVER_ID],\n\t\t\t\tsessionDir: resolveSessionDirectory(),\n\t\t\t\tprovider: command.provider,\n\t\t\t\tmodel: command.model,\n\t\t\t});\n\t\t\troutes = [{ transport: \"unix\", ...activated.route }];\n\t\t\tactivatedClient = activated.client;\n\t\t}\n\t}\n\tif (command.pluginPackages !== undefined && routes.length !== 1) {\n\t\tthrow new Error(\"Plugin selection requires exactly one local server\");\n\t}\n\n\tconst clients: Client[] = [];\n\tconst reconnectors: RadiusClientReconnect[] = [];\n\tconst serviceSources: Array<ServerServiceSource | SessionServiceSource> = [];\n\tconst servers: ClientRuntimeServer[] = [];\n\tlet disposed = false;\n\tconst dispose = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tconst reconnectResults = await Promise.allSettled(reconnectors.map((reconnector) => reconnector.dispose()));\n\t\tconst sourceResults = await Promise.allSettled(\n\t\t\tserviceSources.map((source) => source.dispose(BACKGROUND_CONTEXT)),\n\t\t);\n\t\tconst clientResults = await Promise.allSettled(clients.map((client) => client.dispose()));\n\t\tconst errors = [...reconnectResults, ...sourceResults, ...clientResults].flatMap((result) =>\n\t\t\tresult.status === \"rejected\" ? [result.reason] : [],\n\t\t);\n\t\tif (errors.length === 1) throw errors[0];\n\t\tif (errors.length > 1) throw new AggregateError(errors, \"Failed to dispose experimental client runtime\");\n\t};\n\n\ttry {\n\t\tfor (const route of routes) {\n\t\t\tlet client = activatedClient;\n\t\t\tif (client === undefined) {\n\t\t\t\ttry {\n\t\t\t\t\tclient = await Client.connect({\n\t\t\t\t\t\tserverId: route.serverId,\n\t\t\t\t\t\ttransportFactory:\n\t\t\t\t\t\t\troute.transport === \"unix\"\n\t\t\t\t\t\t\t\t? createUnixTransportFactory({ path: route.path })\n\t\t\t\t\t\t\t\t: createRadiusClientTransportFactory({\n\t\t\t\t\t\t\t\t\t\tserverId: route.serverId,\n\t\t\t\t\t\t\t\t\t\tauth: new RadiusRelayAuthResolver(command.auth),\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tcommand.connect !== undefined ||\n\t\t\t\t\t\troute.transport !== \"unix\" ||\n\t\t\t\t\t\t!(error instanceof ServerError) ||\n\t\t\t\t\t\terror.code !== \"version\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tclient = (\n\t\t\t\t\t\tawait activateServer({\n\t\t\t\t\t\t\tdirectory,\n\t\t\t\t\t\t\trequestedServerId: route.serverId,\n\t\t\t\t\t\t\tsessionDir: resolveSessionDirectory(),\n\t\t\t\t\t\t})\n\t\t\t\t\t).client;\n\t\t\t\t}\n\t\t\t}\n\t\t\tactivatedClient = undefined;\n\t\t\tclients.push(client);\n\t\t\tconst server = createServerServiceSource(client);\n\t\t\tserviceSources.push(server);\n\t\t\tif (route.transport === \"radius\") {\n\t\t\t\tconst reconnectServices = server.open({\n\t\t\t\t\tservices: [SessionManagement],\n\t\t\t\t\tassertAccess() {},\n\t\t\t\t\tonError() {},\n\t\t\t\t});\n\t\t\t\tconst reconnectManagement = reconnectServices.use(SessionManagement);\n\t\t\t\treconnectors.push(\n\t\t\t\t\tnew RadiusClientReconnect(client, async (sessionId) => {\n\t\t\t\t\t\tawait reconnectServices.ready(BACKGROUND_CONTEXT);\n\t\t\t\t\t\tawait reconnectManagement.attach(sessionId, BACKGROUND_CONTEXT);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst session = createSessionServiceSource(client);\n\t\t\tserviceSources.push(session);\n\t\t\tservers.push({ route, client, server, session });\n\t\t}\n\t\treturn { servers, dispose };\n\t} catch (error) {\n\t\ttry {\n\t\t\tawait dispose();\n\t\t} catch (cleanupError) {\n\t\t\tthrow new AggregateError([error, cleanupError], \"Experimental client startup and cleanup failed\");\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/** Acquire and connect the built-in service facades used by the non-interactive client. */\nexport async function activateBuiltinClientServices(\n\tserver: ClientRuntimeServer,\n): Promise<ActivatedClientRuntimeServer> {\n\tconst serverServices = server.server.open({\n\t\tservices: [SessionDirectory, SessionManagement, PresentationPlugins],\n\t\tassertAccess() {},\n\t\tonError() {},\n\t});\n\tconst sessionServices = server.session.open({\n\t\tservices: [Models, AgentController, Transcript],\n\t\tassertAccess() {},\n\t\tonError() {},\n\t});\n\tconst directory = serverServices.use(SessionDirectory);\n\tconst remoteManagement = serverServices.use(SessionManagement);\n\tconst management: SessionManagement = {\n\t\tcreate: (options, context) => remoteManagement.create(options, context),\n\t\tasync remove(sessionId, context) {\n\t\t\tconst removesCurrentAttachment = server.client.attachment?.sessionId === sessionId;\n\t\t\tawait remoteManagement.remove(sessionId, context);\n\t\t\tif (removesCurrentAttachment) await server.session.whenDetached(context);\n\t\t},\n\t\tasync attach(sessionId, context) {\n\t\t\tawait remoteManagement.attach(sessionId, context);\n\t\t\tawait server.session.whenAttached(sessionId, context);\n\t\t},\n\t\tasync detach(context) {\n\t\t\tawait remoteManagement.detach(context);\n\t\t\tawait server.session.whenDetached(context);\n\t\t},\n\t};\n\tconst plugins = serverServices.use(PresentationPlugins);\n\tconst models = sessionServices.use(Models);\n\tconst agent = sessionServices.use(AgentController);\n\tconst transcript = sessionServices.use(Transcript);\n\tawait Promise.all([serverServices.ready(BACKGROUND_CONTEXT), sessionServices.ready(BACKGROUND_CONTEXT)]);\n\treturn { ...server, directory, management, plugins, models, agent, transcript };\n}\n\nfunction routeFromExplicitPath(path: string): UnixServerRoute {\n\tconst name = basename(path);\n\tconst serverId = name.endsWith(\".sock\") ? name.slice(0, -\".sock\".length) : \"\";\n\tif (!isServerId(serverId)) throw new Error(\"--connect path must end with <uuidv4-server-id>.sock\");\n\treturn { serverId, path };\n}\n"]}
@@ -1,183 +0,0 @@
1
- import { basename } from "node:path";
2
- import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
3
- import { Client, ServerError } from "@earendil-works/pi-client";
4
- import { createUnixTransportFactory, discoverUnixServers } from "@earendil-works/pi-client/unix";
5
- import { isServerId } from "@earendil-works/pi-protocol";
6
- import { RadiusRelayAuthResolver } from "./radius-auth.js";
7
- import { createRadiusClientTransportFactory, RadiusClientReconnect } from "./radius-relay.js";
8
- import { activateServer, ENV_SERVER_ID, resolveServerDirectory, resolveSessionDirectory } from "./server.js";
9
- import { AgentController } from "./services/agent-controller.js";
10
- import { createServerServiceSource, createSessionServiceSource, } from "./services/connection.js";
11
- import { Models } from "./services/models.js";
12
- import { PresentationPlugins } from "./services/plugins.js";
13
- import { SessionDirectory, SessionManagement } from "./services/sessions.js";
14
- import { Transcript } from "./services/transcript.js";
15
- /** Open live server/session service namespaces for one experimental presentation. */
16
- export async function openClientRuntime(command, options = {}) {
17
- if (command.auth !== undefined && command.connect?.transport !== "radius") {
18
- throw new Error("Authentication is only supported for experimental Radius connections");
19
- }
20
- if (command.provider !== undefined && command.model === undefined) {
21
- throw new Error("Server model provider requires a model");
22
- }
23
- if (command.connect && command.model !== undefined) {
24
- throw new Error("Model selection is only valid when automatically activating a new server");
25
- }
26
- if (command.connect?.transport === "radius" && command.pluginPackages !== undefined) {
27
- throw new Error("Plugin package paths can only be configured on a local Unix server");
28
- }
29
- const directory = resolveServerDirectory(options.directory);
30
- let routes;
31
- let activatedClient;
32
- if (command.connect) {
33
- routes = [
34
- command.connect.transport === "radius"
35
- ? { transport: "radius", serverId: command.connect.serverId }
36
- : { transport: "unix", ...routeFromExplicitPath(command.connect.path) },
37
- ];
38
- }
39
- else {
40
- routes = (await discoverUnixServers({ directory })).map((route) => ({ transport: "unix", ...route }));
41
- if (routes.length > 0 && command.model !== undefined) {
42
- throw new Error("Model selection is only valid when automatically activating a new server");
43
- }
44
- if (routes.length === 0) {
45
- const activated = await activateServer({
46
- directory,
47
- requestedServerId: process.env[ENV_SERVER_ID],
48
- sessionDir: resolveSessionDirectory(),
49
- provider: command.provider,
50
- model: command.model,
51
- });
52
- routes = [{ transport: "unix", ...activated.route }];
53
- activatedClient = activated.client;
54
- }
55
- }
56
- if (command.pluginPackages !== undefined && routes.length !== 1) {
57
- throw new Error("Plugin selection requires exactly one local server");
58
- }
59
- const clients = [];
60
- const reconnectors = [];
61
- const serviceSources = [];
62
- const servers = [];
63
- let disposed = false;
64
- const dispose = async () => {
65
- if (disposed)
66
- return;
67
- disposed = true;
68
- const reconnectResults = await Promise.allSettled(reconnectors.map((reconnector) => reconnector.dispose()));
69
- const sourceResults = await Promise.allSettled(serviceSources.map((source) => source.dispose(BACKGROUND_CONTEXT)));
70
- const clientResults = await Promise.allSettled(clients.map((client) => client.dispose()));
71
- const errors = [...reconnectResults, ...sourceResults, ...clientResults].flatMap((result) => result.status === "rejected" ? [result.reason] : []);
72
- if (errors.length === 1)
73
- throw errors[0];
74
- if (errors.length > 1)
75
- throw new AggregateError(errors, "Failed to dispose experimental client runtime");
76
- };
77
- try {
78
- for (const route of routes) {
79
- let client = activatedClient;
80
- if (client === undefined) {
81
- try {
82
- client = await Client.connect({
83
- serverId: route.serverId,
84
- transportFactory: route.transport === "unix"
85
- ? createUnixTransportFactory({ path: route.path })
86
- : createRadiusClientTransportFactory({
87
- serverId: route.serverId,
88
- auth: new RadiusRelayAuthResolver(command.auth),
89
- }),
90
- });
91
- }
92
- catch (error) {
93
- if (command.connect !== undefined ||
94
- route.transport !== "unix" ||
95
- !(error instanceof ServerError) ||
96
- error.code !== "version") {
97
- throw error;
98
- }
99
- client = (await activateServer({
100
- directory,
101
- requestedServerId: route.serverId,
102
- sessionDir: resolveSessionDirectory(),
103
- })).client;
104
- }
105
- }
106
- activatedClient = undefined;
107
- clients.push(client);
108
- const server = createServerServiceSource(client);
109
- serviceSources.push(server);
110
- if (route.transport === "radius") {
111
- const reconnectServices = server.open({
112
- services: [SessionManagement],
113
- assertAccess() { },
114
- onError() { },
115
- });
116
- const reconnectManagement = reconnectServices.use(SessionManagement);
117
- reconnectors.push(new RadiusClientReconnect(client, async (sessionId) => {
118
- await reconnectServices.ready(BACKGROUND_CONTEXT);
119
- await reconnectManagement.attach(sessionId, BACKGROUND_CONTEXT);
120
- }));
121
- }
122
- const session = createSessionServiceSource(client);
123
- serviceSources.push(session);
124
- servers.push({ route, client, server, session });
125
- }
126
- return { servers, dispose };
127
- }
128
- catch (error) {
129
- try {
130
- await dispose();
131
- }
132
- catch (cleanupError) {
133
- throw new AggregateError([error, cleanupError], "Experimental client startup and cleanup failed");
134
- }
135
- throw error;
136
- }
137
- }
138
- /** Acquire and connect the built-in service facades used by the non-interactive client. */
139
- export async function activateBuiltinClientServices(server) {
140
- const serverServices = server.server.open({
141
- services: [SessionDirectory, SessionManagement, PresentationPlugins],
142
- assertAccess() { },
143
- onError() { },
144
- });
145
- const sessionServices = server.session.open({
146
- services: [Models, AgentController, Transcript],
147
- assertAccess() { },
148
- onError() { },
149
- });
150
- const directory = serverServices.use(SessionDirectory);
151
- const remoteManagement = serverServices.use(SessionManagement);
152
- const management = {
153
- create: (options, context) => remoteManagement.create(options, context),
154
- async remove(sessionId, context) {
155
- const removesCurrentAttachment = server.client.attachment?.sessionId === sessionId;
156
- await remoteManagement.remove(sessionId, context);
157
- if (removesCurrentAttachment)
158
- await server.session.whenDetached(context);
159
- },
160
- async attach(sessionId, context) {
161
- await remoteManagement.attach(sessionId, context);
162
- await server.session.whenAttached(sessionId, context);
163
- },
164
- async detach(context) {
165
- await remoteManagement.detach(context);
166
- await server.session.whenDetached(context);
167
- },
168
- };
169
- const plugins = serverServices.use(PresentationPlugins);
170
- const models = sessionServices.use(Models);
171
- const agent = sessionServices.use(AgentController);
172
- const transcript = sessionServices.use(Transcript);
173
- await Promise.all([serverServices.ready(BACKGROUND_CONTEXT), sessionServices.ready(BACKGROUND_CONTEXT)]);
174
- return { ...server, directory, management, plugins, models, agent, transcript };
175
- }
176
- function routeFromExplicitPath(path) {
177
- const name = basename(path);
178
- const serverId = name.endsWith(".sock") ? name.slice(0, -".sock".length) : "";
179
- if (!isServerId(serverId))
180
- throw new Error("--connect path must end with <uuidv4-server-id>.sock");
181
- return { serverId, path };
182
- }
183
- //# sourceMappingURL=client-runtime.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client-runtime.js","sourceRoot":"","sources":["../../src/experimental/client-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { basename } from \"node:path\";\nimport { BACKGROUND_CONTEXT } from \"@earendil-works/chord/context\";\nimport { Client, ServerError } from \"@earendil-works/pi-client\";\nimport { createUnixTransportFactory, discoverUnixServers, type UnixServerRoute } from \"@earendil-works/pi-client/unix\";\nimport { isServerId, type ServerId } from \"@earendil-works/pi-protocol\";\nimport type { ClientCommand } from \"../cli/experimental/commands/client.ts\";\nimport { RadiusRelayAuthResolver } from \"./radius-auth.ts\";\nimport { createRadiusClientTransportFactory, RadiusClientReconnect } from \"./radius-relay.ts\";\nimport { activateServer, ENV_SERVER_ID, resolveServerDirectory, resolveSessionDirectory } from \"./server.ts\";\nimport { AgentController } from \"./services/agent-controller.ts\";\nimport {\n\tcreateServerServiceSource,\n\tcreateSessionServiceSource,\n\ttype ServerServiceSource,\n\ttype SessionServiceSource,\n} from \"./services/connection.ts\";\nimport { Models } from \"./services/models.ts\";\nimport { PresentationPlugins } from \"./services/plugins.ts\";\nimport { SessionDirectory, SessionManagement } from \"./services/sessions.ts\";\nimport { Transcript } from \"./services/transcript.ts\";\n\nexport type ClientRuntimeRoute =\n\t| ({ readonly transport: \"unix\" } & UnixServerRoute)\n\t| { readonly transport: \"radius\"; readonly serverId: ServerId };\n\nexport interface ClientRuntimeServer {\n\treadonly route: ClientRuntimeRoute;\n\treadonly client: Client;\n\treadonly server: ServerServiceSource;\n\treadonly session: SessionServiceSource;\n}\n\nexport interface ActivatedClientRuntimeServer extends ClientRuntimeServer {\n\treadonly directory: SessionDirectory;\n\treadonly management: SessionManagement;\n\treadonly plugins: PresentationPlugins;\n\treadonly models: Models;\n\treadonly agent: AgentController;\n\treadonly transcript: Transcript;\n}\n\nexport interface ClientRuntime {\n\treadonly servers: readonly ClientRuntimeServer[];\n\tdispose(): Promise<void>;\n}\n\nexport interface OpenClientRuntimeOptions {\n\t/** Directory searched when --connect is omitted. Defaults to PI_SERVER_DIR or ~/.pi/server. */\n\treadonly directory?: string;\n}\n\n/** Open live server/session service namespaces for one experimental presentation. */\nexport async function openClientRuntime(\n\tcommand: ClientCommand,\n\toptions: OpenClientRuntimeOptions = {},\n): Promise<ClientRuntime> {\n\tif (command.auth !== undefined && command.connect?.transport !== \"radius\") {\n\t\tthrow new Error(\"Authentication is only supported for experimental Radius connections\");\n\t}\n\tif (command.provider !== undefined && command.model === undefined) {\n\t\tthrow new Error(\"Server model provider requires a model\");\n\t}\n\tif (command.connect && command.model !== undefined) {\n\t\tthrow new Error(\"Model selection is only valid when automatically activating a new server\");\n\t}\n\tif (command.connect?.transport === \"radius\" && command.pluginPackages !== undefined) {\n\t\tthrow new Error(\"Plugin package paths can only be configured on a local Unix server\");\n\t}\n\tconst directory = resolveServerDirectory(options.directory);\n\tlet routes: ClientRuntimeRoute[];\n\tlet activatedClient: Client | undefined;\n\tif (command.connect) {\n\t\troutes = [\n\t\t\tcommand.connect.transport === \"radius\"\n\t\t\t\t? { transport: \"radius\", serverId: command.connect.serverId }\n\t\t\t\t: { transport: \"unix\", ...routeFromExplicitPath(command.connect.path) },\n\t\t];\n\t} else {\n\t\troutes = (await discoverUnixServers({ directory })).map((route) => ({ transport: \"unix\", ...route }));\n\t\tif (routes.length > 0 && command.model !== undefined) {\n\t\t\tthrow new Error(\"Model selection is only valid when automatically activating a new server\");\n\t\t}\n\t\tif (routes.length === 0) {\n\t\t\tconst activated = await activateServer({\n\t\t\t\tdirectory,\n\t\t\t\trequestedServerId: process.env[ENV_SERVER_ID],\n\t\t\t\tsessionDir: resolveSessionDirectory(),\n\t\t\t\tprovider: command.provider,\n\t\t\t\tmodel: command.model,\n\t\t\t});\n\t\t\troutes = [{ transport: \"unix\", ...activated.route }];\n\t\t\tactivatedClient = activated.client;\n\t\t}\n\t}\n\tif (command.pluginPackages !== undefined && routes.length !== 1) {\n\t\tthrow new Error(\"Plugin selection requires exactly one local server\");\n\t}\n\n\tconst clients: Client[] = [];\n\tconst reconnectors: RadiusClientReconnect[] = [];\n\tconst serviceSources: Array<ServerServiceSource | SessionServiceSource> = [];\n\tconst servers: ClientRuntimeServer[] = [];\n\tlet disposed = false;\n\tconst dispose = async (): Promise<void> => {\n\t\tif (disposed) return;\n\t\tdisposed = true;\n\t\tconst reconnectResults = await Promise.allSettled(reconnectors.map((reconnector) => reconnector.dispose()));\n\t\tconst sourceResults = await Promise.allSettled(\n\t\t\tserviceSources.map((source) => source.dispose(BACKGROUND_CONTEXT)),\n\t\t);\n\t\tconst clientResults = await Promise.allSettled(clients.map((client) => client.dispose()));\n\t\tconst errors = [...reconnectResults, ...sourceResults, ...clientResults].flatMap((result) =>\n\t\t\tresult.status === \"rejected\" ? [result.reason] : [],\n\t\t);\n\t\tif (errors.length === 1) throw errors[0];\n\t\tif (errors.length > 1) throw new AggregateError(errors, \"Failed to dispose experimental client runtime\");\n\t};\n\n\ttry {\n\t\tfor (const route of routes) {\n\t\t\tlet client = activatedClient;\n\t\t\tif (client === undefined) {\n\t\t\t\ttry {\n\t\t\t\t\tclient = await Client.connect({\n\t\t\t\t\t\tserverId: route.serverId,\n\t\t\t\t\t\ttransportFactory:\n\t\t\t\t\t\t\troute.transport === \"unix\"\n\t\t\t\t\t\t\t\t? createUnixTransportFactory({ path: route.path })\n\t\t\t\t\t\t\t\t: createRadiusClientTransportFactory({\n\t\t\t\t\t\t\t\t\t\tserverId: route.serverId,\n\t\t\t\t\t\t\t\t\t\tauth: new RadiusRelayAuthResolver(command.auth),\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t});\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tcommand.connect !== undefined ||\n\t\t\t\t\t\troute.transport !== \"unix\" ||\n\t\t\t\t\t\t!(error instanceof ServerError) ||\n\t\t\t\t\t\terror.code !== \"version\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t\tclient = (\n\t\t\t\t\t\tawait activateServer({\n\t\t\t\t\t\t\tdirectory,\n\t\t\t\t\t\t\trequestedServerId: route.serverId,\n\t\t\t\t\t\t\tsessionDir: resolveSessionDirectory(),\n\t\t\t\t\t\t})\n\t\t\t\t\t).client;\n\t\t\t\t}\n\t\t\t}\n\t\t\tactivatedClient = undefined;\n\t\t\tclients.push(client);\n\t\t\tconst server = createServerServiceSource(client);\n\t\t\tserviceSources.push(server);\n\t\t\tif (route.transport === \"radius\") {\n\t\t\t\tconst reconnectServices = server.open({\n\t\t\t\t\tservices: [SessionManagement],\n\t\t\t\t\tassertAccess() {},\n\t\t\t\t\tonError() {},\n\t\t\t\t});\n\t\t\t\tconst reconnectManagement = reconnectServices.use(SessionManagement);\n\t\t\t\treconnectors.push(\n\t\t\t\t\tnew RadiusClientReconnect(client, async (sessionId) => {\n\t\t\t\t\t\tawait reconnectServices.ready(BACKGROUND_CONTEXT);\n\t\t\t\t\t\tawait reconnectManagement.attach(sessionId, BACKGROUND_CONTEXT);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst session = createSessionServiceSource(client);\n\t\t\tserviceSources.push(session);\n\t\t\tservers.push({ route, client, server, session });\n\t\t}\n\t\treturn { servers, dispose };\n\t} catch (error) {\n\t\ttry {\n\t\t\tawait dispose();\n\t\t} catch (cleanupError) {\n\t\t\tthrow new AggregateError([error, cleanupError], \"Experimental client startup and cleanup failed\");\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/** Acquire and connect the built-in service facades used by the non-interactive client. */\nexport async function activateBuiltinClientServices(\n\tserver: ClientRuntimeServer,\n): Promise<ActivatedClientRuntimeServer> {\n\tconst serverServices = server.server.open({\n\t\tservices: [SessionDirectory, SessionManagement, PresentationPlugins],\n\t\tassertAccess() {},\n\t\tonError() {},\n\t});\n\tconst sessionServices = server.session.open({\n\t\tservices: [Models, AgentController, Transcript],\n\t\tassertAccess() {},\n\t\tonError() {},\n\t});\n\tconst directory = serverServices.use(SessionDirectory);\n\tconst remoteManagement = serverServices.use(SessionManagement);\n\tconst management: SessionManagement = {\n\t\tcreate: (options, context) => remoteManagement.create(options, context),\n\t\tasync remove(sessionId, context) {\n\t\t\tconst removesCurrentAttachment = server.client.attachment?.sessionId === sessionId;\n\t\t\tawait remoteManagement.remove(sessionId, context);\n\t\t\tif (removesCurrentAttachment) await server.session.whenDetached(context);\n\t\t},\n\t\tasync attach(sessionId, context) {\n\t\t\tawait remoteManagement.attach(sessionId, context);\n\t\t\tawait server.session.whenAttached(sessionId, context);\n\t\t},\n\t\tasync detach(context) {\n\t\t\tawait remoteManagement.detach(context);\n\t\t\tawait server.session.whenDetached(context);\n\t\t},\n\t};\n\tconst plugins = serverServices.use(PresentationPlugins);\n\tconst models = sessionServices.use(Models);\n\tconst agent = sessionServices.use(AgentController);\n\tconst transcript = sessionServices.use(Transcript);\n\tawait Promise.all([serverServices.ready(BACKGROUND_CONTEXT), sessionServices.ready(BACKGROUND_CONTEXT)]);\n\treturn { ...server, directory, management, plugins, models, agent, transcript };\n}\n\nfunction routeFromExplicitPath(path: string): UnixServerRoute {\n\tconst name = basename(path);\n\tconst serverId = name.endsWith(\".sock\") ? name.slice(0, -\".sock\".length) : \"\";\n\tif (!isServerId(serverId)) throw new Error(\"--connect path must end with <uuidv4-server-id>.sock\");\n\treturn { serverId, path };\n}\n"]}
@@ -1,14 +0,0 @@
1
- import type { LaneSnapshot } from "@earendil-works/pi-agent-core";
2
- import { Container, type TUI } from "@earendil-works/pi-tui";
3
- /** Snapshot-driven transcript used by the service-only experimental presentation. */
4
- export declare class ExperimentalChatView {
5
- #private;
6
- readonly transcript: Container;
7
- readonly pendingMessages: Container;
8
- readonly status: Container;
9
- constructor(ui: TUI, cwd: string);
10
- apply(snapshot: LaneSnapshot): void;
11
- refreshTheme(snapshot: LaneSnapshot): void;
12
- dispose(): void;
13
- }
14
- //# sourceMappingURL=client-tui-chat.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client-tui-chat.d.ts","sourceRoot":"","sources":["../../src/experimental/client-tui-chat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAEvF,OAAO,EAAE,SAAS,EAA+B,KAAK,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAiB1F,qFAAqF;AACrF,qBAAa,oBAAoB;;IAGhC,QAAQ,CAAC,UAAU,YAAmB;IACtC,QAAQ,CAAC,eAAe,YAAmB;IAC3C,QAAQ,CAAC,MAAM,YAAmB;IASlC,YAAY,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAG/B;IAED,KAAK,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAiBlC;IAED,YAAY,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAWzC;IAED,OAAO,IAAI,IAAI,CAEd;CA8GD","sourcesContent":["import type { AgentMessage, Entry, LaneSnapshot } from \"@earendil-works/pi-agent-core\";\nimport type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport { Container, Spacer, Text, TruncatedText, type TUI } from \"@earendil-works/pi-tui\";\nimport { createAllToolRenderers } from \"../core/tools/renderers/index.ts\";\nimport { AssistantMessageComponent } from \"../modes/interactive/components/assistant-message.ts\";\nimport { type StatusIndicator, WorkingStatusIndicator } from \"../modes/interactive/components/status-indicator.ts\";\nimport { ToolExecutionComponent, type ToolRenderers } from \"../modes/interactive/components/tool-execution.ts\";\nimport { UserMessageComponent } from \"../modes/interactive/components/user-message.ts\";\nimport { theme } from \"../modes/interactive/theme/theme.ts\";\n\nfunction userMessageText(message: AgentMessage): string {\n\tif (message.role !== \"user\") return \"\";\n\tif (typeof message.content === \"string\") return message.content;\n\treturn message.content\n\t\t.filter((content) => content.type === \"text\")\n\t\t.map((content) => content.text)\n\t\t.join(\"\");\n}\n\n/** Snapshot-driven transcript used by the service-only experimental presentation. */\nexport class ExperimentalChatView {\n\tstatic readonly #renderers: Record<string, ToolRenderers> = createAllToolRenderers();\n\n\treadonly transcript = new Container();\n\treadonly pendingMessages = new Container();\n\treadonly status = new Container();\n\treadonly #ui: TUI;\n\treadonly #cwd: string;\n\treadonly #tools = new Map<string, ToolExecutionComponent>();\n\t#renderedEntryIds: string[] = [];\n\t#streaming: AssistantMessageComponent | undefined;\n\t#indicator: StatusIndicator | undefined;\n\t#working = false;\n\n\tconstructor(ui: TUI, cwd: string) {\n\t\tthis.#ui = ui;\n\t\tthis.#cwd = cwd;\n\t}\n\n\tapply(snapshot: LaneSnapshot): void {\n\t\tthis.#syncTranscript(snapshot.transcript);\n\t\tthis.#syncStreaming(snapshot.operation?.streamingMessage);\n\t\tfor (const tool of snapshot.operation?.runningTools ?? []) {\n\t\t\tconst component = this.#tool(tool.toolName, tool.toolCallId, tool.args);\n\t\t\tif (tool.status === \"running\") {\n\t\t\t\tcomponent.markExecutionStarted();\n\t\t\t\tif (tool.result !== undefined) component.updateResult({ ...tool.result, isError: false }, true);\n\t\t\t} else {\n\t\t\t\tcomponent.updateResult({ ...tool.result, isError: tool.isError }, false);\n\t\t\t}\n\t\t}\n\t\tthis.#syncQueues(snapshot.queues);\n\t\tthis.#setWorking(snapshot.operation !== null);\n\t\tthis.transcript.invalidate();\n\t\tthis.pendingMessages.invalidate();\n\t\tthis.status.invalidate();\n\t}\n\n\trefreshTheme(snapshot: LaneSnapshot): void {\n\t\tthis.#indicator?.dispose();\n\t\tthis.#indicator = undefined;\n\t\tthis.#working = false;\n\t\tthis.transcript.clear();\n\t\tthis.pendingMessages.clear();\n\t\tthis.status.clear();\n\t\tthis.#tools.clear();\n\t\tthis.#renderedEntryIds = [];\n\t\tthis.#streaming = undefined;\n\t\tthis.apply(snapshot);\n\t}\n\n\tdispose(): void {\n\t\tthis.#indicator?.dispose();\n\t}\n\n\t#syncQueues(queues: LaneSnapshot[\"queues\"]): void {\n\t\tthis.pendingMessages.clear();\n\t\tfor (const item of queues) {\n\t\t\tconst text =\n\t\t\t\titem.type === \"message\" ? userMessageText(item.message).replace(/\\s+/g, \" \") : `<${item.customType}>`;\n\t\t\tthis.pendingMessages.addChild(new TruncatedText(theme.fg(\"muted\", `[${item.kind}] ${text}`), 1, 0));\n\t\t}\n\t}\n\n\t#syncTranscript(transcript: readonly Entry[]): void {\n\t\tconst diverged = this.#renderedEntryIds.some((id, index) => transcript[index]?.id !== id);\n\t\tif (diverged) {\n\t\t\tthis.transcript.clear();\n\t\t\tthis.#tools.clear();\n\t\t\tthis.#renderedEntryIds = [];\n\t\t\tthis.#streaming = undefined;\n\t\t}\n\t\tfor (const entry of transcript.slice(this.#renderedEntryIds.length)) {\n\t\t\tthis.#addEntry(entry);\n\t\t\tthis.#renderedEntryIds.push(entry.id);\n\t\t}\n\t}\n\n\t#addEntry(entry: Entry): void {\n\t\tif (entry.type === \"compaction\") {\n\t\t\tthis.#addText(theme.fg(\"muted\", `[compaction] compacted from ${entry.tokensBefore} tokens`));\n\t\t\tfor (const retained of entry.retainedTail) this.#addMessage(retained);\n\t\t\treturn;\n\t\t}\n\t\tif (entry.type === \"branch_summary\") {\n\t\t\tthis.#addText(theme.fg(\"muted\", \"[branch summary]\"));\n\t\t\tthis.#addText(entry.summary);\n\t\t\treturn;\n\t\t}\n\t\tif (entry.type === \"custom\") {\n\t\t\tthis.#addText(theme.fg(\"muted\", `[${entry.customType}]`));\n\t\t\treturn;\n\t\t}\n\t\tthis.#addMessage(entry.message);\n\t}\n\n\t#addMessage(message: AgentMessage): void {\n\t\tif (message.role === \"user\") {\n\t\t\tthis.transcript.addChild(new Spacer(1));\n\t\t\tthis.transcript.addChild(new UserMessageComponent(userMessageText(message)));\n\t\t\treturn;\n\t\t}\n\t\tif (message.role === \"assistant\") {\n\t\t\tconst component = this.#streaming ?? new AssistantMessageComponent();\n\t\t\tif (!this.#streaming) this.transcript.addChild(component);\n\t\t\tthis.#streaming = undefined;\n\t\t\tcomponent.updateContent(message, false);\n\t\t\tfor (const content of message.content) {\n\t\t\t\tif (content.type === \"toolCall\") this.#tool(content.name, content.id, content.arguments).setArgsComplete();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (message.role === \"toolResult\") this.#tool(message.toolName, message.toolCallId).updateResult(message);\n\t}\n\n\t#syncStreaming(message: AssistantMessage | undefined): void {\n\t\tif (!message) return;\n\t\tif (!this.#streaming) {\n\t\t\tthis.#streaming = new AssistantMessageComponent();\n\t\t\tthis.transcript.addChild(this.#streaming);\n\t\t}\n\t\tthis.#streaming.updateContent(message, true);\n\t\tfor (const content of message.content) {\n\t\t\tif (content.type === \"toolCall\") this.#tool(content.name, content.id, content.arguments);\n\t\t}\n\t}\n\n\t#tool(toolName: string, toolCallId: string, args?: unknown): ToolExecutionComponent {\n\t\tconst existing = this.#tools.get(toolCallId);\n\t\tif (existing) {\n\t\t\tif (args !== undefined) existing.updateArgs(args);\n\t\t\treturn existing;\n\t\t}\n\t\tconst component = new ToolExecutionComponent(\n\t\t\ttoolName,\n\t\t\ttoolCallId,\n\t\t\targs ?? {},\n\t\t\t{},\n\t\t\tExperimentalChatView.#renderers[toolName],\n\t\t\tthis.#ui,\n\t\t\tthis.#cwd,\n\t\t);\n\t\tthis.transcript.addChild(component);\n\t\tthis.#tools.set(toolCallId, component);\n\t\treturn component;\n\t}\n\n\t#addText(text: string): void {\n\t\tthis.transcript.addChild(new Spacer(1));\n\t\tthis.transcript.addChild(new Text(text, 1, 0));\n\t}\n\n\t#setWorking(working: boolean): void {\n\t\tif (working === this.#working) return;\n\t\tthis.#working = working;\n\t\tthis.#indicator?.dispose();\n\t\tthis.#indicator = undefined;\n\t\tthis.status.clear();\n\t\tif (working) {\n\t\t\tthis.#indicator = new WorkingStatusIndicator(this.#ui, \"Working... (esc to abort)\");\n\t\t\tthis.status.addChild(this.#indicator);\n\t\t}\n\t}\n}\n"]}
@@ -1,171 +0,0 @@
1
- import { Container, Spacer, Text, TruncatedText } from "@earendil-works/pi-tui";
2
- import { createAllToolRenderers } from "../core/tools/renderers/index.js";
3
- import { AssistantMessageComponent } from "../modes/interactive/components/assistant-message.js";
4
- import { WorkingStatusIndicator } from "../modes/interactive/components/status-indicator.js";
5
- import { ToolExecutionComponent } from "../modes/interactive/components/tool-execution.js";
6
- import { UserMessageComponent } from "../modes/interactive/components/user-message.js";
7
- import { theme } from "../modes/interactive/theme/theme.js";
8
- function userMessageText(message) {
9
- if (message.role !== "user")
10
- return "";
11
- if (typeof message.content === "string")
12
- return message.content;
13
- return message.content
14
- .filter((content) => content.type === "text")
15
- .map((content) => content.text)
16
- .join("");
17
- }
18
- /** Snapshot-driven transcript used by the service-only experimental presentation. */
19
- export class ExperimentalChatView {
20
- static #renderers = createAllToolRenderers();
21
- transcript = new Container();
22
- pendingMessages = new Container();
23
- status = new Container();
24
- #ui;
25
- #cwd;
26
- #tools = new Map();
27
- #renderedEntryIds = [];
28
- #streaming;
29
- #indicator;
30
- #working = false;
31
- constructor(ui, cwd) {
32
- this.#ui = ui;
33
- this.#cwd = cwd;
34
- }
35
- apply(snapshot) {
36
- this.#syncTranscript(snapshot.transcript);
37
- this.#syncStreaming(snapshot.operation?.streamingMessage);
38
- for (const tool of snapshot.operation?.runningTools ?? []) {
39
- const component = this.#tool(tool.toolName, tool.toolCallId, tool.args);
40
- if (tool.status === "running") {
41
- component.markExecutionStarted();
42
- if (tool.result !== undefined)
43
- component.updateResult({ ...tool.result, isError: false }, true);
44
- }
45
- else {
46
- component.updateResult({ ...tool.result, isError: tool.isError }, false);
47
- }
48
- }
49
- this.#syncQueues(snapshot.queues);
50
- this.#setWorking(snapshot.operation !== null);
51
- this.transcript.invalidate();
52
- this.pendingMessages.invalidate();
53
- this.status.invalidate();
54
- }
55
- refreshTheme(snapshot) {
56
- this.#indicator?.dispose();
57
- this.#indicator = undefined;
58
- this.#working = false;
59
- this.transcript.clear();
60
- this.pendingMessages.clear();
61
- this.status.clear();
62
- this.#tools.clear();
63
- this.#renderedEntryIds = [];
64
- this.#streaming = undefined;
65
- this.apply(snapshot);
66
- }
67
- dispose() {
68
- this.#indicator?.dispose();
69
- }
70
- #syncQueues(queues) {
71
- this.pendingMessages.clear();
72
- for (const item of queues) {
73
- const text = item.type === "message" ? userMessageText(item.message).replace(/\s+/g, " ") : `<${item.customType}>`;
74
- this.pendingMessages.addChild(new TruncatedText(theme.fg("muted", `[${item.kind}] ${text}`), 1, 0));
75
- }
76
- }
77
- #syncTranscript(transcript) {
78
- const diverged = this.#renderedEntryIds.some((id, index) => transcript[index]?.id !== id);
79
- if (diverged) {
80
- this.transcript.clear();
81
- this.#tools.clear();
82
- this.#renderedEntryIds = [];
83
- this.#streaming = undefined;
84
- }
85
- for (const entry of transcript.slice(this.#renderedEntryIds.length)) {
86
- this.#addEntry(entry);
87
- this.#renderedEntryIds.push(entry.id);
88
- }
89
- }
90
- #addEntry(entry) {
91
- if (entry.type === "compaction") {
92
- this.#addText(theme.fg("muted", `[compaction] compacted from ${entry.tokensBefore} tokens`));
93
- for (const retained of entry.retainedTail)
94
- this.#addMessage(retained);
95
- return;
96
- }
97
- if (entry.type === "branch_summary") {
98
- this.#addText(theme.fg("muted", "[branch summary]"));
99
- this.#addText(entry.summary);
100
- return;
101
- }
102
- if (entry.type === "custom") {
103
- this.#addText(theme.fg("muted", `[${entry.customType}]`));
104
- return;
105
- }
106
- this.#addMessage(entry.message);
107
- }
108
- #addMessage(message) {
109
- if (message.role === "user") {
110
- this.transcript.addChild(new Spacer(1));
111
- this.transcript.addChild(new UserMessageComponent(userMessageText(message)));
112
- return;
113
- }
114
- if (message.role === "assistant") {
115
- const component = this.#streaming ?? new AssistantMessageComponent();
116
- if (!this.#streaming)
117
- this.transcript.addChild(component);
118
- this.#streaming = undefined;
119
- component.updateContent(message, false);
120
- for (const content of message.content) {
121
- if (content.type === "toolCall")
122
- this.#tool(content.name, content.id, content.arguments).setArgsComplete();
123
- }
124
- return;
125
- }
126
- if (message.role === "toolResult")
127
- this.#tool(message.toolName, message.toolCallId).updateResult(message);
128
- }
129
- #syncStreaming(message) {
130
- if (!message)
131
- return;
132
- if (!this.#streaming) {
133
- this.#streaming = new AssistantMessageComponent();
134
- this.transcript.addChild(this.#streaming);
135
- }
136
- this.#streaming.updateContent(message, true);
137
- for (const content of message.content) {
138
- if (content.type === "toolCall")
139
- this.#tool(content.name, content.id, content.arguments);
140
- }
141
- }
142
- #tool(toolName, toolCallId, args) {
143
- const existing = this.#tools.get(toolCallId);
144
- if (existing) {
145
- if (args !== undefined)
146
- existing.updateArgs(args);
147
- return existing;
148
- }
149
- const component = new ToolExecutionComponent(toolName, toolCallId, args ?? {}, {}, ExperimentalChatView.#renderers[toolName], this.#ui, this.#cwd);
150
- this.transcript.addChild(component);
151
- this.#tools.set(toolCallId, component);
152
- return component;
153
- }
154
- #addText(text) {
155
- this.transcript.addChild(new Spacer(1));
156
- this.transcript.addChild(new Text(text, 1, 0));
157
- }
158
- #setWorking(working) {
159
- if (working === this.#working)
160
- return;
161
- this.#working = working;
162
- this.#indicator?.dispose();
163
- this.#indicator = undefined;
164
- this.status.clear();
165
- if (working) {
166
- this.#indicator = new WorkingStatusIndicator(this.#ui, "Working... (esc to abort)");
167
- this.status.addChild(this.#indicator);
168
- }
169
- }
170
- }
171
- //# sourceMappingURL=client-tui-chat.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client-tui-chat.js","sourceRoot":"","sources":["../../src/experimental/client-tui-chat.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage, Entry, LaneSnapshot } from \"@earendil-works/pi-agent-core\";\nimport type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport { Container, Spacer, Text, TruncatedText, type TUI } from \"@earendil-works/pi-tui\";\nimport { createAllToolRenderers } from \"../core/tools/renderers/index.ts\";\nimport { AssistantMessageComponent } from \"../modes/interactive/components/assistant-message.ts\";\nimport { type StatusIndicator, WorkingStatusIndicator } from \"../modes/interactive/components/status-indicator.ts\";\nimport { ToolExecutionComponent, type ToolRenderers } from \"../modes/interactive/components/tool-execution.ts\";\nimport { UserMessageComponent } from \"../modes/interactive/components/user-message.ts\";\nimport { theme } from \"../modes/interactive/theme/theme.ts\";\n\nfunction userMessageText(message: AgentMessage): string {\n\tif (message.role !== \"user\") return \"\";\n\tif (typeof message.content === \"string\") return message.content;\n\treturn message.content\n\t\t.filter((content) => content.type === \"text\")\n\t\t.map((content) => content.text)\n\t\t.join(\"\");\n}\n\n/** Snapshot-driven transcript used by the service-only experimental presentation. */\nexport class ExperimentalChatView {\n\tstatic readonly #renderers: Record<string, ToolRenderers> = createAllToolRenderers();\n\n\treadonly transcript = new Container();\n\treadonly pendingMessages = new Container();\n\treadonly status = new Container();\n\treadonly #ui: TUI;\n\treadonly #cwd: string;\n\treadonly #tools = new Map<string, ToolExecutionComponent>();\n\t#renderedEntryIds: string[] = [];\n\t#streaming: AssistantMessageComponent | undefined;\n\t#indicator: StatusIndicator | undefined;\n\t#working = false;\n\n\tconstructor(ui: TUI, cwd: string) {\n\t\tthis.#ui = ui;\n\t\tthis.#cwd = cwd;\n\t}\n\n\tapply(snapshot: LaneSnapshot): void {\n\t\tthis.#syncTranscript(snapshot.transcript);\n\t\tthis.#syncStreaming(snapshot.operation?.streamingMessage);\n\t\tfor (const tool of snapshot.operation?.runningTools ?? []) {\n\t\t\tconst component = this.#tool(tool.toolName, tool.toolCallId, tool.args);\n\t\t\tif (tool.status === \"running\") {\n\t\t\t\tcomponent.markExecutionStarted();\n\t\t\t\tif (tool.result !== undefined) component.updateResult({ ...tool.result, isError: false }, true);\n\t\t\t} else {\n\t\t\t\tcomponent.updateResult({ ...tool.result, isError: tool.isError }, false);\n\t\t\t}\n\t\t}\n\t\tthis.#syncQueues(snapshot.queues);\n\t\tthis.#setWorking(snapshot.operation !== null);\n\t\tthis.transcript.invalidate();\n\t\tthis.pendingMessages.invalidate();\n\t\tthis.status.invalidate();\n\t}\n\n\trefreshTheme(snapshot: LaneSnapshot): void {\n\t\tthis.#indicator?.dispose();\n\t\tthis.#indicator = undefined;\n\t\tthis.#working = false;\n\t\tthis.transcript.clear();\n\t\tthis.pendingMessages.clear();\n\t\tthis.status.clear();\n\t\tthis.#tools.clear();\n\t\tthis.#renderedEntryIds = [];\n\t\tthis.#streaming = undefined;\n\t\tthis.apply(snapshot);\n\t}\n\n\tdispose(): void {\n\t\tthis.#indicator?.dispose();\n\t}\n\n\t#syncQueues(queues: LaneSnapshot[\"queues\"]): void {\n\t\tthis.pendingMessages.clear();\n\t\tfor (const item of queues) {\n\t\t\tconst text =\n\t\t\t\titem.type === \"message\" ? userMessageText(item.message).replace(/\\s+/g, \" \") : `<${item.customType}>`;\n\t\t\tthis.pendingMessages.addChild(new TruncatedText(theme.fg(\"muted\", `[${item.kind}] ${text}`), 1, 0));\n\t\t}\n\t}\n\n\t#syncTranscript(transcript: readonly Entry[]): void {\n\t\tconst diverged = this.#renderedEntryIds.some((id, index) => transcript[index]?.id !== id);\n\t\tif (diverged) {\n\t\t\tthis.transcript.clear();\n\t\t\tthis.#tools.clear();\n\t\t\tthis.#renderedEntryIds = [];\n\t\t\tthis.#streaming = undefined;\n\t\t}\n\t\tfor (const entry of transcript.slice(this.#renderedEntryIds.length)) {\n\t\t\tthis.#addEntry(entry);\n\t\t\tthis.#renderedEntryIds.push(entry.id);\n\t\t}\n\t}\n\n\t#addEntry(entry: Entry): void {\n\t\tif (entry.type === \"compaction\") {\n\t\t\tthis.#addText(theme.fg(\"muted\", `[compaction] compacted from ${entry.tokensBefore} tokens`));\n\t\t\tfor (const retained of entry.retainedTail) this.#addMessage(retained);\n\t\t\treturn;\n\t\t}\n\t\tif (entry.type === \"branch_summary\") {\n\t\t\tthis.#addText(theme.fg(\"muted\", \"[branch summary]\"));\n\t\t\tthis.#addText(entry.summary);\n\t\t\treturn;\n\t\t}\n\t\tif (entry.type === \"custom\") {\n\t\t\tthis.#addText(theme.fg(\"muted\", `[${entry.customType}]`));\n\t\t\treturn;\n\t\t}\n\t\tthis.#addMessage(entry.message);\n\t}\n\n\t#addMessage(message: AgentMessage): void {\n\t\tif (message.role === \"user\") {\n\t\t\tthis.transcript.addChild(new Spacer(1));\n\t\t\tthis.transcript.addChild(new UserMessageComponent(userMessageText(message)));\n\t\t\treturn;\n\t\t}\n\t\tif (message.role === \"assistant\") {\n\t\t\tconst component = this.#streaming ?? new AssistantMessageComponent();\n\t\t\tif (!this.#streaming) this.transcript.addChild(component);\n\t\t\tthis.#streaming = undefined;\n\t\t\tcomponent.updateContent(message, false);\n\t\t\tfor (const content of message.content) {\n\t\t\t\tif (content.type === \"toolCall\") this.#tool(content.name, content.id, content.arguments).setArgsComplete();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (message.role === \"toolResult\") this.#tool(message.toolName, message.toolCallId).updateResult(message);\n\t}\n\n\t#syncStreaming(message: AssistantMessage | undefined): void {\n\t\tif (!message) return;\n\t\tif (!this.#streaming) {\n\t\t\tthis.#streaming = new AssistantMessageComponent();\n\t\t\tthis.transcript.addChild(this.#streaming);\n\t\t}\n\t\tthis.#streaming.updateContent(message, true);\n\t\tfor (const content of message.content) {\n\t\t\tif (content.type === \"toolCall\") this.#tool(content.name, content.id, content.arguments);\n\t\t}\n\t}\n\n\t#tool(toolName: string, toolCallId: string, args?: unknown): ToolExecutionComponent {\n\t\tconst existing = this.#tools.get(toolCallId);\n\t\tif (existing) {\n\t\t\tif (args !== undefined) existing.updateArgs(args);\n\t\t\treturn existing;\n\t\t}\n\t\tconst component = new ToolExecutionComponent(\n\t\t\ttoolName,\n\t\t\ttoolCallId,\n\t\t\targs ?? {},\n\t\t\t{},\n\t\t\tExperimentalChatView.#renderers[toolName],\n\t\t\tthis.#ui,\n\t\t\tthis.#cwd,\n\t\t);\n\t\tthis.transcript.addChild(component);\n\t\tthis.#tools.set(toolCallId, component);\n\t\treturn component;\n\t}\n\n\t#addText(text: string): void {\n\t\tthis.transcript.addChild(new Spacer(1));\n\t\tthis.transcript.addChild(new Text(text, 1, 0));\n\t}\n\n\t#setWorking(working: boolean): void {\n\t\tif (working === this.#working) return;\n\t\tthis.#working = working;\n\t\tthis.#indicator?.dispose();\n\t\tthis.#indicator = undefined;\n\t\tthis.status.clear();\n\t\tif (working) {\n\t\t\tthis.#indicator = new WorkingStatusIndicator(this.#ui, \"Working... (esc to abort)\");\n\t\t\tthis.status.addChild(this.#indicator);\n\t\t}\n\t}\n}\n"]}