zcode-acp-server 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/README.md +98 -1
  2. package/README.zh-CN.md +81 -1
  3. package/dist/backend/client.d.ts +12 -4
  4. package/dist/backend/client.d.ts.map +1 -1
  5. package/dist/backend/client.js +72 -7
  6. package/dist/backend/client.js.map +1 -1
  7. package/dist/backend/credentials.d.ts.map +1 -1
  8. package/dist/backend/credentials.js +2 -1
  9. package/dist/backend/credentials.js.map +1 -1
  10. package/dist/backend/listener.d.ts +12 -4
  11. package/dist/backend/listener.d.ts.map +1 -1
  12. package/dist/backend/listener.js +68 -12
  13. package/dist/backend/listener.js.map +1 -1
  14. package/dist/backend/types.d.ts +1 -1
  15. package/dist/backend/types.d.ts.map +1 -1
  16. package/dist/bin/quota.d.ts +54 -0
  17. package/dist/bin/quota.d.ts.map +1 -0
  18. package/dist/bin/quota.js +333 -0
  19. package/dist/bin/quota.js.map +1 -0
  20. package/dist/config/auto-compact.d.ts +23 -0
  21. package/dist/config/auto-compact.d.ts.map +1 -0
  22. package/dist/config/auto-compact.js +67 -0
  23. package/dist/config/auto-compact.js.map +1 -0
  24. package/dist/config/mcp-discovery.d.ts +34 -0
  25. package/dist/config/mcp-discovery.d.ts.map +1 -0
  26. package/dist/config/mcp-discovery.js +153 -0
  27. package/dist/config/mcp-discovery.js.map +1 -0
  28. package/dist/config/model-cache.d.ts +12 -1
  29. package/dist/config/model-cache.d.ts.map +1 -1
  30. package/dist/config/model-cache.js +30 -8
  31. package/dist/config/model-cache.js.map +1 -1
  32. package/dist/config/options.d.ts +87 -9
  33. package/dist/config/options.d.ts.map +1 -1
  34. package/dist/config/options.js +248 -45
  35. package/dist/config/options.js.map +1 -1
  36. package/dist/config/plugin-commands.d.ts +24 -0
  37. package/dist/config/plugin-commands.d.ts.map +1 -0
  38. package/dist/config/plugin-commands.js +107 -0
  39. package/dist/config/plugin-commands.js.map +1 -0
  40. package/dist/config/provider-registry.d.ts +60 -0
  41. package/dist/config/provider-registry.d.ts.map +1 -0
  42. package/dist/config/provider-registry.js +128 -0
  43. package/dist/config/provider-registry.js.map +1 -0
  44. package/dist/config/runtime-model.d.ts +54 -18
  45. package/dist/config/runtime-model.d.ts.map +1 -1
  46. package/dist/config/runtime-model.js +105 -61
  47. package/dist/config/runtime-model.js.map +1 -1
  48. package/dist/config/skill-discovery.d.ts +35 -0
  49. package/dist/config/skill-discovery.d.ts.map +1 -0
  50. package/dist/config/skill-discovery.js +188 -0
  51. package/dist/config/skill-discovery.js.map +1 -0
  52. package/dist/handlers/background-tasks.d.ts +72 -0
  53. package/dist/handlers/background-tasks.d.ts.map +1 -0
  54. package/dist/handlers/background-tasks.js +330 -0
  55. package/dist/handlers/background-tasks.js.map +1 -0
  56. package/dist/handlers/dispatch.d.ts.map +1 -1
  57. package/dist/handlers/dispatch.js +134 -22
  58. package/dist/handlers/dispatch.js.map +1 -1
  59. package/dist/handlers/extensions.d.ts +15 -0
  60. package/dist/handlers/extensions.d.ts.map +1 -1
  61. package/dist/handlers/extensions.js +43 -27
  62. package/dist/handlers/extensions.js.map +1 -1
  63. package/dist/handlers/io.d.ts +11 -2
  64. package/dist/handlers/io.d.ts.map +1 -1
  65. package/dist/handlers/io.js +51 -7
  66. package/dist/handlers/io.js.map +1 -1
  67. package/dist/handlers/server-requests.d.ts +20 -4
  68. package/dist/handlers/server-requests.d.ts.map +1 -1
  69. package/dist/handlers/server-requests.js +293 -63
  70. package/dist/handlers/server-requests.js.map +1 -1
  71. package/dist/handlers/session.d.ts +113 -10
  72. package/dist/handlers/session.d.ts.map +1 -1
  73. package/dist/handlers/session.js +876 -220
  74. package/dist/handlers/session.js.map +1 -1
  75. package/dist/handlers/slash.d.ts +14 -0
  76. package/dist/handlers/slash.d.ts.map +1 -1
  77. package/dist/handlers/slash.js +80 -6
  78. package/dist/handlers/slash.js.map +1 -1
  79. package/dist/index.js +38 -4
  80. package/dist/index.js.map +1 -1
  81. package/dist/interaction/adapter.d.ts +19 -33
  82. package/dist/interaction/adapter.d.ts.map +1 -1
  83. package/dist/interaction/adapter.js +80 -79
  84. package/dist/interaction/adapter.js.map +1 -1
  85. package/dist/lazy-sessions.d.ts +35 -0
  86. package/dist/lazy-sessions.d.ts.map +1 -0
  87. package/dist/lazy-sessions.js +98 -0
  88. package/dist/lazy-sessions.js.map +1 -0
  89. package/dist/quota/cache.d.ts +18 -0
  90. package/dist/quota/cache.d.ts.map +1 -0
  91. package/dist/quota/cache.js +32 -0
  92. package/dist/quota/cache.js.map +1 -0
  93. package/dist/quota/client.d.ts +30 -0
  94. package/dist/quota/client.d.ts.map +1 -0
  95. package/dist/quota/client.js +57 -0
  96. package/dist/quota/client.js.map +1 -0
  97. package/dist/quota/color.d.ts +58 -0
  98. package/dist/quota/color.d.ts.map +1 -0
  99. package/dist/quota/color.js +95 -0
  100. package/dist/quota/color.js.map +1 -0
  101. package/dist/quota/combined.d.ts +66 -0
  102. package/dist/quota/combined.d.ts.map +1 -0
  103. package/dist/quota/combined.js +179 -0
  104. package/dist/quota/combined.js.map +1 -0
  105. package/dist/quota/format.d.ts +105 -0
  106. package/dist/quota/format.d.ts.map +1 -0
  107. package/dist/quota/format.js +219 -0
  108. package/dist/quota/format.js.map +1 -0
  109. package/dist/quota/index.d.ts +23 -0
  110. package/dist/quota/index.d.ts.map +1 -0
  111. package/dist/quota/index.js +42 -0
  112. package/dist/quota/index.js.map +1 -0
  113. package/dist/quota/opencode-go/cache.d.ts +17 -0
  114. package/dist/quota/opencode-go/cache.d.ts.map +1 -0
  115. package/dist/quota/opencode-go/cache.js +31 -0
  116. package/dist/quota/opencode-go/cache.js.map +1 -0
  117. package/dist/quota/opencode-go/client.d.ts +28 -0
  118. package/dist/quota/opencode-go/client.d.ts.map +1 -0
  119. package/dist/quota/opencode-go/client.js +48 -0
  120. package/dist/quota/opencode-go/client.js.map +1 -0
  121. package/dist/quota/opencode-go/config.d.ts +37 -0
  122. package/dist/quota/opencode-go/config.d.ts.map +1 -0
  123. package/dist/quota/opencode-go/config.js +58 -0
  124. package/dist/quota/opencode-go/config.js.map +1 -0
  125. package/dist/quota/opencode-go/format.d.ts +36 -0
  126. package/dist/quota/opencode-go/format.d.ts.map +1 -0
  127. package/dist/quota/opencode-go/format.js +87 -0
  128. package/dist/quota/opencode-go/format.js.map +1 -0
  129. package/dist/quota/opencode-go/index.d.ts +30 -0
  130. package/dist/quota/opencode-go/index.d.ts.map +1 -0
  131. package/dist/quota/opencode-go/index.js +108 -0
  132. package/dist/quota/opencode-go/index.js.map +1 -0
  133. package/dist/quota/opencode-go/parse.d.ts +41 -0
  134. package/dist/quota/opencode-go/parse.d.ts.map +1 -0
  135. package/dist/quota/opencode-go/parse.js +75 -0
  136. package/dist/quota/opencode-go/parse.js.map +1 -0
  137. package/dist/quota/opencode-go/types.d.ts +48 -0
  138. package/dist/quota/opencode-go/types.d.ts.map +1 -0
  139. package/dist/quota/opencode-go/types.js +11 -0
  140. package/dist/quota/opencode-go/types.js.map +1 -0
  141. package/dist/quota/parse.d.ts +33 -0
  142. package/dist/quota/parse.d.ts.map +1 -0
  143. package/dist/quota/parse.js +200 -0
  144. package/dist/quota/parse.js.map +1 -0
  145. package/dist/quota/types.d.ts +72 -0
  146. package/dist/quota/types.d.ts.map +1 -0
  147. package/dist/quota/types.js +10 -0
  148. package/dist/quota/types.js.map +1 -0
  149. package/dist/server.d.ts +104 -0
  150. package/dist/server.d.ts.map +1 -1
  151. package/dist/server.js +119 -2
  152. package/dist/server.js.map +1 -1
  153. package/dist/tasks-index.d.ts +14 -4
  154. package/dist/tasks-index.d.ts.map +1 -1
  155. package/dist/tasks-index.js +145 -46
  156. package/dist/tasks-index.js.map +1 -1
  157. package/dist/translators/event-translator.d.ts +33 -0
  158. package/dist/translators/event-translator.d.ts.map +1 -1
  159. package/dist/translators/event-translator.js +101 -0
  160. package/dist/translators/event-translator.js.map +1 -1
  161. package/dist/translators/index.d.ts +1 -1
  162. package/dist/translators/index.d.ts.map +1 -1
  163. package/dist/translators/index.js +1 -1
  164. package/dist/translators/index.js.map +1 -1
  165. package/dist/translators/projection-differ.d.ts +8 -0
  166. package/dist/translators/projection-differ.d.ts.map +1 -1
  167. package/dist/translators/projection-differ.js +19 -9
  168. package/dist/translators/projection-differ.js.map +1 -1
  169. package/dist/translators/tool-helpers.d.ts +28 -0
  170. package/dist/translators/tool-helpers.d.ts.map +1 -1
  171. package/dist/translators/tool-helpers.js +104 -0
  172. package/dist/translators/tool-helpers.js.map +1 -1
  173. package/dist/translators/types.d.ts +38 -1
  174. package/dist/translators/types.d.ts.map +1 -1
  175. package/dist/translators/types.js.map +1 -1
  176. package/dist/utils.d.ts +35 -6
  177. package/dist/utils.d.ts.map +1 -1
  178. package/dist/utils.js +52 -4
  179. package/dist/utils.js.map +1 -1
  180. package/docs/ARCHITECTURE.md +96 -38
  181. package/docs/BACKLOG.md +57 -0
  182. package/docs/DEVELOPMENT.md +5 -0
  183. package/docs/PROTOCOL.md +270 -5
  184. package/docs/TROUBLESHOOTING.md +98 -14
  185. package/docs/agents/domain.md +51 -0
  186. package/docs/agents/issue-tracker.md +22 -0
  187. package/docs/agents/triage-labels.md +15 -0
  188. package/package.json +6 -5
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Build a provider-registry payload for `workspace/updateProviderRegistry`.
3
+ *
4
+ * The V4 backend doesn't auto-load providers from config.json — the host must
5
+ * push them via this RPC after `session/create`, otherwise third-party
6
+ * providers fail with `provider_not_configured` (misclassified as a network
7
+ * error after turn-retry exhausts). ZCode app does this from its
8
+ * ModelProviderService; the bridge mirrors it by reading config.json directly.
9
+ *
10
+ * Provider element schema (from the backend's `j7t` converter in zcode.cjs):
11
+ * { providerId, apiKey?, apiKeyRequired?, apiFormat?, baseURL?, headers?,
12
+ * kind?, label?, models?, providerOptions?, source? }
13
+ * `apiKey` is a discriminated union `{source:"inline", value:"<key>"}` — a
14
+ * bare string is rejected. `apiFormat` maps from `kind`:
15
+ * anthropic → "anthropic-messages", openai-compatible → "openai-chat-completions".
16
+ */
17
+ import { readFileSync } from "node:fs";
18
+ import { ZCODE_CREDS_PATH, log } from "../utils.js";
19
+ /** Map config.json `kind` → backend `apiFormat`. */
20
+ function apiFormatForKind(kind) {
21
+ if (!kind)
22
+ return undefined;
23
+ if (kind.includes("anthropic"))
24
+ return "anthropic-messages";
25
+ if (kind.includes("openai"))
26
+ return "openai-chat-completions";
27
+ return undefined;
28
+ }
29
+ /**
30
+ * Build a single model element from a config.json model entry.
31
+ *
32
+ * Beyond `{modelId}`, the backend's schema accepts label / contextWindow /
33
+ * maxOutputTokens / reasoning. `reasoning` is the important one: without it
34
+ * the backend falls back to the apiFormat's default thought levels (a 2-state
35
+ * enabled/disabled for anthropic-messages), losing the provider's real
36
+ * variants (e.g. max/high/low) — the session then shows a wrong thought-level
37
+ * dropdown. config.json's `variants`/`defaultVariant` map to the protocol's
38
+ * `levels`/`defaultLevel`.
39
+ *
40
+ * Exported: runtime-model.ts reuses it for the `runtimeModel` overlay — both
41
+ * paths must carry identical model definitions or the overlay (resume /
42
+ * setModel) silently downgrades the session back to the 2-state default.
43
+ */
44
+ export function buildModelElement(modelId, m) {
45
+ const el = { modelId };
46
+ if (m.name)
47
+ el.label = m.name;
48
+ if (m.limit?.context)
49
+ el.contextWindow = m.limit.context;
50
+ if (m.limit?.output)
51
+ el.maxOutputTokens = m.limit.output;
52
+ const variants = m.reasoning?.variants ?? [];
53
+ if (m.reasoning?.enabled && variants.length > 0) {
54
+ const reasoning = {
55
+ enabled: true,
56
+ levels: variants.map((v) => ({ value: v, label: v })),
57
+ };
58
+ if (m.reasoning.defaultVariant)
59
+ reasoning.defaultLevel = m.reasoning.defaultVariant;
60
+ el.reasoning = reasoning;
61
+ }
62
+ return el;
63
+ }
64
+ /** Build a single provider element from a config.json entry. */
65
+ function buildProviderElement(providerId, p) {
66
+ // models MUST be an array — the backend's strict schema rejects the object
67
+ // form ({modelId: {...}}) that config.json uses.
68
+ const models = Object.entries(p.models ?? {}).map(([modelId, m]) => buildModelElement(modelId, m ?? {}));
69
+ const el = {
70
+ providerId,
71
+ kind: p.kind,
72
+ apiFormat: apiFormatForKind(p.kind),
73
+ baseURL: p.options?.baseURL,
74
+ label: p.name ?? providerId,
75
+ models,
76
+ source: p.source ?? "custom",
77
+ };
78
+ if (p.options?.apiKeyRequired !== undefined) {
79
+ el.apiKeyRequired = p.options.apiKeyRequired;
80
+ }
81
+ // apiKey MUST be the inline union shape — a bare string is rejected by the
82
+ // backend's strict schema. When present, the backend stores it into its
83
+ // session secrets and resolves auth from there (no separate headers callback
84
+ // needed for these providers).
85
+ if (p.options?.apiKey) {
86
+ el.apiKey = { source: "inline", value: p.options.apiKey };
87
+ }
88
+ // Omit undefined values so the payload stays clean.
89
+ for (const k of Object.keys(el)) {
90
+ if (el[k] === undefined)
91
+ delete el[k];
92
+ }
93
+ return el;
94
+ }
95
+ /**
96
+ * Build the registry payload from ALL providers in config.json.
97
+ *
98
+ * Unlike `loadAllModels` (dropdown, enabled-only), the registry pushes every
99
+ * configured provider so the backend recognises any of them when a session
100
+ * switches to it. The backend applies its own enable/availability rules.
101
+ */
102
+ export function buildProviderRegistry() {
103
+ const cfg = JSON.parse(readFileSync(ZCODE_CREDS_PATH, "utf8"));
104
+ const providers = Object.entries(cfg.provider ?? {}).map(([pid, p]) => buildProviderElement(pid, p ?? {}));
105
+ const generatedAt = Date.now();
106
+ // revision is a content hash; the backend skips unchanged revisions. A stable
107
+ // JSON hash over provider ids+kinds+baseURLs is enough — apiKey changes are
108
+ // rare and a generatedAt bump alone won't force re-apply (revision is the gate).
109
+ const revision = hashRevision(providers);
110
+ log(`provider-registry: built ${providers.length} provider(s) ` +
111
+ `(ids: ${providers.map((p) => p.providerId).join(", ") || "none"})`);
112
+ return { providers, generatedAt, revision };
113
+ }
114
+ /** Stable short hash over provider ids + kind + baseURL + models (revision gate). */
115
+ function hashRevision(providers) {
116
+ const sig = providers
117
+ .map((p) => `${p.providerId}|${p.kind ?? ""}|${p.baseURL ?? ""}|${JSON.stringify(p.models ?? [])}`)
118
+ .sort()
119
+ .join("\n");
120
+ // FNV-1a 32-bit → hex; cheap, dependency-free, stable.
121
+ let h = 0x811c9dc5;
122
+ for (let i = 0; i < sig.length; i++) {
123
+ h ^= sig.charCodeAt(i);
124
+ h = Math.imul(h, 0x01000193);
125
+ }
126
+ return (h >>> 0).toString(16).padStart(8, "0");
127
+ }
128
+ //# sourceMappingURL=provider-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-registry.js","sourceRoot":"","sources":["../../src/config/provider-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AA8BpD,oDAAoD;AACpD,SAAS,gBAAgB,CAAC,IAAwB;IAChD,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5B,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO,oBAAoB,CAAC;IAC5D,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,yBAAyB,CAAC;IAC9D,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,CAAa;IAC9D,MAAM,EAAE,GAA4B,EAAE,OAAO,EAAE,CAAC;IAChD,IAAI,CAAC,CAAC,IAAI;QAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC;IAC9B,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO;QAAE,EAAE,CAAC,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;IACzD,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM;QAAE,EAAE,CAAC,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;IACzD,MAAM,QAAQ,GAAG,CAAC,CAAC,SAAS,EAAE,QAAQ,IAAI,EAAE,CAAC;IAC7C,IAAI,CAAC,CAAC,SAAS,EAAE,OAAO,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,MAAM,SAAS,GAA4B;YACzC,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;SACtD,CAAC;QACF,IAAI,CAAC,CAAC,SAAS,CAAC,cAAc;YAAE,SAAS,CAAC,YAAY,GAAG,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC;QACpF,EAAE,CAAC,SAAS,GAAG,SAAS,CAAC;IAC3B,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,gEAAgE;AAChE,SAAS,oBAAoB,CAAC,UAAkB,EAAE,CAAgB;IAChE,2EAA2E;IAC3E,iDAAiD;IACjD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CACjE,iBAAiB,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,CACpC,CAAC;IACF,MAAM,EAAE,GAA4B;QAClC,UAAU;QACV,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,SAAS,EAAE,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC;QACnC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO;QAC3B,KAAK,EAAE,CAAC,CAAC,IAAI,IAAI,UAAU;QAC3B,MAAM;QACN,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,QAAQ;KAC7B,CAAC;IACF,IAAI,CAAC,CAAC,OAAO,EAAE,cAAc,KAAK,SAAS,EAAE,CAAC;QAC5C,EAAE,CAAC,cAAc,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC;IAC/C,CAAC;IACD,2EAA2E;IAC3E,wEAAwE;IACxE,6EAA6E;IAC7E,+BAA+B;IAC/B,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QACtB,EAAE,CAAC,MAAM,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;IAC5D,CAAC;IACD,oDAAoD;IACpD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QAChC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS;YAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAgB,CAAC;IAC9E,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CACpE,oBAAoB,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CACnC,CAAC;IACF,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC/B,8EAA8E;IAC9E,4EAA4E;IAC5E,iFAAiF;IACjF,MAAM,QAAQ,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACzC,GAAG,CACD,4BAA4B,SAAS,CAAC,MAAM,eAAe;QACzD,SAAS,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,GAAG,CACtE,CAAC;IACF,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;AAC9C,CAAC;AAED,qFAAqF;AACrF,SAAS,YAAY,CAAC,SAAiD;IACrE,MAAM,GAAG,GAAG,SAAS;SAClB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE,IAAI,CAAC,CAAC,OAAO,IAAI,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;SAClG,IAAI,EAAE;SACN,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,uDAAuD;IACvD,IAAI,CAAC,GAAG,UAAU,CAAC;IACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACjD,CAAC"}
@@ -1,33 +1,69 @@
1
1
  /**
2
2
  * runtimeModel overlay plumbing.
3
3
  *
4
- * The backend resolves auth from its OAuth token store, so the `runtimeModel`
5
- * provider deliberately carries NO `apiKey` (the config.json apiKey is the
6
- * legacy plain key and has expired 401). Two uses:
4
+ * The runtimeModel names the provider+model a session should use. For THIRD-
5
+ * PARTY providers it also carries `apiKey` as `{source:"inline", value:"<key>"}`;
6
+ * the backend resolves model-call auth from the overlay itself, so omitting it
7
+ * yields HTTP 401 "Missing API key". Builtin providers keep using their own
8
+ * OAuth/config auth and never inline a key. `apiFormat` mirrors `kind`.
7
9
  *
8
- * 1. Resume overlay (`buildResumeRuntimeModel`): a resumed session may carry
9
- * a stale provider id in its history that the backend can no longer
10
- * authenticate. Sending the *current* enabled provider's runtimeModel at
11
- * resume makes the backend overlay it and use its own OAuth creds.
10
+ * Two uses:
11
+ *
12
+ * 1. Resume/load overlay (`buildResumeRuntimeModel`): a resumed session may
13
+ * carry a stale/revoked model in its history send fails with "历史模型
14
+ * 不可用". The overlay pins the session onto the default model — the FIRST
15
+ * enabled provider's FIRST model, the same one a fresh `session/new` lands
16
+ * on — so resume never inherits the session's last-used (possibly
17
+ * third-party / unavailable) model.
12
18
  *
13
19
  * 2. Model switch (`applyModelSwitch`): UI/slash model switching goes through
14
- * `session/updateRuntimeModelConfig` with `applyModelSelection:true` (a
15
- * runtime-only change, sidestepping `session/setModel`'s "no loaded config
16
- * file" persistence failure).
20
+ * `session/setModel` with both a `model` ref and a `runtimeModel` provider
21
+ * definition (runtime-only via `persistAsWorkspaceLastUsed:false`).
22
+ *
23
+ * Note: a provider registry push (`workspace/updateProviderRegistry`) is ALSO
24
+ * required for the backend to recognise third-party providers at all — without
25
+ * it the turn fails with `provider_not_configured` before auth is even tried.
26
+ * See provider-registry.ts.
17
27
  */
28
+ import { formatModelValue } from "./options.js";
29
+ import type { ModelRef } from "./options.js";
18
30
  import type { ZcodeAcpServer } from "../server.js";
19
- /** Build a runtimeModel overlay object for the enabled provider. */
20
- export declare function buildRuntimeModel(modelId?: string, revision?: string): unknown | null;
21
- /** Build the resume-time overlay (current enabled provider, default model). */
31
+ /**
32
+ * Build a runtimeModel overlay for the given provider+model.
33
+ *
34
+ * For THIRD-PARTY providers the overlay MUST carry `apiKey` as the inline union
35
+ * `{source:"inline", value:"<key>"}` — the backend resolves model-call auth from
36
+ * the runtimeModel itself, so omitting it yields HTTP 401 "Missing API key".
37
+ * (This was previously believed unnecessary; live probing proved otherwise.)
38
+ * Builtin providers resolve auth from their own OAuth/config store, so no
39
+ * apiKey is sent for them. `apiFormat` mirrors `kind` per the backend's catalog.
40
+ */
41
+ export declare function buildRuntimeModel(ref: ModelRef, revision?: string): unknown | null;
42
+ /**
43
+ * Build the resume-time overlay pinned to the default model: the FIRST enabled
44
+ * provider's FIRST model (the same one a fresh `session/new` lands on). This
45
+ * ensures resume never inherits the session's last-used model, which may be a
46
+ * now-unavailable third-party model (e.g. Nvidia) and cause "历史模型不可用".
47
+ */
22
48
  export declare function buildResumeRuntimeModel(): unknown | null;
23
49
  /**
24
- * Switch a session's model via session/updateRuntimeModelConfig.
50
+ * Switch a session's model via `session/setModel`.
51
+ *
52
+ * `value` is the configOption value: either `"providerId\modelId"` (encoded) or
53
+ * a legacy plain modelId (resolved to the first enabled builtin provider).
54
+ *
55
+ * Sends BOTH a `model` ref (the target) AND a `runtimeModel` (the full provider
56
+ * definition). The runtimeModel lets the backend register the provider into its
57
+ * workspace catalog (so even third-party / non-default models are recognised),
58
+ * while `model` names the selection. `persistAsWorkspaceLastUsed:false` keeps
59
+ * this a runtime-only change. Invalidates the model cache on success.
25
60
  *
26
- * Uses `applyModelSelection:true` so the change applies at runtime without
27
- * persistencesidestepping `session/setModel`'s "no loaded config file"
28
- * failure. Invalidates the model cache on success. Returns true on success.
61
+ * NOTE: the older `session/updateRuntimeModelConfig` path returns `changed:false`
62
+ * on current backends without applying — `session/setModel` is the working
63
+ * protocol since the backend model-management refactor.
29
64
  */
30
- export declare function applyModelSwitch(server: ZcodeAcpServer, zcodeSid: string, modelId: string): Promise<boolean>;
65
+ export declare function applyModelSwitch(server: ZcodeAcpServer, zcodeSid: string, value: string): Promise<boolean>;
31
66
  /** Invalidate the session-level model cache after a switch. */
32
67
  export declare function invalidateModelCache(server: ZcodeAcpServer, zcodeSid: string): void;
68
+ export { formatModelValue };
33
69
  //# sourceMappingURL=runtime-model.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-model.d.ts","sourceRoot":"","sources":["../../src/config/runtime-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAoDnD,oEAAoE;AACpE,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,SAAW,GAAG,OAAO,GAAG,IAAI,CAcvF;AAED,+EAA+E;AAC/E,wBAAgB,uBAAuB,IAAI,OAAO,GAAG,IAAI,CAExD;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,CAmBlB;AAED,+DAA+D;AAC/D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAEnF"}
1
+ {"version":3,"file":"runtime-model.d.ts","sourceRoot":"","sources":["../../src/config/runtime-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAEL,gBAAgB,EAIjB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAWnD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,SAAW,GAAG,OAAO,GAAG,IAAI,CAkCpF;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,IAAI,OAAO,GAAG,IAAI,CAOxD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CAyBlB;AAED,+DAA+D;AAC/D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAEnF;AAGD,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
@@ -1,87 +1,129 @@
1
1
  /**
2
2
  * runtimeModel overlay plumbing.
3
3
  *
4
- * The backend resolves auth from its OAuth token store, so the `runtimeModel`
5
- * provider deliberately carries NO `apiKey` (the config.json apiKey is the
6
- * legacy plain key and has expired 401). Two uses:
4
+ * The runtimeModel names the provider+model a session should use. For THIRD-
5
+ * PARTY providers it also carries `apiKey` as `{source:"inline", value:"<key>"}`;
6
+ * the backend resolves model-call auth from the overlay itself, so omitting it
7
+ * yields HTTP 401 "Missing API key". Builtin providers keep using their own
8
+ * OAuth/config auth and never inline a key. `apiFormat` mirrors `kind`.
7
9
  *
8
- * 1. Resume overlay (`buildResumeRuntimeModel`): a resumed session may carry
9
- * a stale provider id in its history that the backend can no longer
10
- * authenticate. Sending the *current* enabled provider's runtimeModel at
11
- * resume makes the backend overlay it and use its own OAuth creds.
10
+ * Two uses:
11
+ *
12
+ * 1. Resume/load overlay (`buildResumeRuntimeModel`): a resumed session may
13
+ * carry a stale/revoked model in its history send fails with "历史模型
14
+ * 不可用". The overlay pins the session onto the default model — the FIRST
15
+ * enabled provider's FIRST model, the same one a fresh `session/new` lands
16
+ * on — so resume never inherits the session's last-used (possibly
17
+ * third-party / unavailable) model.
12
18
  *
13
19
  * 2. Model switch (`applyModelSwitch`): UI/slash model switching goes through
14
- * `session/updateRuntimeModelConfig` with `applyModelSelection:true` (a
15
- * runtime-only change, sidestepping `session/setModel`'s "no loaded config
16
- * file" persistence failure).
20
+ * `session/setModel` with both a `model` ref and a `runtimeModel` provider
21
+ * definition (runtime-only via `persistAsWorkspaceLastUsed:false`).
22
+ *
23
+ * Note: a provider registry push (`workspace/updateProviderRegistry`) is ALSO
24
+ * required for the backend to recognise third-party providers at all — without
25
+ * it the turn fails with `provider_not_configured` before auth is even tried.
26
+ * See provider-registry.ts.
17
27
  */
18
- import { readFileSync } from "node:fs";
19
- import { ZCODE_CREDS_PATH, log, warn } from "../utils.js";
20
- const DEFAULTS = {
21
- providerId: "builtin:bigmodel-coding-plan",
22
- kind: "anthropic",
23
- baseURL: "https://open.bigmodel.cn/api/anthropic",
24
- modelId: "GLM-5.2",
25
- models: ["GLM-5.2"],
26
- };
27
- /** Read the enabled provider's config from config.json (no apiKey). */
28
- function readEnabledProvider() {
29
- try {
30
- const cfg = JSON.parse(readFileSync(ZCODE_CREDS_PATH, "utf8"));
31
- for (const [pid, p] of Object.entries(cfg.provider ?? {})) {
32
- if (p?.enabled) {
33
- const opts = p.options ?? {};
34
- const modelKeys = Object.keys(p.models ?? {});
35
- return {
36
- providerId: pid,
37
- kind: p.kind ?? DEFAULTS.kind,
38
- baseURL: opts.baseURL || DEFAULTS.baseURL,
39
- modelId: modelKeys[0] ?? DEFAULTS.modelId,
40
- models: modelKeys.length > 0 ? modelKeys : DEFAULTS.models,
41
- };
42
- }
43
- }
28
+ import { buildModelElement } from "./provider-registry.js";
29
+ import { findProviderConfig, formatModelValue, isBuiltinProvider, loadAllModels, parseModelValue, } from "./options.js";
30
+ import { log, warn } from "../utils.js";
31
+ const DEFAULT_KIND = "anthropic";
32
+ const DEFAULT_BASE_URL = "https://open.bigmodel.cn/api/anthropic";
33
+ /** Map config.json `kind` → backend `apiFormat`. */
34
+ function apiFormatForKind(kind) {
35
+ if (kind?.includes("anthropic"))
36
+ return "anthropic-messages";
37
+ return "openai-chat-completions";
38
+ }
39
+ /**
40
+ * Build a runtimeModel overlay for the given provider+model.
41
+ *
42
+ * For THIRD-PARTY providers the overlay MUST carry `apiKey` as the inline union
43
+ * `{source:"inline", value:"<key>"}` the backend resolves model-call auth from
44
+ * the runtimeModel itself, so omitting it yields HTTP 401 "Missing API key".
45
+ * (This was previously believed unnecessary; live probing proved otherwise.)
46
+ * Builtin providers resolve auth from their own OAuth/config store, so no
47
+ * apiKey is sent for them. `apiFormat` mirrors `kind` per the backend's catalog.
48
+ */
49
+ export function buildRuntimeModel(ref, revision = "bridge") {
50
+ const p = findProviderConfig(ref.providerId);
51
+ if (!p) {
52
+ log(`runtime-model: provider "${ref.providerId}" not in config.json`);
53
+ return null;
44
54
  }
45
- catch (e) {
46
- log(`runtime-model: read config.json failed (${e instanceof Error ? e.message : String(e)})`);
55
+ const baseURL = p.options?.baseURL ?? DEFAULT_BASE_URL;
56
+ // Model elements must carry the full definition (reasoning variants /
57
+ // contextWindow / label) — a bare {modelId} overlay makes the backend fall
58
+ // back to the apiFormat's default 2-state thought levels (enabled/disabled),
59
+ // silently resetting the session's max/high/low dropdown on resume/switch.
60
+ const models = Object.entries(p.models ?? {}).map(([modelId, m]) => buildModelElement(modelId, (m ?? {})));
61
+ if (models.length === 0)
62
+ models.push({ modelId: ref.modelId });
63
+ const provider = {
64
+ providerId: ref.providerId,
65
+ kind: p.kind ?? DEFAULT_KIND,
66
+ apiFormat: apiFormatForKind(p.kind),
67
+ baseURL,
68
+ models,
69
+ };
70
+ // Third-party providers must inline their apiKey — the backend won't resolve
71
+ // it from anywhere else and the call fails with 401 without it. Builtin
72
+ // providers use OAuth/config auth and must NOT send an inline key.
73
+ if (!isBuiltinProvider(ref.providerId) && p.options?.apiKey) {
74
+ provider.apiKey = { source: "inline", value: p.options.apiKey };
47
75
  }
48
- return DEFAULTS;
49
- }
50
- /** Build a runtimeModel overlay object for the enabled provider. */
51
- export function buildRuntimeModel(modelId, revision = "bridge") {
52
- const pc = readEnabledProvider();
53
- const targetModel = modelId ?? pc.modelId;
54
76
  return {
55
77
  revision,
56
78
  generatedAt: Date.now(),
57
- model: { providerId: pc.providerId, modelId: targetModel },
58
- provider: {
59
- providerId: pc.providerId,
60
- kind: pc.kind,
61
- baseURL: pc.baseURL,
62
- models: pc.models.map((m) => ({ modelId: m })),
63
- },
79
+ model: { providerId: ref.providerId, modelId: ref.modelId },
80
+ provider,
64
81
  };
65
82
  }
66
- /** Build the resume-time overlay (current enabled provider, default model). */
83
+ /**
84
+ * Build the resume-time overlay pinned to the default model: the FIRST enabled
85
+ * provider's FIRST model (the same one a fresh `session/new` lands on). This
86
+ * ensures resume never inherits the session's last-used model, which may be a
87
+ * now-unavailable third-party model (e.g. Nvidia) and cause "历史模型不可用".
88
+ */
67
89
  export function buildResumeRuntimeModel() {
68
- return buildRuntimeModel(undefined, "bridge-resume");
90
+ const first = loadAllModels()[0];
91
+ if (!first) {
92
+ log("runtime-model: no enabled provider in config.json (resume overlay skipped)");
93
+ return null;
94
+ }
95
+ return buildRuntimeModel(first, "bridge-resume");
69
96
  }
70
97
  /**
71
- * Switch a session's model via session/updateRuntimeModelConfig.
98
+ * Switch a session's model via `session/setModel`.
99
+ *
100
+ * `value` is the configOption value: either `"providerId\modelId"` (encoded) or
101
+ * a legacy plain modelId (resolved to the first enabled builtin provider).
102
+ *
103
+ * Sends BOTH a `model` ref (the target) AND a `runtimeModel` (the full provider
104
+ * definition). The runtimeModel lets the backend register the provider into its
105
+ * workspace catalog (so even third-party / non-default models are recognised),
106
+ * while `model` names the selection. `persistAsWorkspaceLastUsed:false` keeps
107
+ * this a runtime-only change. Invalidates the model cache on success.
72
108
  *
73
- * Uses `applyModelSelection:true` so the change applies at runtime without
74
- * persistencesidestepping `session/setModel`'s "no loaded config file"
75
- * failure. Invalidates the model cache on success. Returns true on success.
109
+ * NOTE: the older `session/updateRuntimeModelConfig` path returns `changed:false`
110
+ * on current backends without applying — `session/setModel` is the working
111
+ * protocol since the backend model-management refactor.
76
112
  */
77
- export async function applyModelSwitch(server, zcodeSid, modelId) {
78
- const runtimeModel = buildRuntimeModel(modelId, "bridge-switch");
113
+ export async function applyModelSwitch(server, zcodeSid, value) {
114
+ const { providerId, modelId } = parseModelValue(value);
115
+ const runtimeModel = buildRuntimeModel({ providerId, providerName: providerId, modelId });
79
116
  if (runtimeModel === null) {
80
- log("runtime-model: cannot read provider config (config.json)");
117
+ log(`runtime-model: cannot build overlay for "${value}" (provider not found)`);
81
118
  return false;
82
119
  }
83
120
  const backend = server.ensureBackend();
84
- const resp = await backend.request(server.nextId(), "session/updateRuntimeModelConfig", { sessionId: zcodeSid, runtimeModel, applyModelSelection: true }, 15000);
121
+ const resp = await backend.request(server.nextId(), "session/setModel", {
122
+ sessionId: zcodeSid,
123
+ model: { providerId, modelId },
124
+ runtimeModel,
125
+ persistAsWorkspaceLastUsed: false,
126
+ }, 15000);
85
127
  if (resp.error) {
86
128
  warn(`runtime-model: switch failed: ${resp.error.message}`);
87
129
  return false;
@@ -93,4 +135,6 @@ export async function applyModelSwitch(server, zcodeSid, modelId) {
93
135
  export function invalidateModelCache(server, zcodeSid) {
94
136
  server.modelCache.delete(zcodeSid);
95
137
  }
138
+ // Re-exported so callers that only import runtime-model.ts can format values.
139
+ export { formatModelValue };
96
140
  //# sourceMappingURL=runtime-model.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-model.js","sourceRoot":"","sources":["../../src/config/runtime-model.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime-model.js","sourceRoot":"","sources":["../../src/config/runtime-model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Skill discovery — scans the same directories ZCode uses to discover Skills,
3
+ * reads each SKILL.md frontmatter, and returns entries suitable for the ACP
4
+ * `available_commands_update` notification.
5
+ *
6
+ * Each discovered skill becomes its own `/skill-name` slash command in the
7
+ * editor's completion menu (matching Claude Code's behaviour). The model
8
+ * resolves the invocation via its `Skill` tool — the bridge just lists them
9
+ * and passes the text through.
10
+ *
11
+ * Discovery sources (in priority order — first occurrence wins on name clash):
12
+ * 1. ~/.zcode/skills/&#42;/SKILL.md (user scope, ZCode native)
13
+ * 2. ~/.agents/skills/&#42;/SKILL.md (user scope, shared agents)
14
+ * 3. enabled plugin <cache>/skills/&#42;/SKILL.md
15
+ * 4. <cwd>/.agents/skills/&#42;/SKILL.md (project scope)
16
+ *
17
+ * Skills explicitly disabled in `~/.zcode/cli/config.json` (skills map with
18
+ * `enable: false`, keyed by absolute SKILL.md path) are excluded.
19
+ */
20
+ /** A slash-command entry compatible with `sendAvailableCommands`. */
21
+ export interface SkillEntry {
22
+ name: string;
23
+ description: string;
24
+ input?: {
25
+ hint: string;
26
+ };
27
+ }
28
+ /**
29
+ * Discover all enabled skills from the filesystem.
30
+ *
31
+ * Returns entries suitable for `available_commands_update`. Best-effort:
32
+ * failures are logged and swallowed (returns whatever was found).
33
+ */
34
+ export declare function loadSkillCommands(): SkillEntry[];
35
+ //# sourceMappingURL=skill-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-discovery.d.ts","sourceRoot":"","sources":["../../src/config/skill-discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AASH,qEAAqE;AACrE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1B;AAkHD;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,UAAU,EAAE,CAwDhD"}