@mclawnet/mcp-server 0.1.7 → 0.1.9

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.
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Cross-process "wake the agent" shim.
3
+ *
4
+ * The MCP server lives in a stdio subprocess spawned by the LLM backend
5
+ * (claude / codex CLI); the agent process owns the real InboxRelay and runs an
6
+ * InboxWatcher (fs.watch on the inbox dir, 50ms debounce) that calls
7
+ * InboxRelay.deliver() whenever anything in the inbox dir changes.
8
+ *
9
+ * When this process needs to wake the agent — e.g. a `wakeup_after` timer
10
+ * fires, or a `watch_path` trigger just wrote a new inbox message — we can't
11
+ * call InboxRelay directly (different process). Instead we touch the
12
+ * recipient's inbox file's mtime so the agent's InboxWatcher picks it up and
13
+ * runs its normal deliver pass.
14
+ *
15
+ * `home` matches the value passed to InboxStore (CLAWNET_HOME or os.homedir());
16
+ * filenames live at `<projectRoot>/swarms/<swarmId>/inboxes/<instanceId>.json`.
17
+ */
18
+ export declare class InboxTouchRelay {
19
+ private home;
20
+ constructor(home: string);
21
+ deliver(workDir: string, swarmId: string, instanceId: string): void;
22
+ }
23
+ //# sourceMappingURL=inbox-touch-relay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox-touch-relay.d.ts","sourceRoot":"","sources":["../src/inbox-touch-relay.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,eAAe;IACd,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,MAAM;IAEhC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;CAiBpE"}
@@ -0,0 +1,41 @@
1
+ import { utimesSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { projectRoot } from "@mclawnet/task";
4
+ import { createLogger } from "@mclawnet/logger";
5
+ const log = createLogger({ module: "mcp-server/inbox-touch-relay" });
6
+ /**
7
+ * Cross-process "wake the agent" shim.
8
+ *
9
+ * The MCP server lives in a stdio subprocess spawned by the LLM backend
10
+ * (claude / codex CLI); the agent process owns the real InboxRelay and runs an
11
+ * InboxWatcher (fs.watch on the inbox dir, 50ms debounce) that calls
12
+ * InboxRelay.deliver() whenever anything in the inbox dir changes.
13
+ *
14
+ * When this process needs to wake the agent — e.g. a `wakeup_after` timer
15
+ * fires, or a `watch_path` trigger just wrote a new inbox message — we can't
16
+ * call InboxRelay directly (different process). Instead we touch the
17
+ * recipient's inbox file's mtime so the agent's InboxWatcher picks it up and
18
+ * runs its normal deliver pass.
19
+ *
20
+ * `home` matches the value passed to InboxStore (CLAWNET_HOME or os.homedir());
21
+ * filenames live at `<projectRoot>/swarms/<swarmId>/inboxes/<instanceId>.json`.
22
+ */
23
+ export class InboxTouchRelay {
24
+ home;
25
+ constructor(home) {
26
+ this.home = home;
27
+ }
28
+ deliver(workDir, swarmId, instanceId) {
29
+ try {
30
+ const fp = join(projectRoot(workDir, this.home), "swarms", swarmId, "inboxes", `${instanceId}.json`);
31
+ const now = new Date();
32
+ utimesSync(fp, now, now);
33
+ }
34
+ catch (err) {
35
+ // File may not exist yet (no messages ever appended) or perms problem.
36
+ // Best-effort: the agent will catch up on the next message_send / scan.
37
+ log.debug({ err, swarmId, instanceId }, "inbox touch failed (best-effort)");
38
+ }
39
+ }
40
+ }
41
+ //# sourceMappingURL=inbox-touch-relay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbox-touch-relay.js","sourceRoot":"","sources":["../src/inbox-touch-relay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,8BAA8B,EAAE,CAAC,CAAC;AAErE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,eAAe;IACN;IAApB,YAAoB,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAEpC,OAAO,CAAC,OAAe,EAAE,OAAe,EAAE,UAAkB;QAC1D,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,IAAI,CACb,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,EAC/B,QAAQ,EACR,OAAO,EACP,SAAS,EACT,GAAG,UAAU,OAAO,CACrB,CAAC;YACF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,UAAU,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,uEAAuE;YACvE,wEAAwE;YACxE,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,kCAAkC,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;CACF"}
package/dist/server.js CHANGED
@@ -14,7 +14,9 @@ import { join } from "node:path";
14
14
  import { createLogger } from "@mclawnet/logger";
15
15
  import { createEmbeddingProviders, EmbeddingService, initDatabase, MemoryStore, } from "@mclawnet/memory";
16
16
  import { SkillStore, EvolutionPipeline } from "@mclawnet/skill-manager";
17
+ import { WakeupScheduler, WatchManager } from "@mclawnet/swarm";
17
18
  import { getAllToolDefinitions, routeToolCall } from "./tools/index.js";
19
+ import { InboxTouchRelay } from "./inbox-touch-relay.js";
18
20
  const log = createLogger({ module: "mcp-server" });
19
21
  // Two distinct roots:
20
22
  // homeDir — user home (no `.clawnet` suffix). TaskStore/InboxStore append
@@ -39,7 +41,89 @@ const context = {
39
41
  task: { rootDir: homeDir },
40
42
  inbox: { rootDir: homeDir },
41
43
  planReview: { rootDir: homeDir },
44
+ swarm: { rootDir: homeDir },
42
45
  };
46
+ // === Self-wakeup wiring (M5 Task 7) ===
47
+ //
48
+ // The MCP server lives in a stdio subprocess (one per LLM session) while the
49
+ // agent — which owns the real InboxRelay and runs an InboxWatcher on the
50
+ // inbox dir — lives in a sibling process. Same-process injection is therefore
51
+ // impossible. The fix:
52
+ // 1. Construct WakeupScheduler + WatchManager inside this process.
53
+ // 2. Wire them into the inbox tool context.
54
+ // 3. When a timer/watch fires, the cross-process touch-relay updates the
55
+ // recipient's inbox file mtime; the agent's InboxWatcher catches the fs
56
+ // event (50ms debounce) and runs its normal InboxRelay.deliver pass,
57
+ // which picks up the newly-deliverable message (notBefore <= now).
58
+ //
59
+ // The scheduler / watchManager from @mclawnet/swarm only know (swarmId,
60
+ // instanceId); the touch-relay also needs workDir to resolve the inbox file
61
+ // path. We keep a small in-process registry mapping (s,i)→workDir, populated
62
+ // at register time by the wrapper. It can grow indefinitely for distinct
63
+ // (s,i) keys but is bounded by the MCP server's process lifetime (single LLM
64
+ // session) — acceptable for v1.
65
+ const touchRelay = new InboxTouchRelay(homeDir);
66
+ const workdirRegistry = new Map();
67
+ const registryKey = (s, i) => `${s}::${i}`;
68
+ const wakeupScheduler = new WakeupScheduler({
69
+ deliver: (swarmId, instanceId) => {
70
+ const key = registryKey(swarmId, instanceId);
71
+ const workDir = workdirRegistry.get(key);
72
+ if (!workDir) {
73
+ // Should not happen — wakeup_after always populates the registry before
74
+ // register. Log so a future eviction policy can be debugged.
75
+ log.warn({ swarmId, instanceId }, "wakeup deliver: no workDir in registry");
76
+ return;
77
+ }
78
+ touchRelay.deliver(workDir, swarmId, instanceId);
79
+ // Wakeup is single-fire — drop the registry entry to bound growth.
80
+ // (Re-registration by a new wakeup_after call will re-populate.)
81
+ workdirRegistry.delete(key);
82
+ },
83
+ });
84
+ const watchManager = new WatchManager();
85
+ context.inbox.scheduler = {
86
+ register: (swarmId, instanceId, notBefore, workDir) => {
87
+ workdirRegistry.set(registryKey(swarmId, instanceId), workDir);
88
+ wakeupScheduler.register(swarmId, instanceId, notBefore);
89
+ },
90
+ countForInstance: (s, i) => wakeupScheduler.countForInstance(s, i),
91
+ };
92
+ context.inbox.watchManager = {
93
+ register: (reg) => {
94
+ workdirRegistry.set(registryKey(reg.swarmId, reg.instanceId), reg.projectRoot);
95
+ watchManager.register(reg);
96
+ },
97
+ countForInstance: (s, i) => watchManager.countForInstance(s, i),
98
+ unregister: (s, i, w) => {
99
+ watchManager.unregister(s, i, w);
100
+ // I3: when the last watch for (s,i) is dropped, prune the registry
101
+ // entry too — long-lived sessions with many distinct (s,i) pairs
102
+ // otherwise grow monotonically. Wakeups re-set the entry on demand;
103
+ // we don't need to worry about racing with an in-flight wakeup
104
+ // because the registry entry is single-fire (wakeup deliver also
105
+ // deletes it on fire).
106
+ if (watchManager.countForInstance(s, i) === 0) {
107
+ workdirRegistry.delete(registryKey(s, i));
108
+ }
109
+ },
110
+ unwatchByInstance: (s, i) => {
111
+ watchManager.unwatchByInstance(s, i);
112
+ workdirRegistry.delete(registryKey(s, i));
113
+ },
114
+ };
115
+ context.inbox.relay = {
116
+ deliver: (swarmId, instanceId) => {
117
+ const workDir = workdirRegistry.get(registryKey(swarmId, instanceId));
118
+ if (workDir)
119
+ touchRelay.deliver(workDir, swarmId, instanceId);
120
+ },
121
+ };
122
+ // Restart safety: timers don't survive process exit. We intentionally do NOT
123
+ // call WakeupScheduler.restoreFromInbox here — mcp-server lifetime equals the
124
+ // LLM session, so restoring across sessions would pile up stale timers. The
125
+ // agent-process restart story is a separate concern (it owns InboxRelay and
126
+ // can re-scan inboxes on its own startup).
43
127
  const server = new Server({ name: "clawnet-mcp", version: "0.1.0" }, { capabilities: { tools: {} } });
44
128
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
45
129
  tools: getAllToolDefinitions(),
@@ -53,6 +137,18 @@ await server.connect(transport);
53
137
  log.info("ClawNet MCP server connected via stdio");
54
138
  function cleanup() {
55
139
  log.info("ClawNet MCP server shutting down");
140
+ try {
141
+ wakeupScheduler.dispose();
142
+ }
143
+ catch {
144
+ // ignore
145
+ }
146
+ try {
147
+ watchManager.dispose();
148
+ }
149
+ catch {
150
+ // ignore
151
+ }
56
152
  try {
57
153
  db.close();
58
154
  }
@@ -60,6 +156,17 @@ function cleanup() {
60
156
  // ignore
61
157
  }
62
158
  }
159
+ // `process.on("exit")` runs cleanup at natural exit too. SIGINT/SIGTERM
160
+ // handlers below call cleanup and then exit; the "exit" handler is a no-op
161
+ // the second time around (dispose / db.close are idempotent enough).
162
+ //
163
+ // We do NOT try to drain in-flight `routeToolCall` work before exiting —
164
+ // MCP protocol over stdio has no graceful-close handshake exposed via the
165
+ // SDK at the time of writing, and a stuck handler would block shutdown
166
+ // indefinitely. The trade-off: a tool call interrupted at the wrong instant
167
+ // may leave a partially-written inbox file. InboxStore uses proper-lockfile +
168
+ // integer-replace writes, so the file stays valid JSON; the worst case is
169
+ // a missing message that the caller will need to retry.
63
170
  process.on("exit", cleanup);
64
171
  process.on("SIGINT", () => {
65
172
  cleanup();
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -16,9 +16,54 @@ export interface InboxToolContext {
16
16
  * agent is woken immediately. Failures are swallowed (best-effort).
17
17
  */
18
18
  relay?: InboxRelayLike;
19
+ /**
20
+ * Optional wakeup scheduler. When present, `wakeup_after` registers a timer
21
+ * after writing the deferred inbox message so it fires in-process when the
22
+ * notBefore time arrives. Without this, the message still lands on disk and
23
+ * will be picked up on the next inbox scan / restart restore.
24
+ */
25
+ scheduler?: {
26
+ /**
27
+ * `workDir` is required by the MCP server's wrapper, which keeps a
28
+ * (swarmId,instanceId)→workDir registry so the cross-process touch-relay
29
+ * can resolve the inbox file path when the timer fires. The underlying
30
+ * @mclawnet/swarm WakeupScheduler still takes only 3 args; the extra
31
+ * parameter is consumed by the wrapper before delegating.
32
+ */
33
+ register(swarmId: string, instanceId: string, notBefore: number, workDir: string): void;
34
+ /** I4 caps: per-instance active timer count, used to reject before write. */
35
+ countForInstance?(swarmId: string, instanceId: string): number;
36
+ };
37
+ /**
38
+ * Optional fs-watch manager. When present, `watch_path` registers a watch
39
+ * whose `onTrigger` writes an inbox message and (best-effort) wakes the
40
+ * recipient via `relay.deliver`. Without it, `watch_path` returns isError.
41
+ */
42
+ watchManager?: {
43
+ register(reg: WatchRegistrationLike): void;
44
+ unregister(swarmId: string, instanceId: string, watchId: string): void;
45
+ unwatchByInstance(swarmId: string, instanceId: string): void;
46
+ /** I4 caps: per-instance active watch count, used to reject before register. */
47
+ countForInstance?(swarmId: string, instanceId: string): number;
48
+ };
49
+ }
50
+ /**
51
+ * Minimal structural shape for a WatchManager registration. Kept local (not
52
+ * imported from @mclawnet/swarm) to keep the contextual coupling loose — the
53
+ * router wires in the real type at start time.
54
+ */
55
+ export interface WatchRegistrationLike {
56
+ swarmId: string;
57
+ instanceId: string;
58
+ watchId: string;
59
+ projectRoot: string;
60
+ includeGlobs: string[];
61
+ ignoreGlobs: string[];
62
+ debounceMs: number;
63
+ onTrigger: (matchedPath: string) => void | Promise<void>;
19
64
  }
20
65
  export declare const INBOX_TOOL_NAMES: Set<string>;
21
- export declare function getInboxToolDefinitions(): {
66
+ export declare function getInboxToolDefinitions(): ({
22
67
  name: string;
23
68
  description: string;
24
69
  inputSchema: {
@@ -60,10 +105,128 @@ export declare function getInboxToolDefinitions(): {
60
105
  type: string[];
61
106
  description: string;
62
107
  };
108
+ instanceId?: undefined;
109
+ seconds?: undefined;
110
+ payload?: undefined;
111
+ includeGlobs?: undefined;
112
+ ignoreGlobs?: undefined;
113
+ debounceMs?: undefined;
114
+ watchId?: undefined;
115
+ };
116
+ required: string[];
117
+ };
118
+ } | {
119
+ name: string;
120
+ description: string;
121
+ inputSchema: {
122
+ type: "object";
123
+ properties: {
124
+ workDir: {
125
+ type: string;
126
+ description: string;
127
+ };
128
+ swarmId: {
129
+ type: string;
130
+ description: string;
131
+ };
132
+ instanceId: {
133
+ type: string;
134
+ description: string;
135
+ };
136
+ seconds: {
137
+ type: string;
138
+ exclusiveMinimum: number;
139
+ maximum: number;
140
+ description: string;
141
+ };
142
+ payload: {
143
+ type: string;
144
+ description: string;
145
+ };
146
+ type: {
147
+ type: string;
148
+ description: string;
149
+ };
150
+ from: {
151
+ type: string;
152
+ description: string;
153
+ };
154
+ to?: undefined;
155
+ data?: undefined;
156
+ taskId?: undefined;
157
+ expectedStatus?: undefined;
158
+ expectedOwner?: undefined;
159
+ includeGlobs?: undefined;
160
+ ignoreGlobs?: undefined;
161
+ debounceMs?: undefined;
162
+ watchId?: undefined;
163
+ };
164
+ required: string[];
165
+ };
166
+ } | {
167
+ name: string;
168
+ description: string;
169
+ inputSchema: {
170
+ type: "object";
171
+ properties: {
172
+ workDir: {
173
+ type: string;
174
+ description: string;
175
+ };
176
+ swarmId: {
177
+ type: string;
178
+ description?: undefined;
179
+ };
180
+ instanceId: {
181
+ type: string;
182
+ description: string;
183
+ };
184
+ includeGlobs: {
185
+ type: string;
186
+ items: {
187
+ type: string;
188
+ };
189
+ minItems: number;
190
+ description: string;
191
+ };
192
+ payload: {
193
+ type: string;
194
+ description: string;
195
+ };
196
+ ignoreGlobs: {
197
+ type: string;
198
+ items: {
199
+ type: string;
200
+ };
201
+ description: string;
202
+ };
203
+ debounceMs: {
204
+ type: string;
205
+ minimum: number;
206
+ description: string;
207
+ };
208
+ type: {
209
+ type: string;
210
+ description: string;
211
+ };
212
+ from: {
213
+ type: string;
214
+ description: string;
215
+ };
216
+ watchId: {
217
+ type: string;
218
+ description: string;
219
+ };
220
+ to?: undefined;
221
+ data?: undefined;
222
+ taskId?: undefined;
223
+ expectedStatus?: undefined;
224
+ expectedOwner?: undefined;
225
+ seconds?: undefined;
63
226
  };
64
227
  required: string[];
65
228
  };
66
- }[];
229
+ })[];
67
230
  export declare function handleInboxToolCall(name: string, args: Record<string, unknown>, context: InboxToolContext): Promise<{
68
231
  content: Array<{
69
232
  type: "text";
@@ -1 +1 @@
1
- {"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../../src/tools/inbox.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpE;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED,eAAO,MAAM,gBAAgB,aAA4B,CAAC;AAE1D,wBAAgB,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA+BtC;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAoBhF"}
1
+ {"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../../src/tools/inbox.ts"],"names":[],"mappings":"AAiCA,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpE;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB;;;;;OAKG;IACH,SAAS,CAAC,EAAE;QACV;;;;;;WAMG;QACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACxF,6EAA6E;QAC7E,gBAAgB,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;KAChE,CAAC;IACF;;;;OAIG;IACH,YAAY,CAAC,EAAE;QACb,QAAQ,CAAC,GAAG,EAAE,qBAAqB,GAAG,IAAI,CAAC;QAC3C,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvE,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7D,gFAAgF;QAChF,gBAAgB,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;KAChE,CAAC;CACH;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED,eAAO,MAAM,gBAAgB,aAA0D,CAAC;AAcxF,wBAAgB,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAkFtC;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAmChF"}