zcode-acp-server 0.67.0 → 0.68.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.
- package/README.md +1 -1
- package/dist/backend/credential-store.d.ts +35 -0
- package/dist/backend/credential-store.d.ts.map +1 -0
- package/dist/backend/credential-store.js +120 -0
- package/dist/backend/credential-store.js.map +1 -0
- package/dist/code-fingerprint.json +2 -2
- package/dist/config/account-provider.d.ts +7 -7
- package/dist/config/account-provider.d.ts.map +1 -1
- package/dist/config/account-provider.js +82 -23
- package/dist/config/account-provider.js.map +1 -1
- package/dist/settings/coding-plan.d.ts.map +1 -1
- package/dist/settings/coding-plan.js +3 -45
- package/dist/settings/coding-plan.js.map +1 -1
- package/docs/BACKLOG.md +67 -22
- package/docs/TROUBLESHOOTING.md +9 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -314,7 +314,7 @@ Thanks to everyone who has contributed (updated automatically from the
|
|
|
314
314
|
<a href="https://github.com/william0wang/zcode-acp/graphs/contributors">
|
|
315
315
|
<!-- release-please re-stamps &v= on every release: the new URL busts the
|
|
316
316
|
contrib.rocks and GitHub camo image caches. -->
|
|
317
|
-
<img src="https://contrib.rocks/image?repo=william0wang/zcode-acp&v=0.
|
|
317
|
+
<img src="https://contrib.rocks/image?repo=william0wang/zcode-acp&v=0.68.1" alt="Contributors" /> <!-- x-release-please-version -->
|
|
318
318
|
</a>
|
|
319
319
|
|
|
320
320
|
## Related Projects
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ZCode encrypted credential store (`~/.zcode/v2/credentials.json`).
|
|
3
|
+
*
|
|
4
|
+
* The desktop app keeps current-account secrets there — OAuth tokens and the
|
|
5
|
+
* per-plan coding-plan API keys (`account-provider:coding-plan:account:<plan>:
|
|
6
|
+
* account:<uid>:api-key`) — AES-256-GCM encrypted, keyed by
|
|
7
|
+
* `ZCODE_CREDENTIAL_SECRET` or a machine-bound fallback string (sha256 of the
|
|
8
|
+
* secret as the key; wire form `enc:v1:<iv>.<authTag>.<ciphertext>`, base64url;
|
|
9
|
+
* plaintext entries pass through unchanged).
|
|
10
|
+
*
|
|
11
|
+
* The cipher primitives are shared with the settings reset-card flow
|
|
12
|
+
* (settings/coding-plan.ts). This module adds the SYNC reader the account
|
|
13
|
+
* snapshot needs — `answerProviderRuntimeHeaders` runs on the frame-arrival
|
|
14
|
+
* path and cannot await — with an mtime+size cache so per-request callers
|
|
15
|
+
* never re-decrypt an unchanged store.
|
|
16
|
+
*/
|
|
17
|
+
/** Machine-bound fallback secret, mirroring ZCode's credential cipher. */
|
|
18
|
+
export declare function resolveCredentialSecret(env?: NodeJS.ProcessEnv): string;
|
|
19
|
+
/**
|
|
20
|
+
* Decrypt one `enc:v1:` credential value.
|
|
21
|
+
*
|
|
22
|
+
* The wire form is `enc:v1:<iv>.<authTag>.<ciphertext>`, all base64url. A value
|
|
23
|
+
* without the prefix is returned as-is (plaintext entries exist in the wild).
|
|
24
|
+
*/
|
|
25
|
+
export declare function decryptCredential(value: string, secret: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Read and decrypt the credential store, synchronously. Returns `{}` when the
|
|
28
|
+
* store is missing or unreadable (a headless-only machine has none). Entries
|
|
29
|
+
* that fail to decrypt are skipped individually — the store also holds OAuth
|
|
30
|
+
* discovery state and other secrets no caller here needs. Cached per
|
|
31
|
+
* mtime+size+secret, so the per-request callers never re-decrypt an unchanged
|
|
32
|
+
* store.
|
|
33
|
+
*/
|
|
34
|
+
export declare function readCredentialStoreSync(env?: NodeJS.ProcessEnv): Record<string, string>;
|
|
35
|
+
//# sourceMappingURL=credential-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential-store.d.ts","sourceRoot":"","sources":["../../src/backend/credential-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAWH,0EAA0E;AAC1E,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAUpF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAiBvE;AAYD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgDxB"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ZCode encrypted credential store (`~/.zcode/v2/credentials.json`).
|
|
3
|
+
*
|
|
4
|
+
* The desktop app keeps current-account secrets there — OAuth tokens and the
|
|
5
|
+
* per-plan coding-plan API keys (`account-provider:coding-plan:account:<plan>:
|
|
6
|
+
* account:<uid>:api-key`) — AES-256-GCM encrypted, keyed by
|
|
7
|
+
* `ZCODE_CREDENTIAL_SECRET` or a machine-bound fallback string (sha256 of the
|
|
8
|
+
* secret as the key; wire form `enc:v1:<iv>.<authTag>.<ciphertext>`, base64url;
|
|
9
|
+
* plaintext entries pass through unchanged).
|
|
10
|
+
*
|
|
11
|
+
* The cipher primitives are shared with the settings reset-card flow
|
|
12
|
+
* (settings/coding-plan.ts). This module adds the SYNC reader the account
|
|
13
|
+
* snapshot needs — `answerProviderRuntimeHeaders` runs on the frame-arrival
|
|
14
|
+
* path and cannot await — with an mtime+size cache so per-request callers
|
|
15
|
+
* never re-decrypt an unchanged store.
|
|
16
|
+
*/
|
|
17
|
+
import { createDecipheriv, createHash } from "node:crypto";
|
|
18
|
+
import { readFileSync, statSync } from "node:fs";
|
|
19
|
+
import { homedir, platform, userInfo } from "node:os";
|
|
20
|
+
import { log, zcodeCredentialsPath } from "../utils.js";
|
|
21
|
+
const ENCRYPTED_PREFIX = "enc:v1:";
|
|
22
|
+
const CIPHER_ALGORITHM = "aes-256-gcm";
|
|
23
|
+
/** Machine-bound fallback secret, mirroring ZCode's credential cipher. */
|
|
24
|
+
export function resolveCredentialSecret(env = process.env) {
|
|
25
|
+
const configured = env.ZCODE_CREDENTIAL_SECRET?.trim();
|
|
26
|
+
if (configured)
|
|
27
|
+
return configured;
|
|
28
|
+
let username = "unknown";
|
|
29
|
+
try {
|
|
30
|
+
username = userInfo().username;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
/* sandboxed runtimes may not resolve it */
|
|
34
|
+
}
|
|
35
|
+
return `zcode-credential-fallback:${platform()}:${homedir()}:${username}`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Decrypt one `enc:v1:` credential value.
|
|
39
|
+
*
|
|
40
|
+
* The wire form is `enc:v1:<iv>.<authTag>.<ciphertext>`, all base64url. A value
|
|
41
|
+
* without the prefix is returned as-is (plaintext entries exist in the wild).
|
|
42
|
+
*/
|
|
43
|
+
export function decryptCredential(value, secret) {
|
|
44
|
+
if (!value.startsWith(ENCRYPTED_PREFIX))
|
|
45
|
+
return value;
|
|
46
|
+
const payload = value.slice(ENCRYPTED_PREFIX.length);
|
|
47
|
+
const parts = payload.split(".");
|
|
48
|
+
if (parts.length !== 3)
|
|
49
|
+
throw new Error("credential_decrypt_malformed");
|
|
50
|
+
const [ivRaw, tagRaw, cipherRaw] = parts;
|
|
51
|
+
const iv = Buffer.from(ivRaw, "base64url");
|
|
52
|
+
const authTag = Buffer.from(tagRaw, "base64url");
|
|
53
|
+
const cipherText = Buffer.from(cipherRaw, "base64url");
|
|
54
|
+
const key = createHash("sha256").update(secret).digest();
|
|
55
|
+
try {
|
|
56
|
+
const decipher = createDecipheriv(CIPHER_ALGORITHM, key, iv);
|
|
57
|
+
decipher.setAuthTag(authTag);
|
|
58
|
+
return Buffer.concat([decipher.update(cipherText), decipher.final()]).toString("utf8");
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
throw new Error("credentials_unavailable");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
let storeCache = null;
|
|
65
|
+
/**
|
|
66
|
+
* Read and decrypt the credential store, synchronously. Returns `{}` when the
|
|
67
|
+
* store is missing or unreadable (a headless-only machine has none). Entries
|
|
68
|
+
* that fail to decrypt are skipped individually — the store also holds OAuth
|
|
69
|
+
* discovery state and other secrets no caller here needs. Cached per
|
|
70
|
+
* mtime+size+secret, so the per-request callers never re-decrypt an unchanged
|
|
71
|
+
* store.
|
|
72
|
+
*/
|
|
73
|
+
export function readCredentialStoreSync(env = process.env) {
|
|
74
|
+
const file = zcodeCredentialsPath();
|
|
75
|
+
let mtimeMs;
|
|
76
|
+
let size;
|
|
77
|
+
try {
|
|
78
|
+
const st = statSync(file);
|
|
79
|
+
mtimeMs = st.mtimeMs;
|
|
80
|
+
size = st.size;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
storeCache = null;
|
|
84
|
+
return {};
|
|
85
|
+
}
|
|
86
|
+
const secret = resolveCredentialSecret(env);
|
|
87
|
+
if (storeCache &&
|
|
88
|
+
storeCache.file === file &&
|
|
89
|
+
storeCache.secret === secret &&
|
|
90
|
+
storeCache.mtimeMs === mtimeMs &&
|
|
91
|
+
storeCache.size === size) {
|
|
92
|
+
return storeCache.entries;
|
|
93
|
+
}
|
|
94
|
+
const out = {};
|
|
95
|
+
try {
|
|
96
|
+
const parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
97
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
98
|
+
throw new Error("not an object");
|
|
99
|
+
}
|
|
100
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
101
|
+
if (typeof value !== "string")
|
|
102
|
+
continue;
|
|
103
|
+
try {
|
|
104
|
+
out[key] = decryptCredential(value, secret);
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
// One undecryptable entry must not sink the rest (same posture as the
|
|
108
|
+
// settings reader).
|
|
109
|
+
log(`credential-store: '${key}' could not be read (${error instanceof Error ? error.message : String(error)})`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
log(`credential-store: unreadable store (${e instanceof Error ? e.message : String(e)}) — treating as empty`);
|
|
115
|
+
return {};
|
|
116
|
+
}
|
|
117
|
+
storeCache = { file, secret, mtimeMs, size, entries: out };
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=credential-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential-store.js","sourceRoot":"","sources":["../../src/backend/credential-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -41,13 +41,13 @@ export declare function configProviderIdFor(providerId: string): string;
|
|
|
41
41
|
* The 3.12+ backend asks its host for provider runtime headers before EVERY
|
|
42
42
|
* model request on a `zhipu-account` provider (bundle-verified: the only other
|
|
43
43
|
* suppliers are the desktop host and the CLI's own "standalone" credential
|
|
44
|
-
* pair, whose identity half this machine never wrote
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* an Aliyun captcha (stays refused, issue #123), and team
|
|
50
|
-
*
|
|
44
|
+
* pair, whose identity half this machine never wrote). The desktop answers
|
|
45
|
+
* with the plan's API key; the bridge serves the same plan's key from legacy
|
|
46
|
+
* config.json when written, and otherwise from the encrypted credential store
|
|
47
|
+
* — a fresh desktop-only install writes no config.json, its plan key lives
|
|
48
|
+
* only there (#320). Only the individual coding plan is served: start-plan
|
|
49
|
+
* needs an Aliyun captcha (stays refused, issue #123), and team keys are not
|
|
50
|
+
* entitlement evidence (see storeIndividualCodingPlanKey).
|
|
51
51
|
*/
|
|
52
52
|
export declare function codingPlanRequestAuthFor(accountProviderId: string | undefined): {
|
|
53
53
|
apiKey: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-provider.d.ts","sourceRoot":"","sources":["../../src/config/account-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAQH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"account-provider.d.ts","sourceRoot":"","sources":["../../src/config/account-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAQH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAgFzD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAiB/D;AAED,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAuB9D;AAyHD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CACtC,iBAAiB,EAAE,MAAM,GAAG,SAAS,GACpC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAyB3B;AAED,0EAA0E,CAAC,MAAM,WAAW,sBAAsB;IAChH,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B,EAAE,MAAM,CAAC;IACpC,SAAS,EAAE,MAAM,CACf,MAAM,EACN;QAAE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,OAAO,CAAA;SAAE,CAAA;KAAE,CAC5E,CAAC;IACF,MAAM,EAAE,MAAM,CACZ,MAAM,EACN;QACE,YAAY,EAAE,WAAW,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAAC;QAClE,QAAQ,EAAE,OAAO,CAAC;QAClB,OAAO,EAAE,OAAO,CAAC;KAClB,CACF,CAAC;CACH;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,sBAAsB,GAAG,IAAI,CA6B1E;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,MAAM,MAAM,GACnB,OAAO,CAAC,OAAO,CAAC,CA2BlB"}
|
|
@@ -27,6 +27,7 @@ import { createHash } from "node:crypto";
|
|
|
27
27
|
import { existsSync, readFileSync } from "node:fs";
|
|
28
28
|
import os from "node:os";
|
|
29
29
|
import path from "node:path";
|
|
30
|
+
import { readCredentialStoreSync } from "../backend/credential-store.js";
|
|
30
31
|
import { BUILTIN_PROVIDER_ENV, builtinProviderEnv } from "../backend/resolve.js";
|
|
31
32
|
import { log, warn, ZCODE_CREDS_PATH } from "../utils.js";
|
|
32
33
|
/** The bundled provider-table file the CLI boots from. */
|
|
@@ -126,35 +127,68 @@ export function configProviderIdFor(providerId) {
|
|
|
126
127
|
return `builtin:${m[1]}-${m[2] === "start-plan" ? "start-plan" : "coding-plan"}`;
|
|
127
128
|
return providerId;
|
|
128
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* The decrypted api-key for an INDIVIDUAL coding plan from the encrypted
|
|
132
|
+
* credential store (`account-provider:coding-plan:account:<plan>:account:<uid>:
|
|
133
|
+
* api-key` — the uid segment is the signed-in account), or null when the store
|
|
134
|
+
* holds no such entry.
|
|
135
|
+
*
|
|
136
|
+
* Team keys are deliberately not served: the store keeps a team api-key even
|
|
137
|
+
* when the desktop's own snapshot says the team plan is not entitled
|
|
138
|
+
* (observed 2026-10: both keys present, desktop verdict individual=true /
|
|
139
|
+
* team=false) — key presence over-claims — and a team request additionally
|
|
140
|
+
* needs organization/project headers this bridge cannot source.
|
|
141
|
+
*/
|
|
142
|
+
function storeIndividualCodingPlanKey(accountProviderId) {
|
|
143
|
+
const slug = accountProviderId.slice("account:".length);
|
|
144
|
+
if (!slug.endsWith("-individual-coding-plan"))
|
|
145
|
+
return null;
|
|
146
|
+
const prefix = `account-provider:coding-plan:account:${slug}:account:`;
|
|
147
|
+
for (const [key, value] of Object.entries(readCredentialStoreSync())) {
|
|
148
|
+
if (key.startsWith(prefix) && key.endsWith(":api-key")) {
|
|
149
|
+
const apiKey = value.trim();
|
|
150
|
+
return apiKey || null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
129
155
|
/**
|
|
130
156
|
* The plans the user actually holds, keyed by the LEGACY `builtin:<family>-<plan>`
|
|
131
157
|
* id — the id every entitlement source below speaks.
|
|
132
158
|
*
|
|
133
|
-
*
|
|
134
|
-
* truth. Ranked by authority:
|
|
159
|
+
* On-disk signals, ranked by authority:
|
|
135
160
|
*
|
|
136
161
|
* 1. `coding-plan-cache.json` — the desktop's own availability verdict
|
|
137
162
|
* (`{items: {"builtin:bigmodel-coding-plan": {status:"available" | "unavailable"}}}`).
|
|
138
163
|
* Carries the resolved available/not-entitled decision, not a raw flag.
|
|
139
164
|
* Desktop-only, so a headless-only machine falls through.
|
|
140
|
-
* 2. `
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
165
|
+
* 2. `config.json` (legacy CLI config) — `builtin:*` entries with
|
|
166
|
+
* `enabled:true` AND an apiKey. Still written by the app.
|
|
167
|
+
* 3. The encrypted credential store (#320) — a fresh desktop-only install
|
|
168
|
+
* writes NEITHER of the above; its plan api-keys live only in
|
|
169
|
+
* `~/.zcode/v2/credentials.json`. Weaker evidence than a verdict (the
|
|
170
|
+
* store also keeps keys for plans the account does not currently hold),
|
|
171
|
+
* so it only speaks when no verdict-bearing source said anything at all,
|
|
172
|
+
* and only for individual plans (see storeIndividualCodingPlanKey).
|
|
173
|
+
* 4. `setting.json` — last resort: the Settings UI's remembered pick per
|
|
174
|
+
* family. A SELECTION record, not an entitlement.
|
|
146
175
|
*
|
|
147
|
-
* Verified 2026-09 against the desktop's own pushed account snapshot:
|
|
148
|
-
*
|
|
149
|
-
*
|
|
176
|
+
* Verified 2026-09 against the desktop's own pushed account snapshot: sources
|
|
177
|
+
* 1+2 produced exactly its entitlement set (bigmodel individual true, every
|
|
178
|
+
* zai/start/team plan false); source 3 restores the same outcome on fresh
|
|
179
|
+
* desktop-only layouts (verified 2026-10 against a real store).
|
|
150
180
|
*/
|
|
151
181
|
function entitledBuiltinProviders() {
|
|
152
182
|
const out = new Set();
|
|
153
183
|
const credsDir = path.dirname(ZCODE_CREDS_PATH);
|
|
184
|
+
let sawVerdict = false;
|
|
154
185
|
// 1) Desktop availability cache (authoritative: the resolved verdict).
|
|
155
186
|
try {
|
|
156
187
|
const cache = JSON.parse(readFileSync(path.join(credsDir, "coding-plan-cache.json"), "utf8"));
|
|
157
|
-
|
|
188
|
+
const items = Object.entries(cache.entryStatus?.items ?? {});
|
|
189
|
+
if (items.length > 0)
|
|
190
|
+
sawVerdict = true;
|
|
191
|
+
for (const [pid, entry] of items) {
|
|
158
192
|
if (entry?.status === "available")
|
|
159
193
|
out.add(pid);
|
|
160
194
|
}
|
|
@@ -165,19 +199,37 @@ function entitledBuiltinProviders() {
|
|
|
165
199
|
// 2) Legacy config.json (still the app's own provider enablement).
|
|
166
200
|
try {
|
|
167
201
|
const cfg = JSON.parse(readFileSync(ZCODE_CREDS_PATH, "utf8"));
|
|
202
|
+
let builtinEntries = 0;
|
|
168
203
|
for (const [pid, p] of Object.entries(cfg.provider ?? {})) {
|
|
169
204
|
if (!pid.startsWith("builtin:"))
|
|
170
205
|
continue;
|
|
206
|
+
builtinEntries += 1;
|
|
171
207
|
if (p?.enabled === true && p.options?.apiKey)
|
|
172
208
|
out.add(pid);
|
|
173
209
|
}
|
|
210
|
+
if (builtinEntries > 0)
|
|
211
|
+
sawVerdict = true;
|
|
174
212
|
}
|
|
175
213
|
catch {
|
|
176
214
|
// unreadable config — the other sources decide
|
|
177
215
|
}
|
|
178
216
|
if (out.size > 0)
|
|
179
217
|
return out;
|
|
180
|
-
// 3)
|
|
218
|
+
// 3) Fresh desktop-only layout (#320): no verdict-bearing source spoke, but
|
|
219
|
+
// the encrypted store holds the account's individual plan key.
|
|
220
|
+
if (!sawVerdict) {
|
|
221
|
+
const rules = readBuiltinTable()?.table.config?.providerConfigRules?.providerRules?.filter((r) => r.config?.access?.type === "zhipu-account") ?? [];
|
|
222
|
+
for (const rule of rules) {
|
|
223
|
+
if (rule.config?.access?.mode !== "individual-coding-plan")
|
|
224
|
+
continue;
|
|
225
|
+
if (storeIndividualCodingPlanKey(rule.providerId)) {
|
|
226
|
+
out.add(configProviderIdFor(rule.providerId));
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (out.size > 0)
|
|
231
|
+
return out;
|
|
232
|
+
// 4) Last resort only (everything above empty — a machine that has never
|
|
181
233
|
// written them): the Settings UI's remembered pick per family. This is a
|
|
182
234
|
// SELECTION record, not an entitlement — `zai` sitting there means the
|
|
183
235
|
// user opened that family's picker, not that the plan is held (observed
|
|
@@ -203,33 +255,40 @@ function entitledBuiltinProviders() {
|
|
|
203
255
|
* The 3.12+ backend asks its host for provider runtime headers before EVERY
|
|
204
256
|
* model request on a `zhipu-account` provider (bundle-verified: the only other
|
|
205
257
|
* suppliers are the desktop host and the CLI's own "standalone" credential
|
|
206
|
-
* pair, whose identity half this machine never wrote
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
* an Aliyun captcha (stays refused, issue #123), and team
|
|
212
|
-
*
|
|
258
|
+
* pair, whose identity half this machine never wrote). The desktop answers
|
|
259
|
+
* with the plan's API key; the bridge serves the same plan's key from legacy
|
|
260
|
+
* config.json when written, and otherwise from the encrypted credential store
|
|
261
|
+
* — a fresh desktop-only install writes no config.json, its plan key lives
|
|
262
|
+
* only there (#320). Only the individual coding plan is served: start-plan
|
|
263
|
+
* needs an Aliyun captcha (stays refused, issue #123), and team keys are not
|
|
264
|
+
* entitlement evidence (see storeIndividualCodingPlanKey).
|
|
213
265
|
*/
|
|
214
266
|
export function codingPlanRequestAuthFor(accountProviderId) {
|
|
215
267
|
if (!accountProviderId?.startsWith("account:"))
|
|
216
268
|
return null;
|
|
217
269
|
const rule = readBuiltinTable()?.table.config?.providerConfigRules?.providerRules?.find((r) => r.providerId === accountProviderId);
|
|
218
|
-
|
|
270
|
+
const individual = rule?.config?.access?.mode === "individual-coding-plan" ||
|
|
271
|
+
(!rule && accountProviderId.endsWith("-individual-coding-plan"));
|
|
272
|
+
if (!individual)
|
|
219
273
|
return null;
|
|
220
274
|
const legacyId = configProviderIdFor(accountProviderId);
|
|
221
275
|
if (legacyId === accountProviderId)
|
|
222
276
|
return null;
|
|
223
277
|
if (!entitledBuiltinProviders().has(legacyId))
|
|
224
278
|
return null;
|
|
279
|
+
// config.json first (the pre-3.12 builtin: provider's own spelling); a fresh
|
|
280
|
+
// desktop-only layout has none — fall through to the stored plan key.
|
|
225
281
|
try {
|
|
226
282
|
const cfg = JSON.parse(readFileSync(ZCODE_CREDS_PATH, "utf8"));
|
|
227
283
|
const apiKey = cfg.provider?.[legacyId]?.options?.apiKey?.trim();
|
|
228
|
-
|
|
284
|
+
if (apiKey)
|
|
285
|
+
return { apiKey };
|
|
229
286
|
}
|
|
230
287
|
catch {
|
|
231
|
-
|
|
288
|
+
// unreadable/absent config — the store decides
|
|
232
289
|
}
|
|
290
|
+
const stored = storeIndividualCodingPlanKey(accountProviderId);
|
|
291
|
+
return stored ? { apiKey: stored } : null;
|
|
233
292
|
}
|
|
234
293
|
/**
|
|
235
294
|
* Build the account snapshot: every coding-plan provider the bundled table
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-provider.js","sourceRoot":"","sources":["../../src/config/account-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"account-provider.js","sourceRoot":"","sources":["../../src/config/account-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coding-plan.d.ts","sourceRoot":"","sources":["../../src/settings/coding-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;
|
|
1
|
+
{"version":3,"file":"coding-plan.d.ts","sourceRoot":"","sources":["../../src/settings/coding-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AA0BH,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,UAAU,CAAC;AAC7C,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,MAAM,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B,2DAA2D;IAC3D,iBAAiB,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,aAAa,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3C,cAAc,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1C,UAAU,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACtC,gBAAgB,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,uBAAuB,EAAE,MAAM,CAAC;IAChC,wDAAwD;IACxD,WAAW,CAAC,EAAE;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7D;AAqCD,6CAA6C;AAC7C,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW,CAE9D;AAED,uDAAuD;AACvD,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAGhE;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,kBAAkB,CAAC,CAc7B;AAmED,wCAAwC;AACxC,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,SAAS,GAAE,OAAO,UAAU,CAAC,KAAwB,EACrD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,eAAe,CAAC,CAqC1B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,MAAM,EACtB,SAAS,GAAE,OAAO,UAAU,CAAC,KAAwB,EACrD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,cAAc,CAAC,CAiBzB;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EACtB,SAAS,GAAE,OAAO,UAAU,CAAC,KAAwB,EACrD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAiBzD;AAED,6DAA6D;AAC7D,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,SAAS,GAAE,OAAO,UAAU,CAAC,KAAwB,EACrD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,IAAI,CAAC,CAYf;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAShD"}
|
|
@@ -28,15 +28,13 @@
|
|
|
28
28
|
* response, a double tap) cannot burn two cards, and the route layer requires a
|
|
29
29
|
* fresh status nonce before it will call it.
|
|
30
30
|
*/
|
|
31
|
-
import {
|
|
31
|
+
import { randomUUID } from "node:crypto";
|
|
32
32
|
import { readFile } from "node:fs/promises";
|
|
33
|
-
import {
|
|
33
|
+
import { decryptCredential, resolveCredentialSecret } from "../backend/credential-store.js";
|
|
34
34
|
import { log, zcodeCredentialsPath } from "../utils.js";
|
|
35
35
|
import { UpstreamError } from "./errors.js";
|
|
36
36
|
/** The only provider ids that own a coding plan. */
|
|
37
37
|
const CODING_PLAN_PROVIDER_PREFIX = "account:";
|
|
38
|
-
const ENCRYPTED_PREFIX = "enc:v1:";
|
|
39
|
-
const CIPHER_ALGORITHM = "aes-256-gcm";
|
|
40
38
|
const ZCODE_JWT_KEY = "zcodejwttoken";
|
|
41
39
|
const OAUTH_TOKEN_KEYS = {
|
|
42
40
|
bigmodel: "oauth:bigmodel:access_token",
|
|
@@ -48,48 +46,8 @@ function apiOrigin(env = process.env) {
|
|
|
48
46
|
}
|
|
49
47
|
const RESET_BASE_PATH = "/api/v1/coding-plan/reset";
|
|
50
48
|
const REQUEST_TIMEOUT_MS = 15_000;
|
|
51
|
-
/** Machine-bound fallback secret, mirroring ZCode's credential cipher. */
|
|
52
|
-
function resolveCredentialSecret(env) {
|
|
53
|
-
const configured = env.ZCODE_CREDENTIAL_SECRET?.trim();
|
|
54
|
-
if (configured)
|
|
55
|
-
return configured;
|
|
56
|
-
let username = "unknown";
|
|
57
|
-
try {
|
|
58
|
-
username = userInfo().username;
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
/* sandboxed runtimes may not resolve it */
|
|
62
|
-
}
|
|
63
|
-
return `zcode-credential-fallback:${platform()}:${homedir()}:${username}`;
|
|
64
|
-
}
|
|
65
49
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* The wire form is `enc:v1:<iv>.<authTag>.<ciphertext>`, all base64url. A value
|
|
69
|
-
* without the prefix is returned as-is (plaintext entries exist in the wild).
|
|
70
|
-
*/
|
|
71
|
-
function decryptCredential(value, secret) {
|
|
72
|
-
if (!value.startsWith(ENCRYPTED_PREFIX))
|
|
73
|
-
return value;
|
|
74
|
-
const payload = value.slice(ENCRYPTED_PREFIX.length);
|
|
75
|
-
const parts = payload.split(".");
|
|
76
|
-
if (parts.length !== 3)
|
|
77
|
-
throw new Error("credential_decrypt_malformed");
|
|
78
|
-
const [ivRaw, tagRaw, cipherRaw] = parts;
|
|
79
|
-
const iv = Buffer.from(ivRaw, "base64url");
|
|
80
|
-
const authTag = Buffer.from(tagRaw, "base64url");
|
|
81
|
-
const cipherText = Buffer.from(cipherRaw, "base64url");
|
|
82
|
-
const key = createHash("sha256").update(secret).digest();
|
|
83
|
-
try {
|
|
84
|
-
const decipher = createDecipheriv(CIPHER_ALGORITHM, key, iv);
|
|
85
|
-
decipher.setAuthTag(authTag);
|
|
86
|
-
return Buffer.concat([decipher.update(cipherText), decipher.final()]).toString("utf8");
|
|
87
|
-
}
|
|
88
|
-
catch {
|
|
89
|
-
throw new Error("credentials_unavailable");
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
/** Read and decrypt the credential store. Throws `credentials_unavailable`. */
|
|
50
|
+
* Read and decrypt the credential store. Throws `credentials_unavailable`. */
|
|
93
51
|
async function loadCredentials(env) {
|
|
94
52
|
let raw;
|
|
95
53
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coding-plan.js","sourceRoot":"","sources":["../../src/settings/coding-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"coding-plan.js","sourceRoot":"","sources":["../../src/settings/coding-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAC5F,OAAO,EAAE,GAAG,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,oDAAoD;AACpD,MAAM,2BAA2B,GAAG,UAAU,CAAC;AAE/C,MAAM,aAAa,GAAG,eAAe,CAAC;AACtC,MAAM,gBAAgB,GAAG;IACvB,QAAQ,EAAE,6BAA6B;IACvC,GAAG,EAAE,wBAAwB;CACrB,CAAC;AAEX,6EAA6E;AAC7E,SAAS,SAAS,CAAC,MAAyB,OAAO,CAAC,GAAG;IACrD,OAAO,GAAG,CAAC,qBAAqB,IAAI,GAAG,CAAC,cAAc,IAAI,oBAAoB,CAAC;AACjF,CAAC;AAED,MAAM,eAAe,GAAG,2BAA2B,CAAC;AACpD,MAAM,kBAAkB,GAAG,MAAM,CAAC;AA2BlC;8EAC8E;AAC9E,KAAK,UAAU,eAAe,CAAC,GAAsB;IACnD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,oBAAoB,EAAE,EAAE,MAAM,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,MAAM,MAAM,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAC5C,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAiC,CAAC,EAAE,CAAC;QAC7E,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,SAAS;QACxC,IAAI,CAAC;YACH,GAAG,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC9C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,yEAAyE;YACzE,+CAA+C;YAC/C,GAAG,CACD,4BAA4B,GAAG,wBAAwB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CACjH,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,cAAc,CAAC,UAAkB;IAC/C,OAAO,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC;AAC3D,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,oBAAoB,CAAC,UAAkB;IACrD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,2BAA2B,CAAC;QAAE,OAAO,KAAK,CAAC;IACtE,OAAO,yDAAyD,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACpF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,UAAkB,EAClB,MAAyB,OAAO,CAAC,GAAG;IAEpC,IAAI,CAAC,oBAAoB,CAAC,UAAU,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,WAAW,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC;IACpD,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,aAAa,GAAG,WAAW,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;IACpE,IAAI,CAAC,aAAa;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACrE,OAAO;QACL,kBAAkB,EAAE,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,QAAQ,EAAE;QAClF,uBAAuB,EAAE,aAAa;KACvC,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,IAAwB,EAAE,YAAqB;IACnE,MAAM,OAAO,GAA2B;QACtC,aAAa,EAAE,IAAI,CAAC,kBAAkB;QACtC,+DAA+D;QAC/D,0BAA0B,EAAE,IAAI,CAAC,uBAAuB;KACzD,CAAC;IACF,IAAI,CAAC,YAAY;QAAE,OAAO,OAAO,CAAC;IAClC,OAAO,CAAC,sBAAsB,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;IACzE,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,OAAO,CAAC,uBAAuB,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC;QACnE,OAAO,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC;IAC3D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAQD;;;;;;GAMG;AACH,KAAK,UAAU,SAAS,CACtB,IAAY,EACZ,IAAuE,EACvE,IAAwB,EACxB,gBAAmC,EAAE,EACrC,YAAqC,UAAU,CAAC,KAAK,EACrD,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE;QAC3D,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,OAAO,EAAE;YACP,GAAG,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC;YACxC,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC3E;QACD,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,kBAAkB,CAAC;KAChD,CAAC,CAAC;IACH,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAY,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC;IACD,MAAM,QAAQ,GAAG,CAAC,OAAO,IAAI,EAAE,CAAa,CAAC;IAC7C,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC7D,IAAI,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO,QAAQ,CAAC;QAC3D,MAAM,IAAI,aAAa,CAAC,+BAA+B,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,aAAa,CAAC,gCAAgC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,yEAAyE;AACzE,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAErC,wCAAwC;AACxC,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,UAAkB,EAClB,YAAqC,UAAU,CAAC,KAAK,EACrD,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,IAAI,GAAG,MAAM,yBAAyB,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,CAAC,MAAM,SAAS,CAC/B,GAAG,eAAe,SAAS,EAC3B,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,EACrC,IAAI,EACJ,EAAE,EACF,SAAS,EACT,GAAG,CACJ,CAAuC,CAAC;IACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;IACjC,MAAM,QAAQ,GAAG,CAAC,GAAW,EAA+B,EAAE;QAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACrC,OAAO,KAAK;aACT,MAAM,CACL,CAAC,IAAI,EAAiC,EAAE,CACtC,OAAO,IAAI,KAAK,QAAQ;YACxB,IAAI,KAAK,IAAI;YACb,OAAQ,IAAgC,CAAC,SAAS,KAAK,QAAQ,CAClE;aACA,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC;IACF,MAAM,WAAW,GAAG,CAAC,GAAW,EAA6B,EAAE;QAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAC7D,MAAM,MAAM,GAAI,KAA+B,CAAC,OAAO,CAAC;QACxD,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,CAAC,CAAC;IACF,OAAO;QACL,iBAAiB,EAAE,QAAQ,CAAC,4BAA4B,CAAC;QACzD,aAAa,EAAE,QAAQ,CAAC,uBAAuB,CAAC;QAChD,cAAc,EAAE,WAAW,CAAC,gCAAgC,CAAC;QAC7D,UAAU,EAAE,WAAW,CAAC,2BAA2B,CAAC;QACpD,gBAAgB,EAAE,IAAI,CAAC,oBAAoB,CAAC,KAAK,IAAI;QACrD,KAAK,EAAE,UAAU,EAAE;KACpB,CAAC;AACJ,CAAC;AAQD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,UAAkB,EAClB,SAAoB,EACpB,cAAsB,EACtB,YAAqC,UAAU,CAAC,KAAK,EACrD,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC;IAClC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC1F,MAAM,IAAI,GAAG,MAAM,yBAAyB,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,CAAC,MAAM,SAAS,CAC/B,GAAG,eAAe,MAAM,EACxB;QACE,MAAM,EAAE,MAAM;QACd,YAAY,EAAE,IAAI;QAClB,IAAI,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE;KACtD,EACD,IAAI,EACJ,EAAE,EACF,SAAS,EACT,GAAG,CACJ,CAAkC,CAAC;IACpC,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE,CAAC;AAChD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,UAAkB,EAClB,cAAsB,EACtB,YAAqC,UAAU,CAAC,KAAK,EACrD,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC;IAClC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC1F,MAAM,IAAI,GAAG,MAAM,yBAAyB,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,CAAC,MAAM,SAAS,CAC/B,GAAG,eAAe,cAAc,EAChC,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,EAAE,EACtE,IAAI,EACJ,CAAC,uBAAuB,CAAC,EACzB,SAAS,EACT,GAAG,CACJ,CAA0E,CAAC;IAC5E,IAAI,QAAQ,CAAC,IAAI,KAAK,uBAAuB,EAAE,CAAC;QAC9C,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;QAC7C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACzF,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACvE,CAAC;AAED,6DAA6D;AAC7D,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,UAAkB,EAClB,YAAqC,UAAU,CAAC,KAAK,EACrD,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,IAAI,GAAG,MAAM,yBAAyB,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IAC9D,uEAAuE;IACvE,6BAA6B;IAC7B,MAAM,SAAS,CACb,GAAG,eAAe,eAAe,EACjC,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,EACvC,IAAI,EACJ,EAAE,EACF,SAAS,EACT,GAAG,CACJ,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,qBAAqB;IACnC,2EAA2E;IAC3E,2DAA2D;IAC3D,OAAO;QACL,yCAAyC;QACzC,mCAAmC;QACnC,oCAAoC;QACpC,8BAA8B;KAC/B,CAAC;AACJ,CAAC"}
|
package/docs/BACKLOG.md
CHANGED
|
@@ -36,6 +36,51 @@ setModel / goal / fork untouched. `bundled-skills.ts` is the DWF skill pack's
|
|
|
36
36
|
own distribution channel (explicitly not in the settings page or `$` panel)
|
|
37
37
|
— no overlap with the bridge's filesystem skill discovery.
|
|
38
38
|
|
|
39
|
+
**3.15.1 sync (2026-10-12, commit `aac47556` — checkout synced, targeted audit,
|
|
40
|
+
alignment items pending)**: single upstream release commit (11,736 files).
|
|
41
|
+
app-server still self-reports `0.16.9`; the desktop app on this machine is at
|
|
42
|
+
3.14.5 and its bundle contains NONE of the 3.15.1 protocol surface except the
|
|
43
|
+
`highspeed` account-mode schema strings — no live breakage today. Verified
|
|
44
|
+
unchanged (zero diff): provider bootstrap (`provider-runtime-env.ts`,
|
|
45
|
+
`runtime-paths.ts`, `zcode-builtin-provider-config-source.ts`,
|
|
46
|
+
`registry-service.ts`), `model-catalog-port.ts`, `session-mode-port.ts`,
|
|
47
|
+
`workflow-model-failure-policy.ts`; `server-operations.ts` moved 107 lines but
|
|
48
|
+
its hunks touch MCP plugin UI, `session/read` `contentProfile`, and the DWF
|
|
49
|
+
gate — the stop/compact/setModel/send-busy turn loop has no hunk. The
|
|
50
|
+
runtime-headers request reason enum is still `["model-request"]` (the new
|
|
51
|
+
`request-security-edition/verification-policy.ts` is an all-stub placeholder).
|
|
52
|
+
New in 3.15.1, bridge-relevant:
|
|
53
|
+
|
|
54
|
+
1. **Guarded permission mode** (UI: "Autonomous mode / 自主模式") — runs like
|
|
55
|
+
yolo but pauses ONCE for AST-recognized dangerous shell commands
|
|
56
|
+
(`docs/dangerous-command-approval-v1-plan.md`, matcher → PermissionService
|
|
57
|
+
→ broker; sub-agent yolo derivations tighten to guarded). Ships with
|
|
58
|
+
`permission_full_access` persisted receipts (yolo escalation covering
|
|
59
|
+
queued items) and `approvalMode:"user-once"` on `permission_requested`.
|
|
60
|
+
The bridge's mode lists are hardcoded WITHOUT guarded —
|
|
61
|
+
`src/config/options.ts` (`availableModes` fallback), `src/utils.ts`
|
|
62
|
+
(mode catalog), `src/config/user-config.ts` (`SESSION_MODES` validation) —
|
|
63
|
+
surfacing it is the pending alignment item (`auto` stays internal-only
|
|
64
|
+
upstream).
|
|
65
|
+
2. **`dynamicWorkflowMode` (onDemand)** — optional param on `session/create`,
|
|
66
|
+
`session/resume`, `workspace/updateDynamicWorkflowPolicy`; absent mode =
|
|
67
|
+
act on the boolean (alwaysOn) for old hosts. Pairs with the bridge's
|
|
68
|
+
workflow-gate local override, which already models `onDemand` — pass it
|
|
69
|
+
through in `ensureWorkflowPolicyPushed` + create/resume (not yet done).
|
|
70
|
+
3. **`highspeed` provider account-access mode** (加速卡) — enum extension only;
|
|
71
|
+
the builtin table carries no modes, coding-plan snapshots unaffected.
|
|
72
|
+
4. **Session event-store retention** — sealed-turn eviction in the in-memory
|
|
73
|
+
event store (memory-leak fix; `session-mapper.ts` now tolerates
|
|
74
|
+
`messageCount` in place of `messages`); audit against the bridge's
|
|
75
|
+
replay/hydration watermark guards before the app rolls to 3.15.x.
|
|
76
|
+
5. **Host-capability methods** — `mcp/ui*` family (plugin UI), `workflows/save`
|
|
77
|
+
- `workflows/forRun`, `topic/resource/*` (bot remote history),
|
|
78
|
+
`bot/channel/reply`, `subagents/readRuntimeConfig` (only armed when the
|
|
79
|
+
host reports `subagentRuntimeConfigEnabled` in requestRuntimePreferences —
|
|
80
|
+
the bridge doesn't). All land in the unhandled-request path by design.
|
|
81
|
+
v3 payloads gained only OPTIONAL fields (`turn.started.executionStartedAt`,
|
|
82
|
+
permission `approvalMode`, `session/read` `contentProfile`).
|
|
83
|
+
|
|
39
84
|
**3.14.0 audit (2026-09-20, app-server 0.16.9 — live-probed end to end)**: the
|
|
40
85
|
dynamic-workflow family (ten model tools led by `CreateWorkflow`) is OFF by
|
|
41
86
|
default headless and enabled per PROCESS via
|
|
@@ -101,29 +146,29 @@ Available in the backend but with no ACP-side counterpart yet. Pick them up
|
|
|
101
146
|
when a concrete ACP/editor need appears. Ranked shortlist in
|
|
102
147
|
"Alignment opportunities" below.
|
|
103
148
|
|
|
104
|
-
| Method | Purpose | Current bridge behavior
|
|
105
|
-
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
106
|
-
| `session/subagents` (`index.ts:1520-1618`) | Sub-agent states: `running{status: running\|waiting\|blocked}`, `ended{total, items[{status: success\|failed\|cancelled\|lost}], nextCursor}` | Sub-agent info is parsed from the `Agent` tool result (`_meta.subagent`); the RPC adds waiting/blocked/lost states for stuck-subagent detection (pairs with the watermark liveness logic in `runEventTurn`)
|
|
107
|
-
| `session/events` (`{sessionId, afterSeq?, limit?}`, `index.ts:1667-1674`) | Pull-mode event history | Not used; gap-fill after the drain gate's close-escalation reload (re-subscribe + replay only the missed window), durable audit for `/debug`
|
|
108
|
-
| `session/subscribe` `afterSeq` + `includeSnapshot` (`index.ts:1496-1513`) | Resume the event stream from a seq watermark, optionally with a full state snapshot | Not used; crash-safe resubscribe instead of full replay
|
|
109
|
-
| `session/usage` / `v4/conversation/usage` | Per-session cumulative usage: input/output/reasoning/cache tokens, `modelRequestCount`, `modelErrorCount` (`index.ts:1627-1646`) | Per-turn billing usage is now carried on the ACP `session/prompt` result (`usage` + `_meta.zcode.usage`), sourced from `turn.completed`; this RPC remains a candidate for session-cumulative reconciliation (deprecated upstream, see table above)
|
|
110
|
-
| `session/compact` `instructions` + `result.compact` (`index.ts:1829-1853`) | Custom compact instructions; result acks `{state: accepted\|already_running, inputId?, operationId?}` | Not forwarded — `/compact <focus>` could pass instructions; the backend's own `already_running` ack can backstop the bridge's `autoCompactInFlight` single-flight
|
|
111
|
-
| `session/debug` (`index.ts:3571`, `bootstrap/src/zcode-protocol/session-debug.ts`) | Per-session debug snapshot accumulated from the live event stream | Not used; `zcode-acp` diagnostics command / `/debug` extension
|
|
112
|
-
| `session/list` rich params (`sessionIds` incl. hidden, `includeArchived`, `limit`, `index.ts:1600-1609`) | Explicit identity lookup, archived sessions | Not used
|
|
113
|
-
| `session/create` extras: `toolAllowlist`/`toolDenylist` (per-session tool face — could move Cron* hiding off process-wide `--disallowed-tools`), `importedHistory` (claudeCode / sharedContext+sha256 provenance), `persistence:"immediate"\|"deferred"`, `titleGenerationEnabled:false` (bridge sets its own titles), `parentSessionId` (`index.ts:1558-1580`) | Session-creation knobs | Not forwarded; `session/resume` also takes `toolAllowlist`/`toolDenylist` — a resume WITHOUT them drops the tool face on cold recovery (`index.ts:1589-1595`)
|
|
114
|
-
| `mcp/list` `mode:"status"` (`index.ts:686-723`) | Status without connecting: per-server `{status, transport, toolCount, failureKind(19-value enum), authorization{authorizationUrl}}` | Not used; editor MCP health panel + OAuth start URL without new transport
|
|
115
|
-
| `process/childProcesses` (3.12.3) | List a session's child processes (`{pid, serverName, mcpSource, pluginName?}`, pure memory) | Not used; potentially useful for background-task diagnostics
|
|
116
|
-
| `skills/referenceCatalog`, `plugins/referenceCatalog[WithCategory]` (categorized variant new in 0.16.9) | Session-scoped FROZEN catalogs — the authoritative per-session view vs the bridge's live disk reads | Not used; fixes the stale-catalog class of bug (backend freezes discovery at session start)
|
|
117
|
-
| `workspace/readPresentation` (3.12.3) | The backend's own view of workspace mode + slash-command list | Not used; cross-check the bridge's disk-based slash discovery for drift
|
|
149
|
+
| Method | Purpose | Current bridge behavior |
|
|
150
|
+
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
151
|
+
| `session/subagents` (`index.ts:1520-1618`) | Sub-agent states: `running{status: running\|waiting\|blocked}`, `ended{total, items[{status: success\|failed\|cancelled\|lost}], nextCursor}` | Sub-agent info is parsed from the `Agent` tool result (`_meta.subagent`); the RPC adds waiting/blocked/lost states for stuck-subagent detection (pairs with the watermark liveness logic in `runEventTurn`) |
|
|
152
|
+
| `session/events` (`{sessionId, afterSeq?, limit?}`, `index.ts:1667-1674`) | Pull-mode event history | Not used; gap-fill after the drain gate's close-escalation reload (re-subscribe + replay only the missed window), durable audit for `/debug` |
|
|
153
|
+
| `session/subscribe` `afterSeq` + `includeSnapshot` (`index.ts:1496-1513`) | Resume the event stream from a seq watermark, optionally with a full state snapshot | Not used; crash-safe resubscribe instead of full replay |
|
|
154
|
+
| `session/usage` / `v4/conversation/usage` | Per-session cumulative usage: input/output/reasoning/cache tokens, `modelRequestCount`, `modelErrorCount` (`index.ts:1627-1646`) | Per-turn billing usage is now carried on the ACP `session/prompt` result (`usage` + `_meta.zcode.usage`), sourced from `turn.completed`; this RPC remains a candidate for session-cumulative reconciliation (deprecated upstream, see table above) |
|
|
155
|
+
| `session/compact` `instructions` + `result.compact` (`index.ts:1829-1853`) | Custom compact instructions; result acks `{state: accepted\|already_running, inputId?, operationId?}` | Not forwarded — `/compact <focus>` could pass instructions; the backend's own `already_running` ack can backstop the bridge's `autoCompactInFlight` single-flight |
|
|
156
|
+
| `session/debug` (`index.ts:3571`, `bootstrap/src/zcode-protocol/session-debug.ts`) | Per-session debug snapshot accumulated from the live event stream | Not used; `zcode-acp` diagnostics command / `/debug` extension |
|
|
157
|
+
| `session/list` rich params (`sessionIds` incl. hidden, `includeArchived`, `limit`, `index.ts:1600-1609`) | Explicit identity lookup, archived sessions | Not used |
|
|
158
|
+
| `session/create` extras: `toolAllowlist`/`toolDenylist` (per-session tool face — could move Cron* hiding off process-wide `--disallowed-tools`), `importedHistory` (claudeCode / sharedContext+sha256 provenance), `persistence:"immediate"\|"deferred"`, `titleGenerationEnabled:false` (bridge sets its own titles), `parentSessionId` (`index.ts:1558-1580`) | Session-creation knobs | Not forwarded; `session/resume` also takes `toolAllowlist`/`toolDenylist` — a resume WITHOUT them drops the tool face on cold recovery (`index.ts:1589-1595`) |
|
|
159
|
+
| `mcp/list` `mode:"status"` (`index.ts:686-723`) | Status without connecting: per-server `{status, transport, toolCount, failureKind(19-value enum), authorization{authorizationUrl}}` | Not used; editor MCP health panel + OAuth start URL without new transport |
|
|
160
|
+
| `process/childProcesses` (3.12.3) | List a session's child processes (`{pid, serverName, mcpSource, pluginName?}`, pure memory) | Not used; potentially useful for background-task diagnostics |
|
|
161
|
+
| `skills/referenceCatalog`, `plugins/referenceCatalog[WithCategory]` (categorized variant new in 0.16.9) | Session-scoped FROZEN catalogs — the authoritative per-session view vs the bridge's live disk reads | Not used; fixes the stale-catalog class of bug (backend freezes discovery at session start) |
|
|
162
|
+
| `workspace/readPresentation` (3.12.3) | The backend's own view of workspace mode + slash-command list | Not used; cross-check the bridge's disk-based slash discovery for drift |
|
|
118
163
|
| `workflows/*` family (NEW 0.16.9: `list/get/updateMeta/delete/runs/move`, `index.ts:2685-2937, 3618-3625`) | Session-less management of saved dynamic workflows (`<cwd>/.zcode/workflows/`, project+global scopes), run history with `artifacts`, cross-cwd runs query | **WIRED (2026-09-24, ADR-0029)**: proxied under `/settings/workflows*` + the local `/workflows` slash listing; availability is the remote `/client/configs` verdict (`src/config/workflow-gate.ts`), and `v4/command startSavedWorkflow`/`resumeWorkflowRun` + the `workflowRun*` queries are wired with it (see the v4 section below) |
|
|
119
|
-
| `provider/testModelConnectivity` (3.12.3) | Probe a provider/model endpoint | Not used; model availability comes from the `session/create` response
|
|
120
|
-
| `runtime/capabilities` (3.12.3; returns `{independentPlanState:true}`) | Trivial capability handshake | Not used; cheap preflight for a `zcode-acp doctor` command
|
|
121
|
-
| `interaction/providerRuntimeHeadersCancelled` notification (`index.ts:336, 2396-2406`) | Backend cancels a pending runtime-headers refresh (workspace/session/requestId scoped) | Not handled; drop pending answerers immediately on turn cancel instead of waiting them out
|
|
122
|
-
| `workspace/generateText` / `workspace/cancelGenerateText` (0.16.5) | Workspace-scoped one-shot text generation | Not used; no ACP counterpart
|
|
123
|
-
| `workspace/updateInteractionPreferences` / `workspace/updateModelIoPreferences` | Client preference updates | Not used
|
|
124
|
-
| `offPeak/{create,list}`, `workspace/updateOffPeakToolPolicy` (3.12.3) | Off-peak (discounted-hours) task family | Not used; `session/send` carries the matching `offPeakTaskId`/`offPeakRunType` params — candidate if a client wants to schedule discounted-hours runs. Off-peak tools are fail-closed at the protocol layer with three unlock channels (per-session param OR'd, process policy method, `offPeakPort` injection)
|
|
125
|
-
| `automation/{create,update,list,delete,checkTaskBinding}` (3.12.3) | Scheduled (cron) task family — served by the host over `automation/*` requests | Not planned (see below)
|
|
126
|
-
| `plugins/{list,setEnabled,overview,install,uninstall,update,cancelOperation,restoreBuiltin,configure,resetConfig,validate,describe}` + `plugins/marketplace/{add,remove,update}` (3.12.3) | Full plugin management + marketplace family | Not used — **compat watchpoint**: if upstream moves plugin distribution to the marketplace, the bridge's disk-based discovery (`config/plugin-commands.ts`) may go stale
|
|
164
|
+
| `provider/testModelConnectivity` (3.12.3) | Probe a provider/model endpoint | Not used; model availability comes from the `session/create` response |
|
|
165
|
+
| `runtime/capabilities` (3.12.3; returns `{independentPlanState:true}`) | Trivial capability handshake | Not used; cheap preflight for a `zcode-acp doctor` command |
|
|
166
|
+
| `interaction/providerRuntimeHeadersCancelled` notification (`index.ts:336, 2396-2406`) | Backend cancels a pending runtime-headers refresh (workspace/session/requestId scoped) | Not handled; drop pending answerers immediately on turn cancel instead of waiting them out |
|
|
167
|
+
| `workspace/generateText` / `workspace/cancelGenerateText` (0.16.5) | Workspace-scoped one-shot text generation | Not used; no ACP counterpart |
|
|
168
|
+
| `workspace/updateInteractionPreferences` / `workspace/updateModelIoPreferences` | Client preference updates | Not used |
|
|
169
|
+
| `offPeak/{create,list}`, `workspace/updateOffPeakToolPolicy` (3.12.3) | Off-peak (discounted-hours) task family | Not used; `session/send` carries the matching `offPeakTaskId`/`offPeakRunType` params — candidate if a client wants to schedule discounted-hours runs. Off-peak tools are fail-closed at the protocol layer with three unlock channels (per-session param OR'd, process policy method, `offPeakPort` injection) |
|
|
170
|
+
| `automation/{create,update,list,delete,checkTaskBinding}` (3.12.3) | Scheduled (cron) task family — served by the host over `automation/*` requests | Not planned (see below) |
|
|
171
|
+
| `plugins/{list,setEnabled,overview,install,uninstall,update,cancelOperation,restoreBuiltin,configure,resetConfig,validate,describe}` + `plugins/marketplace/{add,remove,update}` (3.12.3) | Full plugin management + marketplace family | Not used — **compat watchpoint**: if upstream moves plugin distribution to the marketplace, the bridge's disk-based discovery (`config/plugin-commands.ts`) may go stale |
|
|
127
172
|
|
|
128
173
|
### `session/send` params (0.16.9-verified, `index.ts:1730-1768`)
|
|
129
174
|
|
package/docs/TROUBLESHOOTING.md
CHANGED
|
@@ -27,6 +27,10 @@
|
|
|
27
27
|
```
|
|
28
28
|
- If not found, set: `export ZCODE_BIN=/path/to/zcode`
|
|
29
29
|
|
|
30
|
+
Which engine binary the bridge actually resolved — the `resolve: launching
|
|
31
|
+
zcode with …` line, including every probe fallback — only prints with
|
|
32
|
+
`ZCODE_ACP_DEBUG=1`; set it before reporting backend-resolution issues (#320).
|
|
33
|
+
|
|
30
34
|
3. Check the ZCode configuration:
|
|
31
35
|
|
|
32
36
|
```bash
|
|
@@ -104,8 +108,11 @@ account provider. A `headersApplied:false` answer makes the turn fail with
|
|
|
104
108
|
-32031 and retry. The bridge (0.42.5+) answers with the coding plan's API key
|
|
105
109
|
from `~/.zcode/v2/config.json` (`codingPlanRequestAuthFor`) — if sends still
|
|
106
110
|
fail, check that the enabled `builtin:bigmodel-coding-plan` entry carries a
|
|
107
|
-
non-empty `options.apiKey` in that file.
|
|
108
|
-
|
|
111
|
+
non-empty `options.apiKey` in that file. On a fresh desktop-only install that
|
|
112
|
+
never wrote `config.json`, both the entitlement snapshot and the request key
|
|
113
|
+
come from the encrypted store `~/.zcode/v2/credentials.json` instead (#320) —
|
|
114
|
+
log into the ZCode desktop app once so it exists. Start-plan providers stay
|
|
115
|
+
declined (Aliyun captcha — desktop app only, issue #123).
|
|
109
116
|
|
|
110
117
|
### Authentication / credential errors (401, provider auth failed)
|
|
111
118
|
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zcode-acp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.68.1",
|
|
4
4
|
"description": "Agent Client Protocol (ACP) server bridging headless ZCode to editors like Zed and JetBrains.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"author": "ZCode ACP Server Contributors",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
|
-
"url": "https://github.com/william0wang/zcode-acp.git"
|
|
10
|
+
"url": "git+https://github.com/william0wang/zcode-acp.git"
|
|
11
11
|
},
|
|
12
12
|
"homepage": "https://github.com/william0wang/zcode-acp#readme",
|
|
13
13
|
"bugs": {
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@agentclientprotocol/sdk": "^1.3.0",
|
|
53
53
|
"ws": "^8.21.3",
|
|
54
|
-
"zcode-acp-martty": "0.
|
|
54
|
+
"zcode-acp-martty": "0.3.1-zcode.1"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"zod": "^3.25.0 || ^4.0.0"
|