zcode-acp-server 0.1.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/LICENSE +201 -0
- package/README.md +167 -0
- package/README.zh-CN.md +163 -0
- package/dist/backend/client.d.ts +103 -0
- package/dist/backend/client.d.ts.map +1 -0
- package/dist/backend/client.js +344 -0
- package/dist/backend/client.js.map +1 -0
- package/dist/backend/credentials.d.ts +31 -0
- package/dist/backend/credentials.d.ts.map +1 -0
- package/dist/backend/credentials.js +93 -0
- package/dist/backend/credentials.js.map +1 -0
- package/dist/backend/index.d.ts +7 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +6 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/listener.d.ts +63 -0
- package/dist/backend/listener.d.ts.map +1 -0
- package/dist/backend/listener.js +138 -0
- package/dist/backend/listener.js.map +1 -0
- package/dist/backend/resolve.d.ts +11 -0
- package/dist/backend/resolve.d.ts.map +1 -0
- package/dist/backend/resolve.js +116 -0
- package/dist/backend/resolve.js.map +1 -0
- package/dist/backend/types.d.ts +164 -0
- package/dist/backend/types.d.ts.map +1 -0
- package/dist/backend/types.js +15 -0
- package/dist/backend/types.js.map +1 -0
- package/dist/config/model-cache.d.ts +20 -0
- package/dist/config/model-cache.d.ts.map +1 -0
- package/dist/config/model-cache.js +62 -0
- package/dist/config/model-cache.js.map +1 -0
- package/dist/config/options.d.ts +36 -0
- package/dist/config/options.d.ts.map +1 -0
- package/dist/config/options.js +171 -0
- package/dist/config/options.js.map +1 -0
- package/dist/config/runtime-model.d.ts +33 -0
- package/dist/config/runtime-model.d.ts.map +1 -0
- package/dist/config/runtime-model.js +96 -0
- package/dist/config/runtime-model.js.map +1 -0
- package/dist/handlers/dispatch.d.ts +15 -0
- package/dist/handlers/dispatch.d.ts.map +1 -0
- package/dist/handlers/dispatch.js +183 -0
- package/dist/handlers/dispatch.js.map +1 -0
- package/dist/handlers/extensions.d.ts +43 -0
- package/dist/handlers/extensions.d.ts.map +1 -0
- package/dist/handlers/extensions.js +310 -0
- package/dist/handlers/extensions.js.map +1 -0
- package/dist/handlers/io.d.ts +40 -0
- package/dist/handlers/io.d.ts.map +1 -0
- package/dist/handlers/io.js +55 -0
- package/dist/handlers/io.js.map +1 -0
- package/dist/handlers/server-requests.d.ts +34 -0
- package/dist/handlers/server-requests.d.ts.map +1 -0
- package/dist/handlers/server-requests.js +357 -0
- package/dist/handlers/server-requests.js.map +1 -0
- package/dist/handlers/session.d.ts +46 -0
- package/dist/handlers/session.d.ts.map +1 -0
- package/dist/handlers/session.js +738 -0
- package/dist/handlers/session.js.map +1 -0
- package/dist/handlers/slash.d.ts +16 -0
- package/dist/handlers/slash.d.ts.map +1 -0
- package/dist/handlers/slash.js +107 -0
- package/dist/handlers/slash.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -0
- package/dist/interaction/adapter.d.ts +136 -0
- package/dist/interaction/adapter.d.ts.map +1 -0
- package/dist/interaction/adapter.js +353 -0
- package/dist/interaction/adapter.js.map +1 -0
- package/dist/server.d.ts +73 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +97 -0
- package/dist/server.js.map +1 -0
- package/dist/tasks-index.d.ts +39 -0
- package/dist/tasks-index.d.ts.map +1 -0
- package/dist/tasks-index.js +152 -0
- package/dist/tasks-index.js.map +1 -0
- package/dist/translators/event-translator.d.ts +40 -0
- package/dist/translators/event-translator.d.ts.map +1 -0
- package/dist/translators/event-translator.js +214 -0
- package/dist/translators/event-translator.js.map +1 -0
- package/dist/translators/index.d.ts +6 -0
- package/dist/translators/index.d.ts.map +1 -0
- package/dist/translators/index.js +5 -0
- package/dist/translators/index.js.map +1 -0
- package/dist/translators/projection-differ.d.ts +48 -0
- package/dist/translators/projection-differ.d.ts.map +1 -0
- package/dist/translators/projection-differ.js +239 -0
- package/dist/translators/projection-differ.js.map +1 -0
- package/dist/translators/tool-helpers.d.ts +60 -0
- package/dist/translators/tool-helpers.d.ts.map +1 -0
- package/dist/translators/tool-helpers.js +308 -0
- package/dist/translators/tool-helpers.js.map +1 -0
- package/dist/translators/types.d.ts +58 -0
- package/dist/translators/types.d.ts.map +1 -0
- package/dist/translators/types.js +27 -0
- package/dist/translators/types.js.map +1 -0
- package/dist/utils.d.ts +111 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +110 -0
- package/dist/utils.js.map +1 -0
- package/docs/ARCHITECTURE.md +299 -0
- package/docs/DEVELOPMENT.md +193 -0
- package/docs/PROTOCOL.md +649 -0
- package/docs/TROUBLESHOOTING.md +251 -0
- package/package.json +66 -0
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interaction channel adapter: zcode `interaction/*` server→client requests
|
|
3
|
+
* ↔ ACP `session/requestPermission`.
|
|
4
|
+
*
|
|
5
|
+
* ZCode's `createProtocolInteractionBroker` dispatches server→client requests
|
|
6
|
+
* by tool. Zed supports `session/requestPermission` natively (the allow/reject
|
|
7
|
+
* popup) but NOT elicitation, so all three interaction kinds map onto
|
|
8
|
+
* requestPermission:
|
|
9
|
+
* - interaction/requestPermission (tool approval) → direct mapping
|
|
10
|
+
* - interaction/requestUserInput (plan_approval / ExitPlanMode) → approve/reject
|
|
11
|
+
* - interaction/requestUserInput (AskUserQuestion) → per-question options
|
|
12
|
+
* (single-select: one popup + Skip; multi-select: per-option Include/Skip)
|
|
13
|
+
*
|
|
14
|
+
* `requestPermission` is single-select, so multi-select questions are split
|
|
15
|
+
* into per-option yes/no popups; the user's Include picks are comma-joined
|
|
16
|
+
* into the final answer (mirrors the reference impl's `answers[q]: "a, b"`).
|
|
17
|
+
*/
|
|
18
|
+
// ---------- classification ----------
|
|
19
|
+
export function isPermissionRequest(method) {
|
|
20
|
+
return method === "interaction/requestPermission";
|
|
21
|
+
}
|
|
22
|
+
export function isUserInputRequest(method) {
|
|
23
|
+
return method === "interaction/requestUserInput";
|
|
24
|
+
}
|
|
25
|
+
export function isExitPlanMode(params) {
|
|
26
|
+
if (!params || typeof params !== "object")
|
|
27
|
+
return false;
|
|
28
|
+
const schema = params.schema;
|
|
29
|
+
if (!schema || typeof schema !== "object")
|
|
30
|
+
return false;
|
|
31
|
+
return schema.interaction === "plan_approval";
|
|
32
|
+
}
|
|
33
|
+
/** AskUserQuestion = requestUserInput WITHOUT the plan_approval schema. */
|
|
34
|
+
export function isAskUserQuestion(method, params) {
|
|
35
|
+
return isUserInputRequest(method) && !isExitPlanMode(params);
|
|
36
|
+
}
|
|
37
|
+
// ---------- zcode permission → ACP requestPermission ----------
|
|
38
|
+
/**
|
|
39
|
+
* Normalize a zcode permission-option `kind` to one of the 4 ACP-legal values
|
|
40
|
+
* (`allow_once` | `allow_always` | `reject_once` | `reject_always`).
|
|
41
|
+
*
|
|
42
|
+
* zcode's backend emits a wider/legacy enum that includes `deny`, `allow`,
|
|
43
|
+
* `reject`, etc. The ACP schema (and Zed's deserializer) only accepts the four
|
|
44
|
+
* canonical values — anything else makes the *whole* `requestPermission` fail
|
|
45
|
+
* at the client with "unknown variant", so the popup never renders and the
|
|
46
|
+
* request defaults to decline. `optionId` is free text and stays untouched.
|
|
47
|
+
*
|
|
48
|
+
* Fail-safe: any unrecognized kind maps to `reject_once` (never auto-allow).
|
|
49
|
+
*/
|
|
50
|
+
function normalizeKind(kind) {
|
|
51
|
+
switch (kind) {
|
|
52
|
+
case "allow_once":
|
|
53
|
+
case "allow_always":
|
|
54
|
+
case "reject_once":
|
|
55
|
+
case "reject_always":
|
|
56
|
+
return kind;
|
|
57
|
+
case "allow":
|
|
58
|
+
case "allow_project":
|
|
59
|
+
return "allow_always";
|
|
60
|
+
case "reject":
|
|
61
|
+
case "deny":
|
|
62
|
+
return "reject_once";
|
|
63
|
+
default:
|
|
64
|
+
return "reject_once";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** Convert a zcode tool-permission request into ACP requestPermission params. */
|
|
68
|
+
export function zcodePermissionToAcp(params, acpSid) {
|
|
69
|
+
const options = [];
|
|
70
|
+
for (const opt of params.options ?? []) {
|
|
71
|
+
options.push({
|
|
72
|
+
optionId: opt.optionId ?? "",
|
|
73
|
+
kind: normalizeKind(opt.kind),
|
|
74
|
+
name: opt.name ?? opt.optionId ?? "",
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (options.length === 0)
|
|
78
|
+
return null;
|
|
79
|
+
return {
|
|
80
|
+
options,
|
|
81
|
+
sessionId: acpSid,
|
|
82
|
+
toolCall: { toolCallId: params.toolCallId ?? "", rawInput: params.input },
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Allow-class optionIds that zcode's backend emits. The response mapper must
|
|
87
|
+
* recognize ALL of them — selecting "Allow once" (optionId "allow_once") in
|
|
88
|
+
* the popup otherwise gets reported back as a rejection. optionId is free
|
|
89
|
+
* text defined by the backend, so this set mirrors the backend's naming.
|
|
90
|
+
* Any optionId not in this set is treated as deny (fail-safe). */
|
|
91
|
+
const ALLOW_OPTION_IDS = new Set(["allow", "allow_once", "allow_always", "allow_project"]);
|
|
92
|
+
/** Convert an ACP requestPermission response → zcode {decision, reason?}. */
|
|
93
|
+
export function acpPermissionResponseToZcode(acpResp) {
|
|
94
|
+
if (!acpResp || typeof acpResp !== "object") {
|
|
95
|
+
return { decision: "deny", reason: "invalid client response" };
|
|
96
|
+
}
|
|
97
|
+
const outcome = acpResp.outcome ?? {};
|
|
98
|
+
if (outcome.outcome === "cancelled")
|
|
99
|
+
return { decision: "deny", reason: "cancelled by user" };
|
|
100
|
+
const optionId = outcome.optionId ?? "";
|
|
101
|
+
if (ALLOW_OPTION_IDS.has(optionId))
|
|
102
|
+
return { decision: "allow" };
|
|
103
|
+
return { decision: "deny", reason: `rejected (${optionId})` };
|
|
104
|
+
}
|
|
105
|
+
// ---------- ExitPlanMode → ACP requestPermission ----------
|
|
106
|
+
/** ExitPlanMode rendered as approve/reject permission options. */
|
|
107
|
+
export function exitPlanModeToAcpPermission(params, acpSid) {
|
|
108
|
+
return {
|
|
109
|
+
options: [
|
|
110
|
+
{ kind: "allow_once", name: "Approve — exit plan mode", optionId: "approve" },
|
|
111
|
+
{ kind: "reject_once", name: "Reject — keep planning", optionId: "reject" },
|
|
112
|
+
],
|
|
113
|
+
sessionId: acpSid,
|
|
114
|
+
toolCall: { toolCallId: params.toolCallId ?? "", rawInput: params.input },
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/** Convert an ACP response → zcode ExitPlanMode response. */
|
|
118
|
+
export function acpPermissionResponseToExitPlanMode(acpResp) {
|
|
119
|
+
if (!acpResp || typeof acpResp !== "object") {
|
|
120
|
+
return { action: "decline", reason: "invalid client response" };
|
|
121
|
+
}
|
|
122
|
+
const outcome = acpResp.outcome ?? {};
|
|
123
|
+
if (outcome.outcome === "cancelled")
|
|
124
|
+
return { action: "decline", reason: "cancelled" };
|
|
125
|
+
if (outcome.optionId === "approve") {
|
|
126
|
+
// content must be an object with answer_0 (zcode reads content.answer_0).
|
|
127
|
+
return { action: "accept", content: { answer_0: "approve" } };
|
|
128
|
+
}
|
|
129
|
+
return { action: "decline", reason: "rejected" };
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Split a zcode AskUserQuestion request into per-question descriptors.
|
|
133
|
+
*
|
|
134
|
+
* Single-select: one ACP option per label + a trailing Skip.
|
|
135
|
+
* Multi-select: each label becomes a yes/no pair (optionId `<label>:yes` /
|
|
136
|
+
* `<label>:no`) so the handler can pop one Include/Skip dialog per option.
|
|
137
|
+
*
|
|
138
|
+
* Returns null when there are no valid questions.
|
|
139
|
+
*/
|
|
140
|
+
export function splitAskUserQuestions(params) {
|
|
141
|
+
// zcode carries questions both at the top level and under input.questions; prefer top level.
|
|
142
|
+
let questions = params.questions;
|
|
143
|
+
if (!questions || questions.length === 0) {
|
|
144
|
+
questions = params.input?.questions ?? [];
|
|
145
|
+
}
|
|
146
|
+
const valid = questions.filter((q) => q && typeof q.question === "string");
|
|
147
|
+
if (valid.length === 0)
|
|
148
|
+
return null;
|
|
149
|
+
const result = [];
|
|
150
|
+
for (const q of valid) {
|
|
151
|
+
const labels = [];
|
|
152
|
+
for (const opt of q.options ?? []) {
|
|
153
|
+
const label = opt.label ?? opt.value ?? "";
|
|
154
|
+
if (label)
|
|
155
|
+
labels.push(label);
|
|
156
|
+
}
|
|
157
|
+
if (labels.length === 0)
|
|
158
|
+
continue;
|
|
159
|
+
const multi = q.multiSelect === true;
|
|
160
|
+
if (multi) {
|
|
161
|
+
const options = [];
|
|
162
|
+
for (const lb of labels) {
|
|
163
|
+
options.push({ optionId: `${lb}:yes`, kind: "allow_once", name: `Include: ${lb}` });
|
|
164
|
+
options.push({ optionId: `${lb}:no`, kind: "reject_once", name: `Skip: ${lb}` });
|
|
165
|
+
}
|
|
166
|
+
result.push({ question: q.question, multiSelect: true, options });
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
const options = labels.map((lb) => ({
|
|
170
|
+
optionId: lb,
|
|
171
|
+
kind: "allow_once",
|
|
172
|
+
name: lb,
|
|
173
|
+
}));
|
|
174
|
+
options.push({ optionId: "__skip__", kind: "reject_once", name: "Skip" });
|
|
175
|
+
result.push({ question: q.question, multiSelect: false, options });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return result.length > 0 ? result : null;
|
|
179
|
+
}
|
|
180
|
+
/** Build ACP requestPermission params for one AskUserQuestion question. */
|
|
181
|
+
export function buildAskUserAcpParams(params, acpSid, options) {
|
|
182
|
+
return {
|
|
183
|
+
options,
|
|
184
|
+
sessionId: acpSid,
|
|
185
|
+
toolCall: { toolCallId: params.toolCallId ?? "", rawInput: params.input },
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Parse one ACP requestPermission response → "yes" | "no" | label | null.
|
|
190
|
+
*
|
|
191
|
+
* Multi-select: optionId `<label>:yes` → "yes", `<label>:no` → "no".
|
|
192
|
+
* Single-select: optionId is the label; __skip__ / cancel → null.
|
|
193
|
+
*/
|
|
194
|
+
export function parseAskUserResponse(acpResp) {
|
|
195
|
+
if (!acpResp || typeof acpResp !== "object")
|
|
196
|
+
return null;
|
|
197
|
+
const outcome = acpResp.outcome ?? {};
|
|
198
|
+
if (outcome.outcome === "cancelled")
|
|
199
|
+
return null;
|
|
200
|
+
const optionId = outcome.optionId ?? "";
|
|
201
|
+
if (!optionId || optionId === "__skip__")
|
|
202
|
+
return null;
|
|
203
|
+
if (optionId.endsWith(":yes"))
|
|
204
|
+
return "yes";
|
|
205
|
+
if (optionId.endsWith(":no"))
|
|
206
|
+
return "no";
|
|
207
|
+
return optionId;
|
|
208
|
+
}
|
|
209
|
+
// ---------- elicitation form (preferred when client supports it) ----------
|
|
210
|
+
/**
|
|
211
|
+
* Build an elicitation form schema for an AskUserQuestion request.
|
|
212
|
+
*
|
|
213
|
+
* Each question becomes one property in the form:
|
|
214
|
+
* - Single-select → string enum of labels + a trailing "Skip" option
|
|
215
|
+
* - Multi-select → string array enum of labels
|
|
216
|
+
*
|
|
217
|
+
* When the client supports form-based elicitation, this lets the user answer
|
|
218
|
+
* all questions in one form rather than one popup per question. Single-select
|
|
219
|
+
* fields include a "Skip" option so the user can opt out of a question without
|
|
220
|
+
* cancelling the whole form (mirrors the request_permission fallback, which
|
|
221
|
+
* appends a Skip option per question).
|
|
222
|
+
*/
|
|
223
|
+
export function buildAskUserElicitationForm(params, acpSid, toolCallId) {
|
|
224
|
+
const questions = params.questions?.length ? params.questions : (params.input?.questions ?? []);
|
|
225
|
+
const properties = {};
|
|
226
|
+
const required = [];
|
|
227
|
+
for (let i = 0; i < questions.length; i++) {
|
|
228
|
+
const q = questions[i];
|
|
229
|
+
if (!q || typeof q.question !== "string")
|
|
230
|
+
continue;
|
|
231
|
+
const key = `q_${i}`;
|
|
232
|
+
const labels = (q.options ?? [])
|
|
233
|
+
.map((o) => o.label ?? o.value ?? "")
|
|
234
|
+
.filter((l) => l.length > 0);
|
|
235
|
+
if (labels.length === 0)
|
|
236
|
+
continue;
|
|
237
|
+
if (q.multiSelect) {
|
|
238
|
+
properties[key] = {
|
|
239
|
+
type: "array",
|
|
240
|
+
items: { type: "string", enum: labels },
|
|
241
|
+
title: q.question,
|
|
242
|
+
description: q.question,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
// Append a Skip option so the user can opt out of this question without
|
|
247
|
+
// cancelling the whole form (parity with the request_permission path).
|
|
248
|
+
properties[key] = {
|
|
249
|
+
type: "string",
|
|
250
|
+
enum: [...labels, ELICIT_SKIP],
|
|
251
|
+
title: q.question,
|
|
252
|
+
description: q.question,
|
|
253
|
+
};
|
|
254
|
+
required.push(key);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const message = questions.length === 1
|
|
258
|
+
? (questions[0]?.question ?? "Please answer the question.")
|
|
259
|
+
: `Please answer ${questions.length} questions.`;
|
|
260
|
+
const form = {
|
|
261
|
+
mode: "form",
|
|
262
|
+
sessionId: acpSid,
|
|
263
|
+
message,
|
|
264
|
+
requestedSchema: { type: "object", properties, required },
|
|
265
|
+
};
|
|
266
|
+
if (toolCallId)
|
|
267
|
+
form.toolCallId = toolCallId;
|
|
268
|
+
return form;
|
|
269
|
+
}
|
|
270
|
+
/** Sentinel enum value marking a single-select question as skipped in the form. */
|
|
271
|
+
const ELICIT_SKIP = "__skip__";
|
|
272
|
+
/**
|
|
273
|
+
* Parse an elicitation form response into the zcode answers map.
|
|
274
|
+
*
|
|
275
|
+
* Maps each `q_<i>` form field back to the original question text. Multi-select
|
|
276
|
+
* answers (arrays) are comma-joined to match the request_permission path's
|
|
277
|
+
* `"a, b"` format. Returns null if the user declined/cancelled.
|
|
278
|
+
*/
|
|
279
|
+
export function parseAskUserElicitationResponse(acpResp, params) {
|
|
280
|
+
if (!acpResp || typeof acpResp !== "object")
|
|
281
|
+
return null;
|
|
282
|
+
const resp = acpResp;
|
|
283
|
+
if (resp.action !== "accept" || !resp.content)
|
|
284
|
+
return null;
|
|
285
|
+
const questions = params.questions?.length ? params.questions : (params.input?.questions ?? []);
|
|
286
|
+
const answers = {};
|
|
287
|
+
for (let i = 0; i < questions.length; i++) {
|
|
288
|
+
const q = questions[i];
|
|
289
|
+
if (!q || typeof q.question !== "string")
|
|
290
|
+
continue;
|
|
291
|
+
const key = `q_${i}`;
|
|
292
|
+
const val = resp.content[key];
|
|
293
|
+
if (val == null)
|
|
294
|
+
continue;
|
|
295
|
+
if (Array.isArray(val)) {
|
|
296
|
+
answers[q.question] = val.filter((v) => typeof v === "string").join(", ");
|
|
297
|
+
}
|
|
298
|
+
else if (typeof val === "string" && val !== ELICIT_SKIP) {
|
|
299
|
+
// Skip the sentinel "__skip__" so a skipped single-select question is
|
|
300
|
+
// simply omitted from the answers map (parity with the request_permission
|
|
301
|
+
// path, which leaves the question unanswered on Skip).
|
|
302
|
+
answers[q.question] = val;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return answers;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Build an elicitation form for ExitPlanMode (approve/reject).
|
|
309
|
+
*
|
|
310
|
+
* Uses a single required boolean-style enum so the client renders a clear
|
|
311
|
+
* approve/reject choice in the form UI.
|
|
312
|
+
*/
|
|
313
|
+
export function buildExitPlanModeElicitationForm(params, acpSid, toolCallId) {
|
|
314
|
+
const planText = params.input && typeof params.input === "object"
|
|
315
|
+
? (params.input.plan ?? "")
|
|
316
|
+
: "";
|
|
317
|
+
const message = planText ? `Ready to code?\n\n${planText}` : "Ready to code?";
|
|
318
|
+
const form = {
|
|
319
|
+
mode: "form",
|
|
320
|
+
sessionId: acpSid,
|
|
321
|
+
message,
|
|
322
|
+
requestedSchema: {
|
|
323
|
+
type: "object",
|
|
324
|
+
properties: {
|
|
325
|
+
decision: {
|
|
326
|
+
type: "string",
|
|
327
|
+
enum: ["approve", "reject"],
|
|
328
|
+
title: "Decision",
|
|
329
|
+
description: "Approve to exit plan mode and start coding, or reject to keep planning.",
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
required: ["decision"],
|
|
333
|
+
},
|
|
334
|
+
};
|
|
335
|
+
if (toolCallId)
|
|
336
|
+
form.toolCallId = toolCallId;
|
|
337
|
+
return form;
|
|
338
|
+
}
|
|
339
|
+
/** Parse an ExitPlanMode elicitation response → zcode accept/decline. */
|
|
340
|
+
export function parseExitPlanModeElicitationResponse(acpResp) {
|
|
341
|
+
if (!acpResp || typeof acpResp !== "object") {
|
|
342
|
+
return { action: "decline", reason: "invalid client response" };
|
|
343
|
+
}
|
|
344
|
+
const resp = acpResp;
|
|
345
|
+
if (resp.action !== "accept" || !resp.content) {
|
|
346
|
+
return { action: "decline", reason: "cancelled" };
|
|
347
|
+
}
|
|
348
|
+
if (resp.content.decision === "approve") {
|
|
349
|
+
return { action: "accept", content: { answer_0: "approve" } };
|
|
350
|
+
}
|
|
351
|
+
return { action: "decline", reason: "rejected" };
|
|
352
|
+
}
|
|
353
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/interaction/adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZcodeAcpServer — owns shared server state, the backend client, and registers
|
|
3
|
+
* ACP handlers.
|
|
4
|
+
*
|
|
5
|
+
* This is the long-lived container the entry point wires to the ACP stream.
|
|
6
|
+
* Shared state (session map, pending turns, client capabilities) lives here so
|
|
7
|
+
* every handler layer can reach it without globals.
|
|
8
|
+
*/
|
|
9
|
+
import type * as acp from "@agentclientprotocol/sdk";
|
|
10
|
+
import { ZcodeBackend } from "./backend/index.js";
|
|
11
|
+
/** Client capabilities advertised in the initialize request. */
|
|
12
|
+
export interface ClientCapabilities {
|
|
13
|
+
fs?: {
|
|
14
|
+
readTextFile?: boolean;
|
|
15
|
+
writeTextFile?: boolean;
|
|
16
|
+
};
|
|
17
|
+
terminal?: boolean;
|
|
18
|
+
auth?: Record<string, unknown>;
|
|
19
|
+
elicitation?: {
|
|
20
|
+
form?: unknown;
|
|
21
|
+
url?: unknown;
|
|
22
|
+
};
|
|
23
|
+
_meta?: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
/** A pending prompt turn. */
|
|
26
|
+
export interface PendingTurn {
|
|
27
|
+
zcodeSid: string;
|
|
28
|
+
cancelled: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare class ZcodeAcpServer {
|
|
31
|
+
/** The ZCode subprocess client (lazy — spawned on first use). */
|
|
32
|
+
backend: ZcodeBackend | null;
|
|
33
|
+
/** acp_sid → zcode session id (usually identical, but kept for clarity). */
|
|
34
|
+
readonly sessionMap: Map<string, string>;
|
|
35
|
+
/** Currently running turns, keyed by the ACP request id. */
|
|
36
|
+
readonly pendingTurns: Map<number, PendingTurn>;
|
|
37
|
+
/**
|
|
38
|
+
* Per-session (zcodeSid) preempt lock: a promise chain that serializes the
|
|
39
|
+
* "register self + preempt others" critical section in prompt(). Prevents
|
|
40
|
+
* concurrent prompts from both missing each other and registering at once.
|
|
41
|
+
*/
|
|
42
|
+
readonly preemptLocks: Map<string, Promise<void>>;
|
|
43
|
+
/** Capabilities advertised by the connected client (Zed, JetBrains, ...). */
|
|
44
|
+
clientCapabilities: ClientCapabilities;
|
|
45
|
+
/** Session titles already set, to enforce set-once (acp_sid → title). */
|
|
46
|
+
readonly sessionTitles: Map<string, string>;
|
|
47
|
+
/** Last mode id advertised to the client (acp_sid → modeId), for change detection. */
|
|
48
|
+
readonly lastMode: Map<string, string>;
|
|
49
|
+
/** Per-session ProjectionDiffers (persists across turns). */
|
|
50
|
+
readonly differs: Map<string, import("./translators/projection-differ.js").ProjectionDiffer>;
|
|
51
|
+
/** Per-session model cache for configOptions model dropdown. */
|
|
52
|
+
readonly modelCache: Map<string, string>;
|
|
53
|
+
/** Monotonic id counter; base 10_000_000 to avoid collisions with zcode-originated ids. */
|
|
54
|
+
private msgCounter;
|
|
55
|
+
/** Next JSON-RPC id for messages we send to zcode. */
|
|
56
|
+
nextId(): number;
|
|
57
|
+
/** Lazily spawn the zcode backend on first use (initialize doesn't need it). */
|
|
58
|
+
ensureBackend(): ZcodeBackend;
|
|
59
|
+
/** Resolve the zcode session id for an ACP session id. */
|
|
60
|
+
resolveSid(acpSid: string): string | undefined;
|
|
61
|
+
/** Whether the client declared `_meta.terminal_output` (Zed's Bash UI hook). */
|
|
62
|
+
supportsTerminalOutput(): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Whether the client supports form-based elicitation (`clientCapabilities.
|
|
65
|
+
* elicitation.form`). When true, AskUserQuestion / ExitPlanMode can use the
|
|
66
|
+
* richer `elicitation/create` form UI; otherwise they fall back to
|
|
67
|
+
* `session/request_permission`.
|
|
68
|
+
*/
|
|
69
|
+
supportsElicitationForm(): boolean;
|
|
70
|
+
/** Handle `initialize`: negotiate version + declare agent capabilities. */
|
|
71
|
+
initialize(params: acp.InitializeRequest): Promise<acp.InitializeResponse>;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +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;AAG5B,gEAAgE;AAChE,MAAM,WAAW,kBAAkB;IACjC,EAAE,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAC;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACzD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,WAAW,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,6BAA6B;AAC7B,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,cAAc;IACzB,iEAAiE;IACjE,OAAO,EAAE,YAAY,GAAG,IAAI,CAAQ;IACpC,4EAA4E;IAC5E,QAAQ,CAAC,UAAU,sBAA6B;IAChD,4DAA4D;IAC5D,QAAQ,CAAC,YAAY,2BAAkC;IACvD;;;;OAIG;IACH,QAAQ,CAAC,YAAY,6BAAoC;IACzD,6EAA6E;IAC7E,kBAAkB,EAAE,kBAAkB,CAAM;IAC5C,yEAAyE;IACzE,QAAQ,CAAC,aAAa,sBAA6B;IACnD,sFAAsF;IACtF,QAAQ,CAAC,QAAQ,sBAA6B;IAC9C,6DAA6D;IAC7D,QAAQ,CAAC,OAAO,6EAGZ;IACJ,gEAAgE;IAChE,QAAQ,CAAC,UAAU,sBAA6B;IAChD,2FAA2F;IAC3F,OAAO,CAAC,UAAU,CAAc;IAEhC,sDAAsD;IACtD,MAAM,IAAI,MAAM;IAIhB,gFAAgF;IAChF,aAAa,IAAI,YAAY;IAQ7B,0DAA0D;IAC1D,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI9C,gFAAgF;IAChF,sBAAsB,IAAI,OAAO;IAKjC;;;;;OAKG;IACH,uBAAuB,IAAI,OAAO;IAIlC,2EAA2E;IACrE,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;CAgCjF"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZcodeAcpServer — owns shared server state, the backend client, and registers
|
|
3
|
+
* ACP handlers.
|
|
4
|
+
*
|
|
5
|
+
* This is the long-lived container the entry point wires to the ACP stream.
|
|
6
|
+
* Shared state (session map, pending turns, client capabilities) lives here so
|
|
7
|
+
* every handler layer can reach it without globals.
|
|
8
|
+
*/
|
|
9
|
+
import { loadZcodeCredentials, mergeEnvWithCreds, resolveZcodeCommand, ZcodeBackend, } from "./backend/index.js";
|
|
10
|
+
import { AGENT_INFO, PROTOCOL_VERSION, log } from "./utils.js";
|
|
11
|
+
export class ZcodeAcpServer {
|
|
12
|
+
/** The ZCode subprocess client (lazy — spawned on first use). */
|
|
13
|
+
backend = null;
|
|
14
|
+
/** acp_sid → zcode session id (usually identical, but kept for clarity). */
|
|
15
|
+
sessionMap = new Map();
|
|
16
|
+
/** Currently running turns, keyed by the ACP request id. */
|
|
17
|
+
pendingTurns = new Map();
|
|
18
|
+
/**
|
|
19
|
+
* Per-session (zcodeSid) preempt lock: a promise chain that serializes the
|
|
20
|
+
* "register self + preempt others" critical section in prompt(). Prevents
|
|
21
|
+
* concurrent prompts from both missing each other and registering at once.
|
|
22
|
+
*/
|
|
23
|
+
preemptLocks = new Map();
|
|
24
|
+
/** Capabilities advertised by the connected client (Zed, JetBrains, ...). */
|
|
25
|
+
clientCapabilities = {};
|
|
26
|
+
/** Session titles already set, to enforce set-once (acp_sid → title). */
|
|
27
|
+
sessionTitles = new Map();
|
|
28
|
+
/** Last mode id advertised to the client (acp_sid → modeId), for change detection. */
|
|
29
|
+
lastMode = new Map();
|
|
30
|
+
/** Per-session ProjectionDiffers (persists across turns). */
|
|
31
|
+
differs = new Map();
|
|
32
|
+
/** Per-session model cache for configOptions model dropdown. */
|
|
33
|
+
modelCache = new Map();
|
|
34
|
+
/** Monotonic id counter; base 10_000_000 to avoid collisions with zcode-originated ids. */
|
|
35
|
+
msgCounter = 10_000_000;
|
|
36
|
+
/** Next JSON-RPC id for messages we send to zcode. */
|
|
37
|
+
nextId() {
|
|
38
|
+
return ++this.msgCounter;
|
|
39
|
+
}
|
|
40
|
+
/** Lazily spawn the zcode backend on first use (initialize doesn't need it). */
|
|
41
|
+
ensureBackend() {
|
|
42
|
+
if (this.backend && !this.backend.isDead)
|
|
43
|
+
return this.backend;
|
|
44
|
+
const env = mergeEnvWithCreds(loadZcodeCredentials());
|
|
45
|
+
const argv = resolveZcodeCommand();
|
|
46
|
+
this.backend = new ZcodeBackend(argv, env);
|
|
47
|
+
return this.backend;
|
|
48
|
+
}
|
|
49
|
+
/** Resolve the zcode session id for an ACP session id. */
|
|
50
|
+
resolveSid(acpSid) {
|
|
51
|
+
return this.sessionMap.get(acpSid);
|
|
52
|
+
}
|
|
53
|
+
/** Whether the client declared `_meta.terminal_output` (Zed's Bash UI hook). */
|
|
54
|
+
supportsTerminalOutput() {
|
|
55
|
+
const meta = this.clientCapabilities._meta ?? {};
|
|
56
|
+
return meta["terminal_output"] === true;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Whether the client supports form-based elicitation (`clientCapabilities.
|
|
60
|
+
* elicitation.form`). When true, AskUserQuestion / ExitPlanMode can use the
|
|
61
|
+
* richer `elicitation/create` form UI; otherwise they fall back to
|
|
62
|
+
* `session/request_permission`.
|
|
63
|
+
*/
|
|
64
|
+
supportsElicitationForm() {
|
|
65
|
+
return this.clientCapabilities.elicitation?.form != null;
|
|
66
|
+
}
|
|
67
|
+
/** Handle `initialize`: negotiate version + declare agent capabilities. */
|
|
68
|
+
async initialize(params) {
|
|
69
|
+
const clientInfo = params.clientInfo ?? null;
|
|
70
|
+
this.clientCapabilities = params.clientCapabilities ?? {};
|
|
71
|
+
log(`initialize: client protocolVersion=${params.protocolVersion}` +
|
|
72
|
+
`, client=${clientInfo?.name ?? "unknown"}` +
|
|
73
|
+
`, version=${clientInfo?.version ?? "unknown"}`);
|
|
74
|
+
return {
|
|
75
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
76
|
+
agentInfo: { ...AGENT_INFO },
|
|
77
|
+
agentCapabilities: {
|
|
78
|
+
loadSession: true,
|
|
79
|
+
promptCapabilities: { image: false, audio: false, embeddedContext: false },
|
|
80
|
+
mcpCapabilities: { http: false, sse: false },
|
|
81
|
+
sessionCapabilities: { list: {}, resume: {}, fork: {} },
|
|
82
|
+
},
|
|
83
|
+
// The GLM API key is read from ~/.zcode/v2/config.json by the ZCode
|
|
84
|
+
// backend subprocess; the editor never needs to supply credentials.
|
|
85
|
+
// Declared as AuthMethodAgent (no `type` field → defaults to "agent"),
|
|
86
|
+
// which the ACP registry CI accepts as "agent self-handles auth".
|
|
87
|
+
authMethods: [
|
|
88
|
+
{
|
|
89
|
+
id: "zcode-credentials",
|
|
90
|
+
name: "ZCode built-in credentials",
|
|
91
|
+
description: "Reads the GLM API key from ~/.zcode/v2/config.json managed by the ZCode desktop app. No editor-side credentials required.",
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +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;AAiB/D,MAAM,OAAO,cAAc;IACzB,iEAAiE;IACjE,OAAO,GAAwB,IAAI,CAAC;IACpC,4EAA4E;IACnE,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChD,4DAA4D;IACnD,YAAY,GAAG,IAAI,GAAG,EAAuB,CAAC;IACvD;;;;OAIG;IACM,YAAY,GAAG,IAAI,GAAG,EAAyB,CAAC;IACzD,6EAA6E;IAC7E,kBAAkB,GAAuB,EAAE,CAAC;IAC5C,yEAAyE;IAChE,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IACnD,sFAAsF;IAC7E,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC9C,6DAA6D;IACpD,OAAO,GAAG,IAAI,GAAG,EAGvB,CAAC;IACJ,gEAAgE;IACvD,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChD,2FAA2F;IACnF,UAAU,GAAG,UAAU,CAAC;IAEhC,sDAAsD;IACtD,MAAM;QACJ,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC;IAC3B,CAAC;IAED,gFAAgF;IAChF,aAAa;QACX,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC;QAC9D,MAAM,GAAG,GAAG,iBAAiB,CAAC,oBAAoB,EAAE,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,mBAAmB,EAAE,CAAC;QACnC,IAAI,CAAC,OAAO,GAAG,IAAI,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC3C,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,0DAA0D;IAC1D,UAAU,CAAC,MAAc;QACvB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,gFAAgF;IAChF,sBAAsB;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,kBAAkB,CAAC,KAAK,IAAI,EAAE,CAAC;QACjD,OAAO,IAAI,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAC1C,CAAC;IAED;;;;;OAKG;IACH,uBAAuB;QACrB,OAAO,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,IAAI,IAAI,IAAI,CAAC;IAC3D,CAAC;IAED,2EAA2E;IAC3E,KAAK,CAAC,UAAU,CAAC,MAA6B;QAC5C,MAAM,UAAU,GAAI,MAAM,CAAC,UAAyD,IAAI,IAAI,CAAC;QAC7F,IAAI,CAAC,kBAAkB,GAAI,MAAM,CAAC,kBAAyC,IAAI,EAAE,CAAC;QAClF,GAAG,CACD,sCAAsC,MAAM,CAAC,eAAe,EAAE;YAC5D,YAAY,UAAU,EAAE,IAAI,IAAI,SAAS,EAAE;YAC3C,aAAa,UAAU,EAAE,OAAO,IAAI,SAAS,EAAE,CAClD,CAAC;QAEF,OAAO;YACL,eAAe,EAAE,gBAAgB;YACjC,SAAS,EAAE,EAAE,GAAG,UAAU,EAAE;YAC5B,iBAAiB,EAAE;gBACjB,WAAW,EAAE,IAAI;gBACjB,kBAAkB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE;gBAC1E,eAAe,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE;gBAC5C,mBAAmB,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;aACxD;YACD,oEAAoE;YACpE,oEAAoE;YACpE,uEAAuE;YACvE,kEAAkE;YAClE,WAAW,EAAE;gBACX;oBACE,EAAE,EAAE,mBAAmB;oBACvB,IAAI,EAAE,4BAA4B;oBAClC,WAAW,EACT,2HAA2H;iBAC9H;aACF;SACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZCode App tasks-index sync: let the App UI see ACP-created sessions.
|
|
3
|
+
*
|
|
4
|
+
* The ZCode App's session list reads from `~/.zcode/v2/tasks-index.sqlite`
|
|
5
|
+
* (the `tasks` table), NOT from the CLI's `~/.zcode/cli/db/db.sqlite`. These
|
|
6
|
+
* are independent stores — the App's Electron host maintains tasks-index; the
|
|
7
|
+
* headless app-server (which we drive) writes only to cli/db. As a result,
|
|
8
|
+
* every session created via ACP is invisible in the App's UI until the App
|
|
9
|
+
* happens to reindex.
|
|
10
|
+
*
|
|
11
|
+
* This module bridges that gap by writing a tasks-index row directly after
|
|
12
|
+
* session/create. The App picks it up on its next list refresh. INSERT OR
|
|
13
|
+
* IGNORE avoids clobbering rows the App already manages.
|
|
14
|
+
*
|
|
15
|
+
* Best-effort side-channel: failures (locked DB, schema drift) are logged and
|
|
16
|
+
* swallowed so they never break the session/create path.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Insert (or refresh) a row in tasks-index.sqlite so the App UI shows it.
|
|
20
|
+
* Called after a successful session/create. Uses INSERT OR IGNORE so it never
|
|
21
|
+
* overwrites a row the App is actively managing (e.g. user-renamed titles).
|
|
22
|
+
*
|
|
23
|
+
* Returns true if written, false on failure (logged, never thrown).
|
|
24
|
+
*/
|
|
25
|
+
export declare function upsertSessionTask(opts: {
|
|
26
|
+
workspaceKey: string;
|
|
27
|
+
taskId: string;
|
|
28
|
+
title: string;
|
|
29
|
+
traceId?: string;
|
|
30
|
+
model?: string;
|
|
31
|
+
status?: string;
|
|
32
|
+
}): Promise<boolean>;
|
|
33
|
+
/**
|
|
34
|
+
* Update a session's title after the first turn. session/create leaves title
|
|
35
|
+
* empty; once the first prompt completes, set a meaningful title. Respects
|
|
36
|
+
* title_overridden: if the user already renamed in the App, their title wins.
|
|
37
|
+
*/
|
|
38
|
+
export declare function updateSessionTitle(taskId: string, title: string): Promise<boolean>;
|
|
39
|
+
//# sourceMappingURL=tasks-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks-index.d.ts","sourceRoot":"","sources":["../src/tasks-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA6DH;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,OAAO,CAAC,CA0DnB;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA4BxF"}
|