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,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event-stream listener and turn monitor.
|
|
3
|
+
*
|
|
4
|
+
* `EventStreamListener` subscribes to ZCode's `session/subscribe` event push
|
|
5
|
+
* (deliveryKind `desktop-continuous`) and queues `session/event` notifications
|
|
6
|
+
* for the turn loop to consume. It tracks a `lastSeq` watermark and can
|
|
7
|
+
* resubscribe from it to recover missed events after a stall.
|
|
8
|
+
*
|
|
9
|
+
* `TurnMonitor` is the legacy snapshot path: a one-shot `session/read` that
|
|
10
|
+
* returns the authoritative projection. Used for stall reconciliation and
|
|
11
|
+
* lock-release probing.
|
|
12
|
+
*/
|
|
13
|
+
export class EventStreamListener {
|
|
14
|
+
backend;
|
|
15
|
+
sid;
|
|
16
|
+
/** High-watermark of consumed event sequence numbers. */
|
|
17
|
+
lastSeq = 0;
|
|
18
|
+
subscribed = false;
|
|
19
|
+
queue = [];
|
|
20
|
+
waiters = [];
|
|
21
|
+
constructor(backend, zcodeSid) {
|
|
22
|
+
this.backend = backend;
|
|
23
|
+
this.sid = zcodeSid;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Subscribe and capture the initial snapshot + eventSeq watermark.
|
|
27
|
+
*
|
|
28
|
+
* Returns the snapshot (with projection/messages) or null on failure. ZCode
|
|
29
|
+
* CLI 0.14.8+ always supports this; null means an old/ broken backend and
|
|
30
|
+
* the caller should surface an error (polling fallback was removed).
|
|
31
|
+
*/
|
|
32
|
+
async subscribe(nextId) {
|
|
33
|
+
const resp = await this.backend.request(nextId(), "session/subscribe", {
|
|
34
|
+
sessionId: this.sid,
|
|
35
|
+
deliveryKind: "desktop-continuous",
|
|
36
|
+
includeSnapshot: true,
|
|
37
|
+
afterSeq: 0,
|
|
38
|
+
}, 10000);
|
|
39
|
+
if (resp.error) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
const result = (resp.result ?? {});
|
|
43
|
+
this.lastSeq = result.eventSeq ?? 0;
|
|
44
|
+
this.subscribed = true;
|
|
45
|
+
return result.snapshot ?? null;
|
|
46
|
+
}
|
|
47
|
+
/** Called by the backend reader when a `session/event` arrives. */
|
|
48
|
+
handleEvent(event) {
|
|
49
|
+
if (event.seq > this.lastSeq)
|
|
50
|
+
this.lastSeq = event.seq;
|
|
51
|
+
// Drop waiters that already timed out (their promise settled with null) so
|
|
52
|
+
// a late event never lands on a dead promise — that would silently drop it.
|
|
53
|
+
let waiter = this.waiters.shift();
|
|
54
|
+
while (waiter && waiter.done)
|
|
55
|
+
waiter = this.waiters.shift();
|
|
56
|
+
if (waiter) {
|
|
57
|
+
waiter.done = true;
|
|
58
|
+
clearTimeout(waiter.timer);
|
|
59
|
+
waiter.resolve(event);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
this.queue.push(event);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Wait for the next event, resolving once one arrives or `timeoutMs` elapses
|
|
67
|
+
* (resolves null on timeout). Events arriving with no active waiter are
|
|
68
|
+
* queued. A timed-out waiter is marked `done` so a later event skips it
|
|
69
|
+
* instead of being silently dropped on a settled promise.
|
|
70
|
+
*/
|
|
71
|
+
pollEvent(timeoutMs = 500) {
|
|
72
|
+
const queued = this.queue.shift();
|
|
73
|
+
if (queued)
|
|
74
|
+
return Promise.resolve(queued);
|
|
75
|
+
return new Promise((resolve) => {
|
|
76
|
+
const waiter = {
|
|
77
|
+
done: false,
|
|
78
|
+
resolve,
|
|
79
|
+
timer: undefined,
|
|
80
|
+
};
|
|
81
|
+
waiter.timer = setTimeout(() => {
|
|
82
|
+
if (waiter.done)
|
|
83
|
+
return;
|
|
84
|
+
waiter.done = true;
|
|
85
|
+
const idx = this.waiters.indexOf(waiter);
|
|
86
|
+
if (idx >= 0)
|
|
87
|
+
this.waiters.splice(idx, 1);
|
|
88
|
+
resolve(null);
|
|
89
|
+
}, timeoutMs);
|
|
90
|
+
this.waiters.push(waiter);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Stall recovery: resubscribe from `lastSeq` so the server replays missed
|
|
95
|
+
* events. Failure is logged but non-fatal — the caller degrades to polling.
|
|
96
|
+
* The snapshot (if returned despite `includeSnapshot:false`) is intentionally
|
|
97
|
+
* not consumed; resubscribe only refreshes the watermark + resumes the push.
|
|
98
|
+
*/
|
|
99
|
+
async resubscribe(nextId) {
|
|
100
|
+
const resp = await this.backend.request(nextId(), "session/subscribe", {
|
|
101
|
+
sessionId: this.sid,
|
|
102
|
+
deliveryKind: "desktop-continuous",
|
|
103
|
+
includeSnapshot: false,
|
|
104
|
+
afterSeq: this.lastSeq,
|
|
105
|
+
}, 10000);
|
|
106
|
+
if (resp.error) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
const result = (resp.result ?? {});
|
|
110
|
+
if ((result.eventSeq ?? this.lastSeq) > this.lastSeq) {
|
|
111
|
+
this.lastSeq = result.eventSeq ?? this.lastSeq;
|
|
112
|
+
}
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Legacy snapshot path: a single `session/read` returning the authoritative
|
|
118
|
+
* projection. Used in stall reconciliation and lock-release probing.
|
|
119
|
+
*/
|
|
120
|
+
export class TurnMonitor {
|
|
121
|
+
backend;
|
|
122
|
+
zcodeSid;
|
|
123
|
+
nextId;
|
|
124
|
+
constructor(backend, zcodeSid, nextId) {
|
|
125
|
+
this.backend = backend;
|
|
126
|
+
this.zcodeSid = zcodeSid;
|
|
127
|
+
this.nextId = nextId;
|
|
128
|
+
}
|
|
129
|
+
/** Returns the projection snapshot, or null on error. */
|
|
130
|
+
async pollOnce() {
|
|
131
|
+
const resp = await this.backend.request(this.nextId(), "session/read", { sessionId: this.zcodeSid }, 5000);
|
|
132
|
+
if (resp.error)
|
|
133
|
+
return null;
|
|
134
|
+
const result = (resp.result ?? {});
|
|
135
|
+
return result.projection ?? null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=listener.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listener.js","sourceRoot":"","sources":["../../src/backend/listener.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAgBH,MAAM,OAAO,mBAAmB;IACb,OAAO,CAAe;IAC9B,GAAG,CAAS;IACrB,yDAAyD;IACzD,OAAO,GAAG,CAAC,CAAC;IACZ,UAAU,GAAG,KAAK,CAAC;IACF,KAAK,GAAiB,EAAE,CAAC;IACzB,OAAO,GAAa,EAAE,CAAC;IAExC,YAAY,OAAqB,EAAE,QAAgB;QACjD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,GAAG,GAAG,QAAQ,CAAC;IACtB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,SAAS,CAAC,MAAc;QAC5B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CACrC,MAAM,EAAE,EACR,mBAAmB,EACnB;YACE,SAAS,EAAE,IAAI,CAAC,GAAG;YACnB,YAAY,EAAE,oBAAoB;YAClC,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC;SACZ,EACD,KAAK,CACN,CAAC;QACF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAyB,CAAC;QAC3D,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,OAAO,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC;IACjC,CAAC;IAED,mEAAmE;IACnE,WAAW,CAAC,KAAiB;QAC3B,IAAI,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC;QACvD,2EAA2E;QAC3E,4EAA4E;QAC5E,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAClC,OAAO,MAAM,IAAI,MAAM,CAAC,IAAI;YAAE,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC5D,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;YACnB,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3B,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,SAAS,GAAG,GAAG;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAClC,IAAI,MAAM;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,MAAM,MAAM,GAAW;gBACrB,IAAI,EAAE,KAAK;gBACX,OAAO;gBACP,KAAK,EAAE,SAAqD;aAC7D,CAAC;YACF,MAAM,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC7B,IAAI,MAAM,CAAC,IAAI;oBAAE,OAAO;gBACxB,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;gBACnB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBACzC,IAAI,GAAG,IAAI,CAAC;oBAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBAC1C,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC,EAAE,SAAS,CAAC,CAAC;YACd,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,WAAW,CAAC,MAAc;QAC9B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CACrC,MAAM,EAAE,EACR,mBAAmB,EACnB;YACE,SAAS,EAAE,IAAI,CAAC,GAAG;YACnB,YAAY,EAAE,oBAAoB;YAClC,eAAe,EAAE,KAAK;YACtB,QAAQ,EAAE,IAAI,CAAC,OAAO;SACvB,EACD,KAAK,CACN,CAAC;QACF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAyB,CAAC;QAC3D,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YACrD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC;QACjD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,WAAW;IACL,OAAO,CAAe;IACtB,QAAQ,CAAS;IACjB,MAAM,CAAS;IAEhC,YAAY,OAAqB,EAAE,QAAgB,EAAE,MAAc;QACjE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,yDAAyD;IACzD,KAAK,CAAC,QAAQ;QACZ,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CACrC,IAAI,CAAC,MAAM,EAAE,EACb,cAAc,EACd,EAAE,SAAS,EAAE,IAAI,CAAC,QAAQ,EAAE,EAC5B,IAAI,CACL,CAAC;QACF,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QAC5B,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAqC,CAAC;QACvE,OAAO,MAAM,CAAC,UAAU,IAAI,IAAI,CAAC;IACnC,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the argv to launch the ZCode app-server subprocess.
|
|
3
|
+
*
|
|
4
|
+
* The ZCode CLI is a Node `.cjs` that relies on a `#!/usr/bin/env node` shebang.
|
|
5
|
+
* Processes launched by GUI launchd (no shell profile) have no `node` on PATH,
|
|
6
|
+
* so the shebang fails. We sidestep it by constructing `[node, zcode.cjs,
|
|
7
|
+
* "app-server", "--stdio"]` with an explicit, sqlite-capable Node binary.
|
|
8
|
+
*/
|
|
9
|
+
/** Resolve the full argv to launch `zcode app-server --stdio`. */
|
|
10
|
+
export declare function resolveZcodeCommand(): string[];
|
|
11
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/backend/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA8EH,kEAAkE;AAClE,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CA4B9C"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the argv to launch the ZCode app-server subprocess.
|
|
3
|
+
*
|
|
4
|
+
* The ZCode CLI is a Node `.cjs` that relies on a `#!/usr/bin/env node` shebang.
|
|
5
|
+
* Processes launched by GUI launchd (no shell profile) have no `node` on PATH,
|
|
6
|
+
* so the shebang fails. We sidestep it by constructing `[node, zcode.cjs,
|
|
7
|
+
* "app-server", "--stdio"]` with an explicit, sqlite-capable Node binary.
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
10
|
+
import os from "node:os";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
import process from "node:process";
|
|
13
|
+
import { execFileSync } from "node:child_process";
|
|
14
|
+
import { log } from "../utils.js";
|
|
15
|
+
/** `which bin` — resolve a binary on PATH without external deps. */
|
|
16
|
+
function whichSync(bin) {
|
|
17
|
+
try {
|
|
18
|
+
const out = execFileSync("which", [bin], {
|
|
19
|
+
encoding: "utf8",
|
|
20
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
21
|
+
}).trim();
|
|
22
|
+
return out || null;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** Glob the Zed-bundled node directories, newest version first. */
|
|
29
|
+
function zedBundledNodes() {
|
|
30
|
+
const base = path.join(os.homedir(), "Library/Application Support/Zed/node");
|
|
31
|
+
if (!existsSync(base))
|
|
32
|
+
return [];
|
|
33
|
+
let entries = [];
|
|
34
|
+
try {
|
|
35
|
+
entries = readdirSync(base);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
return entries
|
|
41
|
+
.filter((d) => d.startsWith("node-v"))
|
|
42
|
+
.sort()
|
|
43
|
+
.reverse()
|
|
44
|
+
.map((d) => path.join(base, d, "bin", "node"));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Candidate Node binaries in priority order. Deduped, order-preserving.
|
|
48
|
+
* Falls back to the Zed-bundled Node glob as a last resort.
|
|
49
|
+
*/
|
|
50
|
+
function candidateNodeBinaries() {
|
|
51
|
+
const cands = [];
|
|
52
|
+
const envNode = process.env.ZCODE_NODE;
|
|
53
|
+
if (envNode)
|
|
54
|
+
cands.push(envNode);
|
|
55
|
+
cands.push("/opt/homebrew/bin/node", "/usr/local/bin/node");
|
|
56
|
+
const whichNode = whichSync("node");
|
|
57
|
+
if (whichNode)
|
|
58
|
+
cands.push(whichNode);
|
|
59
|
+
cands.push(...zedBundledNodes());
|
|
60
|
+
const seen = new Set();
|
|
61
|
+
return cands.filter((c) => {
|
|
62
|
+
if (!c || seen.has(c))
|
|
63
|
+
return false;
|
|
64
|
+
seen.add(c);
|
|
65
|
+
return true;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Verify a Node binary can load `node:sqlite` (ZCode depends on it; Node < 22
|
|
70
|
+
* lacks the module and would crash). Uses `new DatabaseSync(...)` because a
|
|
71
|
+
* bare reference would mis-detect support.
|
|
72
|
+
*/
|
|
73
|
+
function nodeSupportsSqlite(nodeBin) {
|
|
74
|
+
if (!nodeBin || !existsSync(nodeBin))
|
|
75
|
+
return false;
|
|
76
|
+
try {
|
|
77
|
+
execFileSync(nodeBin, ["-e", "new (require('node:sqlite').DatabaseSync)(':memory:')"], {
|
|
78
|
+
stdio: ["ignore", "ignore", "ignore"],
|
|
79
|
+
timeout: 5000,
|
|
80
|
+
});
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/** Resolve the full argv to launch `zcode app-server --stdio`. */
|
|
88
|
+
export function resolveZcodeCommand() {
|
|
89
|
+
const zcodeBin = process.env.ZCODE_BIN ?? "zcode";
|
|
90
|
+
// Non-JS bin (e.g. a `zcode` command or wrapper) → use as-is, rely on its own shebang.
|
|
91
|
+
if (!/\.(cjs|mjs|js)$/.test(zcodeBin)) {
|
|
92
|
+
return [zcodeBin, "app-server", "--stdio"];
|
|
93
|
+
}
|
|
94
|
+
// JS file → launch with an explicit sqlite-capable Node to bypass the shebang.
|
|
95
|
+
for (const nodeBin of candidateNodeBinaries()) {
|
|
96
|
+
if (nodeSupportsSqlite(nodeBin)) {
|
|
97
|
+
let ver = "?";
|
|
98
|
+
try {
|
|
99
|
+
// argv form (no shell, space-safe); capture stderr so it doesn't leak.
|
|
100
|
+
ver = execFileSync(nodeBin, ["--version"], {
|
|
101
|
+
encoding: "utf8",
|
|
102
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
103
|
+
}).trim();
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// keep "?"
|
|
107
|
+
}
|
|
108
|
+
log(`resolve: launching zcode with node ${nodeBin} (${ver})`);
|
|
109
|
+
return [nodeBin, zcodeBin, "app-server", "--stdio"];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
log("resolve: no sqlite-capable node found; falling back to PATH-resolved zcode shebang " +
|
|
113
|
+
"(may fail under GUI launch)");
|
|
114
|
+
return [zcodeBin, "app-server", "--stdio"];
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/backend/resolve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZCode app-server protocol type definitions.
|
|
3
|
+
*
|
|
4
|
+
* ZCode speaks a line-delimited JSON protocol over stdio. It is JSON-RPC-like
|
|
5
|
+
* but deliberately omits the `jsonrpc` field. Messages are classified by the
|
|
6
|
+
* presence of `id` and `method`:
|
|
7
|
+
* - id + no method → response to a request we sent
|
|
8
|
+
* - id + method → either our response (id registered) or a server→client request
|
|
9
|
+
* - method + no id → notification (e.g. `session/event`)
|
|
10
|
+
*
|
|
11
|
+
* Only the fields we actually consume are typed; the rest pass through as
|
|
12
|
+
* `unknown`/`Record<string, unknown>` to stay resilient to ZCode schema drift.
|
|
13
|
+
*/
|
|
14
|
+
export interface ZcodeRequest {
|
|
15
|
+
id: number;
|
|
16
|
+
method: string;
|
|
17
|
+
params?: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
export interface ZcodeNotification {
|
|
20
|
+
method: string;
|
|
21
|
+
params?: Record<string, unknown>;
|
|
22
|
+
}
|
|
23
|
+
export interface ZcodeResponse {
|
|
24
|
+
id: number;
|
|
25
|
+
result?: unknown;
|
|
26
|
+
error?: {
|
|
27
|
+
message: string;
|
|
28
|
+
code?: number | string;
|
|
29
|
+
detail?: unknown;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/** Any inbound message from the ZCode subprocess. */
|
|
33
|
+
export type ZcodeInbound = Partial<ZcodeRequest> & Partial<ZcodeResponse> & Partial<ZcodeNotification>;
|
|
34
|
+
export interface ZcodeSessionInfo {
|
|
35
|
+
sessionId: string;
|
|
36
|
+
title?: string;
|
|
37
|
+
traceId?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface ZcodeCreateResult {
|
|
40
|
+
session: ZcodeSessionInfo;
|
|
41
|
+
}
|
|
42
|
+
export interface ZcodeSessionListItem {
|
|
43
|
+
sessionId: string;
|
|
44
|
+
workspace?: {
|
|
45
|
+
workspacePath?: string;
|
|
46
|
+
};
|
|
47
|
+
title?: string;
|
|
48
|
+
updatedAt?: number;
|
|
49
|
+
}
|
|
50
|
+
export interface ZcodeListResult {
|
|
51
|
+
sessions: ZcodeSessionListItem[];
|
|
52
|
+
}
|
|
53
|
+
export type ZcodeEventType = "turn.started" | "model.streaming" | "tool.updated" | "turn.completed" | "turn.failed" | "session.updated";
|
|
54
|
+
export interface ZcodeEvent {
|
|
55
|
+
sessionId: string;
|
|
56
|
+
seq: number;
|
|
57
|
+
type: ZcodeEventType;
|
|
58
|
+
payload: Record<string, unknown>;
|
|
59
|
+
}
|
|
60
|
+
export interface ZcodeSubscribeResult {
|
|
61
|
+
eventSeq: number;
|
|
62
|
+
snapshot?: ZcodeSnapshot;
|
|
63
|
+
}
|
|
64
|
+
export interface ZcodeSnapshot {
|
|
65
|
+
projection?: ZcodeProjection;
|
|
66
|
+
messages?: ZcodeMessage[];
|
|
67
|
+
todos?: unknown[];
|
|
68
|
+
}
|
|
69
|
+
export interface ZcodeProjection {
|
|
70
|
+
status?: string;
|
|
71
|
+
contextUsed?: number;
|
|
72
|
+
contextWindow?: number;
|
|
73
|
+
totalTokenCount?: number;
|
|
74
|
+
}
|
|
75
|
+
export interface ZcodeMessage {
|
|
76
|
+
info: {
|
|
77
|
+
id?: string;
|
|
78
|
+
role: "user" | "assistant" | "system";
|
|
79
|
+
};
|
|
80
|
+
parts: ZcodeMessagePart[];
|
|
81
|
+
}
|
|
82
|
+
export type ZcodeMessagePart = {
|
|
83
|
+
type: "text";
|
|
84
|
+
text: string;
|
|
85
|
+
} | {
|
|
86
|
+
type: "reasoning";
|
|
87
|
+
text?: string;
|
|
88
|
+
content?: string;
|
|
89
|
+
} | {
|
|
90
|
+
type: "tool";
|
|
91
|
+
callID?: string;
|
|
92
|
+
callId?: string;
|
|
93
|
+
tool?: string;
|
|
94
|
+
state?: Record<string, unknown>;
|
|
95
|
+
} | {
|
|
96
|
+
type: "patch";
|
|
97
|
+
hash?: string;
|
|
98
|
+
files?: string[];
|
|
99
|
+
} | {
|
|
100
|
+
type: string;
|
|
101
|
+
[key: string]: unknown;
|
|
102
|
+
};
|
|
103
|
+
export interface ZcodeMessagesResult {
|
|
104
|
+
messages: ZcodeMessage[];
|
|
105
|
+
}
|
|
106
|
+
export interface ZcodeReadResult {
|
|
107
|
+
projection?: ZcodeProjection;
|
|
108
|
+
settings?: Record<string, unknown>;
|
|
109
|
+
todos?: unknown[];
|
|
110
|
+
todoGroups?: Array<{
|
|
111
|
+
entries?: unknown[];
|
|
112
|
+
todos?: unknown[];
|
|
113
|
+
}>;
|
|
114
|
+
}
|
|
115
|
+
export interface ZcodeInteractionPermissionParams {
|
|
116
|
+
requestId: string;
|
|
117
|
+
sessionId: string;
|
|
118
|
+
toolCallId: string;
|
|
119
|
+
toolName?: string;
|
|
120
|
+
reason?: string;
|
|
121
|
+
riskLevel?: string;
|
|
122
|
+
input?: unknown;
|
|
123
|
+
options?: Array<{
|
|
124
|
+
optionId: string;
|
|
125
|
+
kind: string;
|
|
126
|
+
name: string;
|
|
127
|
+
response?: unknown;
|
|
128
|
+
}>;
|
|
129
|
+
}
|
|
130
|
+
export interface ZcodeInteractionUserInputParams {
|
|
131
|
+
requestId: string;
|
|
132
|
+
sessionId: string;
|
|
133
|
+
toolCallId?: string;
|
|
134
|
+
toolName?: string;
|
|
135
|
+
prompt?: string;
|
|
136
|
+
questions?: Array<{
|
|
137
|
+
header?: string;
|
|
138
|
+
question: string;
|
|
139
|
+
multiSelect?: boolean;
|
|
140
|
+
options?: Array<{
|
|
141
|
+
label?: string;
|
|
142
|
+
value?: string;
|
|
143
|
+
description?: string;
|
|
144
|
+
}>;
|
|
145
|
+
}>;
|
|
146
|
+
input?: {
|
|
147
|
+
questions?: ZcodeInteractionUserInputParams["questions"];
|
|
148
|
+
};
|
|
149
|
+
schema?: {
|
|
150
|
+
interaction?: string;
|
|
151
|
+
toolName?: string;
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/** The response we send back to a ZCode server→client request. */
|
|
155
|
+
export type ZcodeInteractionResponse = {
|
|
156
|
+
decision: "allow" | "deny" | "escalate" | "modify";
|
|
157
|
+
reason?: string;
|
|
158
|
+
modifiedInput?: unknown;
|
|
159
|
+
} | {
|
|
160
|
+
action: "accept" | "decline" | "cancel";
|
|
161
|
+
content?: unknown;
|
|
162
|
+
reason?: string;
|
|
163
|
+
};
|
|
164
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/backend/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZCode app-server protocol type definitions.
|
|
3
|
+
*
|
|
4
|
+
* ZCode speaks a line-delimited JSON protocol over stdio. It is JSON-RPC-like
|
|
5
|
+
* but deliberately omits the `jsonrpc` field. Messages are classified by the
|
|
6
|
+
* presence of `id` and `method`:
|
|
7
|
+
* - id + no method → response to a request we sent
|
|
8
|
+
* - id + method → either our response (id registered) or a server→client request
|
|
9
|
+
* - method + no id → notification (e.g. `session/event`)
|
|
10
|
+
*
|
|
11
|
+
* Only the fields we actually consume are typed; the rest pass through as
|
|
12
|
+
* `unknown`/`Record<string, unknown>` to stay resilient to ZCode schema drift.
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/backend/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-level model cache + initial usage emission.
|
|
3
|
+
*
|
|
4
|
+
* `currentModelCached` avoids a `session/read` round-trip on every usage_update
|
|
5
|
+
* (a high-frequency path). `emitInitialUsage` sends one usage_update right
|
|
6
|
+
* after resume/load so the editor shows the context bar immediately (only when
|
|
7
|
+
* there's actual token data — resume before any turn has 0, which we skip).
|
|
8
|
+
*/
|
|
9
|
+
import type * as acp from "@agentclientprotocol/sdk";
|
|
10
|
+
import type { ZcodeAcpServer } from "../server.js";
|
|
11
|
+
import type { ProjectionDiffer } from "../translators/projection-differ.js";
|
|
12
|
+
/** Read the session's current model id, with a per-session cache. */
|
|
13
|
+
export declare function currentModelCached(server: ZcodeAcpServer, zcodeSid: string): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Emit an initial usage_update after resume/load so the editor shows the
|
|
16
|
+
* context bar. Skips when there's no token data (resume before any turn → 0).
|
|
17
|
+
* Also syncs the differ's usage baseline so the first turn won't re-emit it.
|
|
18
|
+
*/
|
|
19
|
+
export declare function emitInitialUsage(server: ZcodeAcpServer, cx: acp.AgentContext, acpSid: string, zcodeSid: string, differ: ProjectionDiffer | undefined): Promise<void>;
|
|
20
|
+
//# sourceMappingURL=model-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-cache.d.ts","sourceRoot":"","sources":["../../src/config/model-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAKrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAE5E,qEAAqE;AACrE,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAcjB;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,cAAc,EACtB,EAAE,EAAE,GAAG,CAAC,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,gBAAgB,GAAG,SAAS,GACnC,OAAO,CAAC,IAAI,CAAC,CAyBf"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-level model cache + initial usage emission.
|
|
3
|
+
*
|
|
4
|
+
* `currentModelCached` avoids a `session/read` round-trip on every usage_update
|
|
5
|
+
* (a high-frequency path). `emitInitialUsage` sends one usage_update right
|
|
6
|
+
* after resume/load so the editor shows the context bar immediately (only when
|
|
7
|
+
* there's actual token data — resume before any turn has 0, which we skip).
|
|
8
|
+
*/
|
|
9
|
+
import { modelContextWindow } from "./options.js";
|
|
10
|
+
import { log } from "../utils.js";
|
|
11
|
+
import { dispatchEvent } from "../handlers/dispatch.js";
|
|
12
|
+
/** Read the session's current model id, with a per-session cache. */
|
|
13
|
+
export async function currentModelCached(server, zcodeSid) {
|
|
14
|
+
const cached = server.modelCache.get(zcodeSid);
|
|
15
|
+
if (cached)
|
|
16
|
+
return cached;
|
|
17
|
+
let modelId = "GLM-5.2";
|
|
18
|
+
try {
|
|
19
|
+
const read = await sessionRead(server, zcodeSid);
|
|
20
|
+
const settings = (read.settings ?? {});
|
|
21
|
+
const cur = settings.model?.current;
|
|
22
|
+
if (cur?.modelId)
|
|
23
|
+
modelId = cur.modelId;
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
log(`model-cache: session/read failed (${e instanceof Error ? e.message : String(e)})`);
|
|
27
|
+
}
|
|
28
|
+
server.modelCache.set(zcodeSid, modelId);
|
|
29
|
+
return modelId;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Emit an initial usage_update after resume/load so the editor shows the
|
|
33
|
+
* context bar. Skips when there's no token data (resume before any turn → 0).
|
|
34
|
+
* Also syncs the differ's usage baseline so the first turn won't re-emit it.
|
|
35
|
+
*/
|
|
36
|
+
export async function emitInitialUsage(server, cx, acpSid, zcodeSid, differ) {
|
|
37
|
+
try {
|
|
38
|
+
const read = await sessionRead(server, zcodeSid);
|
|
39
|
+
const proj = (read.projection ?? {});
|
|
40
|
+
// `||` (not `??`): an explicit contextUsed=0 is falsy and should fall back
|
|
41
|
+
// to totalTokenCount, matching Python's `proj.get("contextUsed",0) or ...`.
|
|
42
|
+
const used = proj.contextUsed || proj.totalTokenCount || 0;
|
|
43
|
+
if (!used)
|
|
44
|
+
return; // resume before any turn: skip to avoid showing 0.
|
|
45
|
+
let size = proj.contextWindow ?? 0;
|
|
46
|
+
if (!size)
|
|
47
|
+
size = modelContextWindow(await currentModelCached(server, zcodeSid));
|
|
48
|
+
await dispatchEvent(server, cx, acpSid, { kind: "UsageDelta", used, size }, `init_${zcodeSid.slice(0, 8)}`);
|
|
49
|
+
differ?.setLastUsage(used);
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
log(`model-cache: emit_initial_usage failed (${e instanceof Error ? e.message : String(e)})`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function sessionRead(server, zcodeSid) {
|
|
56
|
+
const backend = server.ensureBackend();
|
|
57
|
+
const resp = await backend.request(server.nextId(), "session/read", { sessionId: zcodeSid }, 5000);
|
|
58
|
+
if (resp.error)
|
|
59
|
+
throw new Error(resp.error.message);
|
|
60
|
+
return (resp.result ?? {});
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=model-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-cache.js","sourceRoot":"","sources":["../../src/config/model-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* configOptions + modes construction and session/set_config_option dispatch.
|
|
3
|
+
*
|
|
4
|
+
* Reads `session/read` `settings.*` for current values (NOT projection.mode,
|
|
5
|
+
* which is a zombie value), with config.json fallbacks for the model list.
|
|
6
|
+
* set_config_option: mode/thought forward to setMode/setThoughtLevel; model
|
|
7
|
+
* routes through `runtimeModel` (runtime-model.ts) because the backend rejects
|
|
8
|
+
* the persistence path. After a change, re-builds the option and emits a
|
|
9
|
+
* `config_option_update` (+ `current_mode_update` for mode) so the editor UI
|
|
10
|
+
* reflects the new state.
|
|
11
|
+
*/
|
|
12
|
+
import type * as acp from "@agentclientprotocol/sdk";
|
|
13
|
+
import type { ZcodeAcpServer } from "../server.js";
|
|
14
|
+
/** Read the model id list for the enabled provider from config.json. */
|
|
15
|
+
export declare function loadProviderModels(): string[];
|
|
16
|
+
/** Read the context-window size for a model from config.json (limit.context). */
|
|
17
|
+
export declare function modelContextWindow(modelId: string): number;
|
|
18
|
+
/** Build the ACP SessionModeState ({currentModeId, availableModes}). */
|
|
19
|
+
export declare function buildModes(server: ZcodeAcpServer, zcodeSid: string): Promise<acp.SessionModeState>;
|
|
20
|
+
/** Build the ACP configOptions array (3 items: model/mode/thought). */
|
|
21
|
+
export declare function buildConfigOptions(server: ZcodeAcpServer, zcodeSid: string): Promise<acp.SessionConfigOption[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Dispatch session/set_config_option. mode/thought forward to setMode/
|
|
24
|
+
* setThoughtLevel; model routes through applyModelSwitch (runtime-model.ts).
|
|
25
|
+
*
|
|
26
|
+
* Returns `{ kind, currentValue, options }` so the caller can emit the update
|
|
27
|
+
* notifications, or null when the configId is unknown / model switch fails.
|
|
28
|
+
*/
|
|
29
|
+
export declare function setConfigOption(server: ZcodeAcpServer, zcodeSid: string, configId: string, value: string): Promise<{
|
|
30
|
+
kind: "model" | "mode" | "thought";
|
|
31
|
+
currentValue: string;
|
|
32
|
+
} | null>;
|
|
33
|
+
/** Emit a config_option_update (+ current_mode_update for mode) after a change.
|
|
34
|
+
* Returns the rebuilt options so the caller can include them in the response. */
|
|
35
|
+
export declare function emitConfigOptionUpdate(server: ZcodeAcpServer, cx: acp.AgentContext, acpSid: string, zcodeSid: string, kind: "model" | "mode" | "thought"): Promise<acp.SessionConfigOption[]>;
|
|
36
|
+
//# sourceMappingURL=options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/config/options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAIrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAgBnD,wEAAwE;AACxE,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAS7C;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAS1D;AAED,wEAAwE;AACxE,wBAAsB,UAAU,CAC9B,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAc/B;AAED,uEAAuE;AACvE,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC,CAyDpC;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAkB9E;AAED;kFACkF;AAClF,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,cAAc,EACtB,EAAE,EAAE,GAAG,CAAC,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,GACjC,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC,CAcpC"}
|