@atomic-chat/core 0.20.7 → 0.21.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 (303) hide show
  1. package/dist/backend/install/service.d.ts +2 -20
  2. package/dist/backend/install/service.js +1 -0
  3. package/dist/backend/install/service.js.map +1 -1
  4. package/dist/cli/launch.d.ts +23 -3
  5. package/dist/cli/launch.js +59 -8
  6. package/dist/cli/launch.js.map +1 -1
  7. package/dist/cli/main.d.ts +1 -1
  8. package/dist/contracts/diagnostics.d.ts +21 -0
  9. package/dist/contracts/diagnostics.js +70 -0
  10. package/dist/contracts/diagnostics.js.map +1 -0
  11. package/dist/contracts/errors.d.ts +17 -75
  12. package/dist/contracts/errors.js +130 -2
  13. package/dist/contracts/errors.js.map +1 -1
  14. package/dist/contracts/events.d.ts +8 -0
  15. package/dist/contracts/index.d.ts +1 -0
  16. package/dist/contracts/index.js +1 -0
  17. package/dist/contracts/index.js.map +1 -1
  18. package/dist/contracts/settings.d.ts +5 -0
  19. package/dist/contracts/settings.js.map +1 -1
  20. package/dist/core/atomic-core.d.ts +3 -1
  21. package/dist/core/atomic-core.js +6 -2
  22. package/dist/core/atomic-core.js.map +1 -1
  23. package/dist/core/create.js +13 -3
  24. package/dist/core/create.js.map +1 -1
  25. package/dist/core/managed-environment.d.ts +2 -0
  26. package/dist/core/managed-environment.js +2 -0
  27. package/dist/core/managed-environment.js.map +1 -1
  28. package/dist/core/sessions.js +1 -0
  29. package/dist/core/sessions.js.map +1 -1
  30. package/dist/decision/service.d.ts +2 -23
  31. package/dist/decision/service.js +27 -0
  32. package/dist/decision/service.js.map +1 -1
  33. package/dist/decision/wiring.d.ts +2 -0
  34. package/dist/decision/wiring.js +1 -6
  35. package/dist/decision/wiring.js.map +1 -1
  36. package/dist/diffusion/errors.js +3 -3
  37. package/dist/diffusion/errors.js.map +1 -1
  38. package/dist/diffusion/jobs.js +1 -0
  39. package/dist/diffusion/jobs.js.map +1 -1
  40. package/dist/diffusion/remote-job.js +1 -0
  41. package/dist/diffusion/remote-job.js.map +1 -1
  42. package/dist/diffusion/service.d.ts +2 -6
  43. package/dist/diffusion/service.js +1 -0
  44. package/dist/diffusion/service.js.map +1 -1
  45. package/dist/diffusion/session.d.ts +2 -5
  46. package/dist/diffusion/session.js +1 -0
  47. package/dist/diffusion/session.js.map +1 -1
  48. package/dist/diffusion/wiring.d.ts +2 -0
  49. package/dist/diffusion/wiring.js +1 -5
  50. package/dist/diffusion/wiring.js.map +1 -1
  51. package/dist/downloads/downloader.d.ts +2 -18
  52. package/dist/downloads/downloader.js +204 -96
  53. package/dist/downloads/downloader.js.map +1 -1
  54. package/dist/downloads/protocol.d.ts +6 -2
  55. package/dist/downloads/protocol.js +27 -5
  56. package/dist/downloads/protocol.js.map +1 -1
  57. package/dist/embedding/service.d.ts +2 -18
  58. package/dist/embedding/service.js +21 -1
  59. package/dist/embedding/service.js.map +1 -1
  60. package/dist/embedding/wiring.d.ts +2 -0
  61. package/dist/embedding/wiring.js +1 -6
  62. package/dist/embedding/wiring.js.map +1 -1
  63. package/dist/integrations/catalog.d.ts +25 -8
  64. package/dist/integrations/catalog.js +105 -38
  65. package/dist/integrations/catalog.js.map +1 -1
  66. package/dist/integrations/configure/atomic-agent.d.ts +9 -1
  67. package/dist/integrations/configure/atomic-agent.js +42 -3
  68. package/dist/integrations/configure/atomic-agent.js.map +1 -1
  69. package/dist/integrations/configure/backup.d.ts +21 -0
  70. package/dist/integrations/configure/backup.js +52 -0
  71. package/dist/integrations/configure/backup.js.map +1 -0
  72. package/dist/integrations/configure/claude-code.d.ts +11 -4
  73. package/dist/integrations/configure/claude-code.js +73 -24
  74. package/dist/integrations/configure/claude-code.js.map +1 -1
  75. package/dist/integrations/configure/cline.d.ts +14 -4
  76. package/dist/integrations/configure/cline.js +78 -6
  77. package/dist/integrations/configure/cline.js.map +1 -1
  78. package/dist/integrations/configure/codex.d.ts +5 -3
  79. package/dist/integrations/configure/codex.js +12 -5
  80. package/dist/integrations/configure/codex.js.map +1 -1
  81. package/dist/integrations/configure/copilot.d.ts +28 -5
  82. package/dist/integrations/configure/copilot.js +124 -8
  83. package/dist/integrations/configure/copilot.js.map +1 -1
  84. package/dist/integrations/configure/droid.d.ts +13 -7
  85. package/dist/integrations/configure/droid.js +48 -17
  86. package/dist/integrations/configure/droid.js.map +1 -1
  87. package/dist/integrations/configure/dsh.d.ts +36 -20
  88. package/dist/integrations/configure/dsh.js +250 -48
  89. package/dist/integrations/configure/dsh.js.map +1 -1
  90. package/dist/integrations/configure/goose.d.ts +21 -7
  91. package/dist/integrations/configure/goose.js +141 -10
  92. package/dist/integrations/configure/goose.js.map +1 -1
  93. package/dist/integrations/configure/hermes.d.ts +63 -10
  94. package/dist/integrations/configure/hermes.js +360 -75
  95. package/dist/integrations/configure/hermes.js.map +1 -1
  96. package/dist/integrations/configure/json-backup.d.ts +73 -0
  97. package/dist/integrations/configure/json-backup.js +292 -0
  98. package/dist/integrations/configure/json-backup.js.map +1 -0
  99. package/dist/integrations/configure/json-key-backup.d.ts +43 -0
  100. package/dist/integrations/configure/json-key-backup.js +113 -0
  101. package/dist/integrations/configure/json-key-backup.js.map +1 -0
  102. package/dist/integrations/configure/kilo.d.ts +4 -4
  103. package/dist/integrations/configure/kilo.js +6 -9
  104. package/dist/integrations/configure/kilo.js.map +1 -1
  105. package/dist/integrations/configure/legacy-env-block.d.ts +18 -0
  106. package/dist/integrations/configure/legacy-env-block.js +47 -0
  107. package/dist/integrations/configure/legacy-env-block.js.map +1 -0
  108. package/dist/integrations/configure/mimo.d.ts +3 -2
  109. package/dist/integrations/configure/mimo.js +8 -9
  110. package/dist/integrations/configure/mimo.js.map +1 -1
  111. package/dist/integrations/configure/muse.d.ts +3 -3
  112. package/dist/integrations/configure/muse.js +5 -6
  113. package/dist/integrations/configure/muse.js.map +1 -1
  114. package/dist/integrations/configure/openclaude.d.ts +22 -7
  115. package/dist/integrations/configure/openclaude.js +132 -39
  116. package/dist/integrations/configure/openclaude.js.map +1 -1
  117. package/dist/integrations/configure/openclaw.d.ts +19 -5
  118. package/dist/integrations/configure/openclaw.js +79 -23
  119. package/dist/integrations/configure/openclaw.js.map +1 -1
  120. package/dist/integrations/configure/opencode-style.d.ts +53 -11
  121. package/dist/integrations/configure/opencode-style.js +218 -23
  122. package/dist/integrations/configure/opencode-style.js.map +1 -1
  123. package/dist/integrations/configure/opencode.d.ts +5 -4
  124. package/dist/integrations/configure/opencode.js +8 -10
  125. package/dist/integrations/configure/opencode.js.map +1 -1
  126. package/dist/integrations/configure/openhands.d.ts +5 -4
  127. package/dist/integrations/configure/openhands.js +7 -7
  128. package/dist/integrations/configure/openhands.js.map +1 -1
  129. package/dist/integrations/configure/pi.d.ts +6 -5
  130. package/dist/integrations/configure/pi.js +79 -30
  131. package/dist/integrations/configure/pi.js.map +1 -1
  132. package/dist/integrations/configure/poolside.d.ts +5 -4
  133. package/dist/integrations/configure/poolside.js +7 -7
  134. package/dist/integrations/configure/poolside.js.map +1 -1
  135. package/dist/integrations/configure/registry.d.ts +6 -0
  136. package/dist/integrations/configure/registry.js +1 -0
  137. package/dist/integrations/configure/registry.js.map +1 -1
  138. package/dist/integrations/configure/zcode.d.ts +6 -7
  139. package/dist/integrations/configure/zcode.js +26 -11
  140. package/dist/integrations/configure/zcode.js.map +1 -1
  141. package/dist/integrations/configure/zed.d.ts +16 -4
  142. package/dist/integrations/configure/zed.js +61 -13
  143. package/dist/integrations/configure/zed.js.map +1 -1
  144. package/dist/lock/instance-lock.js +7 -3
  145. package/dist/lock/instance-lock.js.map +1 -1
  146. package/dist/models/gguf/kv-cache.d.ts +20 -1
  147. package/dist/models/gguf/kv-cache.js +97 -7
  148. package/dist/models/gguf/kv-cache.js.map +1 -1
  149. package/dist/models/gguf/reader.d.ts +5 -3
  150. package/dist/models/gguf/reader.js +10 -6
  151. package/dist/models/gguf/reader.js.map +1 -1
  152. package/dist/remote-access/manager.d.ts +2 -0
  153. package/dist/remote-access/manager.js +18 -2
  154. package/dist/remote-access/manager.js.map +1 -1
  155. package/dist/runtime/environment/service.d.ts +2 -14
  156. package/dist/runtime/environment/service.js +10 -0
  157. package/dist/runtime/environment/service.js.map +1 -1
  158. package/dist/runtime/environment/wiring.d.ts +2 -23
  159. package/dist/runtime/environment/wiring.js +1 -0
  160. package/dist/runtime/environment/wiring.js.map +1 -1
  161. package/dist/runtime/llamacpp/args.d.ts +14 -0
  162. package/dist/runtime/llamacpp/args.js +48 -4
  163. package/dist/runtime/llamacpp/args.js.map +1 -1
  164. package/dist/runtime/llamacpp/ctx-ladder.d.ts +6 -3
  165. package/dist/runtime/llamacpp/ctx-ladder.js +6 -3
  166. package/dist/runtime/llamacpp/ctx-ladder.js.map +1 -1
  167. package/dist/runtime/llamacpp/errors.d.ts +2 -2
  168. package/dist/runtime/llamacpp/errors.js +29 -19
  169. package/dist/runtime/llamacpp/errors.js.map +1 -1
  170. package/dist/runtime/llamacpp/fit-margin.d.ts +24 -0
  171. package/dist/runtime/llamacpp/fit-margin.js +31 -0
  172. package/dist/runtime/llamacpp/fit-margin.js.map +1 -1
  173. package/dist/runtime/llamacpp/generation-limits.d.ts +45 -0
  174. package/dist/runtime/llamacpp/generation-limits.js +61 -0
  175. package/dist/runtime/llamacpp/generation-limits.js.map +1 -0
  176. package/dist/runtime/llamacpp/load-plan.d.ts +14 -2
  177. package/dist/runtime/llamacpp/load-plan.js +64 -13
  178. package/dist/runtime/llamacpp/load-plan.js.map +1 -1
  179. package/dist/runtime/llamacpp/runtime.d.ts +1 -0
  180. package/dist/runtime/llamacpp/runtime.js +2 -0
  181. package/dist/runtime/llamacpp/runtime.js.map +1 -1
  182. package/dist/runtime/managed-engines/runtime.js +13 -2
  183. package/dist/runtime/managed-engines/runtime.js.map +1 -1
  184. package/dist/runtime/managed-engines/spec.d.ts +6 -0
  185. package/dist/runtime/managed-engines/spec.js.map +1 -1
  186. package/dist/runtime/managed-models/auto-limits.d.ts +47 -0
  187. package/dist/runtime/managed-models/auto-limits.js +60 -0
  188. package/dist/runtime/managed-models/auto-limits.js.map +1 -0
  189. package/dist/runtime/managed-models/index.d.ts +1 -0
  190. package/dist/runtime/managed-models/index.js +1 -0
  191. package/dist/runtime/managed-models/index.js.map +1 -1
  192. package/dist/runtime/mlx/config.d.ts +9 -5
  193. package/dist/runtime/mlx/config.js +12 -6
  194. package/dist/runtime/mlx/config.js.map +1 -1
  195. package/dist/runtime/mlx/model-files.d.ts +9 -0
  196. package/dist/runtime/mlx/model-files.js +26 -0
  197. package/dist/runtime/mlx/model-files.js.map +1 -1
  198. package/dist/runtime/mlx/runtime.d.ts +7 -0
  199. package/dist/runtime/mlx/runtime.js +24 -2
  200. package/dist/runtime/mlx/runtime.js.map +1 -1
  201. package/dist/runtime/sglang/adapter.d.ts +4 -0
  202. package/dist/runtime/sglang/adapter.js +9 -6
  203. package/dist/runtime/sglang/adapter.js.map +1 -1
  204. package/dist/runtime/sglang/engine.js +2 -1
  205. package/dist/runtime/sglang/engine.js.map +1 -1
  206. package/dist/runtime/sglang/memory.d.ts +11 -1
  207. package/dist/runtime/sglang/memory.js +34 -3
  208. package/dist/runtime/sglang/memory.js.map +1 -1
  209. package/dist/runtime/sglang/settings.d.ts +2 -1
  210. package/dist/runtime/sglang/settings.js +11 -7
  211. package/dist/runtime/sglang/settings.js.map +1 -1
  212. package/dist/runtime/vllm/adapter.d.ts +4 -0
  213. package/dist/runtime/vllm/adapter.js +9 -6
  214. package/dist/runtime/vllm/adapter.js.map +1 -1
  215. package/dist/runtime/vllm/engine.js +1 -0
  216. package/dist/runtime/vllm/engine.js.map +1 -1
  217. package/dist/runtime/vllm/memory.d.ts +12 -1
  218. package/dist/runtime/vllm/memory.js +44 -2
  219. package/dist/runtime/vllm/memory.js.map +1 -1
  220. package/dist/runtime/vllm/settings.d.ts +2 -1
  221. package/dist/runtime/vllm/settings.js +12 -7
  222. package/dist/runtime/vllm/settings.js.map +1 -1
  223. package/dist/server/public/context-window.d.ts +29 -0
  224. package/dist/server/public/context-window.js +77 -0
  225. package/dist/server/public/context-window.js.map +1 -0
  226. package/dist/server/public/decision-preview.js +1 -0
  227. package/dist/server/public/decision-preview.js.map +1 -1
  228. package/dist/server/public/errors.d.ts +17 -4
  229. package/dist/server/public/errors.js +58 -8
  230. package/dist/server/public/errors.js.map +1 -1
  231. package/dist/server/public/forward.js +86 -22
  232. package/dist/server/public/forward.js.map +1 -1
  233. package/dist/server/public/index.d.ts +1 -0
  234. package/dist/server/public/index.js +1 -0
  235. package/dist/server/public/index.js.map +1 -1
  236. package/dist/server/public/listing.d.ts +9 -2
  237. package/dist/server/public/listing.js +30 -9
  238. package/dist/server/public/listing.js.map +1 -1
  239. package/dist/server/public/responses.js +9 -5
  240. package/dist/server/public/responses.js.map +1 -1
  241. package/dist/server/public/system-messages.d.ts +39 -0
  242. package/dist/server/public/system-messages.js +166 -0
  243. package/dist/server/public/system-messages.js.map +1 -0
  244. package/dist/server/public/telemetry.d.ts +9 -0
  245. package/dist/server/public/telemetry.js +42 -6
  246. package/dist/server/public/telemetry.js.map +1 -1
  247. package/dist/server/public/thinking.d.ts +26 -0
  248. package/dist/server/public/thinking.js +62 -0
  249. package/dist/server/public/thinking.js.map +1 -0
  250. package/dist/server/public/trace.d.ts +8 -0
  251. package/dist/server/public/trace.js +17 -0
  252. package/dist/server/public/trace.js.map +1 -1
  253. package/dist/server/public/types.d.ts +8 -0
  254. package/dist/server/shims/index.d.ts +1 -0
  255. package/dist/server/shims/index.js +1 -0
  256. package/dist/server/shims/index.js.map +1 -1
  257. package/dist/server/shims/reminders.d.ts +8 -0
  258. package/dist/server/shims/reminders.js +14 -0
  259. package/dist/server/shims/reminders.js.map +1 -0
  260. package/dist/server/shims/responses.d.ts +33 -9
  261. package/dist/server/shims/responses.js +160 -36
  262. package/dist/server/shims/responses.js.map +1 -1
  263. package/dist/settings/default-migrations.d.ts +34 -0
  264. package/dist/settings/default-migrations.js +47 -0
  265. package/dist/settings/default-migrations.js.map +1 -0
  266. package/dist/settings/schema/atomic-prism.json +23 -9
  267. package/dist/settings/schema/llamacpp-upstream.json +23 -9
  268. package/dist/settings/schema/llamacpp.json +23 -9
  269. package/dist/settings/schema/sglang.json +8 -8
  270. package/dist/settings/schema/vllm.json +8 -8
  271. package/dist/settings/schema.js +1 -0
  272. package/dist/settings/schema.js.map +1 -1
  273. package/dist/settings/store.d.ts +6 -0
  274. package/dist/settings/store.js +19 -2
  275. package/dist/settings/store.js.map +1 -1
  276. package/dist/telemetry/diagnostics.d.ts +14 -0
  277. package/dist/telemetry/diagnostics.js +285 -0
  278. package/dist/telemetry/diagnostics.js.map +1 -0
  279. package/dist/telemetry/envelope.d.ts +1 -1
  280. package/dist/telemetry/envelope.js +57 -28
  281. package/dist/telemetry/envelope.js.map +1 -1
  282. package/dist/telemetry/index.d.ts +1 -0
  283. package/dist/telemetry/index.js +1 -0
  284. package/dist/telemetry/index.js.map +1 -1
  285. package/dist/telemetry/policy.d.ts +1 -1
  286. package/dist/telemetry/policy.js +45 -2
  287. package/dist/telemetry/policy.js.map +1 -1
  288. package/dist/telemetry/reporter.d.ts +1 -0
  289. package/dist/telemetry/reporter.js +0 -0
  290. package/dist/telemetry/reporter.js.map +1 -1
  291. package/dist/telemetry/reports.d.ts +2 -7
  292. package/dist/telemetry/reports.js +34 -29
  293. package/dist/telemetry/reports.js.map +1 -1
  294. package/dist/telemetry/stack.d.ts +1 -1
  295. package/dist/telemetry/stack.js +8 -1
  296. package/dist/telemetry/stack.js.map +1 -1
  297. package/dist/telemetry/subscribe.d.ts +1 -1
  298. package/dist/telemetry/subscribe.js +7 -5
  299. package/dist/telemetry/subscribe.js.map +1 -1
  300. package/dist/telemetry/types.d.ts +3 -2
  301. package/dist/version.d.ts +1 -1
  302. package/dist/version.js +1 -1
  303. package/package.json +1 -1
@@ -1,10 +1,33 @@
1
1
  /**
2
- * GitHub Copilot CLI has no provider config file — it reads its BYOK settings from the environment
3
- * at launch — so configuring it means persisting `COPILOT_*` to the shell rc (Windows: `setx`).
4
- * `COPILOT_OFFLINE` is on so no GitHub sign-in is required and traffic stays on the local provider.
2
+ * GitHub Copilot CLI — an `atomic-chat` provider and its model in Copilot's `providers.json`.
3
+ * Twin of `copilot_config.rs` in the app.
5
4
  *
6
- * Copilot is the one agent that OMITS the key variable entirely when there is none, rather than
7
- * writing an `atomic` placeholder: an empty `COPILOT_PROVIDER_API_KEY` would be sent as a credential.
5
+ * Earlier releases persisted `COPILOT_PROVIDER_*`, `COPILOT_MODEL` and `COPILOT_OFFLINE=true`
6
+ * user-wide (a marked block in the shell rc, `setx` on Windows), which put every `copilot` the user
7
+ * ran on the local server — and a `providers.json` with any provider in it overrides those
8
+ * variables anyway. The file is Copilot's documented home for named providers, holds the window
9
+ * limits the variables could not, and lists the model beside the user's own; `launch` selects it for
10
+ * the run through `COPILOT_MODEL=atomic-chat/<model>` (catalog `childEnv`), which Copilot reads like
11
+ * `--model`. Our entries are replaced in place; every other provider and model is kept.
12
+ *
13
+ * Copilot reads `apiKey` literally (no variable references), so a keyed server's key is written into
14
+ * the owner-only file, and a keyless one gets no key at all, as Copilot allows for a local server.
15
+ *
16
+ * Connect also removes exactly the rc blocks an earlier release wrote: a block must open and close
17
+ * with our marker and hold only `export COPILOT_…` and blank lines, or the file stays as it is. The
18
+ * Windows variables are removed by the desktop app.
8
19
  */
9
20
  import type { ConfigureWriter } from './registry.js';
21
+ /** Our provider's `name`; Copilot addresses the model as `atomic-chat/<model id>`. */
22
+ export declare const COPILOT_PROVIDER_NAME = "atomic-chat";
23
+ /**
24
+ * `providers.json` where Copilot reads it: `$COPILOT_PROVIDERS_CONFIG`, else
25
+ * `$COPILOT_HOME/providers.json`, else `~/.copilot/providers.json`.
26
+ */
27
+ export declare function copilotProvidersPath(env: NodeJS.ProcessEnv, home: string): string;
28
+ /**
29
+ * `text` without the blocks an earlier release wrote, or `undefined` when there is nothing it can
30
+ * vouch for.
31
+ */
32
+ export declare function stripLegacyCopilotBlock(text: string): string | undefined;
10
33
  export declare const configureCopilot: ConfigureWriter;
@@ -1,14 +1,130 @@
1
1
  /**
2
- * GitHub Copilot CLI has no provider config file — it reads its BYOK settings from the environment
3
- * at launch — so configuring it means persisting `COPILOT_*` to the shell rc (Windows: `setx`).
4
- * `COPILOT_OFFLINE` is on so no GitHub sign-in is required and traffic stays on the local provider.
2
+ * GitHub Copilot CLI — an `atomic-chat` provider and its model in Copilot's `providers.json`.
3
+ * Twin of `copilot_config.rs` in the app.
5
4
  *
6
- * Copilot is the one agent that OMITS the key variable entirely when there is none, rather than
7
- * writing an `atomic` placeholder: an empty `COPILOT_PROVIDER_API_KEY` would be sent as a credential.
5
+ * Earlier releases persisted `COPILOT_PROVIDER_*`, `COPILOT_MODEL` and `COPILOT_OFFLINE=true`
6
+ * user-wide (a marked block in the shell rc, `setx` on Windows), which put every `copilot` the user
7
+ * ran on the local server — and a `providers.json` with any provider in it overrides those
8
+ * variables anyway. The file is Copilot's documented home for named providers, holds the window
9
+ * limits the variables could not, and lists the model beside the user's own; `launch` selects it for
10
+ * the run through `COPILOT_MODEL=atomic-chat/<model>` (catalog `childEnv`), which Copilot reads like
11
+ * `--model`. Our entries are replaced in place; every other provider and model is kept.
12
+ *
13
+ * Copilot reads `apiKey` literally (no variable references), so a keyed server's key is written into
14
+ * the owner-only file, and a keyless one gets no key at all, as Copilot allows for a local server.
15
+ *
16
+ * Connect also removes exactly the rc blocks an earlier release wrote: a block must open and close
17
+ * with our marker and hold only `export COPILOT_…` and blank lines, or the file stays as it is. The
18
+ * Windows variables are removed by the desktop app.
8
19
  */
20
+ import { AtomicCoreError } from '../../contracts/index.js';
21
+ import { canonicalJson, expandTilde, parseJsonStrict } from '../config-io.js';
22
+ import { knownWindow, outputCap } from './backup.js';
23
+ import { asJsonObject } from './json-tree.js';
9
24
  import { registerWriter } from './registry.js';
10
- import { configureEnvAgent } from './env-agent.js';
11
- const MARKER = '# Atomic Chat - Copilot CLI Config';
12
- export const configureCopilot = (input) => configureEnvAgent(input, { agentId: 'copilot', marker: MARKER, prefix: 'COPILOT_' });
25
+ /** Our provider's `name`; Copilot addresses the model as `atomic-chat/<model id>`. */
26
+ export const COPILOT_PROVIDER_NAME = 'atomic-chat';
27
+ const LEGACY_MARKER = '# Atomic Chat - Copilot CLI Config';
28
+ /** Every rc file an earlier release could have written to. */
29
+ const LEGACY_RC_FILES = ['.zshenv', '.bash_profile', '.bashrc'];
30
+ /**
31
+ * `providers.json` where Copilot reads it: `$COPILOT_PROVIDERS_CONFIG`, else
32
+ * `$COPILOT_HOME/providers.json`, else `~/.copilot/providers.json`.
33
+ */
34
+ export function copilotProvidersPath(env, home) {
35
+ const value = (name) => {
36
+ const raw = env[name]?.trim();
37
+ return raw ? expandTilde(raw, home) : undefined;
38
+ };
39
+ return value('COPILOT_PROVIDERS_CONFIG') ?? `${value('COPILOT_HOME') ?? '.copilot'}/providers.json`;
40
+ }
41
+ const named = (entry, field) => asJsonObject(entry)?.[field] === COPILOT_PROVIDER_NAME;
42
+ /** `root[key]` as a list, created when absent or null (Copilot reads both as empty). */
43
+ function list(root, key, path) {
44
+ const value = root[key];
45
+ if (value === undefined || value === null)
46
+ root[key] = [];
47
+ const out = root[key];
48
+ if (!Array.isArray(out)) {
49
+ throw new AtomicCoreError('IO_ERROR', `\`${key}\` in ${path} is not a list. Fix or remove it and try again.`);
50
+ }
51
+ return out;
52
+ }
53
+ /**
54
+ * `text` without the blocks an earlier release wrote, or `undefined` when there is nothing it can
55
+ * vouch for.
56
+ */
57
+ export function stripLegacyCopilotBlock(text) {
58
+ const isMarker = (line) => line.replace(/[\r\n]+$/, '') === LEGACY_MARKER;
59
+ const lines = text.split(/(?<=\n)/);
60
+ if (!lines.some(isMarker))
61
+ return undefined;
62
+ const kept = [];
63
+ let open = false;
64
+ for (const line of lines) {
65
+ if (isMarker(line)) {
66
+ open = !open;
67
+ continue;
68
+ }
69
+ if (open) {
70
+ const bare = line.replace(/[\r\n]+$/, '');
71
+ if (bare.trim() !== '' && !bare.startsWith('export COPILOT_'))
72
+ return undefined;
73
+ continue;
74
+ }
75
+ kept.push(line);
76
+ }
77
+ return open ? undefined : kept.join('');
78
+ }
79
+ export const configureCopilot = async ({ apiUrl, model, apiKey, fs, env, platform, contextLength, }) => {
80
+ const path = copilotProvidersPath(env, fs.home);
81
+ const text = await fs.read(path);
82
+ const root = asJsonObject(text === undefined ? {} : parseJsonStrict(text, fs.absolute(path)));
83
+ if (!root)
84
+ throw new AtomicCoreError('IO_ERROR', `${fs.absolute(path)} is not a JSON object`);
85
+ const providers = list(root, 'providers', fs.absolute(path));
86
+ const provider = {
87
+ name: COPILOT_PROVIDER_NAME,
88
+ type: 'openai',
89
+ baseUrl: apiUrl,
90
+ ...(apiKey ? { apiKey } : {}),
91
+ };
92
+ const at = providers.findIndex((p) => named(p, 'name'));
93
+ if (at >= 0) {
94
+ providers[at] = provider;
95
+ root['providers'] = providers.filter((p, i) => i <= at || !named(p, 'name'));
96
+ }
97
+ else {
98
+ providers.push(provider);
99
+ }
100
+ const models = list(root, 'models', fs.absolute(path));
101
+ const first = models.findIndex((m) => named(m, 'provider'));
102
+ const others = models.filter((m) => !named(m, 'provider'));
103
+ // A known window becomes Copilot's limits: the reply capped at a quarter of it (8192 at most) and
104
+ // the prompt given the rest. Unknown, Copilot assumes 128K for a model it does not know.
105
+ const window = knownWindow(contextLength);
106
+ const ours = {
107
+ id: model,
108
+ provider: COPILOT_PROVIDER_NAME,
109
+ ...(window !== undefined
110
+ ? {
111
+ maxContextWindowTokens: window,
112
+ maxPromptTokens: window - outputCap(window),
113
+ maxOutputTokens: outputCap(window),
114
+ }
115
+ : {}),
116
+ };
117
+ others.splice(first >= 0 ? Math.min(first, others.length) : others.length, 0, ours);
118
+ root['models'] = others;
119
+ // Plain text keys, the user's own among them.
120
+ await fs.write(path, canonicalJson(root), platform === 'win32' ? {} : { mode: 0o600 });
121
+ for (const rc of LEGACY_RC_FILES) {
122
+ const existing = await fs.read(rc);
123
+ const stripped = existing === undefined ? undefined : stripLegacyCopilotBlock(existing);
124
+ // Written through a symbolic link (dotfile managers link rc files), never over it.
125
+ if (stripped !== undefined)
126
+ await fs.write(await fs.linkTarget(rc), stripped);
127
+ }
128
+ };
13
129
  registerWriter('copilot', configureCopilot);
14
130
  //# sourceMappingURL=copilot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"copilot.js","sourceRoot":"","sources":["../../../src/integrations/configure/copilot.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAElD,MAAM,MAAM,GAAG,oCAAoC,CAAA;AAEnD,MAAM,CAAC,MAAM,gBAAgB,GAAoB,CAAC,KAAK,EAAE,EAAE,CACzD,iBAAiB,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAA;AAEtF,cAAc,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAA"}
1
+ {"version":3,"file":"copilot.js","sourceRoot":"","sources":["../../../src/integrations/configure/copilot.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,18 @@
1
1
  /**
2
- * Factory Droid keeps its BYOK providers in `~/.factory/settings.json` as a `customModels` array,
3
- * and selects one with a top-level `model` string.
2
+ * Factory Droid keeps its BYOK providers in `~/.factory/settings.json` as a `customModels` array.
3
+ * Twin of `droid_config.rs` in the app.
4
4
  *
5
- * The selector is the awkward part: Droid addresses a custom model by its POSITION in the array
6
- * (`custom:<displayName with spaces->dashes>-<index>`), not by name. So the value we write depends
7
- * on where our entry lands — seeding other models first shifts it. We upsert by `displayName`
8
- * (our managed marker) precisely so a rerun replaces our entry in place and the selector stays valid
9
- * instead of appending a duplicate and renumbering the user's models.
5
+ * Droid addresses a custom model by its `id`, `custom:<displayName with dashes>-<n>`; our entry
6
+ * carries `id` and `index` explicitly so the selector cannot drift when other entries move, and we
7
+ * upsert by `displayName` (our managed marker) so a rerun replaces it in place. The default for new
8
+ * sessions lives in `sessionDefaultSettings.model`: Droid moves a legacy top-level `model` there only
9
+ * when that key is empty, so the top-level value earlier releases wrote lost to any default the user
10
+ * had. That one is removed; the default the user had before is kept in the backup sidecar for the
11
+ * desktop's Disconnect.
12
+ *
13
+ * A known served window caps the reply at a quarter of it (8192 at most) and gives Droid the rest
14
+ * as `maxContextLimit`; an unknown one writes neither, where earlier releases claimed 16384 output
15
+ * tokens — the whole of a 16K window.
10
16
  */
11
17
  import type { ConfigureWriter } from './registry.js';
12
18
  export declare const configureDroid: ConfigureWriter;
@@ -1,47 +1,78 @@
1
1
  /**
2
- * Factory Droid keeps its BYOK providers in `~/.factory/settings.json` as a `customModels` array,
3
- * and selects one with a top-level `model` string.
2
+ * Factory Droid keeps its BYOK providers in `~/.factory/settings.json` as a `customModels` array.
3
+ * Twin of `droid_config.rs` in the app.
4
4
  *
5
- * The selector is the awkward part: Droid addresses a custom model by its POSITION in the array
6
- * (`custom:<displayName with spaces->dashes>-<index>`), not by name. So the value we write depends
7
- * on where our entry lands — seeding other models first shifts it. We upsert by `displayName`
8
- * (our managed marker) precisely so a rerun replaces our entry in place and the selector stays valid
9
- * instead of appending a duplicate and renumbering the user's models.
5
+ * Droid addresses a custom model by its `id`, `custom:<displayName with dashes>-<n>`; our entry
6
+ * carries `id` and `index` explicitly so the selector cannot drift when other entries move, and we
7
+ * upsert by `displayName` (our managed marker) so a rerun replaces it in place. The default for new
8
+ * sessions lives in `sessionDefaultSettings.model`: Droid moves a legacy top-level `model` there only
9
+ * when that key is empty, so the top-level value earlier releases wrote lost to any default the user
10
+ * had. That one is removed; the default the user had before is kept in the backup sidecar for the
11
+ * desktop's Disconnect.
12
+ *
13
+ * A known served window caps the reply at a quarter of it (8192 at most) and gives Droid the rest
14
+ * as `maxContextLimit`; an unknown one writes neither, where earlier releases claimed 16384 output
15
+ * tokens — the whole of a 16K window.
10
16
  */
11
17
  import { AtomicCoreError } from '../../contracts/index.js';
12
18
  import { canonicalJson, keyOr, parseJsonStrict } from '../config-io.js';
19
+ import { knownWindow, outputCap, readSidecar, sameJson, writeSidecar } from './backup.js';
13
20
  import { asJsonArray, asJsonObject } from './json-tree.js';
14
21
  import { registerWriter } from './registry.js';
15
22
  const DISPLAY_NAME = 'Atomic Chat';
23
+ /** `custom:` + the display name with whitespace runs turned into dashes. */
24
+ const SELECTOR_PREFIX = 'custom:Atomic-Chat-';
16
25
  const SETTINGS_PATH = '.factory/settings.json';
17
- /** Droid's own ceiling for a generic chat-completions provider; lower values truncate long edits. */
18
- const MAX_OUTPUT_TOKENS = 16_384;
19
- export const configureDroid = async ({ apiUrl, model, apiKey, fs }) => {
26
+ const SESSION_DEFAULTS = 'sessionDefaultSettings';
27
+ const isOurSelector = (value) => typeof value === 'string' && value.startsWith(SELECTOR_PREFIX);
28
+ export const configureDroid = async ({ apiUrl, model, apiKey, fs, platform, contextLength, }) => {
20
29
  const text = await fs.read(SETTINGS_PATH);
21
30
  const parsed = text === undefined ? {} : parseJsonStrict(text, fs.absolute(SETTINGS_PATH));
22
31
  const root = asJsonObject(parsed);
23
32
  if (!root)
24
33
  throw new AtomicCoreError('IO_ERROR', 'settings.json is not a JSON object');
34
+ // What the desktop's Disconnect puts back: the default before the first Connect, kept across
35
+ // reconnects while the file still has ours.
36
+ const currentDefault = asJsonObject(root[SESSION_DEFAULTS])?.['model'];
37
+ const backup = await readSidecar(fs, SETTINGS_PATH);
38
+ const previous = backup !== undefined &&
39
+ currentDefault !== undefined &&
40
+ sameJson(asJsonObject(backup['written'])?.['defaultModel'], currentDefault)
41
+ ? (backup['previous'] ?? null)
42
+ : {
43
+ defaultModel: currentDefault ?? null,
44
+ sessionDefaultSettings: Object.hasOwn(root, SESSION_DEFAULTS),
45
+ };
25
46
  // A `customModels` that is not an array is unusable to Droid anyway, so it is replaced rather than
26
47
  // preserved — unlike the individual entries inside it, which are the user's own providers.
27
48
  const models = asJsonArray(root['customModels']) ?? [];
49
+ const found = models.findIndex((m) => asJsonObject(m)?.['displayName'] === DISPLAY_NAME);
50
+ const index = found >= 0 ? found : models.length;
51
+ const selector = `${SELECTOR_PREFIX}${index}`;
52
+ const window = knownWindow(contextLength);
28
53
  const entry = {
29
54
  model,
55
+ id: selector,
56
+ index,
30
57
  displayName: DISPLAY_NAME,
31
58
  baseUrl: apiUrl,
32
59
  // Droid rejects an empty apiKey outright, so a keyless local server still needs a placeholder.
33
60
  apiKey: keyOr(apiKey, 'atomic'),
34
61
  provider: 'generic-chat-completion-api',
35
- maxOutputTokens: MAX_OUTPUT_TOKENS,
62
+ ...(window !== undefined
63
+ ? { maxOutputTokens: outputCap(window), maxContextLimit: window - outputCap(window) }
64
+ : {}),
36
65
  };
37
- let index = models.findIndex((m) => asJsonObject(m)?.['displayName'] === DISPLAY_NAME);
38
- if (index >= 0)
39
- models[index] = entry;
40
- else
41
- index = models.push(entry) - 1;
66
+ models[index] = entry;
42
67
  root['customModels'] = models;
43
- root['model'] = `custom:${DISPLAY_NAME.split(' ').join('-')}-${index}`;
68
+ // Earlier releases selected us through the legacy top-level key.
69
+ if (isOurSelector(root['model']))
70
+ delete root['model'];
71
+ const defaults = asJsonObject(root[SESSION_DEFAULTS]) ?? {};
72
+ defaults['model'] = selector;
73
+ root[SESSION_DEFAULTS] = defaults;
44
74
  await fs.write(SETTINGS_PATH, canonicalJson(root));
75
+ await writeSidecar(fs, SETTINGS_PATH, { previous, written: { defaultModel: selector } }, platform);
45
76
  };
46
77
  registerWriter('droid', configureDroid);
47
78
  //# sourceMappingURL=droid.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"droid.js","sourceRoot":"","sources":["../../../src/integrations/configure/droid.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEvE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAE9C,MAAM,YAAY,GAAG,aAAa,CAAA;AAClC,MAAM,aAAa,GAAG,wBAAwB,CAAA;AAC9C,qGAAqG;AACrG,MAAM,iBAAiB,GAAG,MAAM,CAAA;AAEhC,MAAM,CAAC,MAAM,cAAc,GAAoB,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE;IACrF,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IACzC,MAAM,MAAM,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAA;IAC1F,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;IACjC,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,eAAe,CAAC,UAAU,EAAE,oCAAoC,CAAC,CAAA;IAEtF,mGAAmG;IACnG,2FAA2F;IAC3F,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,EAAE,CAAA;IACtD,MAAM,KAAK,GAAe;QACxB,KAAK;QACL,WAAW,EAAE,YAAY;QACzB,OAAO,EAAE,MAAM;QACf,+FAA+F;QAC/F,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC;QAC/B,QAAQ,EAAE,6BAA6B;QACvC,eAAe,EAAE,iBAAiB;KACnC,CAAA;IAED,IAAI,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,KAAK,YAAY,CAAC,CAAA;IACtF,IAAI,KAAK,IAAI,CAAC;QAAE,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAA;;QAChC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAEnC,IAAI,CAAC,cAAc,CAAC,GAAG,MAAM,CAAA;IAC7B,IAAI,CAAC,OAAO,CAAC,GAAG,UAAU,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,EAAE,CAAA;IAEtE,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC,CAAA;AACpD,CAAC,CAAA;AAED,cAAc,CAAC,OAAO,EAAE,cAAc,CAAC,CAAA"}
1
+ {"version":3,"file":"droid.js","sourceRoot":"","sources":["../../../src/integrations/configure/droid.ts"],"names":[],"mappings":"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"}
@@ -1,33 +1,49 @@
1
1
  /**
2
- * DeepSeek Harness (`dsh`) reads `$DSH_HOME/settings.yaml` (default `~/.dsh`) live, so pointing it at
3
- * the local server is a single upsert of the `llm-pi-ai.providers.atomic` route — no restart needed.
2
+ * DeepSeek Harness (`dsh`). Twin of `configure_dsh_at` in the app's `commands.rs` and `dsh_config.rs`.
4
3
  *
5
- * This is the only writer here that refuses its input, and the reason is blast radius: dsh rejects
6
- * the ENTIRE `llm-pi-ai` section when one route in it is invalid, taking the user's other providers
7
- * down with it. A route needs `api`, `baseURL` and a non-empty `models` list, so a blank URL or model
8
- * is refused before the tree is touched at all. The credential is validated for the same reason: an
9
- * unquoted dotenv value ends at whitespace or `#`, and a newline would inject a second assignment, so
10
- * a key carrying any of those is rejected — with a message that names the variable and never the
11
- * value, so a rejected key cannot leak into a log or a toast.
4
+ * dsh 0.2 dropped the live `$DSH_HOME/settings.yaml` (default `~/.dsh`): settings now live in the
5
+ * active profile's `cordis.patch.yml`, a YAML list of entry overrides (`- id: llm-pi-ai` /
6
+ * `config: …`), and a leftover `settings.yaml` is merged into that profile once and renamed
7
+ * `settings.yaml.imported`. `dsh web`, which `launch` runs, boots the `web` profile, so the `atomic`
8
+ * route goes under its `llm-pi-ai` row's `providers` and its `agent-default-model` row is set to it,
9
+ * so new sessions open on the local model instead of DeepSeek's. dsh picks both up without a restart.
12
10
  *
13
- * Two more things are load-bearing. The route is replaced WHOLESALE rather than deep-merged: a merge
14
- * would let a stale `apiKeyEnv` from an earlier keyed run survive a keyless run and break every
15
- * request with MISSING_CREDENTIAL. And because the YAML round trip drops comments and expands
16
- * anchors, the pre-existing file is copied to `settings.yaml.atomic-backup` — once, so a later run
17
- * cannot overwrite the true pre-Atomic state with our own generated output.
11
+ * The profile patch is the user's (dsh's Settings page edits it, keeping comments and `!!js`
12
+ * expressions), so only our two rows are re-serialized; every other row, comment and blank line is
13
+ * kept byte for byte. A file whose rows cannot be told apart that way is rewritten whole only when
14
+ * nothing but comments would be lost, and refused when it holds `!!js` expressions. The default the
15
+ * user had is kept in the backup sidecar for the desktop's Disconnect.
16
+ *
17
+ * A `settings.yaml` that is still there is read live by dsh before 0.2 and merged over the profile
18
+ * by 0.2+, so it gets the route too (and our default, when it names one); one is never created, and
19
+ * `settings.yaml.imported` is never touched.
20
+ *
21
+ * This writer refuses its input when it would do harm: dsh rejects the ENTIRE `llm-pi-ai` section
22
+ * when one route in it is invalid, taking the user's other providers down with it. A route needs
23
+ * `api`, `baseURL` and a non-empty `models` list, so a blank URL or model is refused before anything
24
+ * is touched. The credential is validated for the same reason: an unquoted dotenv value ends at
25
+ * whitespace or `#`, and a newline would inject a second assignment, so a key carrying any of those
26
+ * is rejected — with a message that names the variable and never the value. The route is replaced
27
+ * WHOLESALE rather than deep-merged: a merge would let a stale `apiKeyEnv` from an earlier keyed run
28
+ * survive a keyless run and break every request with MISSING_CREDENTIAL.
18
29
  */
19
30
  import type { ConfigureWriter } from './registry.js';
20
31
  type YamlMapping = Record<string, unknown>;
21
32
  /** Reject a value no dotenv line can carry. The message names the variable, never the value. */
22
33
  export declare function dshValidateEnvValue(name: string, value: string): void;
23
- /** The `llm-pi-ai.providers.atomic` node. Keyless omits `apiKeyEnv` rather than writing an empty one. */
24
- export declare function dshRouteNode(apiUrl: string, model: string, withKey: boolean): YamlMapping;
25
34
  /**
26
- * Upsert our route into an already-parsed tree. Pure: no I/O, no environment. Everything outside
27
- * `llm-pi-ai.providers.atomic` is preserved, including relative order — assigning to an existing key
28
- * keeps its position, in JavaScript as in `serde_yaml`'s insertion-ordered mapping.
35
+ * The `atomic` route node. Keyless omits `apiKeyEnv` rather than writing an empty one. A model the
36
+ * pi-ai catalog does not ship falls back to a 262144 window and 32768 output tokens; a known served
37
+ * window is declared instead, with a reply of a quarter of it (8192 at most).
38
+ */
39
+ export declare function dshRouteNode(apiUrl: string, model: string, withKey: boolean, contextLength?: number): YamlMapping;
40
+ /**
41
+ * Upsert our route into an already-parsed legacy `settings.yaml` tree. Pure: no I/O, no environment.
42
+ * Everything outside `llm-pi-ai.providers.atomic` is preserved, including relative order.
29
43
  */
30
- export declare function applyDshProvider(root: unknown, apiUrl: string, model: string, withKey: boolean): unknown;
44
+ export declare function applyDshProvider(root: unknown, apiUrl: string, model: string, withKey: boolean, contextLength?: number): unknown;
45
+ /** A YAML tag such as `!!js`, which a re-serialization would drop. */
46
+ export declare function hasYamlTag(text: string): boolean;
31
47
  /** `$DSH_HOME` when set, else `~/.dsh`. A literal `~` can reach us from a quoted rc-file value. */
32
48
  export declare function dshHome(env: NodeJS.ProcessEnv, home: string): string;
33
49
  export declare const configureDsh: ConfigureWriter;