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.
- package/README.md +98 -1
- package/README.zh-CN.md +81 -1
- package/dist/backend/client.d.ts +12 -4
- package/dist/backend/client.d.ts.map +1 -1
- package/dist/backend/client.js +72 -7
- package/dist/backend/client.js.map +1 -1
- package/dist/backend/credentials.d.ts.map +1 -1
- package/dist/backend/credentials.js +2 -1
- package/dist/backend/credentials.js.map +1 -1
- package/dist/backend/listener.d.ts +12 -4
- package/dist/backend/listener.d.ts.map +1 -1
- package/dist/backend/listener.js +68 -12
- package/dist/backend/listener.js.map +1 -1
- package/dist/backend/types.d.ts +1 -1
- package/dist/backend/types.d.ts.map +1 -1
- package/dist/bin/quota.d.ts +54 -0
- package/dist/bin/quota.d.ts.map +1 -0
- package/dist/bin/quota.js +333 -0
- package/dist/bin/quota.js.map +1 -0
- package/dist/config/auto-compact.d.ts +23 -0
- package/dist/config/auto-compact.d.ts.map +1 -0
- package/dist/config/auto-compact.js +67 -0
- package/dist/config/auto-compact.js.map +1 -0
- package/dist/config/mcp-discovery.d.ts +34 -0
- package/dist/config/mcp-discovery.d.ts.map +1 -0
- package/dist/config/mcp-discovery.js +153 -0
- package/dist/config/mcp-discovery.js.map +1 -0
- package/dist/config/model-cache.d.ts +12 -1
- package/dist/config/model-cache.d.ts.map +1 -1
- package/dist/config/model-cache.js +30 -8
- package/dist/config/model-cache.js.map +1 -1
- package/dist/config/options.d.ts +87 -9
- package/dist/config/options.d.ts.map +1 -1
- package/dist/config/options.js +248 -45
- package/dist/config/options.js.map +1 -1
- package/dist/config/plugin-commands.d.ts +24 -0
- package/dist/config/plugin-commands.d.ts.map +1 -0
- package/dist/config/plugin-commands.js +107 -0
- package/dist/config/plugin-commands.js.map +1 -0
- package/dist/config/provider-registry.d.ts +60 -0
- package/dist/config/provider-registry.d.ts.map +1 -0
- package/dist/config/provider-registry.js +128 -0
- package/dist/config/provider-registry.js.map +1 -0
- package/dist/config/runtime-model.d.ts +54 -18
- package/dist/config/runtime-model.d.ts.map +1 -1
- package/dist/config/runtime-model.js +105 -61
- package/dist/config/runtime-model.js.map +1 -1
- package/dist/config/skill-discovery.d.ts +35 -0
- package/dist/config/skill-discovery.d.ts.map +1 -0
- package/dist/config/skill-discovery.js +188 -0
- package/dist/config/skill-discovery.js.map +1 -0
- package/dist/handlers/background-tasks.d.ts +72 -0
- package/dist/handlers/background-tasks.d.ts.map +1 -0
- package/dist/handlers/background-tasks.js +330 -0
- package/dist/handlers/background-tasks.js.map +1 -0
- package/dist/handlers/dispatch.d.ts.map +1 -1
- package/dist/handlers/dispatch.js +134 -22
- package/dist/handlers/dispatch.js.map +1 -1
- package/dist/handlers/extensions.d.ts +15 -0
- package/dist/handlers/extensions.d.ts.map +1 -1
- package/dist/handlers/extensions.js +43 -27
- package/dist/handlers/extensions.js.map +1 -1
- package/dist/handlers/io.d.ts +11 -2
- package/dist/handlers/io.d.ts.map +1 -1
- package/dist/handlers/io.js +51 -7
- package/dist/handlers/io.js.map +1 -1
- package/dist/handlers/server-requests.d.ts +20 -4
- package/dist/handlers/server-requests.d.ts.map +1 -1
- package/dist/handlers/server-requests.js +293 -63
- package/dist/handlers/server-requests.js.map +1 -1
- package/dist/handlers/session.d.ts +113 -10
- package/dist/handlers/session.d.ts.map +1 -1
- package/dist/handlers/session.js +876 -220
- package/dist/handlers/session.js.map +1 -1
- package/dist/handlers/slash.d.ts +14 -0
- package/dist/handlers/slash.d.ts.map +1 -1
- package/dist/handlers/slash.js +80 -6
- package/dist/handlers/slash.js.map +1 -1
- package/dist/index.js +38 -4
- package/dist/index.js.map +1 -1
- package/dist/interaction/adapter.d.ts +19 -33
- package/dist/interaction/adapter.d.ts.map +1 -1
- package/dist/interaction/adapter.js +80 -79
- package/dist/interaction/adapter.js.map +1 -1
- package/dist/lazy-sessions.d.ts +35 -0
- package/dist/lazy-sessions.d.ts.map +1 -0
- package/dist/lazy-sessions.js +98 -0
- package/dist/lazy-sessions.js.map +1 -0
- package/dist/quota/cache.d.ts +18 -0
- package/dist/quota/cache.d.ts.map +1 -0
- package/dist/quota/cache.js +32 -0
- package/dist/quota/cache.js.map +1 -0
- package/dist/quota/client.d.ts +30 -0
- package/dist/quota/client.d.ts.map +1 -0
- package/dist/quota/client.js +57 -0
- package/dist/quota/client.js.map +1 -0
- package/dist/quota/color.d.ts +58 -0
- package/dist/quota/color.d.ts.map +1 -0
- package/dist/quota/color.js +95 -0
- package/dist/quota/color.js.map +1 -0
- package/dist/quota/combined.d.ts +66 -0
- package/dist/quota/combined.d.ts.map +1 -0
- package/dist/quota/combined.js +179 -0
- package/dist/quota/combined.js.map +1 -0
- package/dist/quota/format.d.ts +105 -0
- package/dist/quota/format.d.ts.map +1 -0
- package/dist/quota/format.js +219 -0
- package/dist/quota/format.js.map +1 -0
- package/dist/quota/index.d.ts +23 -0
- package/dist/quota/index.d.ts.map +1 -0
- package/dist/quota/index.js +42 -0
- package/dist/quota/index.js.map +1 -0
- package/dist/quota/opencode-go/cache.d.ts +17 -0
- package/dist/quota/opencode-go/cache.d.ts.map +1 -0
- package/dist/quota/opencode-go/cache.js +31 -0
- package/dist/quota/opencode-go/cache.js.map +1 -0
- package/dist/quota/opencode-go/client.d.ts +28 -0
- package/dist/quota/opencode-go/client.d.ts.map +1 -0
- package/dist/quota/opencode-go/client.js +48 -0
- package/dist/quota/opencode-go/client.js.map +1 -0
- package/dist/quota/opencode-go/config.d.ts +37 -0
- package/dist/quota/opencode-go/config.d.ts.map +1 -0
- package/dist/quota/opencode-go/config.js +58 -0
- package/dist/quota/opencode-go/config.js.map +1 -0
- package/dist/quota/opencode-go/format.d.ts +36 -0
- package/dist/quota/opencode-go/format.d.ts.map +1 -0
- package/dist/quota/opencode-go/format.js +87 -0
- package/dist/quota/opencode-go/format.js.map +1 -0
- package/dist/quota/opencode-go/index.d.ts +30 -0
- package/dist/quota/opencode-go/index.d.ts.map +1 -0
- package/dist/quota/opencode-go/index.js +108 -0
- package/dist/quota/opencode-go/index.js.map +1 -0
- package/dist/quota/opencode-go/parse.d.ts +41 -0
- package/dist/quota/opencode-go/parse.d.ts.map +1 -0
- package/dist/quota/opencode-go/parse.js +75 -0
- package/dist/quota/opencode-go/parse.js.map +1 -0
- package/dist/quota/opencode-go/types.d.ts +48 -0
- package/dist/quota/opencode-go/types.d.ts.map +1 -0
- package/dist/quota/opencode-go/types.js +11 -0
- package/dist/quota/opencode-go/types.js.map +1 -0
- package/dist/quota/parse.d.ts +33 -0
- package/dist/quota/parse.d.ts.map +1 -0
- package/dist/quota/parse.js +200 -0
- package/dist/quota/parse.js.map +1 -0
- package/dist/quota/types.d.ts +72 -0
- package/dist/quota/types.d.ts.map +1 -0
- package/dist/quota/types.js +10 -0
- package/dist/quota/types.js.map +1 -0
- package/dist/server.d.ts +104 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +119 -2
- package/dist/server.js.map +1 -1
- package/dist/tasks-index.d.ts +14 -4
- package/dist/tasks-index.d.ts.map +1 -1
- package/dist/tasks-index.js +145 -46
- package/dist/tasks-index.js.map +1 -1
- package/dist/translators/event-translator.d.ts +33 -0
- package/dist/translators/event-translator.d.ts.map +1 -1
- package/dist/translators/event-translator.js +101 -0
- package/dist/translators/event-translator.js.map +1 -1
- package/dist/translators/index.d.ts +1 -1
- package/dist/translators/index.d.ts.map +1 -1
- package/dist/translators/index.js +1 -1
- package/dist/translators/index.js.map +1 -1
- package/dist/translators/projection-differ.d.ts +8 -0
- package/dist/translators/projection-differ.d.ts.map +1 -1
- package/dist/translators/projection-differ.js +19 -9
- package/dist/translators/projection-differ.js.map +1 -1
- package/dist/translators/tool-helpers.d.ts +28 -0
- package/dist/translators/tool-helpers.d.ts.map +1 -1
- package/dist/translators/tool-helpers.js +104 -0
- package/dist/translators/tool-helpers.js.map +1 -1
- package/dist/translators/types.d.ts +38 -1
- package/dist/translators/types.d.ts.map +1 -1
- package/dist/translators/types.js.map +1 -1
- package/dist/utils.d.ts +35 -6
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +52 -4
- package/dist/utils.js.map +1 -1
- package/docs/ARCHITECTURE.md +96 -38
- package/docs/BACKLOG.md +57 -0
- package/docs/DEVELOPMENT.md +5 -0
- package/docs/PROTOCOL.md +270 -5
- package/docs/TROUBLESHOOTING.md +98 -14
- package/docs/agents/domain.md +51 -0
- package/docs/agents/issue-tracker.md +22 -0
- package/docs/agents/triage-labels.md +15 -0
- package/package.json +6 -5
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quota response parsing — turns the raw GLM `limits[]` array into a flat list
|
|
3
|
+
* of normalised {@link QuotaItem}s.
|
|
4
|
+
*
|
|
5
|
+
* Design goals (vs. the reference project):
|
|
6
|
+
* - **No hardcoded type whitelist.** Unknown `type` values still render,
|
|
7
|
+
* labelled by their raw type string, so future windows surface
|
|
8
|
+
* automatically.
|
|
9
|
+
* - **Percentage fallback chain** that tolerates inconsistent field sets
|
|
10
|
+
* across limit kinds (some carry absolute counters, some only a legacy
|
|
11
|
+
* `percentage`).
|
|
12
|
+
* - **Labels derived from `type` + `number`**, without magic-number coupling.
|
|
13
|
+
*/
|
|
14
|
+
/** Coerce an unknown value to a finite number, or `null`. */
|
|
15
|
+
function asFiniteNumber(value) {
|
|
16
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
17
|
+
return Number.isFinite(n) ? n : null;
|
|
18
|
+
}
|
|
19
|
+
/** Clamp a percentage to the valid [0, 100] range, or `null` if not finite. */
|
|
20
|
+
function clampPercent(value) {
|
|
21
|
+
const n = asFiniteNumber(value);
|
|
22
|
+
if (n === null)
|
|
23
|
+
return null;
|
|
24
|
+
return Math.max(0, Math.min(100, Math.round(n)));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Compute `{ leftPercent, usedPercent }` from a single raw limit, tolerating
|
|
28
|
+
* several field combinations (preferred → fallback):
|
|
29
|
+
* 1. `remaining` + `currentValue` (absolute counters) — most precise;
|
|
30
|
+
* 2. `currentValue` / `usage` — used over total;
|
|
31
|
+
* 3. `percentage` (legacy, treated as *used* percent) — last resort.
|
|
32
|
+
* Returns `null` when no percentage can be derived.
|
|
33
|
+
*/
|
|
34
|
+
function computePercentages(limit) {
|
|
35
|
+
const usage = asFiniteNumber(limit.usage);
|
|
36
|
+
const remaining = asFiniteNumber(limit.remaining);
|
|
37
|
+
const currentValue = asFiniteNumber(limit.currentValue);
|
|
38
|
+
// Path 1: absolute remaining/used counters → derive total from parts.
|
|
39
|
+
const totalFromParts = remaining !== null && currentValue !== null ? remaining + currentValue : null;
|
|
40
|
+
const total = totalFromParts !== null && totalFromParts > 0 ? totalFromParts : usage;
|
|
41
|
+
if (total !== null && total > 0) {
|
|
42
|
+
if (remaining !== null && remaining >= 0 && remaining <= total) {
|
|
43
|
+
const leftPercent = clampPercent((remaining / total) * 100);
|
|
44
|
+
if (leftPercent !== null) {
|
|
45
|
+
return { leftPercent, usedPercent: 100 - leftPercent };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (currentValue !== null && currentValue >= 0 && currentValue <= total) {
|
|
49
|
+
const usedPercent = clampPercent((currentValue / total) * 100);
|
|
50
|
+
if (usedPercent !== null) {
|
|
51
|
+
return { leftPercent: 100 - usedPercent, usedPercent };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Path 3: legacy `percentage` (treated as used percent — GLM convention).
|
|
56
|
+
const usedPercent = clampPercent(limit.percentage);
|
|
57
|
+
if (usedPercent === null)
|
|
58
|
+
return null;
|
|
59
|
+
return { leftPercent: 100 - usedPercent, usedPercent };
|
|
60
|
+
}
|
|
61
|
+
/** Map a `type` to a coarse category used for label/key derivation. */
|
|
62
|
+
function categoryOf(type) {
|
|
63
|
+
switch (type) {
|
|
64
|
+
case "TOKENS_LIMIT":
|
|
65
|
+
return "token";
|
|
66
|
+
case "MCP_LIMIT":
|
|
67
|
+
case "TIME_LIMIT":
|
|
68
|
+
return "mcp";
|
|
69
|
+
default:
|
|
70
|
+
return "other";
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Derive a stable key and human-readable label for a limit.
|
|
75
|
+
*
|
|
76
|
+
* Known windows get friendly labels; anything else falls back to the raw
|
|
77
|
+
* `type` (or `"Quota"`) so it still renders.
|
|
78
|
+
*/
|
|
79
|
+
function deriveLabel(limit, category) {
|
|
80
|
+
const number = limit.number;
|
|
81
|
+
if (category === "token") {
|
|
82
|
+
// GLM convention: number===5 → 5-hour window; number===7 → weekly.
|
|
83
|
+
if (number === 5)
|
|
84
|
+
return { key: "token_5h", label: "5h" };
|
|
85
|
+
if (number === 7)
|
|
86
|
+
return { key: "token_week", label: "Week" };
|
|
87
|
+
if (number !== undefined)
|
|
88
|
+
return { key: `token_${number}`, label: `${number}` };
|
|
89
|
+
return { key: "token", label: "Token" };
|
|
90
|
+
}
|
|
91
|
+
if (category === "mcp") {
|
|
92
|
+
return { key: "mcp", label: "MCP" };
|
|
93
|
+
}
|
|
94
|
+
// Unknown type — surface it verbatim rather than hide it.
|
|
95
|
+
const fallback = limit.type || "Quota";
|
|
96
|
+
return { key: fallback.toLowerCase(), label: fallback };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Parse one raw limit into a {@link QuotaItem}, or `null` if no percentage
|
|
100
|
+
* can be computed (the limit is then dropped from display).
|
|
101
|
+
*/
|
|
102
|
+
export function parseLimit(limit) {
|
|
103
|
+
const percent = computePercentages(limit);
|
|
104
|
+
if (!percent)
|
|
105
|
+
return null;
|
|
106
|
+
const category = categoryOf(limit.type);
|
|
107
|
+
const { key, label } = deriveLabel(limit, category);
|
|
108
|
+
const item = {
|
|
109
|
+
key,
|
|
110
|
+
label,
|
|
111
|
+
usedPercent: percent.usedPercent,
|
|
112
|
+
leftPercent: percent.leftPercent,
|
|
113
|
+
};
|
|
114
|
+
// Absolute counters — only some limit kinds carry them (MCP/TIME_LIMIT do,
|
|
115
|
+
// legacy TOKENS_LIMIT often does not). Surface them when present so the
|
|
116
|
+
// formatter can show "(used / total)".
|
|
117
|
+
const usedCount = asFiniteNumber(limit.currentValue);
|
|
118
|
+
if (usedCount !== null)
|
|
119
|
+
item.usedCount = usedCount;
|
|
120
|
+
const totalCount = asFiniteNumber(limit.usage);
|
|
121
|
+
if (totalCount !== null)
|
|
122
|
+
item.totalCount = totalCount;
|
|
123
|
+
const nextResetTime = asFiniteNumber(limit.nextResetTime);
|
|
124
|
+
if (nextResetTime !== null)
|
|
125
|
+
item.nextResetTime = nextResetTime;
|
|
126
|
+
if (Array.isArray(limit.usageDetails) && limit.usageDetails.length > 0) {
|
|
127
|
+
item.detail = limit.usageDetails;
|
|
128
|
+
}
|
|
129
|
+
return item;
|
|
130
|
+
}
|
|
131
|
+
/** Auth-failure detection from the business-layer `msg` (zh/en keywords). */
|
|
132
|
+
function isAuthFailureMessage(msg) {
|
|
133
|
+
return typeof msg === "string" && /authorization|auth|token|鉴权|授权|未登录/i.test(msg);
|
|
134
|
+
}
|
|
135
|
+
/** Rate-limit detection from the business-layer `msg` (zh/en keywords). */
|
|
136
|
+
function isRateLimitedMessage(msg) {
|
|
137
|
+
return (typeof msg === "string" &&
|
|
138
|
+
/rate\s*limit|too many requests|too frequent|frequency|限流|频率|过于频繁|稍后再试/i.test(msg));
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Parse the full API response (already classified by the fetch layer as a
|
|
142
|
+
* `response` with a status + body) into a {@link QuotaResult}.
|
|
143
|
+
*
|
|
144
|
+
* State machine: 429/rate-limit text → `rate_limited`; auth codes/text →
|
|
145
|
+
* `auth_error`; success with zero parseable items → `unavailable`; otherwise
|
|
146
|
+
* the items are returned in original order.
|
|
147
|
+
*/
|
|
148
|
+
export function parseQuotaEnvelope(envelope) {
|
|
149
|
+
// HTTP-level rate limit.
|
|
150
|
+
if (envelope.status === 429 || isRateLimitedMessage(envelope.text)) {
|
|
151
|
+
return { kind: "rate_limited" };
|
|
152
|
+
}
|
|
153
|
+
const payload = envelope.json;
|
|
154
|
+
if (!payload || typeof payload !== "object") {
|
|
155
|
+
return { kind: "unavailable" };
|
|
156
|
+
}
|
|
157
|
+
if (payload.success !== true) {
|
|
158
|
+
if (payload.code === 1001 || payload.code === 401 || isAuthFailureMessage(payload.msg)) {
|
|
159
|
+
return { kind: "auth_error" };
|
|
160
|
+
}
|
|
161
|
+
if (isRateLimitedMessage(payload.msg)) {
|
|
162
|
+
return { kind: "rate_limited" };
|
|
163
|
+
}
|
|
164
|
+
return { kind: "unavailable" };
|
|
165
|
+
}
|
|
166
|
+
const limits = Array.isArray(payload.data?.limits) ? payload.data.limits : [];
|
|
167
|
+
const items = limits
|
|
168
|
+
.map(parseLimit)
|
|
169
|
+
.filter((x) => x !== null)
|
|
170
|
+
.sort(byDisplayOrder);
|
|
171
|
+
if (items.length === 0) {
|
|
172
|
+
return { kind: "unavailable" };
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
kind: "success",
|
|
176
|
+
level: typeof payload.data?.level === "string" ? payload.data.level : "",
|
|
177
|
+
items,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Display ordering: token windows first (5h before Week before other token
|
|
182
|
+
* windows), then MCP, then anything else — by stable key. Keeps the card
|
|
183
|
+
* layout predictable regardless of the API's array order.
|
|
184
|
+
*/
|
|
185
|
+
function byDisplayOrder(a, b) {
|
|
186
|
+
return rankOf(a.key) - rankOf(b.key) || a.key.localeCompare(b.key);
|
|
187
|
+
}
|
|
188
|
+
/** Stable rank for a quota key — lower renders first. */
|
|
189
|
+
function rankOf(key) {
|
|
190
|
+
if (key === "token_5h")
|
|
191
|
+
return 0;
|
|
192
|
+
if (key === "token_week")
|
|
193
|
+
return 1;
|
|
194
|
+
if (key.startsWith("token_"))
|
|
195
|
+
return 2; // other token windows
|
|
196
|
+
if (key === "mcp")
|
|
197
|
+
return 3;
|
|
198
|
+
return 4; // unknown types last
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/quota/parse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the GLM Coding Plan quota feature.
|
|
3
|
+
*
|
|
4
|
+
* The `/quota` slash command queries `bigmodel.cn` / `api.z.ai` for the
|
|
5
|
+
* current account's usage limits and renders them as a multi-line card.
|
|
6
|
+
* These types model the raw API response and the normalised shape consumed
|
|
7
|
+
* by the formatter.
|
|
8
|
+
*/
|
|
9
|
+
/** A single raw limit entry from the GLM quota API (`data.limits[]`). */
|
|
10
|
+
export interface RawLimit {
|
|
11
|
+
/** Limit family — "TOKENS_LIMIT" | "TIME_LIMIT" | "MCP_LIMIT" | <unknown>. */
|
|
12
|
+
type: string;
|
|
13
|
+
/** Window-count sub-identifier; meaning varies by backend (unused for classification). */
|
|
14
|
+
unit?: number;
|
|
15
|
+
/** Window span; GLM uses 5 for the 5-hour window, 7 for the weekly window. */
|
|
16
|
+
number?: number;
|
|
17
|
+
/** Total allowance for the window (absolute counter). */
|
|
18
|
+
usage?: number;
|
|
19
|
+
/** Absolute remaining counter (preferred for percentage). */
|
|
20
|
+
remaining?: number;
|
|
21
|
+
/** Absolute used counter (preferred for percentage alongside `usage`). */
|
|
22
|
+
currentValue?: number;
|
|
23
|
+
/** Legacy percentage field — historically represents *used* percent. */
|
|
24
|
+
percentage?: number;
|
|
25
|
+
/** Reset timestamp in epoch milliseconds. */
|
|
26
|
+
nextResetTime?: number;
|
|
27
|
+
/** Per-model usage breakdown (present on MCP/TIME limits). */
|
|
28
|
+
usageDetails?: {
|
|
29
|
+
modelCode: string;
|
|
30
|
+
usage: number;
|
|
31
|
+
}[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Normalised quota item — one rendered line.
|
|
35
|
+
*
|
|
36
|
+
* Every raw limit that yields a valid percentage becomes a `QuotaItem`;
|
|
37
|
+
* limits with no computable percentage are silently dropped.
|
|
38
|
+
*/
|
|
39
|
+
export interface QuotaItem {
|
|
40
|
+
/** Stable key derived from type+number, e.g. "token_5h" / "mcp". */
|
|
41
|
+
key: string;
|
|
42
|
+
/** Human-readable label for the line, e.g. "5h" / "MCP" / "Week". */
|
|
43
|
+
label: string;
|
|
44
|
+
/** Used percentage, clamped to [0, 100]. */
|
|
45
|
+
usedPercent: number;
|
|
46
|
+
/** Remaining percentage = 100 - usedPercent. */
|
|
47
|
+
leftPercent: number;
|
|
48
|
+
/** Absolute used count (only some limits carry this, e.g. MCP/TIME). */
|
|
49
|
+
usedCount?: number;
|
|
50
|
+
/** Absolute total allowance (only some limits carry this). */
|
|
51
|
+
totalCount?: number;
|
|
52
|
+
/** Reset timestamp in epoch milliseconds, if present. */
|
|
53
|
+
nextResetTime?: number;
|
|
54
|
+
/** Per-model usage breakdown, if present (rendered as indented sub-lines). */
|
|
55
|
+
detail?: {
|
|
56
|
+
modelCode: string;
|
|
57
|
+
usage: number;
|
|
58
|
+
}[];
|
|
59
|
+
}
|
|
60
|
+
/** Top-level parsed result — a 4-state sum type. */
|
|
61
|
+
export type QuotaResult = {
|
|
62
|
+
kind: "success";
|
|
63
|
+
level: string;
|
|
64
|
+
items: QuotaItem[];
|
|
65
|
+
} | {
|
|
66
|
+
kind: "auth_error";
|
|
67
|
+
} | {
|
|
68
|
+
kind: "rate_limited";
|
|
69
|
+
} | {
|
|
70
|
+
kind: "unavailable";
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/quota/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,yEAAyE;AACzE,MAAM,WAAW,QAAQ;IACvB,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,0FAA0F;IAC1F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,YAAY,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvD;AAED;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACxB,oEAAoE;IACpE,GAAG,EAAE,MAAM,CAAC;IACZ,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8EAA8E;IAC9E,MAAM,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACjD;AAED,oDAAoD;AACpD,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,EAAE,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the GLM Coding Plan quota feature.
|
|
3
|
+
*
|
|
4
|
+
* The `/quota` slash command queries `bigmodel.cn` / `api.z.ai` for the
|
|
5
|
+
* current account's usage limits and renders them as a multi-line card.
|
|
6
|
+
* These types model the raw API response and the normalised shape consumed
|
|
7
|
+
* by the formatter.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/quota/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
package/dist/server.d.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type * as acp from "@agentclientprotocol/sdk";
|
|
10
10
|
import { ZcodeBackend } from "./backend/index.js";
|
|
11
|
+
import { BackgroundTaskListener } from "./handlers/background-tasks.js";
|
|
11
12
|
/** Client capabilities advertised in the initialize request. */
|
|
12
13
|
export interface ClientCapabilities {
|
|
13
14
|
fs?: {
|
|
@@ -26,12 +27,51 @@ export interface ClientCapabilities {
|
|
|
26
27
|
export interface PendingTurn {
|
|
27
28
|
zcodeSid: string;
|
|
28
29
|
cancelled: boolean;
|
|
30
|
+
/** Set once session/stop has been fired for this turn, to avoid re-sending. */
|
|
31
|
+
stopSent?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Set when the turn was ended by the stall-recovery heuristic (backend
|
|
34
|
+
* reported idle after a silence) rather than a real turn.completed event.
|
|
35
|
+
* prompt() skips auto-compact for such turns — the completion was inferred,
|
|
36
|
+
* and compressing an in-flight task's context would destroy the work.
|
|
37
|
+
*/
|
|
38
|
+
stallRecovered?: boolean;
|
|
29
39
|
}
|
|
30
40
|
export declare class ZcodeAcpServer {
|
|
31
41
|
/** The ZCode subprocess client (lazy — spawned on first use). */
|
|
32
42
|
backend: ZcodeBackend | null;
|
|
33
43
|
/** acp_sid → zcode session id (usually identical, but kept for clarity). */
|
|
34
44
|
readonly sessionMap: Map<string, string>;
|
|
45
|
+
/**
|
|
46
|
+
* Reverse map: zcode session id → acp_sid. The background-task listener only
|
|
47
|
+
* knows the zcode sid (it comes from backend events), but ACP notifications
|
|
48
|
+
* must address the acp_sid the client knows. Usually the two are identical,
|
|
49
|
+
* but forked/loaded sessions can diverge, so we maintain an explicit reverse
|
|
50
|
+
* index rather than assuming equality.
|
|
51
|
+
*/
|
|
52
|
+
readonly acpSidByZcodeSid: Map<string, string>;
|
|
53
|
+
/**
|
|
54
|
+
* Sessions returned by `session/new` whose backend session has not been
|
|
55
|
+
* created yet (acp_sid → { cwd }). session/new defers `session/create` until
|
|
56
|
+
* the session is first used, so an editor startup that never prompts leaves
|
|
57
|
+
* no empty session in the backend or the App's task index. `ensureRealSession`
|
|
58
|
+
* materializes these on first use; entries live only as long as the bridge
|
|
59
|
+
* process (a never-used placeholder vanishes with it).
|
|
60
|
+
*
|
|
61
|
+
* `creating` holds the in-flight materialization promise while a first-use
|
|
62
|
+
* create is running, so concurrent first-uses (e.g. a raced double prompt)
|
|
63
|
+
* share one `session/create` instead of creating two backend sessions.
|
|
64
|
+
*/
|
|
65
|
+
readonly pendingSessions: Map<string, {
|
|
66
|
+
cwd: string;
|
|
67
|
+
creating?: Promise<string>;
|
|
68
|
+
/** Client-provided MCP servers from session/new, replayed verbatim into
|
|
69
|
+
* the backend's session/create when the lazy session materializes. The
|
|
70
|
+
* backend's mcpServers schema matches the ACP array shape (stdio entries
|
|
71
|
+
* carry command/args/env; remote entries carry type/url), so entries are
|
|
72
|
+
* passed through unchanged. */
|
|
73
|
+
mcpServers?: acp.McpServer[];
|
|
74
|
+
}>;
|
|
35
75
|
/** Currently running turns, keyed by the ACP request id. */
|
|
36
76
|
readonly pendingTurns: Map<number, PendingTurn>;
|
|
37
77
|
/**
|
|
@@ -42,14 +82,53 @@ export declare class ZcodeAcpServer {
|
|
|
42
82
|
readonly preemptLocks: Map<string, Promise<void>>;
|
|
43
83
|
/** Capabilities advertised by the connected client (Zed, JetBrains, ...). */
|
|
44
84
|
clientCapabilities: ClientCapabilities;
|
|
85
|
+
/**
|
|
86
|
+
* Connection-scoped AgentContext, captured at `connect()` time. Held so that
|
|
87
|
+
* background listeners can push `session/update` notifications OUTSIDE a
|
|
88
|
+
* request handler (e.g. when a background task completes after `session/
|
|
89
|
+
* prompt` has already returned). Null before `connect()` runs (only during
|
|
90
|
+
* the brief startup window — sessions can't be created before connect).
|
|
91
|
+
*/
|
|
92
|
+
acpClient: acp.AgentContext | null;
|
|
45
93
|
/** Session titles already set, to enforce set-once (acp_sid → title). */
|
|
46
94
|
readonly sessionTitles: Map<string, string>;
|
|
95
|
+
/**
|
|
96
|
+
* Sessions eligible for auto-title on first end_turn. Only `session/new`
|
|
97
|
+
* populates this — resumed/loaded sessions already carry a title, so their
|
|
98
|
+
* first post-load message must NOT overwrite it. (sessionTitles alone can't
|
|
99
|
+
* distinguish "freshly created" from "resumed but not yet titled in-process".)
|
|
100
|
+
*/
|
|
101
|
+
readonly titleEligibleSessions: Set<string>;
|
|
47
102
|
/** Last mode id advertised to the client (acp_sid → modeId), for change detection. */
|
|
48
103
|
readonly lastMode: Map<string, string>;
|
|
104
|
+
/**
|
|
105
|
+
* Timestamp of the last cancel (user stop or preempt), keyed by zcodeSid.
|
|
106
|
+
* Set in cancel() and preemptInFlightTurn(); read in runEventTurn's stall
|
|
107
|
+
* reconciliation to fast-fail turns that collide with the backend's
|
|
108
|
+
* ~20s model-connection recovery window after a mid-stream abort.
|
|
109
|
+
*/
|
|
110
|
+
readonly lastCancelledAt: Map<string, number>;
|
|
49
111
|
/** Per-session ProjectionDiffers (persists across turns). */
|
|
50
112
|
readonly differs: Map<string, import("./translators/projection-differ.js").ProjectionDiffer>;
|
|
51
113
|
/** Per-session model cache for configOptions model dropdown. */
|
|
52
114
|
readonly modelCache: Map<string, string>;
|
|
115
|
+
/**
|
|
116
|
+
* Per-session (zcodeSid) background-task listeners. Registered once when a
|
|
117
|
+
* session is created/resumed/loaded and lives across prompts, forwarding
|
|
118
|
+
* background task status + result notifications to the client outside of
|
|
119
|
+
* request handlers. The turn loop's own listener coexists with this one
|
|
120
|
+
* (backend.listeners is now a Set per session).
|
|
121
|
+
*/
|
|
122
|
+
readonly backgroundListeners: Map<string, BackgroundTaskListener>;
|
|
123
|
+
/**
|
|
124
|
+
* Per-Bash-callId stdout snapshot already streamed via terminal_output. Used
|
|
125
|
+
* by dispatchTerminalUpdate for two dedup guards:
|
|
126
|
+
* - progress: diff cumulative stdoutTail snapshots, emit only the suffix.
|
|
127
|
+
* - result: if present, the output was already streamed → skip replay.
|
|
128
|
+
* Presence of a key also signals "progress fired for this call" (absent =
|
|
129
|
+
* short command with no progress, so the result emits output once).
|
|
130
|
+
*/
|
|
131
|
+
readonly terminalSentData: Map<string, string>;
|
|
53
132
|
/** Monotonic id counter; base 10_000_000 to avoid collisions with zcode-originated ids. */
|
|
54
133
|
private msgCounter;
|
|
55
134
|
/** Next JSON-RPC id for messages we send to zcode. */
|
|
@@ -58,6 +137,31 @@ export declare class ZcodeAcpServer {
|
|
|
58
137
|
ensureBackend(): ZcodeBackend;
|
|
59
138
|
/** Resolve the zcode session id for an ACP session id. */
|
|
60
139
|
resolveSid(acpSid: string): string | undefined;
|
|
140
|
+
/**
|
|
141
|
+
* Register the acp_sid ↔ zcode_sid mapping both ways. Use this instead of
|
|
142
|
+
* `sessionMap.set(...)` directly so the reverse index stays in sync (the
|
|
143
|
+
* background-task listener needs the reverse lookup to address notifications).
|
|
144
|
+
*/
|
|
145
|
+
registerSession(acpSid: string, zcodeSid: string): void;
|
|
146
|
+
/**
|
|
147
|
+
* Ensure a background-task listener is registered for the session. Idempotent
|
|
148
|
+
* — returns the existing listener if already registered (covers resume/load
|
|
149
|
+
* after new, and fork). Lives for the whole session so background agents that
|
|
150
|
+
* finish AFTER `session/prompt` returns still get their status/result
|
|
151
|
+
* forwarded to the client. The turn loop's own listener coexists via the
|
|
152
|
+
* backend's per-session listener Set.
|
|
153
|
+
*/
|
|
154
|
+
ensureBackgroundListener(zcodeSid: string): BackgroundTaskListener;
|
|
155
|
+
/** Resolve the ACP session id for a zcode session id (reverse of resolveSid). */
|
|
156
|
+
resolveAcpSid(zcodeSid: string): string | undefined;
|
|
157
|
+
/**
|
|
158
|
+
* Push a `session/update` notification to the client from OUTSIDE a request
|
|
159
|
+
* handler (used by the background-task listener). Resolves the acp_sid from
|
|
160
|
+
* the zcode_sid and no-ops (returning false) if the client or session is
|
|
161
|
+
* unknown. Never throws — callers run in the event loop and must not crash
|
|
162
|
+
* the bridge on a notification failure.
|
|
163
|
+
*/
|
|
164
|
+
notifyByZcodeSid(zcodeSid: string, update: acp.SessionUpdate): Promise<boolean>;
|
|
61
165
|
/** Whether the client declared `_meta.terminal_output` (Zed's Bash UI hook). */
|
|
62
166
|
supportsTerminalOutput(): boolean;
|
|
63
167
|
/**
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAErD,OAAO,EAIL,YAAY,EACb,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -7,12 +7,34 @@
|
|
|
7
7
|
* every handler layer can reach it without globals.
|
|
8
8
|
*/
|
|
9
9
|
import { loadZcodeCredentials, mergeEnvWithCreds, resolveZcodeCommand, ZcodeBackend, } from "./backend/index.js";
|
|
10
|
+
import { BackgroundTaskListener } from "./handlers/background-tasks.js";
|
|
10
11
|
import { AGENT_INFO, PROTOCOL_VERSION, log } from "./utils.js";
|
|
11
12
|
export class ZcodeAcpServer {
|
|
12
13
|
/** The ZCode subprocess client (lazy — spawned on first use). */
|
|
13
14
|
backend = null;
|
|
14
15
|
/** acp_sid → zcode session id (usually identical, but kept for clarity). */
|
|
15
16
|
sessionMap = new Map();
|
|
17
|
+
/**
|
|
18
|
+
* Reverse map: zcode session id → acp_sid. The background-task listener only
|
|
19
|
+
* knows the zcode sid (it comes from backend events), but ACP notifications
|
|
20
|
+
* must address the acp_sid the client knows. Usually the two are identical,
|
|
21
|
+
* but forked/loaded sessions can diverge, so we maintain an explicit reverse
|
|
22
|
+
* index rather than assuming equality.
|
|
23
|
+
*/
|
|
24
|
+
acpSidByZcodeSid = new Map();
|
|
25
|
+
/**
|
|
26
|
+
* Sessions returned by `session/new` whose backend session has not been
|
|
27
|
+
* created yet (acp_sid → { cwd }). session/new defers `session/create` until
|
|
28
|
+
* the session is first used, so an editor startup that never prompts leaves
|
|
29
|
+
* no empty session in the backend or the App's task index. `ensureRealSession`
|
|
30
|
+
* materializes these on first use; entries live only as long as the bridge
|
|
31
|
+
* process (a never-used placeholder vanishes with it).
|
|
32
|
+
*
|
|
33
|
+
* `creating` holds the in-flight materialization promise while a first-use
|
|
34
|
+
* create is running, so concurrent first-uses (e.g. a raced double prompt)
|
|
35
|
+
* share one `session/create` instead of creating two backend sessions.
|
|
36
|
+
*/
|
|
37
|
+
pendingSessions = new Map();
|
|
16
38
|
/** Currently running turns, keyed by the ACP request id. */
|
|
17
39
|
pendingTurns = new Map();
|
|
18
40
|
/**
|
|
@@ -23,14 +45,53 @@ export class ZcodeAcpServer {
|
|
|
23
45
|
preemptLocks = new Map();
|
|
24
46
|
/** Capabilities advertised by the connected client (Zed, JetBrains, ...). */
|
|
25
47
|
clientCapabilities = {};
|
|
48
|
+
/**
|
|
49
|
+
* Connection-scoped AgentContext, captured at `connect()` time. Held so that
|
|
50
|
+
* background listeners can push `session/update` notifications OUTSIDE a
|
|
51
|
+
* request handler (e.g. when a background task completes after `session/
|
|
52
|
+
* prompt` has already returned). Null before `connect()` runs (only during
|
|
53
|
+
* the brief startup window — sessions can't be created before connect).
|
|
54
|
+
*/
|
|
55
|
+
acpClient = null;
|
|
26
56
|
/** Session titles already set, to enforce set-once (acp_sid → title). */
|
|
27
57
|
sessionTitles = new Map();
|
|
58
|
+
/**
|
|
59
|
+
* Sessions eligible for auto-title on first end_turn. Only `session/new`
|
|
60
|
+
* populates this — resumed/loaded sessions already carry a title, so their
|
|
61
|
+
* first post-load message must NOT overwrite it. (sessionTitles alone can't
|
|
62
|
+
* distinguish "freshly created" from "resumed but not yet titled in-process".)
|
|
63
|
+
*/
|
|
64
|
+
titleEligibleSessions = new Set();
|
|
28
65
|
/** Last mode id advertised to the client (acp_sid → modeId), for change detection. */
|
|
29
66
|
lastMode = new Map();
|
|
67
|
+
/**
|
|
68
|
+
* Timestamp of the last cancel (user stop or preempt), keyed by zcodeSid.
|
|
69
|
+
* Set in cancel() and preemptInFlightTurn(); read in runEventTurn's stall
|
|
70
|
+
* reconciliation to fast-fail turns that collide with the backend's
|
|
71
|
+
* ~20s model-connection recovery window after a mid-stream abort.
|
|
72
|
+
*/
|
|
73
|
+
lastCancelledAt = new Map();
|
|
30
74
|
/** Per-session ProjectionDiffers (persists across turns). */
|
|
31
75
|
differs = new Map();
|
|
32
76
|
/** Per-session model cache for configOptions model dropdown. */
|
|
33
77
|
modelCache = new Map();
|
|
78
|
+
/**
|
|
79
|
+
* Per-session (zcodeSid) background-task listeners. Registered once when a
|
|
80
|
+
* session is created/resumed/loaded and lives across prompts, forwarding
|
|
81
|
+
* background task status + result notifications to the client outside of
|
|
82
|
+
* request handlers. The turn loop's own listener coexists with this one
|
|
83
|
+
* (backend.listeners is now a Set per session).
|
|
84
|
+
*/
|
|
85
|
+
backgroundListeners = new Map();
|
|
86
|
+
/**
|
|
87
|
+
* Per-Bash-callId stdout snapshot already streamed via terminal_output. Used
|
|
88
|
+
* by dispatchTerminalUpdate for two dedup guards:
|
|
89
|
+
* - progress: diff cumulative stdoutTail snapshots, emit only the suffix.
|
|
90
|
+
* - result: if present, the output was already streamed → skip replay.
|
|
91
|
+
* Presence of a key also signals "progress fired for this call" (absent =
|
|
92
|
+
* short command with no progress, so the result emits output once).
|
|
93
|
+
*/
|
|
94
|
+
terminalSentData = new Map();
|
|
34
95
|
/** Monotonic id counter; base 10_000_000 to avoid collisions with zcode-originated ids. */
|
|
35
96
|
msgCounter = 10_000_000;
|
|
36
97
|
/** Next JSON-RPC id for messages we send to zcode. */
|
|
@@ -50,6 +111,61 @@ export class ZcodeAcpServer {
|
|
|
50
111
|
resolveSid(acpSid) {
|
|
51
112
|
return this.sessionMap.get(acpSid);
|
|
52
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Register the acp_sid ↔ zcode_sid mapping both ways. Use this instead of
|
|
116
|
+
* `sessionMap.set(...)` directly so the reverse index stays in sync (the
|
|
117
|
+
* background-task listener needs the reverse lookup to address notifications).
|
|
118
|
+
*/
|
|
119
|
+
registerSession(acpSid, zcodeSid) {
|
|
120
|
+
this.sessionMap.set(acpSid, zcodeSid);
|
|
121
|
+
this.acpSidByZcodeSid.set(zcodeSid, acpSid);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Ensure a background-task listener is registered for the session. Idempotent
|
|
125
|
+
* — returns the existing listener if already registered (covers resume/load
|
|
126
|
+
* after new, and fork). Lives for the whole session so background agents that
|
|
127
|
+
* finish AFTER `session/prompt` returns still get their status/result
|
|
128
|
+
* forwarded to the client. The turn loop's own listener coexists via the
|
|
129
|
+
* backend's per-session listener Set.
|
|
130
|
+
*/
|
|
131
|
+
ensureBackgroundListener(zcodeSid) {
|
|
132
|
+
const existing = this.backgroundListeners.get(zcodeSid);
|
|
133
|
+
if (existing)
|
|
134
|
+
return existing;
|
|
135
|
+
const backend = this.ensureBackend();
|
|
136
|
+
const listener = new BackgroundTaskListener(this, zcodeSid);
|
|
137
|
+
this.backgroundListeners.set(zcodeSid, listener);
|
|
138
|
+
backend.registerEventListener(zcodeSid, listener);
|
|
139
|
+
log(` [bg] background listener registered for ${zcodeSid}`);
|
|
140
|
+
return listener;
|
|
141
|
+
}
|
|
142
|
+
/** Resolve the ACP session id for a zcode session id (reverse of resolveSid). */
|
|
143
|
+
resolveAcpSid(zcodeSid) {
|
|
144
|
+
return this.acpSidByZcodeSid.get(zcodeSid);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Push a `session/update` notification to the client from OUTSIDE a request
|
|
148
|
+
* handler (used by the background-task listener). Resolves the acp_sid from
|
|
149
|
+
* the zcode_sid and no-ops (returning false) if the client or session is
|
|
150
|
+
* unknown. Never throws — callers run in the event loop and must not crash
|
|
151
|
+
* the bridge on a notification failure.
|
|
152
|
+
*/
|
|
153
|
+
async notifyByZcodeSid(zcodeSid, update) {
|
|
154
|
+
const cx = this.acpClient;
|
|
155
|
+
if (!cx)
|
|
156
|
+
return false;
|
|
157
|
+
const acpSid = this.resolveAcpSid(zcodeSid);
|
|
158
|
+
if (!acpSid)
|
|
159
|
+
return false;
|
|
160
|
+
try {
|
|
161
|
+
await cx.notify("session/update", { sessionId: acpSid, update });
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
catch (e) {
|
|
165
|
+
log(`notifyByZcodeSid: session/update failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
53
169
|
/** Whether the client declared `_meta.terminal_output` (Zed's Bash UI hook). */
|
|
54
170
|
supportsTerminalOutput() {
|
|
55
171
|
const meta = this.clientCapabilities._meta ?? {};
|
|
@@ -70,13 +186,14 @@ export class ZcodeAcpServer {
|
|
|
70
186
|
this.clientCapabilities = params.clientCapabilities ?? {};
|
|
71
187
|
log(`initialize: client protocolVersion=${params.protocolVersion}` +
|
|
72
188
|
`, client=${clientInfo?.name ?? "unknown"}` +
|
|
73
|
-
`, version=${clientInfo?.version ?? "unknown"}`
|
|
189
|
+
`, version=${clientInfo?.version ?? "unknown"}` +
|
|
190
|
+
`, elicitation.form=${this.clientCapabilities.elicitation?.form == null ? "no" : "yes"}`);
|
|
74
191
|
return {
|
|
75
192
|
protocolVersion: PROTOCOL_VERSION,
|
|
76
193
|
agentInfo: { ...AGENT_INFO },
|
|
77
194
|
agentCapabilities: {
|
|
78
195
|
loadSession: true,
|
|
79
|
-
promptCapabilities: { image:
|
|
196
|
+
promptCapabilities: { image: true, audio: false, embeddedContext: false },
|
|
80
197
|
mcpCapabilities: { http: false, sse: false },
|
|
81
198
|
sessionCapabilities: { list: {}, resume: {}, fork: {} },
|
|
82
199
|
},
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|