pi-forge 1.2.4 → 1.3.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 (86) hide show
  1. package/README.md +1 -1
  2. package/dist/client/assets/{CodeMirrorEditor-M7HIAKX2.js → CodeMirrorEditor-BuLFJjB1.js} +13 -13
  3. package/dist/client/assets/CodeMirrorEditor-BuLFJjB1.js.map +1 -0
  4. package/dist/client/assets/index-CEqSkIuy.css +1 -0
  5. package/dist/client/assets/index-GubcPYw6.js +375 -0
  6. package/dist/client/assets/index-GubcPYw6.js.map +1 -0
  7. package/dist/client/assets/{workbox-window.prod.es5-Cch4wiA5.js → workbox-window.prod.es5-Bd17z0YL.js} +2 -2
  8. package/dist/client/assets/{workbox-window.prod.es5-Cch4wiA5.js.map → workbox-window.prod.es5-Bd17z0YL.js.map} +1 -1
  9. package/dist/client/index.html +2 -2
  10. package/dist/client/sw.js +1 -1
  11. package/dist/client/sw.js.map +1 -1
  12. package/dist/server/agent-extensions/compaction-continuation.js +65 -0
  13. package/dist/server/agent-extensions/compaction-continuation.js.map +1 -0
  14. package/dist/server/agent-resource-loader.js +10 -0
  15. package/dist/server/agent-resource-loader.js.map +1 -1
  16. package/dist/server/git-clone.js +364 -0
  17. package/dist/server/git-clone.js.map +1 -0
  18. package/dist/server/index.js +26 -1
  19. package/dist/server/index.js.map +1 -1
  20. package/dist/server/mcp/tool-bridge.js +14 -8
  21. package/dist/server/mcp/tool-bridge.js.map +1 -1
  22. package/dist/server/orchestration/config.js +61 -0
  23. package/dist/server/orchestration/config.js.map +1 -0
  24. package/dist/server/orchestration/event-bridge.js +93 -0
  25. package/dist/server/orchestration/event-bridge.js.map +1 -0
  26. package/dist/server/orchestration/inbox.js +199 -0
  27. package/dist/server/orchestration/inbox.js.map +1 -0
  28. package/dist/server/orchestration/init.js +39 -0
  29. package/dist/server/orchestration/init.js.map +1 -0
  30. package/dist/server/orchestration/store.js +352 -0
  31. package/dist/server/orchestration/store.js.map +1 -0
  32. package/dist/server/orchestration/tools.js +769 -0
  33. package/dist/server/orchestration/tools.js.map +1 -0
  34. package/dist/server/orchestration/types.js +57 -0
  35. package/dist/server/orchestration/types.js.map +1 -0
  36. package/dist/server/processes/envelope.js +60 -0
  37. package/dist/server/processes/envelope.js.map +1 -0
  38. package/dist/server/processes/log-store.js +132 -0
  39. package/dist/server/processes/log-store.js.map +1 -0
  40. package/dist/server/processes/manager.js +370 -0
  41. package/dist/server/processes/manager.js.map +1 -0
  42. package/dist/server/processes/prompt-strings.js +43 -0
  43. package/dist/server/processes/prompt-strings.js.map +1 -0
  44. package/dist/server/processes/tool.js +273 -0
  45. package/dist/server/processes/tool.js.map +1 -0
  46. package/dist/server/processes/types.js +21 -0
  47. package/dist/server/processes/types.js.map +1 -0
  48. package/dist/server/processes/watches.js +59 -0
  49. package/dist/server/processes/watches.js.map +1 -0
  50. package/dist/server/project-manager.js +46 -32
  51. package/dist/server/project-manager.js.map +1 -1
  52. package/dist/server/routes/config.js +5 -0
  53. package/dist/server/routes/config.js.map +1 -1
  54. package/dist/server/routes/control.js +9 -0
  55. package/dist/server/routes/control.js.map +1 -1
  56. package/dist/server/routes/health.js +14 -1
  57. package/dist/server/routes/health.js.map +1 -1
  58. package/dist/server/routes/orchestration.js +464 -0
  59. package/dist/server/routes/orchestration.js.map +1 -0
  60. package/dist/server/routes/processes.js +228 -0
  61. package/dist/server/routes/processes.js.map +1 -0
  62. package/dist/server/routes/projects.js +239 -14
  63. package/dist/server/routes/projects.js.map +1 -1
  64. package/dist/server/routes/sessions.js +53 -34
  65. package/dist/server/routes/sessions.js.map +1 -1
  66. package/dist/server/routes/webhooks.js +362 -0
  67. package/dist/server/routes/webhooks.js.map +1 -0
  68. package/dist/server/session-registry.js +246 -3
  69. package/dist/server/session-registry.js.map +1 -1
  70. package/dist/server/sse-bridge.js +226 -18
  71. package/dist/server/sse-bridge.js.map +1 -1
  72. package/dist/server/webhooks/dispatcher.js +254 -0
  73. package/dist/server/webhooks/dispatcher.js.map +1 -0
  74. package/dist/server/webhooks/event-bridge.js +185 -0
  75. package/dist/server/webhooks/event-bridge.js.map +1 -0
  76. package/dist/server/webhooks/init.js +55 -0
  77. package/dist/server/webhooks/init.js.map +1 -0
  78. package/dist/server/webhooks/store.js +394 -0
  79. package/dist/server/webhooks/store.js.map +1 -0
  80. package/dist/server/webhooks/types.js +32 -0
  81. package/dist/server/webhooks/types.js.map +1 -0
  82. package/package.json +4 -4
  83. package/dist/client/assets/CodeMirrorEditor-M7HIAKX2.js.map +0 -1
  84. package/dist/client/assets/index-DFDpaYie.css +0 -1
  85. package/dist/client/assets/index-DjYKKZRm.js +0 -363
  86. package/dist/client/assets/index-DjYKKZRm.js.map +0 -1
@@ -0,0 +1,370 @@
1
+ import { spawn } from "node:child_process";
2
+ import { rm } from "node:fs/promises";
3
+ import { randomBytes } from "node:crypto";
4
+ import { join } from "node:path";
5
+ import { config } from "../config.js";
6
+ import { scrubbedEnv } from "../pty-manager.js";
7
+ import { LogChannel, processLogDir } from "./log-store.js";
8
+ import { buildMatchEvent, compileWatches, evaluateWatches } from "./watches.js";
9
+ import { LIVE_STATUSES, } from "./types.js";
10
+ /**
11
+ * Per-session background process manager. One instance per
12
+ * sessionId; `createManagerForSession` lazily constructs and
13
+ * registers. On session dispose the registry calls
14
+ * `disposeManagerForSession` which SIGTERMs every live process,
15
+ * waits briefly for graceful exit, escalates to SIGKILL, then
16
+ * removes the session's log directory.
17
+ *
18
+ * State is in-memory only by deliberate choice (matches
19
+ * `@aliou/pi-processes`): a server restart drops everything;
20
+ * the OS may leak the actual children if pi-forge crashes mid-
21
+ * lifecycle, same as the plugin.
22
+ */
23
+ const GRACE_MS = 5_000;
24
+ const SIGKILL_TIMEOUT_MS = 2_000;
25
+ class ProcessManagerRegistry {
26
+ bySession = new Map();
27
+ listeners = new Set();
28
+ subscribe(fn) {
29
+ this.listeners.add(fn);
30
+ return () => {
31
+ this.listeners.delete(fn);
32
+ };
33
+ }
34
+ notify(event) {
35
+ for (const fn of this.listeners) {
36
+ try {
37
+ fn(event);
38
+ }
39
+ catch {
40
+ // best-effort fanout — listener errors must not break the manager
41
+ }
42
+ }
43
+ }
44
+ getOrCreateSession(sessionId) {
45
+ let s = this.bySession.get(sessionId);
46
+ if (s === undefined) {
47
+ s = { sessionId, processes: new Map() };
48
+ this.bySession.set(sessionId, s);
49
+ }
50
+ return s;
51
+ }
52
+ /** Spawn a new process bound to this session. */
53
+ start(sessionId, name, command, cwd, opts) {
54
+ const session = this.getOrCreateSession(sessionId);
55
+ const id = randomBytes(4).toString("hex");
56
+ const logDir = processLogDir(config.forgeDataDir, sessionId, id);
57
+ const stdoutFile = join(logDir, "stdout.log");
58
+ const stderrFile = join(logDir, "stderr.log");
59
+ // Spawn under `/bin/sh -c` so the command can use shell
60
+ // features (pipes, &&, env expansion). Scrubbed env matches
61
+ // the terminal + quick-actions posture: no pi-forge / provider
62
+ // secrets leak to the child.
63
+ const child = spawn("/bin/sh", ["-c", command], {
64
+ cwd,
65
+ env: scrubbedEnv(),
66
+ stdio: ["pipe", "pipe", "pipe"],
67
+ // detached=false on purpose — when pi-forge exits, the OS
68
+ // sends SIGTERM to the process group via the parent's death,
69
+ // matching the plugin's behavior. detached=true would orphan
70
+ // processes; we want them tied to our lifetime.
71
+ detached: false,
72
+ });
73
+ const info = {
74
+ id,
75
+ name,
76
+ pid: child.pid ?? -1,
77
+ command,
78
+ cwd,
79
+ startTime: Date.now(),
80
+ endTime: null,
81
+ status: "running",
82
+ exitCode: null,
83
+ success: null,
84
+ stdoutFile,
85
+ stderrFile,
86
+ alertOnSuccess: opts.alertOnSuccess === true,
87
+ alertOnFailure: opts.alertOnFailure !== false, // default true
88
+ alertOnKill: opts.alertOnKill === true,
89
+ };
90
+ const managed = {
91
+ info,
92
+ child,
93
+ stdout: new LogChannel(stdoutFile),
94
+ stderr: new LogChannel(stderrFile),
95
+ watches: compileWatches(opts.logWatches),
96
+ killSent: null,
97
+ killTimer: null,
98
+ };
99
+ session.processes.set(id, managed);
100
+ const wireUp = (source) => {
101
+ const stream = source === "stdout" ? child.stdout : child.stderr;
102
+ const channel = source === "stdout" ? managed.stdout : managed.stderr;
103
+ stream.on("data", (chunk) => {
104
+ channel.append(chunk, (line) => {
105
+ const hits = evaluateWatches(managed.watches, source, line);
106
+ for (const w of hits) {
107
+ this.notify({
108
+ type: "process_watch_matched",
109
+ sessionId,
110
+ match: buildMatchEvent(w, id, name, command, source, line),
111
+ });
112
+ }
113
+ });
114
+ this.notify({ type: "process_output_changed", sessionId, id });
115
+ });
116
+ };
117
+ wireUp("stdout");
118
+ wireUp("stderr");
119
+ child.on("error", (err) => {
120
+ // Spawn failure path — child never came up. Surface as a
121
+ // failed exit so the agent gets a clean result.
122
+ const text = `[spawn error] ${err.message}\n`;
123
+ managed.stderr.append(Buffer.from(text, "utf8"));
124
+ info.endTime = Date.now();
125
+ info.exitCode = -1;
126
+ info.success = false;
127
+ info.status = "exited";
128
+ // Notify BEFORE async log cleanup so the UI updates
129
+ // immediately. Log dispose runs in the background.
130
+ this.notify({ type: "process_ended", sessionId, info });
131
+ this.notify({ type: "processes_changed", sessionId });
132
+ void this.finalize(managed);
133
+ });
134
+ child.on("close", (code, signal) => {
135
+ info.endTime = Date.now();
136
+ info.exitCode = typeof code === "number" ? code : null;
137
+ // `killSent` is set when WE called .kill() (via the `process
138
+ // kill` tool); `signal` is non-null when the child died from
139
+ // any signal (ours or external). Both contribute to "wasKilled"
140
+ // for the status display, but only the EXTERNAL case (signal
141
+ // present, killSent absent) triggers an `alertOnKill` —
142
+ // alerting the agent that it killed something is redundant
143
+ // and noisy.
144
+ const killedByUs = managed.killSent !== null;
145
+ const killedExternally = !killedByUs && signal !== null;
146
+ const wasKilled = killedByUs || killedExternally;
147
+ info.status = wasKilled ? "killed" : "exited";
148
+ info.success = info.exitCode === 0 && !wasKilled;
149
+ if (managed.killTimer !== null) {
150
+ clearTimeout(managed.killTimer);
151
+ managed.killTimer = null;
152
+ }
153
+ // Notify BEFORE flushing logs. The old order awaited
154
+ // stdout.dispose() + stderr.dispose() FIRST and only
155
+ // fanned out the status change after — for any process
156
+ // with non-trivial output, that gated the UI update on
157
+ // a multi-tick filesystem flush and made Kill feel
158
+ // broken (status visibly stuck on "terminating" until
159
+ // the flush finished). Status flip is what the user
160
+ // needs to see; log cleanup is bookkeeping.
161
+ this.notify({ type: "process_ended", sessionId, info });
162
+ this.notify({ type: "processes_changed", sessionId });
163
+ // Agent-alert events. The three alertOn* flags were captured
164
+ // at start() time; honor them now. Order chosen so a single
165
+ // outcome only fires one alert — a failure isn't ALSO a "non-
166
+ // success" alert, etc.
167
+ if (killedExternally && info.alertOnKill) {
168
+ this.notify({ type: "process_alert", sessionId, info, reason: "killed" });
169
+ }
170
+ else if (!wasKilled && info.exitCode === 0 && info.alertOnSuccess) {
171
+ this.notify({ type: "process_alert", sessionId, info, reason: "success" });
172
+ }
173
+ else if (!wasKilled && info.exitCode !== 0 && info.alertOnFailure) {
174
+ this.notify({ type: "process_alert", sessionId, info, reason: "failure" });
175
+ }
176
+ void this.finalize(managed);
177
+ });
178
+ this.notify({ type: "process_started", sessionId, info });
179
+ this.notify({ type: "processes_changed", sessionId });
180
+ return cloneInfo(info);
181
+ }
182
+ /**
183
+ * Async log-cleanup tail. Lifecycle notification fires
184
+ * synchronously from the close/error handler that called this;
185
+ * this method just flushes and closes the on-disk log streams
186
+ * so a slow filesystem can't delay the UI update.
187
+ */
188
+ async finalize(managed) {
189
+ await managed.stdout.dispose();
190
+ await managed.stderr.dispose();
191
+ }
192
+ /** List every process for this session, newest-first. */
193
+ list(sessionId) {
194
+ const s = this.bySession.get(sessionId);
195
+ if (s === undefined)
196
+ return [];
197
+ return [...s.processes.values()]
198
+ .map((m) => cloneInfo(m.info))
199
+ .sort((a, b) => b.startTime - a.startTime);
200
+ }
201
+ /** Recent tail of stdout/stderr for a single process. */
202
+ output(sessionId, id, tail = 200) {
203
+ const m = this.getManaged(sessionId, id);
204
+ if (m === undefined)
205
+ return undefined;
206
+ return {
207
+ stdout: m.stdout.tail(tail),
208
+ stderr: m.stderr.tail(tail),
209
+ status: m.info.status,
210
+ };
211
+ }
212
+ logFiles(sessionId, id) {
213
+ const m = this.getManaged(sessionId, id);
214
+ if (m === undefined)
215
+ return undefined;
216
+ return { stdoutFile: m.info.stdoutFile, stderrFile: m.info.stderrFile };
217
+ }
218
+ /**
219
+ * Kill a process. SIGTERM, 5 s grace, then SIGKILL. Resolves
220
+ * once we've initiated the signal — the `process_ended` event
221
+ * fans out async when the OS reports close. The promise's
222
+ * resolved value tells the caller what happened immediately
223
+ * (process_already_dead, signal_sent, etc.).
224
+ */
225
+ async kill(sessionId, id) {
226
+ const m = this.getManaged(sessionId, id);
227
+ if (m === undefined) {
228
+ return { ok: false, info: undefined, reason: "not_found" };
229
+ }
230
+ if (!LIVE_STATUSES.has(m.info.status)) {
231
+ // Already exited — return success with the final info so the
232
+ // caller can render a clean result instead of an error.
233
+ return { ok: true, info: cloneInfo(m.info) };
234
+ }
235
+ try {
236
+ m.killSent = "SIGTERM";
237
+ m.info.status = "terminating";
238
+ this.notify({ type: "processes_changed", sessionId });
239
+ m.child.kill("SIGTERM");
240
+ m.killTimer = setTimeout(() => {
241
+ if (!LIVE_STATUSES.has(m.info.status))
242
+ return;
243
+ m.info.status = "terminate_timeout";
244
+ m.killSent = "SIGKILL";
245
+ this.notify({ type: "processes_changed", sessionId });
246
+ try {
247
+ m.child.kill("SIGKILL");
248
+ }
249
+ catch {
250
+ // ignore
251
+ }
252
+ // Last-resort timeout — if SIGKILL still doesn't move the
253
+ // process (zombie / kernel state), wait one more beat then
254
+ // report timeout to the caller. The OS WILL eventually
255
+ // close the streams; we just can't wait forever.
256
+ setTimeout(() => {
257
+ // no-op — the close handler will mark the final state
258
+ }, SIGKILL_TIMEOUT_MS).unref();
259
+ }, GRACE_MS);
260
+ return { ok: true, info: cloneInfo(m.info) };
261
+ }
262
+ catch (err) {
263
+ void err;
264
+ return { ok: false, info: cloneInfo(m.info), reason: "error" };
265
+ }
266
+ }
267
+ /** Pipe input to a live process's stdin. `end:true` closes the stream. */
268
+ async write(sessionId, id, input, end) {
269
+ const m = this.getManaged(sessionId, id);
270
+ if (m === undefined)
271
+ return { ok: false, reason: "not_found" };
272
+ if (!LIVE_STATUSES.has(m.info.status)) {
273
+ return { ok: false, reason: "process_exited" };
274
+ }
275
+ const stdin = m.child.stdin;
276
+ if (stdin === null || stdin.writableEnded) {
277
+ return { ok: false, reason: "stdin_closed" };
278
+ }
279
+ return await new Promise((resolve) => {
280
+ stdin.write(input, (err) => {
281
+ if (err !== null && err !== undefined) {
282
+ resolve({ ok: false, reason: "write_error" });
283
+ return;
284
+ }
285
+ if (end) {
286
+ stdin.end(() => resolve({ ok: true }));
287
+ }
288
+ else {
289
+ resolve({ ok: true });
290
+ }
291
+ });
292
+ });
293
+ }
294
+ /** Drop all FINISHED processes for the session. Live ones stay. */
295
+ clear(sessionId) {
296
+ const s = this.bySession.get(sessionId);
297
+ if (s === undefined)
298
+ return 0;
299
+ let count = 0;
300
+ for (const [id, m] of s.processes) {
301
+ if (!LIVE_STATUSES.has(m.info.status)) {
302
+ s.processes.delete(id);
303
+ count += 1;
304
+ }
305
+ }
306
+ if (count > 0)
307
+ this.notify({ type: "processes_changed", sessionId });
308
+ return count;
309
+ }
310
+ /**
311
+ * Dispose every process for this session: SIGTERM, brief wait,
312
+ * SIGKILL. Then unlink the session's entire log directory.
313
+ * Called from session-registry.disposeSession.
314
+ */
315
+ async disposeSession(sessionId) {
316
+ const s = this.bySession.get(sessionId);
317
+ if (s === undefined)
318
+ return;
319
+ const live = [...s.processes.values()].filter((m) => LIVE_STATUSES.has(m.info.status));
320
+ for (const m of live) {
321
+ try {
322
+ m.killSent = "SIGTERM";
323
+ m.child.kill("SIGTERM");
324
+ }
325
+ catch {
326
+ // ignore
327
+ }
328
+ }
329
+ if (live.length > 0) {
330
+ await new Promise((resolve) => setTimeout(resolve, GRACE_MS).unref());
331
+ for (const m of live) {
332
+ if (LIVE_STATUSES.has(m.info.status)) {
333
+ try {
334
+ m.child.kill("SIGKILL");
335
+ }
336
+ catch {
337
+ // ignore
338
+ }
339
+ }
340
+ }
341
+ }
342
+ // Best-effort log cleanup. A failure here (e.g. EBUSY on
343
+ // Windows) just leaves the files on disk — harmless, the
344
+ // session dir will be cleaned up by deleteColdSession's
345
+ // cascade.
346
+ const logRoot = join(config.forgeDataDir, "processes", sessionId);
347
+ await rm(logRoot, { recursive: true, force: true }).catch(() => undefined);
348
+ this.bySession.delete(sessionId);
349
+ }
350
+ /**
351
+ * Test-only: nuke everything WITHOUT signalling children. Use
352
+ * between integration test cases that spawn real processes;
353
+ * combine with explicit dispose for the cleanup of children
354
+ * the test actually started.
355
+ */
356
+ _resetForTests() {
357
+ this.bySession.clear();
358
+ // listeners intentionally NOT cleared — the SSE bridge's
359
+ // subscription is process-lifetime.
360
+ }
361
+ getManaged(sessionId, id) {
362
+ return this.bySession.get(sessionId)?.processes.get(id);
363
+ }
364
+ }
365
+ function cloneInfo(info) {
366
+ return { ...info };
367
+ }
368
+ /** Singleton — one registry per process. */
369
+ export const processManager = new ProcessManagerRegistry();
370
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/processes/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Prompt snippet + guidelines + tool description for the `process`
3
+ * tool.
4
+ *
5
+ * ─────────────────────────────────────────────────────────────────
6
+ * Adapted from @aliou/pi-processes (MIT).
7
+ * Copyright (c) aliou.
8
+ * https://github.com/aliou/pi-processes
9
+ * ─────────────────────────────────────────────────────────────────
10
+ *
11
+ * The wording is preserved because it's been tuned against real
12
+ * model behavior — rules like "avoid &, nohup, disown, or setsid
13
+ * when the process tool fits" steer the model toward the right
14
+ * primitive. The reducer, lifecycle, log handling, UI, and SSE
15
+ * wiring are pi-forge's own.
16
+ */
17
+ export const PROMPT_SNIPPET = "Manage background processes without blocking the conversation";
18
+ export const PROMPT_GUIDELINES = [
19
+ "Use the process tool for long-running commands such as dev servers, test watchers, build watchers, and log tails instead of bash.",
20
+ "Avoid shell background patterns such as &, nohup, disown, or setsid when the process tool fits.",
21
+ "After starting a process, continue other work instead of waiting for it.",
22
+ "Use the pi-forge process tool's notify flags (alertOnSuccess / alertOnFailure / alertOnKill) and logWatches when you need to react to events without polling.",
23
+ ];
24
+ export const TOOL_DESCRIPTION = `Manage background processes. Actions:
25
+ - start: Run command in background (requires 'name' and 'command')
26
+ - alertOnSuccess (default: false): Get a turn to react when process completes successfully
27
+ - alertOnFailure (default: true): Get a turn to react when process crashes/fails
28
+ - alertOnKill (default: false): Get a turn to react if killed by external signal (killing via tool never triggers a turn)
29
+ - logWatches (optional): Runtime output watches that trigger immediate alerts while running
30
+ - pattern: regex string to match per output line
31
+ - stream: stdout | stderr | both (default both)
32
+ - repeat: false by default (single-fire). Set true for repeat alerts
33
+ - list: Show all managed processes with their IDs and names
34
+ - output: Get recent stdout/stderr (requires 'id')
35
+ - logs: Get log file paths to inspect with read tool (requires 'id')
36
+ - kill: Terminate a process (requires 'id')
37
+ - clear: Remove all finished processes from the list
38
+ - write: Write to process stdin (requires 'id' and 'input', optional 'end' to close stdin)
39
+
40
+ Important: You DON'T need to poll or wait for processes. Notifications arrive automatically based on your preferences. Start processes and continue with other work — you'll be informed if something requires attention.
41
+
42
+ Note: User always sees process updates in the UI. The notify flags control whether YOU (the agent) get a turn to react (e.g. check results, fix code, restart).`;
43
+ //# sourceMappingURL=prompt-strings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-strings.js","sourceRoot":"","sources":["../../src/processes/prompt-strings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,+DAA+D,CAAC;AAE9F,MAAM,CAAC,MAAM,iBAAiB,GAAa;IACzC,mIAAmI;IACnI,iGAAiG;IACjG,0EAA0E;IAC1E,+JAA+J;CAChK,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;gKAkBgI,CAAC"}