@soulcraft/sdk 1.6.2 → 2.0.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 (176) hide show
  1. package/dist/client/create-client-sdk.d.ts +16 -2
  2. package/dist/client/create-client-sdk.d.ts.map +1 -1
  3. package/dist/client/create-client-sdk.js +2 -7
  4. package/dist/client/create-client-sdk.js.map +1 -1
  5. package/dist/client/index.d.ts +48 -37
  6. package/dist/client/index.d.ts.map +1 -1
  7. package/dist/client/index.js +61 -42
  8. package/dist/client/index.js.map +1 -1
  9. package/dist/client/namespace-proxy.d.ts +108 -0
  10. package/dist/client/namespace-proxy.d.ts.map +1 -0
  11. package/dist/client/namespace-proxy.js +151 -0
  12. package/dist/client/namespace-proxy.js.map +1 -0
  13. package/dist/index.d.ts +3 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/modules/app-context/index.d.ts +214 -0
  17. package/dist/modules/app-context/index.d.ts.map +1 -0
  18. package/dist/modules/app-context/index.js +569 -0
  19. package/dist/modules/app-context/index.js.map +1 -0
  20. package/dist/modules/auth/products.d.ts +208 -0
  21. package/dist/modules/auth/products.d.ts.map +1 -0
  22. package/dist/modules/auth/products.js +165 -0
  23. package/dist/modules/auth/products.js.map +1 -0
  24. package/dist/namespaces.d.ts +2942 -0
  25. package/dist/namespaces.d.ts.map +1 -0
  26. package/dist/namespaces.js +37 -0
  27. package/dist/namespaces.js.map +1 -0
  28. package/dist/rpc.d.ts +156 -0
  29. package/dist/rpc.d.ts.map +1 -0
  30. package/dist/rpc.js +26 -0
  31. package/dist/rpc.js.map +1 -0
  32. package/dist/server/create-sdk.d.ts.map +1 -1
  33. package/dist/server/create-sdk.js +3 -13
  34. package/dist/server/create-sdk.js.map +1 -1
  35. package/dist/server/handlers/annotations.d.ts +52 -0
  36. package/dist/server/handlers/annotations.d.ts.map +1 -0
  37. package/dist/server/handlers/annotations.js +204 -0
  38. package/dist/server/handlers/annotations.js.map +1 -0
  39. package/dist/server/handlers/auth.d.ts +53 -0
  40. package/dist/server/handlers/auth.d.ts.map +1 -0
  41. package/dist/server/handlers/auth.js +66 -0
  42. package/dist/server/handlers/auth.js.map +1 -0
  43. package/dist/server/handlers/certification.d.ts +32 -0
  44. package/dist/server/handlers/certification.d.ts.map +1 -0
  45. package/dist/server/handlers/certification.js +253 -0
  46. package/dist/server/handlers/certification.js.map +1 -0
  47. package/dist/server/handlers/chat/conversations.d.ts +91 -0
  48. package/dist/server/handlers/chat/conversations.d.ts.map +1 -0
  49. package/dist/server/handlers/chat/conversations.js +314 -0
  50. package/dist/server/handlers/chat/conversations.js.map +1 -0
  51. package/dist/server/handlers/chat/delegator.d.ts +144 -0
  52. package/dist/server/handlers/chat/delegator.d.ts.map +1 -0
  53. package/dist/server/handlers/chat/delegator.js +431 -0
  54. package/dist/server/handlers/chat/delegator.js.map +1 -0
  55. package/dist/server/handlers/chat/engine.d.ts +81 -0
  56. package/dist/server/handlers/chat/engine.d.ts.map +1 -0
  57. package/dist/server/handlers/chat/engine.js +442 -0
  58. package/dist/server/handlers/chat/engine.js.map +1 -0
  59. package/dist/server/handlers/chat/executor.d.ts +65 -0
  60. package/dist/server/handlers/chat/executor.d.ts.map +1 -0
  61. package/dist/server/handlers/chat/executor.js +375 -0
  62. package/dist/server/handlers/chat/executor.js.map +1 -0
  63. package/dist/server/handlers/chat/index.d.ts +62 -0
  64. package/dist/server/handlers/chat/index.d.ts.map +1 -0
  65. package/dist/server/handlers/chat/index.js +182 -0
  66. package/dist/server/handlers/chat/index.js.map +1 -0
  67. package/dist/server/handlers/chat/memory.d.ts +91 -0
  68. package/dist/server/handlers/chat/memory.d.ts.map +1 -0
  69. package/dist/server/handlers/chat/memory.js +293 -0
  70. package/dist/server/handlers/chat/memory.js.map +1 -0
  71. package/dist/server/handlers/chat/models.d.ts +180 -0
  72. package/dist/server/handlers/chat/models.d.ts.map +1 -0
  73. package/dist/server/handlers/chat/models.js +304 -0
  74. package/dist/server/handlers/chat/models.js.map +1 -0
  75. package/dist/server/handlers/chat/planner.d.ts +116 -0
  76. package/dist/server/handlers/chat/planner.d.ts.map +1 -0
  77. package/dist/server/handlers/chat/planner.js +344 -0
  78. package/dist/server/handlers/chat/planner.js.map +1 -0
  79. package/dist/server/handlers/chat/types.d.ts +500 -0
  80. package/dist/server/handlers/chat/types.d.ts.map +1 -0
  81. package/dist/server/handlers/chat/types.js +11 -0
  82. package/dist/server/handlers/chat/types.js.map +1 -0
  83. package/dist/server/handlers/collections.d.ts +67 -0
  84. package/dist/server/handlers/collections.d.ts.map +1 -0
  85. package/dist/server/handlers/collections.js +484 -0
  86. package/dist/server/handlers/collections.js.map +1 -0
  87. package/dist/server/handlers/commerce.d.ts +106 -0
  88. package/dist/server/handlers/commerce.d.ts.map +1 -0
  89. package/dist/server/handlers/commerce.js +62 -0
  90. package/dist/server/handlers/commerce.js.map +1 -0
  91. package/dist/server/handlers/config.d.ts +112 -0
  92. package/dist/server/handlers/config.d.ts.map +1 -0
  93. package/dist/server/handlers/config.js +122 -0
  94. package/dist/server/handlers/config.js.map +1 -0
  95. package/dist/server/handlers/export.d.ts +72 -0
  96. package/dist/server/handlers/export.d.ts.map +1 -0
  97. package/dist/server/handlers/export.js +175 -0
  98. package/dist/server/handlers/export.js.map +1 -0
  99. package/dist/server/handlers/formats.d.ts +77 -0
  100. package/dist/server/handlers/formats.d.ts.map +1 -0
  101. package/dist/server/handlers/formats.js +65 -0
  102. package/dist/server/handlers/formats.js.map +1 -0
  103. package/dist/server/handlers/graph.d.ts +31 -0
  104. package/dist/server/handlers/graph.d.ts.map +1 -0
  105. package/dist/server/handlers/graph.js +490 -0
  106. package/dist/server/handlers/graph.js.map +1 -0
  107. package/dist/server/handlers/import.d.ts +96 -0
  108. package/dist/server/handlers/import.d.ts.map +1 -0
  109. package/dist/server/handlers/import.js +108 -0
  110. package/dist/server/handlers/import.js.map +1 -0
  111. package/dist/server/handlers/index.d.ts +68 -0
  112. package/dist/server/handlers/index.d.ts.map +1 -0
  113. package/dist/server/handlers/index.js +71 -0
  114. package/dist/server/handlers/index.js.map +1 -0
  115. package/dist/server/handlers/media.d.ts +76 -0
  116. package/dist/server/handlers/media.d.ts.map +1 -0
  117. package/dist/server/handlers/media.js +53 -0
  118. package/dist/server/handlers/media.js.map +1 -0
  119. package/dist/server/handlers/project.d.ts +45 -0
  120. package/dist/server/handlers/project.d.ts.map +1 -0
  121. package/dist/server/handlers/project.js +181 -0
  122. package/dist/server/handlers/project.js.map +1 -0
  123. package/dist/server/handlers/publish.d.ts +102 -0
  124. package/dist/server/handlers/publish.d.ts.map +1 -0
  125. package/dist/server/handlers/publish.js +130 -0
  126. package/dist/server/handlers/publish.js.map +1 -0
  127. package/dist/server/handlers/pulse.d.ts +39 -0
  128. package/dist/server/handlers/pulse.d.ts.map +1 -0
  129. package/dist/server/handlers/pulse.js +78 -0
  130. package/dist/server/handlers/pulse.js.map +1 -0
  131. package/dist/server/handlers/realtime.d.ts +55 -0
  132. package/dist/server/handlers/realtime.d.ts.map +1 -0
  133. package/dist/server/handlers/realtime.js +49 -0
  134. package/dist/server/handlers/realtime.js.map +1 -0
  135. package/dist/server/handlers/search.d.ts +21 -0
  136. package/dist/server/handlers/search.d.ts.map +1 -0
  137. package/dist/server/handlers/search.js +237 -0
  138. package/dist/server/handlers/search.js.map +1 -0
  139. package/dist/server/handlers/session.d.ts +47 -0
  140. package/dist/server/handlers/session.d.ts.map +1 -0
  141. package/dist/server/handlers/session.js +286 -0
  142. package/dist/server/handlers/session.js.map +1 -0
  143. package/dist/server/handlers/settings.d.ts +97 -0
  144. package/dist/server/handlers/settings.d.ts.map +1 -0
  145. package/dist/server/handlers/settings.js +131 -0
  146. package/dist/server/handlers/settings.js.map +1 -0
  147. package/dist/server/handlers/workspace.d.ts +78 -0
  148. package/dist/server/handlers/workspace.d.ts.map +1 -0
  149. package/dist/server/handlers/workspace.js +270 -0
  150. package/dist/server/handlers/workspace.js.map +1 -0
  151. package/dist/server/hono-router.d.ts +66 -0
  152. package/dist/server/hono-router.d.ts.map +1 -0
  153. package/dist/server/hono-router.js +203 -0
  154. package/dist/server/hono-router.js.map +1 -0
  155. package/dist/server/index.d.ts +29 -19
  156. package/dist/server/index.d.ts.map +1 -1
  157. package/dist/server/index.js +33 -19
  158. package/dist/server/index.js.map +1 -1
  159. package/dist/server/namespace-router.d.ts +204 -0
  160. package/dist/server/namespace-router.d.ts.map +1 -0
  161. package/dist/server/namespace-router.js +262 -0
  162. package/dist/server/namespace-router.js.map +1 -0
  163. package/dist/transports/http-namespace.d.ts +210 -0
  164. package/dist/transports/http-namespace.d.ts.map +1 -0
  165. package/dist/transports/http-namespace.js +514 -0
  166. package/dist/transports/http-namespace.js.map +1 -0
  167. package/dist/transports/workshop.d.ts +173 -0
  168. package/dist/transports/workshop.d.ts.map +1 -0
  169. package/dist/transports/workshop.js +307 -0
  170. package/dist/transports/workshop.js.map +1 -0
  171. package/dist/types.d.ts +65 -67
  172. package/dist/types.d.ts.map +1 -1
  173. package/dist/types.js +7 -3
  174. package/dist/types.js.map +1 -1
  175. package/docs/ADR-004-product-registry.md +108 -0
  176. package/package.json +1 -1
@@ -0,0 +1,304 @@
1
+ /**
2
+ * @module server/handlers/chat/models
3
+ * @description Model routing, complexity analysis, and cost estimation for
4
+ * the tiered AI strategy.
5
+ *
6
+ * The chat engine uses a multi-model approach:
7
+ * - **Plan Mode ON**: Opus (deep analysis, planning) → Haiku (fast execution)
8
+ * - **Plan Mode OFF**: Sonnet (triage, synthesis) → Haiku (task execution)
9
+ *
10
+ * Complexity analysis scores each user message on 6 signals (multi-file ops,
11
+ * architecture keywords, question patterns, single-tool hints, entity count,
12
+ * conditional logic) to decide whether to recommend Plan Mode.
13
+ *
14
+ * All model IDs and pricing are configurable — products can override defaults
15
+ * via the {@link ModelSelector} interface in `types.ts`.
16
+ */
17
+ /**
18
+ * Default model catalog — Anthropic Claude models with current pricing.
19
+ *
20
+ * Products can supplement this with additional models. The engine only needs
21
+ * model IDs; it doesn't validate against this catalog at runtime.
22
+ */
23
+ export const DEFAULT_MODELS = {
24
+ 'claude-opus-4-5-20251101': {
25
+ id: 'claude-opus-4-5-20251101',
26
+ name: 'Claude Opus 4.5',
27
+ shortName: 'Opus 4.5',
28
+ pricing: { input: 15.00, output: 75.00, cacheHit: 1.50 },
29
+ supportsThinking: true,
30
+ maxTokens: 32000,
31
+ bestFor: ['complex architecture', 'deep reasoning', 'creative tasks'],
32
+ },
33
+ 'claude-sonnet-4-20250514': {
34
+ id: 'claude-sonnet-4-20250514',
35
+ name: 'Claude Sonnet 4',
36
+ shortName: 'Sonnet 4',
37
+ pricing: { input: 3.00, output: 15.00, cacheHit: 0.30 },
38
+ supportsThinking: true,
39
+ maxTokens: 16000,
40
+ bestFor: ['planning', 'reasoning', 'analysis', 'multi-step tasks'],
41
+ },
42
+ 'claude-3-5-haiku-latest': {
43
+ id: 'claude-3-5-haiku-latest',
44
+ name: 'Claude Haiku 3.5',
45
+ shortName: 'Haiku 3.5',
46
+ pricing: { input: 1.00, output: 5.00, cacheHit: 0.10 },
47
+ supportsThinking: true,
48
+ maxTokens: 8192,
49
+ bestFor: ['implementation', 'simple tasks', 'fast responses'],
50
+ },
51
+ 'claude-haiku-3-20240307': {
52
+ id: 'claude-haiku-3-20240307',
53
+ name: 'Claude Haiku 3',
54
+ shortName: 'Haiku 3',
55
+ pricing: { input: 0.25, output: 1.25, cacheHit: 0.03 },
56
+ supportsThinking: false,
57
+ maxTokens: 4096,
58
+ bestFor: ['high-volume', 'simple queries', 'cost optimization'],
59
+ },
60
+ };
61
+ // ─────────────────────────────────────────────────────────────────────────────
62
+ // Default Tier Assignments
63
+ // ─────────────────────────────────────────────────────────────────────────────
64
+ /** Default model assignments for each tier role. */
65
+ export const DEFAULT_MODEL_TIERS = {
66
+ planner: 'claude-opus-4-5-20251101',
67
+ triage: 'claude-sonnet-4-20250514',
68
+ executor: 'claude-3-5-haiku-latest',
69
+ fallback: 'claude-sonnet-4-20250514',
70
+ };
71
+ const ARCHITECTURE_KEYWORDS = [
72
+ 'refactor', 'redesign', 'implement', 'create', 'build', 'add feature',
73
+ 'restructure', 'migrate', 'integrate', 'connect', 'architecture',
74
+ ];
75
+ const MULTI_FILE_PATTERNS = [
76
+ /create.*and.*update/i,
77
+ /add.*to.*and/i,
78
+ /multiple\s+(files?|slides?|entities)/i,
79
+ /all\s+(the\s+)?(files?|slides?|entities)/i,
80
+ ];
81
+ const QUESTION_PATTERNS = [
82
+ /^what\s+(is|are|does)/i, /^how\s+(does|do|can|should)/i,
83
+ /^why\s+(is|are|does|do)/i, /^where\s+(is|are|can)/i,
84
+ /^when\s+(should|can|does)/i, /^can\s+(you|I|we)/i,
85
+ /^explain/i, /^describe/i,
86
+ ];
87
+ const SINGLE_TOOL_PATTERNS = [
88
+ /^read\s+(the\s+)?/i, /^show\s+(me\s+)?/i,
89
+ /^list\s+/i, /^search\s+/i, /^find\s+/i, /^get\s+/i,
90
+ ];
91
+ const CONDITIONAL_PATTERNS = [
92
+ /\bif\b.*\bthen\b/i, /\bwhen\b.*\belse\b/i,
93
+ /\botherwise\b/i, /\bdepending\s+on\b/i,
94
+ /\bbased\s+on\b.*\b(then|do)\b/i,
95
+ ];
96
+ /**
97
+ * Analyze a user message's complexity across 6 signal dimensions.
98
+ *
99
+ * @param message - The user's raw message text.
100
+ * @returns Signal scores (sum them for the total complexity score).
101
+ */
102
+ export function analyzeComplexity(message) {
103
+ const signals = {
104
+ multiFileOperations: 0,
105
+ architectureKeywords: 0,
106
+ questionWords: 0,
107
+ singleToolImplied: 0,
108
+ multipleEntities: 0,
109
+ conditionalLogic: 0,
110
+ };
111
+ const lowerMessage = message.toLowerCase();
112
+ for (const pattern of MULTI_FILE_PATTERNS) {
113
+ if (pattern.test(message)) {
114
+ signals.multiFileOperations = 3;
115
+ break;
116
+ }
117
+ }
118
+ for (const keyword of ARCHITECTURE_KEYWORDS) {
119
+ if (lowerMessage.includes(keyword)) {
120
+ signals.architectureKeywords = 2;
121
+ break;
122
+ }
123
+ }
124
+ for (const pattern of QUESTION_PATTERNS) {
125
+ if (pattern.test(message)) {
126
+ signals.questionWords = -2;
127
+ break;
128
+ }
129
+ }
130
+ for (const pattern of SINGLE_TOOL_PATTERNS) {
131
+ if (pattern.test(message)) {
132
+ signals.singleToolImplied = -1;
133
+ break;
134
+ }
135
+ }
136
+ const entityMentions = (message.match(/\b(slide|file|document|entity|concept|node)\s*\d*/gi) || []).length;
137
+ if (entityMentions >= 2)
138
+ signals.multipleEntities = 2;
139
+ for (const pattern of CONDITIONAL_PATTERNS) {
140
+ if (pattern.test(message)) {
141
+ signals.conditionalLogic = 2;
142
+ break;
143
+ }
144
+ }
145
+ return signals;
146
+ }
147
+ /**
148
+ * Sum all signal scores into a single complexity number.
149
+ *
150
+ * @param signals - Complexity signals from {@link analyzeComplexity}.
151
+ * @returns Total score (negative = simple, positive = complex).
152
+ */
153
+ export function calculateComplexityScore(signals) {
154
+ return (signals.multiFileOperations +
155
+ signals.architectureKeywords +
156
+ signals.questionWords +
157
+ signals.singleToolImplied +
158
+ signals.multipleEntities +
159
+ signals.conditionalLogic);
160
+ }
161
+ // ─────────────────────────────────────────────────────────────────────────────
162
+ // Tiered Routing
163
+ // ─────────────────────────────────────────────────────────────────────────────
164
+ /** Complexity score at which auto plan-execute mode activates. */
165
+ const COMPLEXITY_THRESHOLD = 3;
166
+ /** Complexity score at which the engine recommends enabling Plan Mode. */
167
+ const PLAN_RECOMMENDATION_THRESHOLD = 5;
168
+ /**
169
+ * Select the tiered routing strategy for a message.
170
+ *
171
+ * When Plan Mode is ON, uses Opus for planning and Haiku for execution.
172
+ * When OFF, uses Sonnet for triage and Haiku for tasks — and recommends
173
+ * Plan Mode if complexity exceeds the recommendation threshold.
174
+ *
175
+ * @param message - The user's message.
176
+ * @param planModeEnabled - Whether Plan Mode is explicitly enabled by the user.
177
+ * @param modelOverrides - Optional per-tier model overrides.
178
+ * @returns Complete routing decision.
179
+ */
180
+ export function selectTieredRouting(message, planModeEnabled, modelOverrides) {
181
+ const tiers = { ...DEFAULT_MODEL_TIERS, ...modelOverrides };
182
+ const signals = analyzeComplexity(message);
183
+ const score = calculateComplexityScore(signals);
184
+ if (planModeEnabled) {
185
+ return {
186
+ planModeEnabled: true,
187
+ triageModel: tiers.planner,
188
+ executeModel: tiers.executor,
189
+ complexityScore: score,
190
+ shouldRecommendPlan: false,
191
+ reason: 'Plan Mode enabled — using Opus for planning, Haiku for execution',
192
+ };
193
+ }
194
+ const shouldRecommendPlan = score >= PLAN_RECOMMENDATION_THRESHOLD;
195
+ return {
196
+ planModeEnabled: false,
197
+ triageModel: tiers.triage,
198
+ executeModel: tiers.executor,
199
+ complexityScore: score,
200
+ shouldRecommendPlan,
201
+ reason: shouldRecommendPlan
202
+ ? `Complexity score ${score} >= ${PLAN_RECOMMENDATION_THRESHOLD} — recommend enabling Plan Mode`
203
+ : 'Using Sonnet for triage, Haiku for tasks',
204
+ };
205
+ }
206
+ // ─────────────────────────────────────────────────────────────────────────────
207
+ // Default Model Selector
208
+ // ─────────────────────────────────────────────────────────────────────────────
209
+ /**
210
+ * Create the default {@link ModelSelector} implementation.
211
+ *
212
+ * Uses complexity analysis and the default tier assignments. Products can
213
+ * pass custom tier overrides or replace this entirely.
214
+ *
215
+ * @param modelOverrides - Optional per-tier model overrides.
216
+ * @returns A ModelSelector using complexity-based routing.
217
+ */
218
+ export function createDefaultModelSelector(modelOverrides) {
219
+ return {
220
+ selectRouting(message, options) {
221
+ if (options.forcedModel) {
222
+ return {
223
+ planModeEnabled: options.planModeEnabled ?? false,
224
+ triageModel: options.forcedModel,
225
+ executeModel: options.forcedModel,
226
+ complexityScore: 0,
227
+ shouldRecommendPlan: false,
228
+ reason: `Forced model: ${options.forcedModel}`,
229
+ };
230
+ }
231
+ return selectTieredRouting(message, options.planModeEnabled ?? false, modelOverrides);
232
+ },
233
+ };
234
+ }
235
+ /**
236
+ * Estimate cost for a plan-execute flow based on token counts.
237
+ *
238
+ * @param planInputTokens - Input tokens for the planning phase.
239
+ * @param planOutputTokens - Output tokens for the planning phase.
240
+ * @param executeInputTokens - Input tokens for the execution phase.
241
+ * @param executeOutputTokens - Output tokens for the execution phase.
242
+ * @param planModel - Model used for planning.
243
+ * @param executeModel - Model used for execution.
244
+ * @returns Detailed cost estimate with savings comparison.
245
+ */
246
+ export function estimateCost(planInputTokens, planOutputTokens, executeInputTokens, executeOutputTokens, planModel = 'claude-sonnet-4-20250514', executeModel = 'claude-3-5-haiku-latest') {
247
+ const planPricing = getModelPricing(planModel);
248
+ const executePricing = getModelPricing(executeModel);
249
+ const planCost = (planInputTokens / 1_000_000) * planPricing.input +
250
+ (planOutputTokens / 1_000_000) * planPricing.output;
251
+ const executeCost = (executeInputTokens / 1_000_000) * executePricing.input +
252
+ (executeOutputTokens / 1_000_000) * executePricing.output;
253
+ const totalUSD = planCost + executeCost;
254
+ const singleModelCost = ((planInputTokens + executeInputTokens) / 1_000_000) * planPricing.input +
255
+ ((planOutputTokens + executeOutputTokens) / 1_000_000) * planPricing.output;
256
+ const savings = singleModelCost - totalUSD;
257
+ const savingsPercent = singleModelCost > 0 ? (savings / singleModelCost) * 100 : 0;
258
+ return {
259
+ planTokens: { input: planInputTokens, output: planOutputTokens },
260
+ executeTokens: { input: executeInputTokens, output: executeOutputTokens },
261
+ totalUSD,
262
+ breakdown: { planCost, executeCost },
263
+ comparisonSingleModel: singleModelCost,
264
+ savings,
265
+ savingsPercent,
266
+ };
267
+ }
268
+ /**
269
+ * Get pricing for a model, falling back to Sonnet pricing for unknown models.
270
+ *
271
+ * @param modelId - Model identifier.
272
+ * @returns Pricing per million tokens.
273
+ */
274
+ export function getModelPricing(modelId) {
275
+ const model = DEFAULT_MODELS[modelId];
276
+ if (model)
277
+ return model.pricing;
278
+ return { input: 3.00, output: 15.00, cacheHit: 0.30 };
279
+ }
280
+ /**
281
+ * Get display name for a model, falling back to the raw ID.
282
+ *
283
+ * @param modelId - Model identifier.
284
+ * @returns Short display name.
285
+ */
286
+ export function getModelShortName(modelId) {
287
+ return DEFAULT_MODELS[modelId]?.shortName ?? modelId;
288
+ }
289
+ /**
290
+ * Format a USD cost for display.
291
+ *
292
+ * @param cost - Cost in USD.
293
+ * @returns Formatted string (e.g. "$0.0032", "<$0.001").
294
+ */
295
+ export function formatCost(cost) {
296
+ if (cost === 0)
297
+ return '$0.00';
298
+ if (cost < 0.001)
299
+ return '<$0.001';
300
+ if (cost < 0.01)
301
+ return `$${cost.toFixed(4)}`;
302
+ return `$${cost.toFixed(2)}`;
303
+ }
304
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../../../src/server/handlers/chat/models.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAmCH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAgC;IACzD,0BAA0B,EAAE;QAC1B,EAAE,EAAE,0BAA0B;QAC9B,IAAI,EAAE,iBAAiB;QACvB,SAAS,EAAE,UAAU;QACrB,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE;QACxD,gBAAgB,EAAE,IAAI;QACtB,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,CAAC,sBAAsB,EAAE,gBAAgB,EAAE,gBAAgB,CAAC;KACtE;IACD,0BAA0B,EAAE;QAC1B,EAAE,EAAE,0BAA0B;QAC9B,IAAI,EAAE,iBAAiB;QACvB,SAAS,EAAE,UAAU;QACrB,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE;QACvD,gBAAgB,EAAE,IAAI;QACtB,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,kBAAkB,CAAC;KACnE;IACD,yBAAyB,EAAE;QACzB,EAAE,EAAE,yBAAyB;QAC7B,IAAI,EAAE,kBAAkB;QACxB,SAAS,EAAE,WAAW;QACtB,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;QACtD,gBAAgB,EAAE,IAAI;QACtB,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,CAAC,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,CAAC;KAC9D;IACD,yBAAyB,EAAE;QACzB,EAAE,EAAE,yBAAyB;QAC7B,IAAI,EAAE,gBAAgB;QACtB,SAAS,EAAE,SAAS;QACpB,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;QACtD,gBAAgB,EAAE,KAAK;QACvB,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,CAAC,aAAa,EAAE,gBAAgB,EAAE,mBAAmB,CAAC;KAChE;CACF,CAAA;AAED,gFAAgF;AAChF,2BAA2B;AAC3B,gFAAgF;AAEhF,oDAAoD;AACpD,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,OAAO,EAAE,0BAA0B;IACnC,MAAM,EAAE,0BAA0B;IAClC,QAAQ,EAAE,yBAAyB;IACnC,QAAQ,EAAE,0BAA0B;CAC5B,CAAA;AA2BV,MAAM,qBAAqB,GAAG;IAC5B,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa;IACrE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc;CACjE,CAAA;AAED,MAAM,mBAAmB,GAAG;IAC1B,sBAAsB;IACtB,eAAe;IACf,uCAAuC;IACvC,2CAA2C;CAC5C,CAAA;AAED,MAAM,iBAAiB,GAAG;IACxB,wBAAwB,EAAE,8BAA8B;IACxD,0BAA0B,EAAE,wBAAwB;IACpD,4BAA4B,EAAE,oBAAoB;IAClD,WAAW,EAAE,YAAY;CAC1B,CAAA;AAED,MAAM,oBAAoB,GAAG;IAC3B,oBAAoB,EAAE,mBAAmB;IACzC,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU;CACpD,CAAA;AAED,MAAM,oBAAoB,GAAG;IAC3B,mBAAmB,EAAE,qBAAqB;IAC1C,gBAAgB,EAAE,qBAAqB;IACvC,gCAAgC;CACjC,CAAA;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,MAAM,OAAO,GAAsB;QACjC,mBAAmB,EAAE,CAAC;QACtB,oBAAoB,EAAE,CAAC;QACvB,aAAa,EAAE,CAAC;QAChB,iBAAiB,EAAE,CAAC;QACpB,gBAAgB,EAAE,CAAC;QACnB,gBAAgB,EAAE,CAAC;KACpB,CAAA;IAED,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,EAAE,CAAA;IAE1C,KAAK,MAAM,OAAO,IAAI,mBAAmB,EAAE,CAAC;QAC1C,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAAC,OAAO,CAAC,mBAAmB,GAAG,CAAC,CAAC;YAAC,MAAK;QAAC,CAAC;IACvE,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,qBAAqB,EAAE,CAAC;QAC5C,IAAI,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAAC,OAAO,CAAC,oBAAoB,GAAG,CAAC,CAAC;YAAC,MAAK;QAAC,CAAC;IACjF,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,iBAAiB,EAAE,CAAC;QACxC,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAAC,OAAO,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;YAAC,MAAK;QAAC,CAAC;IAClE,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,oBAAoB,EAAE,CAAC;QAC3C,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAAC,OAAO,CAAC,iBAAiB,GAAG,CAAC,CAAC,CAAC;YAAC,MAAK;QAAC,CAAC;IACtE,CAAC;IAED,MAAM,cAAc,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAA;IAC1G,IAAI,cAAc,IAAI,CAAC;QAAE,OAAO,CAAC,gBAAgB,GAAG,CAAC,CAAA;IAErD,KAAK,MAAM,OAAO,IAAI,oBAAoB,EAAE,CAAC;QAC3C,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAAC,OAAO,CAAC,gBAAgB,GAAG,CAAC,CAAC;YAAC,MAAK;QAAC,CAAC;IACpE,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAA0B;IACjE,OAAO,CACL,OAAO,CAAC,mBAAmB;QAC3B,OAAO,CAAC,oBAAoB;QAC5B,OAAO,CAAC,aAAa;QACrB,OAAO,CAAC,iBAAiB;QACzB,OAAO,CAAC,gBAAgB;QACxB,OAAO,CAAC,gBAAgB,CACzB,CAAA;AACH,CAAC;AAED,gFAAgF;AAChF,iBAAiB;AACjB,gFAAgF;AAEhF,kEAAkE;AAClE,MAAM,oBAAoB,GAAG,CAAC,CAAA;AAE9B,0EAA0E;AAC1E,MAAM,6BAA6B,GAAG,CAAC,CAAA;AAEvC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAe,EACf,eAAwB,EACxB,cAAoD;IAEpD,MAAM,KAAK,GAAG,EAAE,GAAG,mBAAmB,EAAE,GAAG,cAAc,EAAE,CAAA;IAC3D,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAA;IAC1C,MAAM,KAAK,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAA;IAE/C,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO;YACL,eAAe,EAAE,IAAI;YACrB,WAAW,EAAE,KAAK,CAAC,OAAO;YAC1B,YAAY,EAAE,KAAK,CAAC,QAAQ;YAC5B,eAAe,EAAE,KAAK;YACtB,mBAAmB,EAAE,KAAK;YAC1B,MAAM,EAAE,kEAAkE;SAC3E,CAAA;IACH,CAAC;IAED,MAAM,mBAAmB,GAAG,KAAK,IAAI,6BAA6B,CAAA;IAElE,OAAO;QACL,eAAe,EAAE,KAAK;QACtB,WAAW,EAAE,KAAK,CAAC,MAAM;QACzB,YAAY,EAAE,KAAK,CAAC,QAAQ;QAC5B,eAAe,EAAE,KAAK;QACtB,mBAAmB;QACnB,MAAM,EAAE,mBAAmB;YACzB,CAAC,CAAC,oBAAoB,KAAK,OAAO,6BAA6B,iCAAiC;YAChG,CAAC,CAAC,0CAA0C;KAC/C,CAAA;AACH,CAAC;AAED,gFAAgF;AAChF,yBAAyB;AACzB,gFAAgF;AAEhF;;;;;;;;GAQG;AACH,MAAM,UAAU,0BAA0B,CACxC,cAAoD;IAEpD,OAAO;QACL,aAAa,CAAC,OAAO,EAAE,OAAO;YAC5B,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;gBACxB,OAAO;oBACL,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,KAAK;oBACjD,WAAW,EAAE,OAAO,CAAC,WAAW;oBAChC,YAAY,EAAE,OAAO,CAAC,WAAW;oBACjC,eAAe,EAAE,CAAC;oBAClB,mBAAmB,EAAE,KAAK;oBAC1B,MAAM,EAAE,iBAAiB,OAAO,CAAC,WAAW,EAAE;iBAC/C,CAAA;YACH,CAAC;YACD,OAAO,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,IAAI,KAAK,EAAE,cAAc,CAAC,CAAA;QACvF,CAAC;KACF,CAAA;AACH,CAAC;AA0BD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAC1B,eAAuB,EACvB,gBAAwB,EACxB,kBAA0B,EAC1B,mBAA2B,EAC3B,YAAoB,0BAA0B,EAC9C,eAAuB,yBAAyB;IAEhD,MAAM,WAAW,GAAG,eAAe,CAAC,SAAS,CAAC,CAAA;IAC9C,MAAM,cAAc,GAAG,eAAe,CAAC,YAAY,CAAC,CAAA;IAEpD,MAAM,QAAQ,GAAG,CAAC,eAAe,GAAG,SAAS,CAAC,GAAG,WAAW,CAAC,KAAK;QACjD,CAAC,gBAAgB,GAAG,SAAS,CAAC,GAAG,WAAW,CAAC,MAAM,CAAA;IAEpE,MAAM,WAAW,GAAG,CAAC,kBAAkB,GAAG,SAAS,CAAC,GAAG,cAAc,CAAC,KAAK;QACvD,CAAC,mBAAmB,GAAG,SAAS,CAAC,GAAG,cAAc,CAAC,MAAM,CAAA;IAE7E,MAAM,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAA;IAEvC,MAAM,eAAe,GAAG,CAAC,CAAC,eAAe,GAAG,kBAAkB,CAAC,GAAG,SAAS,CAAC,GAAG,WAAW,CAAC,KAAK;QACxE,CAAC,CAAC,gBAAgB,GAAG,mBAAmB,CAAC,GAAG,SAAS,CAAC,GAAG,WAAW,CAAC,MAAM,CAAA;IAEnG,MAAM,OAAO,GAAG,eAAe,GAAG,QAAQ,CAAA;IAC1C,MAAM,cAAc,GAAG,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,eAAe,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;IAElF,OAAO;QACL,UAAU,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,gBAAgB,EAAE;QAChE,aAAa,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,mBAAmB,EAAE;QACzE,QAAQ;QACR,SAAS,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE;QACpC,qBAAqB,EAAE,eAAe;QACtC,OAAO;QACP,cAAc;KACf,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,CAAA;IACrC,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC,OAAO,CAAA;IAC/B,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,OAAO,cAAc,CAAC,OAAO,CAAC,EAAE,SAAS,IAAI,OAAO,CAAA;AACtD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,IAAI,KAAK,CAAC;QAAE,OAAO,OAAO,CAAA;IAC9B,IAAI,IAAI,GAAG,KAAK;QAAE,OAAO,SAAS,CAAA;IAClC,IAAI,IAAI,GAAG,IAAI;QAAE,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;IAC7C,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAA;AAC9B,CAAC"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * @module server/handlers/chat/planner
3
+ * @description Plan generation, storage, approval, and modification.
4
+ *
5
+ * When Plan Mode is enabled, the planner uses a smart model (Opus) to:
6
+ * 1. Analyze the user's request and identify the high-level strategy
7
+ * 2. Break it into discrete, dependency-ordered steps
8
+ * 3. Identify required tools, files, entities, and skills
9
+ * 4. Estimate execution cost
10
+ *
11
+ * Plans are stored as Brainy `collection` entities with `_aiDataType: 'plan'`,
12
+ * linked to their conversation via `contains` edges. Plans must be approved
13
+ * before the executor runs them.
14
+ */
15
+ import type { Brainy } from '@soulcraft/brainy';
16
+ import type { ChatAIClient, ToolDefinition, AIPlan, PlanStep } from './types.js';
17
+ /**
18
+ * Options for generating a plan.
19
+ */
20
+ export interface GeneratePlanOptions {
21
+ /** The user's message to plan for. */
22
+ userMessage: string;
23
+ /** Conversation ID for linking the plan. */
24
+ conversationId: string;
25
+ /** AI client for calling Claude. */
26
+ aiClient: ChatAIClient;
27
+ /** Available tool definitions (included in the prompt for reference). */
28
+ tools: ToolDefinition[];
29
+ /** Product-specific context (e.g. selected files, active kit). */
30
+ productContext?: Record<string, unknown>;
31
+ /** Model for planning. Defaults to Opus. */
32
+ planModel?: string;
33
+ /** Model for execution. Defaults to Haiku (used in cost estimation). */
34
+ executeModel?: string;
35
+ }
36
+ /**
37
+ * Generate an execution plan from a user message.
38
+ *
39
+ * Uses the planning model (Opus by default) to analyze the request and
40
+ * produce a structured, dependency-ordered plan.
41
+ *
42
+ * @param options - Plan generation configuration.
43
+ * @returns The generated plan with cost estimates.
44
+ */
45
+ export declare function generatePlan(options: GeneratePlanOptions): Promise<AIPlan>;
46
+ /**
47
+ * Store a plan as a Brainy collection entity.
48
+ *
49
+ * Creates the entity and links it to the conversation via `contains`.
50
+ *
51
+ * @param brain - Brainy instance.
52
+ * @param plan - The plan to store.
53
+ * @returns The Brainy entity ID.
54
+ */
55
+ export declare function storePlan(brain: Brainy, plan: AIPlan): Promise<string>;
56
+ /**
57
+ * Load a plan from Brainy by entity ID.
58
+ *
59
+ * @param brain - Brainy instance.
60
+ * @param planId - Brainy entity ID.
61
+ * @returns The plan, or null if not found.
62
+ */
63
+ export declare function loadPlan(brain: Brainy, planId: string): Promise<AIPlan | null>;
64
+ /**
65
+ * Update a plan in Brainy.
66
+ *
67
+ * @param brain - Brainy instance.
68
+ * @param planId - Brainy entity ID.
69
+ * @param updates - Partial plan updates.
70
+ */
71
+ export declare function updatePlan(brain: Brainy, planId: string, updates: Partial<AIPlan>): Promise<void>;
72
+ /**
73
+ * Approve a pending plan for execution.
74
+ *
75
+ * @param brain - Brainy instance.
76
+ * @param planId - Brainy entity ID.
77
+ * @returns The approved plan.
78
+ */
79
+ export declare function approvePlan(brain: Brainy, planId: string): Promise<AIPlan>;
80
+ /**
81
+ * Cancel a plan.
82
+ *
83
+ * @param brain - Brainy instance.
84
+ * @param planId - Brainy entity ID.
85
+ */
86
+ export declare function cancelPlan(brain: Brainy, planId: string): Promise<void>;
87
+ /**
88
+ * Get all pending plans for a conversation.
89
+ *
90
+ * @param brain - Brainy instance.
91
+ * @param conversationId - Conversation entity ID.
92
+ * @returns Array of pending plans.
93
+ */
94
+ export declare function getPendingPlans(brain: Brainy, conversationId: string): Promise<AIPlan[]>;
95
+ /**
96
+ * Add a step to a pending plan.
97
+ *
98
+ * @param brain - Brainy instance.
99
+ * @param planId - Brainy entity ID.
100
+ * @param step - Step to add (status is set to 'pending').
101
+ * @param afterStepId - Insert after this step ID. Appends if omitted.
102
+ * @returns Updated plan.
103
+ */
104
+ export declare function addPlanStep(brain: Brainy, planId: string, step: Omit<PlanStep, 'status'>, afterStepId?: string): Promise<AIPlan>;
105
+ /**
106
+ * Remove a step from a pending plan.
107
+ *
108
+ * Also cleans up dependency references to the removed step.
109
+ *
110
+ * @param brain - Brainy instance.
111
+ * @param planId - Brainy entity ID.
112
+ * @param stepId - Step to remove.
113
+ * @returns Updated plan.
114
+ */
115
+ export declare function removePlanStep(brain: Brainy, planId: string, stepId: string): Promise<AIPlan>;
116
+ //# sourceMappingURL=planner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../../../../src/server/handlers/chat/planner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,MAAM,EACN,QAAQ,EACT,MAAM,YAAY,CAAA;AAmDnB;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAA;IACnB,4CAA4C;IAC5C,cAAc,EAAE,MAAM,CAAA;IACtB,oCAAoC;IACpC,QAAQ,EAAE,YAAY,CAAA;IACtB,yEAAyE;IACzE,KAAK,EAAE,cAAc,EAAE,CAAA;IACvB,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2IhF;AAMD;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAuB5E;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIpF;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,GACvB,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAchF;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7E;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,MAAM,EAAE,CAAC,CAanB;AAMD;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAC9B,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAcjB"}