zcode-acp-server 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/README.md +98 -1
  2. package/README.zh-CN.md +81 -1
  3. package/dist/backend/client.d.ts +12 -4
  4. package/dist/backend/client.d.ts.map +1 -1
  5. package/dist/backend/client.js +72 -7
  6. package/dist/backend/client.js.map +1 -1
  7. package/dist/backend/credentials.d.ts.map +1 -1
  8. package/dist/backend/credentials.js +2 -1
  9. package/dist/backend/credentials.js.map +1 -1
  10. package/dist/backend/listener.d.ts +12 -4
  11. package/dist/backend/listener.d.ts.map +1 -1
  12. package/dist/backend/listener.js +68 -12
  13. package/dist/backend/listener.js.map +1 -1
  14. package/dist/backend/types.d.ts +1 -1
  15. package/dist/backend/types.d.ts.map +1 -1
  16. package/dist/bin/quota.d.ts +54 -0
  17. package/dist/bin/quota.d.ts.map +1 -0
  18. package/dist/bin/quota.js +333 -0
  19. package/dist/bin/quota.js.map +1 -0
  20. package/dist/config/auto-compact.d.ts +23 -0
  21. package/dist/config/auto-compact.d.ts.map +1 -0
  22. package/dist/config/auto-compact.js +67 -0
  23. package/dist/config/auto-compact.js.map +1 -0
  24. package/dist/config/mcp-discovery.d.ts +34 -0
  25. package/dist/config/mcp-discovery.d.ts.map +1 -0
  26. package/dist/config/mcp-discovery.js +153 -0
  27. package/dist/config/mcp-discovery.js.map +1 -0
  28. package/dist/config/model-cache.d.ts +12 -1
  29. package/dist/config/model-cache.d.ts.map +1 -1
  30. package/dist/config/model-cache.js +30 -8
  31. package/dist/config/model-cache.js.map +1 -1
  32. package/dist/config/options.d.ts +87 -9
  33. package/dist/config/options.d.ts.map +1 -1
  34. package/dist/config/options.js +248 -45
  35. package/dist/config/options.js.map +1 -1
  36. package/dist/config/plugin-commands.d.ts +24 -0
  37. package/dist/config/plugin-commands.d.ts.map +1 -0
  38. package/dist/config/plugin-commands.js +107 -0
  39. package/dist/config/plugin-commands.js.map +1 -0
  40. package/dist/config/provider-registry.d.ts +60 -0
  41. package/dist/config/provider-registry.d.ts.map +1 -0
  42. package/dist/config/provider-registry.js +128 -0
  43. package/dist/config/provider-registry.js.map +1 -0
  44. package/dist/config/runtime-model.d.ts +54 -18
  45. package/dist/config/runtime-model.d.ts.map +1 -1
  46. package/dist/config/runtime-model.js +105 -61
  47. package/dist/config/runtime-model.js.map +1 -1
  48. package/dist/config/skill-discovery.d.ts +35 -0
  49. package/dist/config/skill-discovery.d.ts.map +1 -0
  50. package/dist/config/skill-discovery.js +188 -0
  51. package/dist/config/skill-discovery.js.map +1 -0
  52. package/dist/handlers/background-tasks.d.ts +72 -0
  53. package/dist/handlers/background-tasks.d.ts.map +1 -0
  54. package/dist/handlers/background-tasks.js +330 -0
  55. package/dist/handlers/background-tasks.js.map +1 -0
  56. package/dist/handlers/dispatch.d.ts.map +1 -1
  57. package/dist/handlers/dispatch.js +134 -22
  58. package/dist/handlers/dispatch.js.map +1 -1
  59. package/dist/handlers/extensions.d.ts +15 -0
  60. package/dist/handlers/extensions.d.ts.map +1 -1
  61. package/dist/handlers/extensions.js +43 -27
  62. package/dist/handlers/extensions.js.map +1 -1
  63. package/dist/handlers/io.d.ts +11 -2
  64. package/dist/handlers/io.d.ts.map +1 -1
  65. package/dist/handlers/io.js +51 -7
  66. package/dist/handlers/io.js.map +1 -1
  67. package/dist/handlers/server-requests.d.ts +20 -4
  68. package/dist/handlers/server-requests.d.ts.map +1 -1
  69. package/dist/handlers/server-requests.js +293 -63
  70. package/dist/handlers/server-requests.js.map +1 -1
  71. package/dist/handlers/session.d.ts +113 -10
  72. package/dist/handlers/session.d.ts.map +1 -1
  73. package/dist/handlers/session.js +876 -220
  74. package/dist/handlers/session.js.map +1 -1
  75. package/dist/handlers/slash.d.ts +14 -0
  76. package/dist/handlers/slash.d.ts.map +1 -1
  77. package/dist/handlers/slash.js +80 -6
  78. package/dist/handlers/slash.js.map +1 -1
  79. package/dist/index.js +38 -4
  80. package/dist/index.js.map +1 -1
  81. package/dist/interaction/adapter.d.ts +19 -33
  82. package/dist/interaction/adapter.d.ts.map +1 -1
  83. package/dist/interaction/adapter.js +80 -79
  84. package/dist/interaction/adapter.js.map +1 -1
  85. package/dist/lazy-sessions.d.ts +35 -0
  86. package/dist/lazy-sessions.d.ts.map +1 -0
  87. package/dist/lazy-sessions.js +98 -0
  88. package/dist/lazy-sessions.js.map +1 -0
  89. package/dist/quota/cache.d.ts +18 -0
  90. package/dist/quota/cache.d.ts.map +1 -0
  91. package/dist/quota/cache.js +32 -0
  92. package/dist/quota/cache.js.map +1 -0
  93. package/dist/quota/client.d.ts +30 -0
  94. package/dist/quota/client.d.ts.map +1 -0
  95. package/dist/quota/client.js +57 -0
  96. package/dist/quota/client.js.map +1 -0
  97. package/dist/quota/color.d.ts +58 -0
  98. package/dist/quota/color.d.ts.map +1 -0
  99. package/dist/quota/color.js +95 -0
  100. package/dist/quota/color.js.map +1 -0
  101. package/dist/quota/combined.d.ts +66 -0
  102. package/dist/quota/combined.d.ts.map +1 -0
  103. package/dist/quota/combined.js +179 -0
  104. package/dist/quota/combined.js.map +1 -0
  105. package/dist/quota/format.d.ts +105 -0
  106. package/dist/quota/format.d.ts.map +1 -0
  107. package/dist/quota/format.js +219 -0
  108. package/dist/quota/format.js.map +1 -0
  109. package/dist/quota/index.d.ts +23 -0
  110. package/dist/quota/index.d.ts.map +1 -0
  111. package/dist/quota/index.js +42 -0
  112. package/dist/quota/index.js.map +1 -0
  113. package/dist/quota/opencode-go/cache.d.ts +17 -0
  114. package/dist/quota/opencode-go/cache.d.ts.map +1 -0
  115. package/dist/quota/opencode-go/cache.js +31 -0
  116. package/dist/quota/opencode-go/cache.js.map +1 -0
  117. package/dist/quota/opencode-go/client.d.ts +28 -0
  118. package/dist/quota/opencode-go/client.d.ts.map +1 -0
  119. package/dist/quota/opencode-go/client.js +48 -0
  120. package/dist/quota/opencode-go/client.js.map +1 -0
  121. package/dist/quota/opencode-go/config.d.ts +37 -0
  122. package/dist/quota/opencode-go/config.d.ts.map +1 -0
  123. package/dist/quota/opencode-go/config.js +58 -0
  124. package/dist/quota/opencode-go/config.js.map +1 -0
  125. package/dist/quota/opencode-go/format.d.ts +36 -0
  126. package/dist/quota/opencode-go/format.d.ts.map +1 -0
  127. package/dist/quota/opencode-go/format.js +87 -0
  128. package/dist/quota/opencode-go/format.js.map +1 -0
  129. package/dist/quota/opencode-go/index.d.ts +30 -0
  130. package/dist/quota/opencode-go/index.d.ts.map +1 -0
  131. package/dist/quota/opencode-go/index.js +108 -0
  132. package/dist/quota/opencode-go/index.js.map +1 -0
  133. package/dist/quota/opencode-go/parse.d.ts +41 -0
  134. package/dist/quota/opencode-go/parse.d.ts.map +1 -0
  135. package/dist/quota/opencode-go/parse.js +75 -0
  136. package/dist/quota/opencode-go/parse.js.map +1 -0
  137. package/dist/quota/opencode-go/types.d.ts +48 -0
  138. package/dist/quota/opencode-go/types.d.ts.map +1 -0
  139. package/dist/quota/opencode-go/types.js +11 -0
  140. package/dist/quota/opencode-go/types.js.map +1 -0
  141. package/dist/quota/parse.d.ts +33 -0
  142. package/dist/quota/parse.d.ts.map +1 -0
  143. package/dist/quota/parse.js +200 -0
  144. package/dist/quota/parse.js.map +1 -0
  145. package/dist/quota/types.d.ts +72 -0
  146. package/dist/quota/types.d.ts.map +1 -0
  147. package/dist/quota/types.js +10 -0
  148. package/dist/quota/types.js.map +1 -0
  149. package/dist/server.d.ts +104 -0
  150. package/dist/server.d.ts.map +1 -1
  151. package/dist/server.js +119 -2
  152. package/dist/server.js.map +1 -1
  153. package/dist/tasks-index.d.ts +14 -4
  154. package/dist/tasks-index.d.ts.map +1 -1
  155. package/dist/tasks-index.js +145 -46
  156. package/dist/tasks-index.js.map +1 -1
  157. package/dist/translators/event-translator.d.ts +33 -0
  158. package/dist/translators/event-translator.d.ts.map +1 -1
  159. package/dist/translators/event-translator.js +101 -0
  160. package/dist/translators/event-translator.js.map +1 -1
  161. package/dist/translators/index.d.ts +1 -1
  162. package/dist/translators/index.d.ts.map +1 -1
  163. package/dist/translators/index.js +1 -1
  164. package/dist/translators/index.js.map +1 -1
  165. package/dist/translators/projection-differ.d.ts +8 -0
  166. package/dist/translators/projection-differ.d.ts.map +1 -1
  167. package/dist/translators/projection-differ.js +19 -9
  168. package/dist/translators/projection-differ.js.map +1 -1
  169. package/dist/translators/tool-helpers.d.ts +28 -0
  170. package/dist/translators/tool-helpers.d.ts.map +1 -1
  171. package/dist/translators/tool-helpers.js +104 -0
  172. package/dist/translators/tool-helpers.js.map +1 -1
  173. package/dist/translators/types.d.ts +38 -1
  174. package/dist/translators/types.d.ts.map +1 -1
  175. package/dist/translators/types.js.map +1 -1
  176. package/dist/utils.d.ts +35 -6
  177. package/dist/utils.d.ts.map +1 -1
  178. package/dist/utils.js +52 -4
  179. package/dist/utils.js.map +1 -1
  180. package/docs/ARCHITECTURE.md +96 -38
  181. package/docs/BACKLOG.md +57 -0
  182. package/docs/DEVELOPMENT.md +5 -0
  183. package/docs/PROTOCOL.md +270 -5
  184. package/docs/TROUBLESHOOTING.md +98 -14
  185. package/docs/agents/domain.md +51 -0
  186. package/docs/agents/issue-tracker.md +22 -0
  187. package/docs/agents/triage-labels.md +15 -0
  188. package/package.json +6 -5
@@ -0,0 +1,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
  /**
@@ -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;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"}
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: false, audio: false, embeddedContext: false },
196
+ promptCapabilities: { image: true, audio: false, embeddedContext: false },
80
197
  mcpCapabilities: { http: false, sse: false },
81
198
  sessionCapabilities: { list: {}, resume: {}, fork: {} },
82
199
  },
@@ -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;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"}
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,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AA0B/D,MAAM,OAAO,cAAc;IACzB,iEAAiE;IACjE,OAAO,GAAwB,IAAI,CAAC;IACpC,4EAA4E;IACnE,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChD;;;;;;OAMG;IACM,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtD;;;;;;;;;;;OAWG;IACM,eAAe,GAAG,IAAI,GAAG,EAS9B,CAAC;IACL,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;;;;;;OAMG;IACH,SAAS,GAA4B,IAAI,CAAC;IAC1C,yEAAyE;IAChE,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IACnD;;;;;OAKG;IACM,qBAAqB,GAAG,IAAI,GAAG,EAAU,CAAC;IACnD,sFAAsF;IAC7E,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC9C;;;;;OAKG;IACM,eAAe,GAAG,IAAI,GAAG,EAAkB,CAAC;IACrD,6DAA6D;IACpD,OAAO,GAAG,IAAI,GAAG,EAGvB,CAAC;IACJ,gEAAgE;IACvD,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChD;;;;;;OAMG;IACM,mBAAmB,GAAG,IAAI,GAAG,EAAkC,CAAC;IACzE;;;;;;;OAOG;IACM,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtD,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;;;;OAIG;IACH,eAAe,CAAC,MAAc,EAAE,QAAgB;QAC9C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED;;;;;;;OAOG;IACH,wBAAwB,CAAC,QAAgB;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACxD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,IAAI,sBAAsB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC5D,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACjD,OAAO,CAAC,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAClD,GAAG,CAAC,6CAA6C,QAAQ,EAAE,CAAC,CAAC;QAC7D,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,iFAAiF;IACjF,aAAa,CAAC,QAAgB;QAC5B,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,gBAAgB,CAAC,QAAgB,EAAE,MAAyB;QAChE,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC;QAC1B,IAAI,CAAC,EAAE;YAAE,OAAO,KAAK,CAAC;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YACjE,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,GAAG,CAAC,4CAA4C,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC9F,OAAO,KAAK,CAAC;QACf,CAAC;IACH,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;YAC/C,sBAAsB,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,CAC3F,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,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE;gBACzE,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"}