@mcoda/mswarm 0.1.108 → 0.1.110

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 (157) hide show
  1. package/dist/codali-executor.d.ts.map +1 -1
  2. package/dist/codali-executor.js +17 -3
  3. package/dist/codali-executor.js.map +1 -1
  4. package/dist/runtime.d.ts.map +1 -1
  5. package/dist/runtime.js +55 -2
  6. package/dist/runtime.js.map +1 -1
  7. package/dist/vendor/codali/agents/AgentInventory.d.ts +56 -0
  8. package/dist/vendor/codali/agents/AgentInventory.d.ts.map +1 -0
  9. package/dist/vendor/codali/agents/AgentInventory.js +131 -0
  10. package/dist/vendor/codali/agents/RoleResolution.d.ts +49 -0
  11. package/dist/vendor/codali/agents/RoleResolution.d.ts.map +1 -0
  12. package/dist/vendor/codali/agents/RoleResolution.js +166 -0
  13. package/dist/vendor/codali/api/ChatCompletionsAdapter.d.ts +76 -0
  14. package/dist/vendor/codali/api/ChatCompletionsAdapter.d.ts.map +1 -0
  15. package/dist/vendor/codali/api/ChatCompletionsAdapter.js +54 -0
  16. package/dist/vendor/codali/api/CodaliApi.d.ts +78 -0
  17. package/dist/vendor/codali/api/CodaliApi.d.ts.map +1 -0
  18. package/dist/vendor/codali/api/CodaliApi.js +273 -0
  19. package/dist/vendor/codali/api/CodaliServer.d.ts +42 -0
  20. package/dist/vendor/codali/api/CodaliServer.d.ts.map +1 -0
  21. package/dist/vendor/codali/api/CodaliServer.js +118 -0
  22. package/dist/vendor/codali/cli/AskCommand.d.ts +66 -0
  23. package/dist/vendor/codali/cli/AskCommand.d.ts.map +1 -0
  24. package/dist/vendor/codali/cli/AskCommand.js +536 -0
  25. package/dist/vendor/codali/cli/AuthCommand.d.ts +19 -0
  26. package/dist/vendor/codali/cli/AuthCommand.d.ts.map +1 -0
  27. package/dist/vendor/codali/cli/AuthCommand.js +161 -0
  28. package/dist/vendor/codali/cli/ServeCommand.d.ts +5 -0
  29. package/dist/vendor/codali/cli/ServeCommand.d.ts.map +1 -0
  30. package/dist/vendor/codali/cli/ServeCommand.js +87 -0
  31. package/dist/vendor/codali/cli/ToolsCommand.d.ts +22 -0
  32. package/dist/vendor/codali/cli/ToolsCommand.d.ts.map +1 -0
  33. package/dist/vendor/codali/cli/ToolsCommand.js +208 -0
  34. package/dist/vendor/codali/cli.d.ts.map +1 -1
  35. package/dist/vendor/codali/cli.js +29 -1
  36. package/dist/vendor/codali/connectors/http/HttpToolDefinition.d.ts +74 -0
  37. package/dist/vendor/codali/connectors/http/HttpToolDefinition.d.ts.map +1 -0
  38. package/dist/vendor/codali/connectors/http/HttpToolDefinition.js +190 -0
  39. package/dist/vendor/codali/connectors/http/HttpToolSource.d.ts +18 -0
  40. package/dist/vendor/codali/connectors/http/HttpToolSource.d.ts.map +1 -0
  41. package/dist/vendor/codali/connectors/http/HttpToolSource.js +29 -0
  42. package/dist/vendor/codali/connectors/mcp/McpClient.d.ts +132 -0
  43. package/dist/vendor/codali/connectors/mcp/McpClient.d.ts.map +1 -0
  44. package/dist/vendor/codali/connectors/mcp/McpClient.js +215 -0
  45. package/dist/vendor/codali/connectors/mcp/McpServerRegistry.d.ts +75 -0
  46. package/dist/vendor/codali/connectors/mcp/McpServerRegistry.d.ts.map +1 -0
  47. package/dist/vendor/codali/connectors/mcp/McpServerRegistry.js +180 -0
  48. package/dist/vendor/codali/connectors/mcp/McpToolAdapter.d.ts +48 -0
  49. package/dist/vendor/codali/connectors/mcp/McpToolAdapter.d.ts.map +1 -0
  50. package/dist/vendor/codali/connectors/mcp/McpToolAdapter.js +101 -0
  51. package/dist/vendor/codali/connectors/mcp/McpToolSource.d.ts +27 -0
  52. package/dist/vendor/codali/connectors/mcp/McpToolSource.d.ts.map +1 -0
  53. package/dist/vendor/codali/connectors/mcp/McpToolSource.js +33 -0
  54. package/dist/vendor/codali/connectors/media/ImageGenerationTool.d.ts +43 -0
  55. package/dist/vendor/codali/connectors/media/ImageGenerationTool.d.ts.map +1 -0
  56. package/dist/vendor/codali/connectors/media/ImageGenerationTool.js +122 -0
  57. package/dist/vendor/codali/connectors/oauth/DeviceCodeAuth.d.ts +74 -0
  58. package/dist/vendor/codali/connectors/oauth/DeviceCodeAuth.d.ts.map +1 -0
  59. package/dist/vendor/codali/connectors/oauth/DeviceCodeAuth.js +153 -0
  60. package/dist/vendor/codali/docdex/DocdexClient.d.ts +2 -0
  61. package/dist/vendor/codali/docdex/DocdexClient.d.ts.map +1 -1
  62. package/dist/vendor/codali/docdex/DocdexClient.js +4 -0
  63. package/dist/vendor/codali/gateway/CodaliGateway.d.ts +51 -3
  64. package/dist/vendor/codali/gateway/CodaliGateway.d.ts.map +1 -1
  65. package/dist/vendor/codali/gateway/CodaliGateway.js +241 -3
  66. package/dist/vendor/codali/gateway/CodaliGatewayTypes.d.ts +34 -0
  67. package/dist/vendor/codali/gateway/CodaliGatewayTypes.d.ts.map +1 -1
  68. package/dist/vendor/codali/gateway/EvidenceNormalizer.d.ts.map +1 -1
  69. package/dist/vendor/codali/gateway/EvidenceNormalizer.js +98 -1
  70. package/dist/vendor/codali/gateway/Finalizer.d.ts +50 -0
  71. package/dist/vendor/codali/gateway/Finalizer.d.ts.map +1 -0
  72. package/dist/vendor/codali/gateway/Finalizer.js +79 -0
  73. package/dist/vendor/codali/gateway/GatewayPlanner.d.ts +13 -0
  74. package/dist/vendor/codali/gateway/GatewayPlanner.d.ts.map +1 -1
  75. package/dist/vendor/codali/gateway/GatewayPlanner.js +81 -16
  76. package/dist/vendor/codali/gateway/GatewayStateMachine.d.ts.map +1 -1
  77. package/dist/vendor/codali/gateway/GatewayStateMachine.js +6 -0
  78. package/dist/vendor/codali/gateway/GatewayTracer.d.ts +93 -0
  79. package/dist/vendor/codali/gateway/GatewayTracer.d.ts.map +1 -0
  80. package/dist/vendor/codali/gateway/GatewayTracer.js +214 -0
  81. package/dist/vendor/codali/gateway/LocalGatewayProvider.d.ts +59 -0
  82. package/dist/vendor/codali/gateway/LocalGatewayProvider.d.ts.map +1 -0
  83. package/dist/vendor/codali/gateway/LocalGatewayProvider.js +195 -0
  84. package/dist/vendor/codali/gateway/LocalGatewayTaskRunner.d.ts +79 -0
  85. package/dist/vendor/codali/gateway/LocalGatewayTaskRunner.d.ts.map +1 -0
  86. package/dist/vendor/codali/gateway/LocalGatewayTaskRunner.js +361 -0
  87. package/dist/vendor/codali/gateway/RelevanceJudge.d.ts +25 -0
  88. package/dist/vendor/codali/gateway/RelevanceJudge.d.ts.map +1 -0
  89. package/dist/vendor/codali/gateway/RelevanceJudge.js +124 -0
  90. package/dist/vendor/codali/gateway/ResponseSchema.d.ts +32 -0
  91. package/dist/vendor/codali/gateway/ResponseSchema.d.ts.map +1 -0
  92. package/dist/vendor/codali/gateway/ResponseSchema.js +120 -0
  93. package/dist/vendor/codali/gateway/TemporalContext.d.ts +36 -0
  94. package/dist/vendor/codali/gateway/TemporalContext.d.ts.map +1 -0
  95. package/dist/vendor/codali/gateway/TemporalContext.js +115 -0
  96. package/dist/vendor/codali/gateway/ToolCapabilityCompiler.d.ts +5 -0
  97. package/dist/vendor/codali/gateway/ToolCapabilityCompiler.d.ts.map +1 -1
  98. package/dist/vendor/codali/gateway/ToolCapabilityCompiler.js +27 -2
  99. package/dist/vendor/codali/gateway/ToolDescriptorSource.d.ts +6 -0
  100. package/dist/vendor/codali/gateway/ToolDescriptorSource.d.ts.map +1 -0
  101. package/dist/vendor/codali/gateway/ToolDescriptorSource.js +30 -0
  102. package/dist/vendor/codali/gateway/ToolExposure.d.ts +36 -0
  103. package/dist/vendor/codali/gateway/ToolExposure.d.ts.map +1 -0
  104. package/dist/vendor/codali/gateway/ToolExposure.js +154 -0
  105. package/dist/vendor/codali/index.d.ts +57 -0
  106. package/dist/vendor/codali/index.d.ts.map +1 -1
  107. package/dist/vendor/codali/index.js +45 -0
  108. package/dist/vendor/codali/providers/ClaudeCliProvider.d.ts +2 -0
  109. package/dist/vendor/codali/providers/ClaudeCliProvider.d.ts.map +1 -1
  110. package/dist/vendor/codali/providers/ClaudeCliProvider.js +2 -0
  111. package/dist/vendor/codali/providers/CodexCliProvider.d.ts +2 -0
  112. package/dist/vendor/codali/providers/CodexCliProvider.d.ts.map +1 -1
  113. package/dist/vendor/codali/providers/CodexCliProvider.js +2 -0
  114. package/dist/vendor/codali/providers/MswarmWorkerProvider.d.ts +2 -0
  115. package/dist/vendor/codali/providers/MswarmWorkerProvider.d.ts.map +1 -1
  116. package/dist/vendor/codali/providers/MswarmWorkerProvider.js +2 -0
  117. package/dist/vendor/codali/providers/OllamaRemoteProvider.d.ts +2 -0
  118. package/dist/vendor/codali/providers/OllamaRemoteProvider.d.ts.map +1 -1
  119. package/dist/vendor/codali/providers/OllamaRemoteProvider.js +2 -0
  120. package/dist/vendor/codali/providers/OpenAiCompatibleProvider.d.ts +2 -0
  121. package/dist/vendor/codali/providers/OpenAiCompatibleProvider.d.ts.map +1 -1
  122. package/dist/vendor/codali/providers/OpenAiCompatibleProvider.js +2 -0
  123. package/dist/vendor/codali/providers/ProviderTypes.d.ts +13 -0
  124. package/dist/vendor/codali/providers/ProviderTypes.d.ts.map +1 -1
  125. package/dist/vendor/codali/providers/ProviderTypes.js +1 -1
  126. package/dist/vendor/codali/runcontext/CredentialFile.d.ts +12 -0
  127. package/dist/vendor/codali/runcontext/CredentialFile.d.ts.map +1 -0
  128. package/dist/vendor/codali/runcontext/CredentialFile.js +81 -0
  129. package/dist/vendor/codali/runcontext/RunContextResolver.d.ts +126 -0
  130. package/dist/vendor/codali/runcontext/RunContextResolver.d.ts.map +1 -0
  131. package/dist/vendor/codali/runcontext/RunContextResolver.js +389 -0
  132. package/dist/vendor/codali/storage/CodaliDatasetPrivacyEngine.d.ts +1 -1
  133. package/dist/vendor/codali/storage/CodaliDatasetPrivacyEngine.d.ts.map +1 -1
  134. package/dist/vendor/codali/storage/CodaliDatasetPrivacyEngine.js +12 -0
  135. package/dist/vendor/codali/tools/ToolRegistry.d.ts +14 -1
  136. package/dist/vendor/codali/tools/ToolRegistry.d.ts.map +1 -1
  137. package/dist/vendor/codali/tools/ToolRegistry.js +38 -1
  138. package/dist/vendor/codali/tools/ToolTypes.d.ts +35 -0
  139. package/dist/vendor/codali/tools/ToolTypes.d.ts.map +1 -1
  140. package/dist/vendor/codali/tools/ToolTypes.js +21 -0
  141. package/dist/vendor/codali/tools/TruncateResult.d.ts +29 -0
  142. package/dist/vendor/codali/tools/TruncateResult.d.ts.map +1 -0
  143. package/dist/vendor/codali/tools/TruncateResult.js +91 -0
  144. package/dist/vendor/codali/tools/diff/DiffTool.d.ts.map +1 -1
  145. package/dist/vendor/codali/tools/diff/DiffTool.js +2 -0
  146. package/dist/vendor/codali/tools/docdex/DocdexTools.d.ts +21 -1
  147. package/dist/vendor/codali/tools/docdex/DocdexTools.d.ts.map +1 -1
  148. package/dist/vendor/codali/tools/docdex/DocdexTools.js +151 -17
  149. package/dist/vendor/codali/tools/filesystem/FileTools.d.ts.map +1 -1
  150. package/dist/vendor/codali/tools/filesystem/FileTools.js +8 -0
  151. package/dist/vendor/codali/tools/search/SearchTool.d.ts.map +1 -1
  152. package/dist/vendor/codali/tools/search/SearchTool.js +3 -1
  153. package/dist/vendor/codali/tools/shell/ShellTool.d.ts.map +1 -1
  154. package/dist/vendor/codali/tools/shell/ShellTool.js +2 -0
  155. package/package.json +3 -3
  156. package/scripts/stable-diffusion-cpp-auth-guard.py +475 -0
  157. package/scripts/stable-diffusion-cpp-openai-server.py +44 -0
@@ -0,0 +1,180 @@
1
+ import { ToolExecutionError } from "../../tools/ToolTypes.js";
2
+ import { McpClient, McpClientError, } from "./McpClient.js";
3
+ import { mcpToolsToDefinitions } from "./McpToolAdapter.js";
4
+ /**
5
+ * Owns the lifetime of every configured MCP server.
6
+ *
7
+ * Three properties matter more than features here:
8
+ *
9
+ * - **Isolation.** One broken server degrades its own tools to unavailable
10
+ * and never fails the run or affects another server.
11
+ * - **Boundedness.** Every call has a timeout, at most one retry, and
12
+ * competes for a global concurrency budget, so a slow server cannot
13
+ * monopolise a run.
14
+ * - **Cleanup.** stdio servers are child processes. They must be shut down
15
+ * even when a run fails, or the CLI leaves orphans behind.
16
+ */
17
+ /** Concurrent in-flight MCP calls across all servers. */
18
+ export const DEFAULT_MAX_CONCURRENT_CALLS = 4;
19
+ /** One retry, and only for transport-level failures. */
20
+ const MAX_CALL_ATTEMPTS = 2;
21
+ /** A minimal semaphore. Keeps concurrent MCP work inside a known bound. */
22
+ class Semaphore {
23
+ constructor(limit) {
24
+ this.limit = limit;
25
+ this.active = 0;
26
+ this.waiting = [];
27
+ }
28
+ async acquire() {
29
+ if (this.active < this.limit) {
30
+ this.active += 1;
31
+ return () => this.release();
32
+ }
33
+ await new Promise((resolve) => this.waiting.push(resolve));
34
+ this.active += 1;
35
+ return () => this.release();
36
+ }
37
+ release() {
38
+ this.active -= 1;
39
+ const next = this.waiting.shift();
40
+ if (next)
41
+ next();
42
+ }
43
+ }
44
+ export class McpServerRegistry {
45
+ constructor(options) {
46
+ this.options = options;
47
+ this.clients = new Map();
48
+ this.health = new Map();
49
+ this.discovered = false;
50
+ this.semaphore = new Semaphore(options.maxConcurrentCalls ?? DEFAULT_MAX_CONCURRENT_CALLS);
51
+ }
52
+ /**
53
+ * Connects to every enabled server and returns their tools as Codali tool
54
+ * definitions. Servers are contacted in parallel; a failure is recorded as
55
+ * unhealthy rather than thrown, so one bad entry in a tenant's config cannot
56
+ * take down the run.
57
+ */
58
+ async discoverTools() {
59
+ const definitions = [];
60
+ const results = await Promise.all(this.options.servers.map(async (definition) => {
61
+ if (definition.enabled === false) {
62
+ this.health.set(definition.name, {
63
+ name: definition.name,
64
+ status: "disabled",
65
+ toolCount: 0,
66
+ });
67
+ this.options.onEvent?.({
68
+ type: "server_skipped",
69
+ server: definition.name,
70
+ reason: "disabled",
71
+ });
72
+ return [];
73
+ }
74
+ const startedMs = Date.now();
75
+ const client = this.options.createClient
76
+ ? this.options.createClient(definition)
77
+ : new McpClient({ definition });
78
+ this.clients.set(definition.name, client);
79
+ let tools;
80
+ try {
81
+ tools = await client.listTools();
82
+ }
83
+ catch (error) {
84
+ const message = error instanceof McpClientError
85
+ ? error.message
86
+ : error instanceof Error
87
+ ? error.message
88
+ : String(error);
89
+ this.health.set(definition.name, {
90
+ name: definition.name,
91
+ status: "failed",
92
+ toolCount: 0,
93
+ error: message,
94
+ });
95
+ this.options.onEvent?.({
96
+ type: "server_failed",
97
+ server: definition.name,
98
+ error: message,
99
+ });
100
+ // Drop the client so a later call does not retry a dead connection.
101
+ this.clients.delete(definition.name);
102
+ await client.close();
103
+ return [];
104
+ }
105
+ const durationMs = Date.now() - startedMs;
106
+ this.health.set(definition.name, {
107
+ name: definition.name,
108
+ status: "connected",
109
+ toolCount: tools.length,
110
+ discoveryMs: durationMs,
111
+ });
112
+ this.options.onEvent?.({
113
+ type: "server_connected",
114
+ server: definition.name,
115
+ toolCount: tools.length,
116
+ durationMs,
117
+ });
118
+ return mcpToolsToDefinitions(tools, {
119
+ client: this.wrapClient(client),
120
+ server: definition.name,
121
+ capability: definition.name,
122
+ // Operator declaration only. Claiming read-only for an unvetted
123
+ // server would mislabel tools like `edit_file` and `move_file`, which
124
+ // is worse than admitting we do not know.
125
+ readOnly: definition.readOnly === true,
126
+ });
127
+ }));
128
+ for (const group of results)
129
+ definitions.push(...group);
130
+ this.discovered = true;
131
+ return definitions;
132
+ }
133
+ /**
134
+ * Wraps a client so every tool call is bounded by the concurrency budget and
135
+ * retried once on a transport failure. Retrying is safe here because Phase 2
136
+ * connectors are read-only.
137
+ */
138
+ wrapClient(client) {
139
+ const semaphore = this.semaphore;
140
+ const wrapped = Object.create(client);
141
+ wrapped.callTool = async (name, args) => {
142
+ const release = await semaphore.acquire();
143
+ try {
144
+ let lastError;
145
+ for (let attempt = 1; attempt <= MAX_CALL_ATTEMPTS; attempt += 1) {
146
+ try {
147
+ return await client.callTool(name, args);
148
+ }
149
+ catch (error) {
150
+ lastError = error;
151
+ const retryable = error instanceof McpClientError && error.retryable;
152
+ if (!retryable || attempt === MAX_CALL_ATTEMPTS)
153
+ break;
154
+ }
155
+ }
156
+ throw new ToolExecutionError("tool_execution_failed", lastError instanceof Error ? lastError.message : String(lastError), { retryable: false, details: { tool: name } });
157
+ }
158
+ finally {
159
+ release();
160
+ }
161
+ };
162
+ return wrapped;
163
+ }
164
+ healthReport() {
165
+ return [...this.health.values()];
166
+ }
167
+ get isDiscovered() {
168
+ return this.discovered;
169
+ }
170
+ /**
171
+ * Shuts down every connection. Must run even when a run fails: stdio servers
172
+ * are child processes and would otherwise be orphaned.
173
+ */
174
+ async close() {
175
+ const clients = [...this.clients.values()];
176
+ this.clients.clear();
177
+ await Promise.all(clients.map((client) => client.close()));
178
+ }
179
+ }
180
+ export const createMcpServerRegistry = (options) => new McpServerRegistry(options);
@@ -0,0 +1,48 @@
1
+ import type { ToolDefinition, ToolInputSchema } from "../../tools/ToolTypes.js";
2
+ import type { McpClient, McpToolDefinition } from "./McpClient.js";
3
+ /**
4
+ * Adapts MCP tools into Codali's own tool contract.
5
+ *
6
+ * The direction matters: MCP adapts *into* the neutral `ToolDefinition`, never
7
+ * the reverse. Codali's internals stay decoupled from MCP's evolution, and a
8
+ * built-in tool, a docdex tool and an MCP tool are indistinguishable to the
9
+ * planner and the executor.
10
+ */
11
+ /** `mcp:<server>:<tool>` — the namespace that keeps two servers from colliding. */
12
+ export declare const mcpToolName: (server: string, tool: string) => string;
13
+ export declare const parseMcpToolName: (name: string) => {
14
+ server: string;
15
+ tool: string;
16
+ } | undefined;
17
+ /**
18
+ * Normalizes an MCP input schema into Codali's `ToolInputSchema`.
19
+ *
20
+ * `additionalProperties` is forced open because the registry rejects unknown
21
+ * arguments by default, and MCP servers frequently omit properties they still
22
+ * accept. Rejecting a valid argument is worse here than passing an extra one
23
+ * through: the server validates its own inputs.
24
+ */
25
+ export declare const normalizeMcpInputSchema: (schema: Record<string, unknown> | undefined) => ToolInputSchema;
26
+ export interface McpToolAdapterOptions {
27
+ client: McpClient;
28
+ server: string;
29
+ /**
30
+ * Capability group the server's tools belong to, used for the orchestrator's
31
+ * first-stage selection. Defaults to the server name, which is usually what
32
+ * an operator means ("github", "jira").
33
+ */
34
+ capability?: string;
35
+ /**
36
+ * Whether these tools may mutate anything.
37
+ *
38
+ * Decided by Codali policy — an operator marking a connector read-only —
39
+ * never by the server's own `readOnlyHint`. A server asserting it is harmless
40
+ * is the party being constrained vouching for itself.
41
+ */
42
+ readOnly: boolean;
43
+ /** Result text beyond this is truncated before it reaches a model. */
44
+ maxOutputChars?: number;
45
+ }
46
+ export declare const mcpToolToDefinition: (tool: McpToolDefinition, options: McpToolAdapterOptions) => ToolDefinition;
47
+ export declare const mcpToolsToDefinitions: (tools: readonly McpToolDefinition[], options: McpToolAdapterOptions) => ToolDefinition[];
48
+ //# sourceMappingURL=McpToolAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"McpToolAdapter.d.ts","sourceRoot":"","sources":["../../../src/connectors/mcp/McpToolAdapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEhF,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnE;;;;;;;GAOG;AAEH,mFAAmF;AACnF,eAAO,MAAM,WAAW,GAAI,QAAQ,MAAM,EAAE,MAAM,MAAM,KAAG,MAClC,CAAC;AAE1B,eAAO,MAAM,gBAAgB,GAC3B,MAAM,MAAM,KACX;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAIrC,CAAC;AAKF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,GAClC,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,KAC1C,eAeF,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AA4BD,eAAO,MAAM,mBAAmB,GAC9B,MAAM,iBAAiB,EACvB,SAAS,qBAAqB,KAC7B,cAsCF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,OAAO,SAAS,iBAAiB,EAAE,EACnC,SAAS,qBAAqB,KAC7B,cAAc,EAA6D,CAAC"}
@@ -0,0 +1,101 @@
1
+ import { ToolExecutionError } from "../../tools/ToolTypes.js";
2
+ import { truncateToolResult } from "../../tools/TruncateResult.js";
3
+ /**
4
+ * Adapts MCP tools into Codali's own tool contract.
5
+ *
6
+ * The direction matters: MCP adapts *into* the neutral `ToolDefinition`, never
7
+ * the reverse. Codali's internals stay decoupled from MCP's evolution, and a
8
+ * built-in tool, a docdex tool and an MCP tool are indistinguishable to the
9
+ * planner and the executor.
10
+ */
11
+ /** `mcp:<server>:<tool>` — the namespace that keeps two servers from colliding. */
12
+ export const mcpToolName = (server, tool) => `mcp:${server}:${tool}`;
13
+ export const parseMcpToolName = (name) => {
14
+ const parts = name.split(":");
15
+ if (parts.length < 3 || parts[0] !== "mcp")
16
+ return undefined;
17
+ return { server: parts[1] ?? "", tool: parts.slice(2).join(":") };
18
+ };
19
+ const isRecord = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
20
+ /**
21
+ * Normalizes an MCP input schema into Codali's `ToolInputSchema`.
22
+ *
23
+ * `additionalProperties` is forced open because the registry rejects unknown
24
+ * arguments by default, and MCP servers frequently omit properties they still
25
+ * accept. Rejecting a valid argument is worse here than passing an extra one
26
+ * through: the server validates its own inputs.
27
+ */
28
+ export const normalizeMcpInputSchema = (schema) => {
29
+ if (!isRecord(schema)) {
30
+ return { type: "object", properties: {}, additionalProperties: true };
31
+ }
32
+ return {
33
+ ...schema,
34
+ type: "object",
35
+ properties: isRecord(schema.properties)
36
+ ? schema.properties
37
+ : {},
38
+ required: Array.isArray(schema.required)
39
+ ? schema.required.filter((entry) => typeof entry === "string")
40
+ : undefined,
41
+ additionalProperties: true,
42
+ };
43
+ };
44
+ const DEFAULT_MAX_OUTPUT_CHARS = 12000;
45
+ const tryParseJson = (value) => {
46
+ try {
47
+ return JSON.parse(value);
48
+ }
49
+ catch {
50
+ return undefined;
51
+ }
52
+ };
53
+ const truncate = (value, limit) => value.length > limit
54
+ ? `${value.slice(0, limit)}\n…[truncated ${value.length - limit} characters]`
55
+ : value;
56
+ /**
57
+ * Builds a description the planner can act on. MCP descriptions are sometimes
58
+ * absent, in which case the tool name is all we have — say so plainly rather
59
+ * than inventing capability the tool may not have.
60
+ */
61
+ const describeMcpTool = (tool, server) => {
62
+ const base = tool.description?.trim();
63
+ if (base)
64
+ return base;
65
+ return `${tool.name} (provided by the ${server} MCP server; no description supplied).`;
66
+ };
67
+ export const mcpToolToDefinition = (tool, options) => {
68
+ const maxOutputChars = options.maxOutputChars ?? DEFAULT_MAX_OUTPUT_CHARS;
69
+ const qualified = mcpToolName(options.server, tool.name);
70
+ return {
71
+ name: qualified,
72
+ description: describeMcpTool(tool, options.server),
73
+ inputSchema: normalizeMcpInputSchema(tool.inputSchema),
74
+ outputSchema: tool.outputSchema,
75
+ readOnly: options.readOnly,
76
+ capability: options.capability ?? options.server,
77
+ handler: async (args) => {
78
+ const result = await options.client.callTool(tool.name, args);
79
+ if (!result.ok) {
80
+ // Surface as a tool failure so the runner records it and the model is
81
+ // told, rather than passing an error string off as a result.
82
+ throw new ToolExecutionError("tool_execution_failed", result.text || `MCP tool ${qualified} reported an error.`, { retryable: false, details: { server: options.server, tool: tool.name } });
83
+ }
84
+ // Structural where possible: an oversized list keeps whole items so the
85
+ // model receives valid JSON, not a document cut mid-token.
86
+ const structured = result.structured ?? tryParseJson(result.text);
87
+ const trimmed = structured !== undefined
88
+ ? truncateToolResult(structured, result.text, maxOutputChars)
89
+ : { text: truncate(result.text, maxOutputChars), truncated: false };
90
+ return {
91
+ output: trimmed.text || "(the tool returned no content)",
92
+ // The *parsed* payload, not the MCP envelope. Evidence normalization
93
+ // reads this to turn each returned record into its own evidence item;
94
+ // handed `{content:[{type:"text",…}]}` it finds no records and emits a
95
+ // single "returned structured data" placeholder instead.
96
+ data: structured ?? result.raw,
97
+ };
98
+ },
99
+ };
100
+ };
101
+ export const mcpToolsToDefinitions = (tools, options) => tools.map((tool) => mcpToolToDefinition(tool, options));
@@ -0,0 +1,27 @@
1
+ import { createMcpServerRegistry, type McpServerRegistry } from "./McpServerRegistry.js";
2
+ import type { McpServerHealth } from "./McpServerRegistry.js";
3
+ import type { RunContext } from "../../runcontext/RunContextResolver.js";
4
+ import type { ToolRegistry } from "../../tools/ToolRegistry.js";
5
+ /**
6
+ * Connects a run's configured MCP servers and registers what they expose into
7
+ * the run's `ToolRegistry`.
8
+ *
9
+ * Registration goes into the *existing* registry rather than a parallel store:
10
+ * one source of truth means the planner cannot see a schema the executor would
11
+ * not honour, no matter where the tool came from.
12
+ */
13
+ export interface McpAttachResult {
14
+ registry?: McpServerRegistry;
15
+ health: McpServerHealth[];
16
+ registered: string[];
17
+ warnings: string[];
18
+ }
19
+ export interface McpAttachOptions {
20
+ context: RunContext;
21
+ toolRegistry: ToolRegistry;
22
+ maxConcurrentCalls?: number;
23
+ /** Injected in tests. */
24
+ createRegistry?: typeof createMcpServerRegistry;
25
+ }
26
+ export declare const attachMcpTools: (options: McpAttachOptions) => Promise<McpAttachResult>;
27
+ //# sourceMappingURL=McpToolSource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"McpToolSource.d.ts","sourceRoot":"","sources":["../../../src/connectors/mcp/McpToolSource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,KAAK,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AACzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;;;;;;GAOG;AAEH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,UAAU,CAAC;IACpB,YAAY,EAAE,YAAY,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yBAAyB;IACzB,cAAc,CAAC,EAAE,OAAO,uBAAuB,CAAC;CACjD;AAED,eAAO,MAAM,cAAc,GACzB,SAAS,gBAAgB,KACxB,OAAO,CAAC,eAAe,CAuCzB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { createMcpServerRegistry } from "./McpServerRegistry.js";
2
+ export const attachMcpTools = async (options) => {
3
+ const servers = options.context.mcpServers ?? [];
4
+ if (servers.length === 0) {
5
+ return { health: [], registered: [], warnings: [] };
6
+ }
7
+ const warnings = [];
8
+ const registry = (options.createRegistry ?? createMcpServerRegistry)({
9
+ servers,
10
+ maxConcurrentCalls: options.maxConcurrentCalls,
11
+ });
12
+ const definitions = await registry.discoverTools();
13
+ const registered = [];
14
+ for (const definition of definitions) {
15
+ try {
16
+ options.toolRegistry.register(definition);
17
+ registered.push(definition.name);
18
+ }
19
+ catch (error) {
20
+ // A duplicate name means two servers claimed the same namespaced tool,
21
+ // which the `mcp:<server>:<tool>` scheme should prevent. Report rather
22
+ // than crash, and keep the first registration.
23
+ warnings.push(`mcp_tool_registration_failed:${definition.name}:${error instanceof Error ? error.message : String(error)}`);
24
+ }
25
+ }
26
+ const health = registry.healthReport();
27
+ for (const entry of health) {
28
+ if (entry.status === "failed") {
29
+ warnings.push(`mcp_server_unavailable:${entry.name}:${entry.error ?? "unknown"}`);
30
+ }
31
+ }
32
+ return { registry, health, registered, warnings };
33
+ };
@@ -0,0 +1,43 @@
1
+ import type { ToolDefinition } from "../../tools/ToolTypes.js";
2
+ /**
3
+ * Image generation, as an ordinary tool.
4
+ *
5
+ * The original design gave media its own orchestration route, which forced
6
+ * every request to be classified as "media or not" up front and duplicated the
7
+ * planning path. It is simpler and more accurate to treat generation as a tool
8
+ * the orchestrator may call: "generate an image of a puppy" becomes a plan with
9
+ * one task, exactly like any other single-source question, and a request that
10
+ * needs both research *and* an image needs no special case at all.
11
+ *
12
+ * The tool returns an `ArtifactRef`. Image bytes are written to disk and
13
+ * referenced — never inlined into evidence or an answer, which would blow the
14
+ * context budget and put base64 in the trace.
15
+ */
16
+ export interface ImageGenerationConfig {
17
+ /** OpenAI-compatible `/v1/images/generations` endpoint. */
18
+ baseUrl: string;
19
+ model: string;
20
+ apiKey?: string;
21
+ /** Where artifacts are written. Defaults to `<workspace>/.codali/artifacts`. */
22
+ artifactDir?: string;
23
+ timeoutMs?: number;
24
+ size?: string;
25
+ }
26
+ export interface ImageToolOptions {
27
+ config: ImageGenerationConfig;
28
+ workspaceRoot: string;
29
+ runId?: string;
30
+ fetchImpl?: typeof fetch;
31
+ /** Called for each artifact so the gateway can surface it in the result. */
32
+ onArtifact?: (artifact: {
33
+ id: string;
34
+ type: string;
35
+ path: string;
36
+ mimeType: string;
37
+ model: string;
38
+ prompt: string;
39
+ }) => void;
40
+ }
41
+ export declare const IMAGE_TOOL_NAME = "media_generate_image";
42
+ export declare const createImageGenerationTool: (options: ImageToolOptions) => ToolDefinition;
43
+ //# sourceMappingURL=ImageGenerationTool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImageGenerationTool.d.ts","sourceRoot":"","sources":["../../../src/connectors/media/ImageGenerationTool.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,qBAAqB;IACpC,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA0BD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,qBAAqB,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE;QACtB,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,KAAK,IAAI,CAAC;CACZ;AAED,eAAO,MAAM,eAAe,yBAAyB,CAAC;AAEtD,eAAO,MAAM,yBAAyB,GAAI,SAAS,gBAAgB,KAAG,cAgIrE,CAAC"}
@@ -0,0 +1,122 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { mkdir, writeFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { ToolExecutionError } from "../../tools/ToolTypes.js";
5
+ const DEFAULT_TIMEOUT_MS = 180000;
6
+ const DEFAULT_SIZE = "512x512";
7
+ const isRecord = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
8
+ /**
9
+ * Extracts image bytes from an OpenAI-compatible response. Servers return
10
+ * either `b64_json` or a `url`; both shapes are handled because local
11
+ * stable-diffusion servers and hosted APIs differ here.
12
+ */
13
+ const readImagePayload = (payload) => {
14
+ if (!isRecord(payload))
15
+ return undefined;
16
+ const data = payload.data;
17
+ if (!Array.isArray(data) || data.length === 0)
18
+ return undefined;
19
+ const first = data[0];
20
+ if (!isRecord(first))
21
+ return undefined;
22
+ const b64 = typeof first.b64_json === "string" ? first.b64_json : undefined;
23
+ const url = typeof first.url === "string" ? first.url : undefined;
24
+ return b64 || url ? { b64, url } : undefined;
25
+ };
26
+ export const IMAGE_TOOL_NAME = "media_generate_image";
27
+ export const createImageGenerationTool = (options) => {
28
+ const { config } = options;
29
+ const fetchImpl = options.fetchImpl ?? fetch;
30
+ return {
31
+ name: IMAGE_TOOL_NAME,
32
+ description: "Generate an image from a text prompt. Returns the path to the written image file, not the image itself. Use for any request to draw, render, or generate a picture.",
33
+ capability: "media",
34
+ // Generation writes a file, but only inside the run's own artifact
35
+ // directory — it cannot touch the workspace or anything the user owns.
36
+ readOnly: true,
37
+ inputSchema: {
38
+ type: "object",
39
+ required: ["prompt"],
40
+ properties: {
41
+ prompt: { type: "string", minLength: 1 },
42
+ size: { type: "string" },
43
+ },
44
+ },
45
+ handler: async (args) => {
46
+ const record = isRecord(args) ? args : {};
47
+ const prompt = typeof record.prompt === "string" ? record.prompt.trim() : "";
48
+ if (!prompt) {
49
+ throw new ToolExecutionError("tool_invalid_args", "An image prompt is required.", {
50
+ retryable: false,
51
+ });
52
+ }
53
+ const controller = new AbortController();
54
+ const timer = setTimeout(() => controller.abort(), config.timeoutMs ?? DEFAULT_TIMEOUT_MS);
55
+ let response;
56
+ try {
57
+ response = await fetchImpl(new URL("images/generations", config.baseUrl.endsWith("/")
58
+ ? config.baseUrl
59
+ : `${config.baseUrl}/`).toString(), {
60
+ method: "POST",
61
+ headers: {
62
+ "Content-Type": "application/json",
63
+ ...(config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}),
64
+ },
65
+ body: JSON.stringify({
66
+ model: config.model,
67
+ prompt,
68
+ n: 1,
69
+ size: typeof record.size === "string" ? record.size : (config.size ?? DEFAULT_SIZE),
70
+ response_format: "b64_json",
71
+ }),
72
+ signal: controller.signal,
73
+ });
74
+ }
75
+ catch (error) {
76
+ throw new ToolExecutionError("tool_execution_failed", `Image generation request failed: ${error instanceof Error ? error.message : String(error)}`, { retryable: true });
77
+ }
78
+ finally {
79
+ clearTimeout(timer);
80
+ }
81
+ if (!response.ok) {
82
+ throw new ToolExecutionError("tool_execution_failed", `Image generation returned HTTP ${response.status}.`, { retryable: response.status >= 500, details: { status: response.status } });
83
+ }
84
+ const payload = await response.json();
85
+ const image = readImagePayload(payload);
86
+ if (!image) {
87
+ throw new ToolExecutionError("tool_execution_failed", "Image generation returned no image data.", { retryable: false });
88
+ }
89
+ let bytes;
90
+ if (image.b64) {
91
+ bytes = Buffer.from(image.b64, "base64");
92
+ }
93
+ else {
94
+ const fetched = await fetchImpl(image.url);
95
+ if (!fetched.ok) {
96
+ throw new ToolExecutionError("tool_execution_failed", `Could not download the generated image (HTTP ${fetched.status}).`, { retryable: true });
97
+ }
98
+ bytes = Buffer.from(await fetched.arrayBuffer());
99
+ }
100
+ const artifactDir = config.artifactDir ??
101
+ path.join(options.workspaceRoot, ".codali", "artifacts", options.runId ?? "run");
102
+ await mkdir(artifactDir, { recursive: true });
103
+ const id = `img-${randomUUID()}`;
104
+ const filePath = path.join(artifactDir, `${id}.png`);
105
+ await writeFile(filePath, bytes);
106
+ options.onArtifact?.({
107
+ id,
108
+ type: "image",
109
+ path: filePath,
110
+ mimeType: "image/png",
111
+ model: config.model,
112
+ prompt,
113
+ });
114
+ return {
115
+ // The path, not the bytes: inlining base64 would blow the context
116
+ // budget and put megabytes of noise in the trace.
117
+ output: `Generated an image and wrote it to ${filePath}`,
118
+ data: { artifactId: id, path: filePath, mimeType: "image/png", prompt },
119
+ };
120
+ },
121
+ };
122
+ };
@@ -0,0 +1,74 @@
1
+ /**
2
+ * OAuth 2.0 device authorization grant (RFC 8628).
3
+ *
4
+ * The right flow for a CLI. Authorization-code needs a redirect URI and a local
5
+ * web server; client-credentials gets app-only permissions, which for
6
+ * "summarize *my* mail" would mean reading the entire tenant — both overreach
7
+ * and a different consent conversation.
8
+ *
9
+ * Device code needs neither: the user is shown a short code, approves in a
10
+ * browser on any device, and we receive an access token plus a refresh token.
11
+ * The refresh token is what gets stored; access tokens live about an hour and
12
+ * are minted on demand.
13
+ */
14
+ export interface DeviceCodeStartResult {
15
+ deviceCode: string;
16
+ userCode: string;
17
+ verificationUri: string;
18
+ expiresInSeconds: number;
19
+ intervalSeconds: number;
20
+ message?: string;
21
+ }
22
+ export interface DeviceCodeTokens {
23
+ accessToken: string;
24
+ refreshToken?: string;
25
+ expiresInSeconds: number;
26
+ scope?: string;
27
+ tokenType: string;
28
+ }
29
+ export interface DeviceCodeConfig {
30
+ deviceCodeUrl: string;
31
+ tokenUrl: string;
32
+ clientId: string;
33
+ scope: string;
34
+ }
35
+ export declare class DeviceCodeError extends Error {
36
+ readonly code: string;
37
+ readonly description?: string;
38
+ constructor(code: string, description?: string);
39
+ }
40
+ export declare const startDeviceCode: (config: DeviceCodeConfig, fetchImpl?: typeof fetch) => Promise<DeviceCodeStartResult>;
41
+ export interface PollOptions {
42
+ onPending?: (secondsRemaining: number) => void;
43
+ now?: () => number;
44
+ sleep?: (ms: number) => Promise<void>;
45
+ }
46
+ /**
47
+ * Polls until the user approves, declines, or the code expires.
48
+ *
49
+ * `authorization_pending` is the normal state and must not be treated as an
50
+ * error; `slow_down` requires backing off, and ignoring it gets the request
51
+ * throttled.
52
+ */
53
+ export declare const pollForDeviceCodeTokens: (config: DeviceCodeConfig, start: DeviceCodeStartResult, fetchImpl?: typeof fetch, options?: PollOptions) => Promise<DeviceCodeTokens>;
54
+ /**
55
+ * Exchanges a stored refresh token for a fresh access token.
56
+ *
57
+ * Microsoft rotates refresh tokens, so the response may carry a new one; a
58
+ * caller that ignores it will find its stored token dead after the old one's
59
+ * sliding window closes.
60
+ */
61
+ export declare const refreshAccessToken: (config: Omit<DeviceCodeConfig, "deviceCodeUrl">, refreshToken: string, fetchImpl?: typeof fetch) => Promise<DeviceCodeTokens>;
62
+ /** Microsoft identity platform endpoints for a tenant. */
63
+ export declare const microsoftEndpoints: (tenantId: string) => {
64
+ deviceCodeUrl: string;
65
+ tokenUrl: string;
66
+ };
67
+ /**
68
+ * Delegated Graph scopes Codali asks for, matching what okacam's
69
+ * `microsoft-integration-service` already requests. `offline_access` is what
70
+ * yields a refresh token — without it the grant is good for one hour and then
71
+ * gone.
72
+ */
73
+ export declare const MICROSOFT_GRAPH_SCOPES: string;
74
+ //# sourceMappingURL=DeviceCodeAuth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeviceCodeAuth.d.ts","sourceRoot":"","sources":["../../../src/connectors/oauth/DeviceCodeAuth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;gBAElB,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM;CAM/C;AAQD,eAAO,MAAM,eAAe,GAC1B,QAAQ,gBAAgB,EACxB,YAAW,OAAO,KAAa,KAC9B,OAAO,CAAC,qBAAqB,CAyB/B,CAAC;AAWF,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,CAAC,gBAAgB,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,GAClC,QAAQ,gBAAgB,EACxB,OAAO,qBAAqB,EAC5B,YAAW,OAAO,KAAa,EAC/B,UAAS,WAAgB,KACxB,OAAO,CAAC,gBAAgB,CA+C1B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,IAAI,CAAC,gBAAgB,EAAE,eAAe,CAAC,EAC/C,cAAc,MAAM,EACpB,YAAW,OAAO,KAAa,KAC9B,OAAO,CAAC,gBAAgB,CAsB1B,CAAC;AAEF,0DAA0D;AAC1D,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM;;;CAGjD,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,QASxB,CAAC"}