@a5c-ai/tula 5.0.1-staging.3edc9d7b8d6f

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 (56) hide show
  1. package/README.md +34 -0
  2. package/dist/cli/amuxEventsFormatter.d.ts +26 -0
  3. package/dist/cli/amuxEventsFormatter.d.ts.map +1 -0
  4. package/dist/cli/amuxEventsFormatter.js +86 -0
  5. package/dist/cli/args/argFlags.d.ts +6 -0
  6. package/dist/cli/args/argFlags.d.ts.map +1 -0
  7. package/dist/cli/args/argFlags.js +72 -0
  8. package/dist/cli/args/argPositionals.d.ts +3 -0
  9. package/dist/cli/args/argPositionals.d.ts.map +1 -0
  10. package/dist/cli/args/argPositionals.js +18 -0
  11. package/dist/cli/args/index.d.ts +4 -0
  12. package/dist/cli/args/index.d.ts.map +1 -0
  13. package/dist/cli/args/index.js +75 -0
  14. package/dist/cli/args/types.d.ts +13 -0
  15. package/dist/cli/args/types.d.ts.map +1 -0
  16. package/dist/cli/args/types.js +2 -0
  17. package/dist/cli/commands/daemon.d.ts +31 -0
  18. package/dist/cli/commands/daemon.d.ts.map +1 -0
  19. package/dist/cli/commands/daemon.js +156 -0
  20. package/dist/cli/commands/harness/createRun.d.ts +3 -0
  21. package/dist/cli/commands/harness/createRun.d.ts.map +1 -0
  22. package/dist/cli/commands/harness/createRun.js +8 -0
  23. package/dist/cli/commands/harness/resumeRun.d.ts +20 -0
  24. package/dist/cli/commands/harness/resumeRun.d.ts.map +1 -0
  25. package/dist/cli/commands/harness/resumeRun.js +341 -0
  26. package/dist/cli/commands/jsonlInteractive.d.ts +35 -0
  27. package/dist/cli/commands/jsonlInteractive.d.ts.map +1 -0
  28. package/dist/cli/commands/jsonlInteractive.js +302 -0
  29. package/dist/cli/commands/mcpServe.d.ts +18 -0
  30. package/dist/cli/commands/mcpServe.d.ts.map +1 -0
  31. package/dist/cli/commands/mcpServe.js +59 -0
  32. package/dist/cli/commands/session/history.d.ts +14 -0
  33. package/dist/cli/commands/session/history.d.ts.map +1 -0
  34. package/dist/cli/commands/session/history.js +100 -0
  35. package/dist/cli/commands/tui.d.ts +23 -0
  36. package/dist/cli/commands/tui.d.ts.map +1 -0
  37. package/dist/cli/commands/tui.js +183 -0
  38. package/dist/cli/dispatch.d.ts +4 -0
  39. package/dist/cli/dispatch.d.ts.map +1 -0
  40. package/dist/cli/dispatch.js +348 -0
  41. package/dist/cli/main.d.ts +7 -0
  42. package/dist/cli/main.d.ts.map +1 -0
  43. package/dist/cli/main.js +41 -0
  44. package/dist/cli/program.d.ts +7 -0
  45. package/dist/cli/program.d.ts.map +1 -0
  46. package/dist/cli/program.js +8 -0
  47. package/dist/cli/ui.d.ts +9 -0
  48. package/dist/cli/ui.d.ts.map +1 -0
  49. package/dist/cli/ui.js +125 -0
  50. package/dist/index.d.ts +18 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +59 -0
  53. package/dist/prompts/commandTemplates.d.ts +3 -0
  54. package/dist/prompts/commandTemplates.d.ts.map +1 -0
  55. package/dist/prompts/commandTemplates.js +238 -0
  56. package/package.json +76 -0
@@ -0,0 +1,18 @@
1
+ /**
2
+ * start-server command - Launch the babysitter MCP server on stdio or WebSocket transport.
3
+ *
4
+ * stdout is reserved for MCP protocol messages; all logging goes to stderr.
5
+ */
6
+ export declare function handleMcpServe(args: {
7
+ json: boolean;
8
+ transport?: string;
9
+ port?: number;
10
+ host?: string;
11
+ authToken?: string;
12
+ wsOptions?: {
13
+ pingIntervalMs?: number;
14
+ maxMessagesPerSecond?: number;
15
+ sessionGracePeriodMs?: number;
16
+ };
17
+ }): Promise<number>;
18
+ //# sourceMappingURL=mcpServe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcpServe.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/mcpServe.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE;QACV,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;KAC/B,CAAC;CACH,GAAG,OAAO,CAAC,MAAM,CAAC,CAwDlB"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ /**
3
+ * start-server command - Launch the babysitter MCP server on stdio or WebSocket transport.
4
+ *
5
+ * stdout is reserved for MCP protocol messages; all logging goes to stderr.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.handleMcpServe = handleMcpServe;
9
+ const babysitter_sdk_1 = require("@a5c-ai/babysitter-sdk");
10
+ const transport_1 = require("@a5c-ai/agent-platform/mcp/transport");
11
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
12
+ function installShutdownHandlers(shutdownFn) {
13
+ process.on("SIGINT", () => void shutdownFn());
14
+ process.on("SIGTERM", () => void shutdownFn());
15
+ }
16
+ async function handleMcpServe(args) {
17
+ const transportType = args.transport ?? "stdio";
18
+ if (transportType === "ws" || transportType === "websocket") {
19
+ const wsTransport = await (0, transport_1.createWebSocketTransport)({
20
+ port: args.port ?? 9600,
21
+ host: args.host ?? "127.0.0.1",
22
+ authToken: args.authToken,
23
+ pingIntervalMs: args.wsOptions?.pingIntervalMs,
24
+ maxMessagesPerSecond: args.wsOptions?.maxMessagesPerSecond,
25
+ sessionGracePeriodMs: args.wsOptions?.sessionGracePeriodMs,
26
+ });
27
+ // Each new WebSocket connection gets its own McpServer instance
28
+ wsTransport.onconnection = (connectionTransport) => {
29
+ const server = (0, babysitter_sdk_1.createBabysitterMcpServer)();
30
+ void server.connect(connectionTransport);
31
+ };
32
+ process.stderr.write(args.json
33
+ ? JSON.stringify({
34
+ status: "running",
35
+ transport: "websocket",
36
+ port: wsTransport.port,
37
+ }) + "\n"
38
+ : `Babysitter MCP server running on WebSocket port ${wsTransport.port}\n`);
39
+ installShutdownHandlers(async () => {
40
+ process.stderr.write("Shutting down MCP server...\n");
41
+ await wsTransport.close();
42
+ process.exit(0);
43
+ });
44
+ return await new Promise(() => { });
45
+ }
46
+ // Default: stdio transport
47
+ const server = (0, babysitter_sdk_1.createBabysitterMcpServer)();
48
+ const transport = new stdio_js_1.StdioServerTransport();
49
+ await server.connect(transport);
50
+ process.stderr.write(args.json
51
+ ? JSON.stringify({ status: "running", transport: "stdio" }) + "\n"
52
+ : "Babysitter MCP server running on stdio\n");
53
+ installShutdownHandlers(async () => {
54
+ process.stderr.write("Shutting down MCP server...\n");
55
+ await server.close();
56
+ process.exit(0);
57
+ });
58
+ return await new Promise(() => { });
59
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * session:history command — Browse session history (GAP-SESSION-002).
3
+ *
4
+ * Displays accumulated decisions, run summaries, and context snapshots
5
+ * for a session. Supports --json and --run-id filtering.
6
+ */
7
+ export interface SessionHistoryArgs {
8
+ sessionId: string;
9
+ stateDir: string;
10
+ json?: boolean;
11
+ runId?: string;
12
+ }
13
+ export declare function handleSessionHistory(args: SessionHistoryArgs): Promise<number>;
14
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/session/history.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BpF"}
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ /**
3
+ * session:history command — Browse session history (GAP-SESSION-002).
4
+ *
5
+ * Displays accumulated decisions, run summaries, and context snapshots
6
+ * for a session. Supports --json and --run-id filtering.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.handleSessionHistory = handleSessionHistory;
10
+ const session_1 = require("@a5c-ai/agent-platform/session");
11
+ async function handleSessionHistory(args) {
12
+ const { sessionId, stateDir } = args;
13
+ if (!sessionId) {
14
+ console.error("[session:history] --session-id is required");
15
+ return 1;
16
+ }
17
+ if (!stateDir) {
18
+ console.error("[session:history] --state-dir is required");
19
+ return 1;
20
+ }
21
+ const history = await (0, session_1.getSessionHistory)(stateDir, sessionId);
22
+ // Apply run-id filter if requested
23
+ const filtered = args.runId ? filterByRunId(history, args.runId) : history;
24
+ if (args.json) {
25
+ console.log(JSON.stringify(filtered, null, 2));
26
+ return 0;
27
+ }
28
+ // Text mode
29
+ renderTextHistory(filtered);
30
+ return 0;
31
+ }
32
+ function filterByRunId(history, runId) {
33
+ return {
34
+ notes: history.notes,
35
+ sharedKnowledge: history.sharedKnowledge,
36
+ worktree: history.worktree,
37
+ decisions: history.decisions.filter((d) => d.runId === runId),
38
+ runSummaries: history.runSummaries.filter((r) => r.runId === runId),
39
+ contextSnapshots: history.contextSnapshots.filter((s) => s.runId === runId),
40
+ };
41
+ }
42
+ function renderTextHistory(history) {
43
+ console.log("=== Session Context ===");
44
+ if (history.worktree?.workspacePath) {
45
+ const parts = [`workspace ${history.worktree.workspacePath}`];
46
+ if (history.worktree.currentPath)
47
+ parts.push(`current ${history.worktree.currentPath}`);
48
+ if (history.worktree.mode)
49
+ parts.push(`mode ${history.worktree.mode}`);
50
+ if (history.worktree.repoAlias)
51
+ parts.push(`repo ${history.worktree.repoAlias}`);
52
+ if (history.worktree.branch)
53
+ parts.push(`branch ${history.worktree.branch}`);
54
+ console.log(` ${parts.join(" | ")}`);
55
+ }
56
+ else {
57
+ console.log("(no worktree metadata)");
58
+ }
59
+ console.log("");
60
+ console.log("=== Decisions ===");
61
+ if (history.decisions.length === 0) {
62
+ console.log("(none)");
63
+ }
64
+ else {
65
+ for (const d of history.decisions) {
66
+ const runPart = d.runId ? ` [${d.runId}]` : "";
67
+ const ratPart = d.rationale ? ` — ${d.rationale}` : "";
68
+ console.log(` ${d.timestamp}${runPart}: ${d.description}${ratPart}`);
69
+ }
70
+ }
71
+ console.log("");
72
+ console.log("=== Run Summaries ===");
73
+ if (history.runSummaries.length === 0) {
74
+ console.log("(none)");
75
+ }
76
+ else {
77
+ for (const r of history.runSummaries) {
78
+ const parts = [`${r.runId} (${r.processId})`, r.status, `started ${r.startedAt}`];
79
+ if (r.completedAt)
80
+ parts.push(`completed ${r.completedAt}`);
81
+ if (r.outcome)
82
+ parts.push(r.outcome);
83
+ if (r.score !== undefined)
84
+ parts.push(`score: ${r.score}`);
85
+ console.log(` ${parts.join(" | ")}`);
86
+ }
87
+ }
88
+ console.log("");
89
+ console.log("=== Context Snapshots ===");
90
+ if (history.contextSnapshots.length === 0) {
91
+ console.log("(none)");
92
+ }
93
+ else {
94
+ for (const s of history.contextSnapshots) {
95
+ const keys = Object.keys(s.snapshot).length;
96
+ const runPart = s.runId ? ` [${s.runId}]` : "";
97
+ console.log(` ${s.timestamp}${runPart}: ${keys} key(s)`);
98
+ }
99
+ }
100
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * tui command -- stub redirecting to agent-mux TUI with babysitter plugins.
3
+ *
4
+ * The tula dashboard uses the agent-mux TUI
5
+ * with babysitter-tui-plugins instead (packages/babysitter-tui-plugins/).
6
+ *
7
+ * `babysitter tui --json` still works as a non-interactive JSON fallback
8
+ * for run listing / detail inspection.
9
+ */
10
+ interface TuiArgs {
11
+ runsDir: string;
12
+ json?: boolean;
13
+ verbose?: boolean;
14
+ positional?: string[];
15
+ harness?: string;
16
+ workspace?: string;
17
+ prompt?: string;
18
+ runId?: string;
19
+ verbosity?: string;
20
+ }
21
+ export declare function handleTui(args: TuiArgs): Promise<number>;
22
+ export {};
23
+ //# sourceMappingURL=tui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/tui.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,UAAU,OAAO;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAgJD,wBAAsB,SAAS,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAe9D"}
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ /**
3
+ * tui command -- stub redirecting to agent-mux TUI with babysitter plugins.
4
+ *
5
+ * The tula dashboard uses the agent-mux TUI
6
+ * with babysitter-tui-plugins instead (packages/babysitter-tui-plugins/).
7
+ *
8
+ * `babysitter tui --json` still works as a non-interactive JSON fallback
9
+ * for run listing / detail inspection.
10
+ */
11
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ var desc = Object.getOwnPropertyDescriptor(m, k);
14
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
15
+ desc = { enumerable: true, get: function() { return m[k]; } };
16
+ }
17
+ Object.defineProperty(o, k2, desc);
18
+ }) : (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ o[k2] = m[k];
21
+ }));
22
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
23
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
24
+ }) : function(o, v) {
25
+ o["default"] = v;
26
+ });
27
+ var __importStar = (this && this.__importStar) || (function () {
28
+ var ownKeys = function(o) {
29
+ ownKeys = Object.getOwnPropertyNames || function (o) {
30
+ var ar = [];
31
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
32
+ return ar;
33
+ };
34
+ return ownKeys(o);
35
+ };
36
+ return function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ })();
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.handleTui = handleTui;
46
+ const path = __importStar(require("node:path"));
47
+ const node_fs_1 = require("node:fs");
48
+ const babysitter_sdk_1 = require("@a5c-ai/babysitter-sdk");
49
+ async function scanRunsForJson(runsDir) {
50
+ const resolvedDir = path.resolve(runsDir);
51
+ let entries;
52
+ try {
53
+ entries = await node_fs_1.promises.readdir(resolvedDir);
54
+ }
55
+ catch {
56
+ return [];
57
+ }
58
+ const summaries = [];
59
+ for (const entry of entries) {
60
+ const runDir = path.join(resolvedDir, entry);
61
+ const metadataPath = path.join(runDir, "run.json");
62
+ try {
63
+ await node_fs_1.promises.access(metadataPath);
64
+ }
65
+ catch {
66
+ continue;
67
+ }
68
+ try {
69
+ const metadata = await (0, babysitter_sdk_1.readRunMetadata)(runDir);
70
+ let journal = [];
71
+ try {
72
+ journal = await (0, babysitter_sdk_1.loadJournal)(runDir);
73
+ }
74
+ catch {
75
+ // Journal may not exist yet
76
+ }
77
+ const lastLifecycleType = [...journal].reverse().find((e) => e.type === "RUN_COMPLETED" || e.type === "RUN_FAILED")?.type;
78
+ const pendingCount = journal.filter((e) => e.type === "EFFECT_REQUESTED").length
79
+ - journal.filter((e) => e.type === "EFFECT_RESOLVED").length;
80
+ let state;
81
+ if (lastLifecycleType === "RUN_COMPLETED")
82
+ state = "completed";
83
+ else if (lastLifecycleType === "RUN_FAILED")
84
+ state = "failed";
85
+ else if (pendingCount > 0)
86
+ state = "waiting";
87
+ else
88
+ state = "created";
89
+ summaries.push({
90
+ runId: metadata.runId ?? entry,
91
+ state,
92
+ processId: metadata.processId ?? "unknown",
93
+ createdAt: metadata.createdAt ?? "",
94
+ eventCount: journal.length,
95
+ pendingCount: Math.max(0, pendingCount),
96
+ prompt: metadata.prompt,
97
+ });
98
+ }
99
+ catch {
100
+ // Skip malformed runs
101
+ }
102
+ }
103
+ summaries.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
104
+ return summaries;
105
+ }
106
+ async function handleJsonMode(args) {
107
+ const runIdArg = args.runId ?? args.positional?.[0];
108
+ if (runIdArg) {
109
+ const runDir = (0, babysitter_sdk_1.getRunDir)(args.runsDir, runIdArg);
110
+ try {
111
+ const metadata = await (0, babysitter_sdk_1.readRunMetadata)(runDir);
112
+ const journal = await (0, babysitter_sdk_1.loadJournal)(runDir);
113
+ const index = await (0, babysitter_sdk_1.buildEffectIndex)({ runDir, events: journal });
114
+ const lastLifecycleType = [...journal].reverse().find((e) => e.type === "RUN_COMPLETED" || e.type === "RUN_FAILED")?.type;
115
+ const pendingCount = journal.filter((e) => e.type === "EFFECT_REQUESTED").length
116
+ - journal.filter((e) => e.type === "EFFECT_RESOLVED").length;
117
+ let state;
118
+ if (lastLifecycleType === "RUN_COMPLETED")
119
+ state = "completed";
120
+ else if (lastLifecycleType === "RUN_FAILED")
121
+ state = "failed";
122
+ else if (pendingCount > 0)
123
+ state = "waiting";
124
+ else
125
+ state = "created";
126
+ const allEffects = index.listEffects();
127
+ const effects = allEffects.map((rec) => ({
128
+ effectId: rec.effectId,
129
+ kind: rec.kind ?? "unknown",
130
+ status: rec.status === "resolved_ok" || rec.status === "resolved_error"
131
+ ? "completed" : rec.status === "requested" ? "pending" : "running",
132
+ title: rec.taskId ?? rec.effectId,
133
+ }));
134
+ console.log(JSON.stringify({
135
+ runId: runIdArg,
136
+ state,
137
+ processId: metadata.processId,
138
+ createdAt: metadata.createdAt,
139
+ events: journal.map((e) => ({
140
+ type: e.type,
141
+ recordedAt: e.recordedAt,
142
+ seq: e.seq,
143
+ })),
144
+ effects,
145
+ pendingCount: Math.max(0, pendingCount),
146
+ }, null, 2));
147
+ }
148
+ catch (err) {
149
+ console.error(`[tui] unable to read run ${runIdArg}: ${err.message}`);
150
+ return 1;
151
+ }
152
+ return 0;
153
+ }
154
+ const runs = await scanRunsForJson(args.runsDir);
155
+ console.log(JSON.stringify({
156
+ runs: runs.map((r) => ({
157
+ runId: r.runId,
158
+ state: r.state,
159
+ processId: r.processId,
160
+ createdAt: r.createdAt,
161
+ eventCount: r.eventCount,
162
+ pendingCount: r.pendingCount,
163
+ prompt: r.prompt,
164
+ })),
165
+ }, null, 2));
166
+ return 0;
167
+ }
168
+ // ---------------------------------------------------------------------------
169
+ // Main handler
170
+ // ---------------------------------------------------------------------------
171
+ async function handleTui(args) {
172
+ // JSON mode: non-interactive listing (retained for backward compat)
173
+ if (args.json) {
174
+ return handleJsonMode(args);
175
+ }
176
+ // Interactive TUI: redirect to agent-mux TUI
177
+ console.error("The tula TUI delegates to agent-mux.\n" +
178
+ "Use agent-mux TUI with babysitter plugins instead:\n" +
179
+ " npx agent-mux tui --workspace .\n" +
180
+ "\n" +
181
+ "For non-interactive run listing, use: tula tui --json");
182
+ return 1;
183
+ }
@@ -0,0 +1,4 @@
1
+ import type { HarnessParsedArgs } from "./args";
2
+ export declare function formatAgentHelp(_surface: "agent" | "human"): string;
3
+ export declare function executeAgentCliCommand(parsed: HarnessParsedArgs): Promise<number>;
4
+ //# sourceMappingURL=dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/cli/dispatch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAuBhD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAkCnE;AAED,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsHvF"}