@superatomai/sdk-node 0.0.53-dsp → 0.0.54-dsp

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.
package/dist/index.js CHANGED
@@ -390,8 +390,7 @@ var ComponentPropsSchema = import_zod3.z.object({
390
390
  query: import_zod3.z.string().or(import_zod3.z.object({})).nullable().optional(),
391
391
  title: import_zod3.z.string().optional(),
392
392
  description: import_zod3.z.string().optional(),
393
- config: import_zod3.z.record(import_zod3.z.unknown()).optional(),
394
- actions: import_zod3.z.array(import_zod3.z.any()).optional()
393
+ config: import_zod3.z.record(import_zod3.z.unknown()).optional()
395
394
  }).passthrough();
396
395
  var ComponentSchema = import_zod3.z.object({
397
396
  id: import_zod3.z.string(),
@@ -505,19 +504,6 @@ var UILogsMessageSchema = import_zod3.z.object({
505
504
  type: import_zod3.z.literal("UI_LOGS"),
506
505
  payload: UILogsPayloadSchema
507
506
  });
508
- var ActionsRequestPayloadSchema = import_zod3.z.object({
509
- userId: import_zod3.z.string().optional(),
510
- SA_RUNTIME: import_zod3.z.object({
511
- threadId: import_zod3.z.string(),
512
- uiBlockId: import_zod3.z.string()
513
- }).optional()
514
- });
515
- var ActionsRequestMessageSchema = import_zod3.z.object({
516
- id: import_zod3.z.string(),
517
- from: MessageParticipantSchema,
518
- type: import_zod3.z.literal("ACTIONS"),
519
- payload: ActionsRequestPayloadSchema
520
- });
521
507
  var DashboardQueryFiltersSchema = import_zod3.z.object({
522
508
  dashboardId: import_zod3.z.string().optional(),
523
509
  projectId: import_zod3.z.string().optional(),
@@ -627,8 +613,6 @@ var UIBlockSchema = import_zod3.z.object({
627
613
  generatedComponentMetadata: ComponentSchema.optional(),
628
614
  // Actual field used by UIBlock class
629
615
  componentData: import_zod3.z.record(import_zod3.z.any()).optional(),
630
- actions: import_zod3.z.array(import_zod3.z.any()).optional(),
631
- isFetchingActions: import_zod3.z.boolean().optional(),
632
616
  createdAt: import_zod3.z.string().optional(),
633
617
  /**
634
618
  * Which script recipe produced this answer. Set whenever the turn was answered
@@ -1152,11 +1136,10 @@ var UIBlock = class {
1152
1136
  * @param userQuestion - The user's question or input
1153
1137
  * @param componentData - The component data object
1154
1138
  * @param generatedComponentMetadata - Optional metadata about the generated component
1155
- * @param actions - Optional array of available actions
1156
1139
  * @param id - Optional custom ID, generates UUID if not provided
1157
1140
  * @param textResponse - Optional text response from LLM
1158
1141
  */
1159
- constructor(userQuestion, componentData = {}, generatedComponentMetadata = {}, actions = [], id, textResponse = null) {
1142
+ constructor(userQuestion, componentData = {}, generatedComponentMetadata = {}, id, textResponse = null) {
1160
1143
  /**
1161
1144
  * Which script recipe produced this answer, when a script did. Read on the
1162
1145
  * NEXT turn so the user can say "use mode instead" and have the matcher
@@ -1168,7 +1151,6 @@ var UIBlock = class {
1168
1151
  this.userQuestion = userQuestion;
1169
1152
  this.componentData = componentData;
1170
1153
  this.generatedComponentMetadata = generatedComponentMetadata;
1171
- this.actions = actions;
1172
1154
  this.textResponse = textResponse;
1173
1155
  this.createdAt = /* @__PURE__ */ new Date();
1174
1156
  }
@@ -1297,76 +1279,6 @@ var UIBlock = class {
1297
1279
  setTextResponse(textResponse) {
1298
1280
  this.textResponse = textResponse;
1299
1281
  }
1300
- /**
1301
- * Get all actions (only if they are resolved, not if fetching)
1302
- */
1303
- getActions() {
1304
- return this.actions;
1305
- }
1306
- /**
1307
- * Get or fetch actions
1308
- * If actions don't exist or are a Promise, calls the generateFn and stores the promise
1309
- * If actions already exist, returns them
1310
- * @param generateFn - Async function to generate actions
1311
- * @returns Promise resolving to Action[]
1312
- */
1313
- async getOrFetchActions(generateFn) {
1314
- if (this.actions && !(this.actions instanceof Promise) && Array.isArray(this.actions) && this.actions.length > 0) {
1315
- return this.actions;
1316
- }
1317
- const fetchPromise = generateFn();
1318
- this.actions = fetchPromise;
1319
- try {
1320
- const resolvedActions = await fetchPromise;
1321
- logger.info(`Fetched ${resolvedActions.length} actions for UIBlock: ${this.id}`);
1322
- this.actions = resolvedActions;
1323
- return resolvedActions;
1324
- } catch (error) {
1325
- this.actions = null;
1326
- throw error;
1327
- }
1328
- }
1329
- /**
1330
- * Set or replace all actions
1331
- */
1332
- setActions(actions) {
1333
- this.actions = actions;
1334
- }
1335
- /**
1336
- * Add a single action (only if actions are resolved)
1337
- */
1338
- addAction(action) {
1339
- if (this.actions && Array.isArray(this.actions)) {
1340
- this.actions.push(action);
1341
- }
1342
- }
1343
- /**
1344
- * Add multiple actions (only if actions are resolved)
1345
- */
1346
- addActions(actions) {
1347
- if (this.actions && Array.isArray(this.actions)) {
1348
- this.actions.push(...actions);
1349
- }
1350
- }
1351
- /**
1352
- * Remove an action by ID (only if actions are resolved)
1353
- */
1354
- removeAction(actionId) {
1355
- if (this.actions && Array.isArray(this.actions)) {
1356
- const index = this.actions.findIndex((a) => a.id === actionId);
1357
- if (index > -1) {
1358
- this.actions.splice(index, 1);
1359
- return true;
1360
- }
1361
- }
1362
- return false;
1363
- }
1364
- /**
1365
- * Clear all actions
1366
- */
1367
- clearActions() {
1368
- this.actions = null;
1369
- }
1370
1282
  /**
1371
1283
  * Bind this block to the script recipe that produced its answer.
1372
1284
  */
@@ -1396,18 +1308,12 @@ var UIBlock = class {
1396
1308
  * Convert UIBlock to JSON-serializable object
1397
1309
  */
1398
1310
  toJSON() {
1399
- let actionsValue = null;
1400
- if (this.actions && !(this.actions instanceof Promise) && Array.isArray(this.actions)) {
1401
- actionsValue = this.actions;
1402
- }
1403
1311
  return {
1404
1312
  id: this.id,
1405
1313
  userQuestion: this.userQuestion,
1406
1314
  generatedComponentMetadata: this.generatedComponentMetadata,
1407
1315
  componentData: this.componentData,
1408
1316
  textResponse: this.textResponse,
1409
- actions: actionsValue,
1410
- isFetchingActions: this.actions instanceof Promise,
1411
1317
  createdAt: this.createdAt.toISOString(),
1412
1318
  ...this.scriptBinding ? { scriptBinding: this.scriptBinding } : {},
1413
1319
  ...this.programAnswer ? { programAnswer: this.programAnswer } : {}
@@ -1545,23 +1451,55 @@ var Thread = class {
1545
1451
  * since-edited) live body. Owned by the caller (needs a ScriptStore, which
1546
1452
  * Thread doesn't hold) — omit it and every turn falls back to the
1547
1453
  * no-script summary below.
1548
- */
1549
- async getConversationContext(limit = 5, currentUIBlockId, getScriptBody) {
1454
+ * @param fetchRecentFromDb When provided, this is now the SOURCE OF TRUTH
1455
+ * for history instead of this process's in-memory `uiblocks` map — reads
1456
+ * the persisted `user_conversations` rows (DB `response` jsonb shape, see
1457
+ * transformUIBlockForDB in conversation-saver.ts) via the caller's own
1458
+ * `user-conversations.getRecentForContext` collection. Rows come back
1459
+ * newest-first (already excluding status='aborted' — the query itself
1460
+ * filters that, matching what the in-memory path achieved via
1461
+ * thread.removeUIBlock() on abort). Fixes the standing gap where a backend
1462
+ * restart lost every thread's history (ThreadManager has no DB-backed
1463
+ * rehydration) — DB-backed history survives that, and is correct even if
1464
+ * a different process instance saved the row. Omit it and this falls back
1465
+ * to the in-memory map, for any caller not yet updated.
1466
+ */
1467
+ async getConversationContext(limit = 5, currentUIBlockId, getScriptBody, fetchRecentFromDb) {
1550
1468
  if (limit === 0) {
1551
1469
  return "";
1552
1470
  }
1553
- const allBlocks = Array.from(this.uiblocks.values()).filter((block) => !currentUIBlockId || block.getId() !== currentUIBlockId).sort((a, b) => a.getCreatedAt().getTime() - b.getCreatedAt().getTime());
1554
- if (allBlocks.length === 0) {
1471
+ let turns;
1472
+ if (fetchRecentFromDb) {
1473
+ const rows = await fetchRecentFromDb(limit);
1474
+ turns = rows.slice().reverse().map((row) => {
1475
+ const r = row.response || {};
1476
+ return {
1477
+ question: row.userprompt || r.user_prompt || "",
1478
+ metadata: r.component || {},
1479
+ programAnswer: r.programAnswer || null,
1480
+ textResponse: r.analysis || "",
1481
+ scriptBinding: r.scriptBinding || null
1482
+ };
1483
+ });
1484
+ } else {
1485
+ const allBlocks = Array.from(this.uiblocks.values()).filter((block) => !currentUIBlockId || block.getId() !== currentUIBlockId).sort((a, b) => a.getCreatedAt().getTime() - b.getCreatedAt().getTime());
1486
+ if (allBlocks.length === 0) {
1487
+ return "";
1488
+ }
1489
+ turns = allBlocks.slice(-limit).map((block) => ({
1490
+ question: block.getUserQuestion(),
1491
+ metadata: block.getComponentMetadata(),
1492
+ programAnswer: block.getProgramAnswer(),
1493
+ textResponse: block.getTextResponse(),
1494
+ scriptBinding: block.getScriptBinding()
1495
+ }));
1496
+ }
1497
+ if (turns.length === 0) {
1555
1498
  return "";
1556
1499
  }
1557
- const recentBlocks = allBlocks.slice(-limit);
1558
1500
  const contextLines = [];
1559
- for (const block of recentBlocks) {
1560
- const question = block.getUserQuestion();
1561
- const metadata = block.getComponentMetadata();
1562
- const programAnswer = block.getProgramAnswer();
1563
- const textResponse = block.getTextResponse();
1564
- const scriptBinding = block.getScriptBinding();
1501
+ for (const turn of turns) {
1502
+ const { question, metadata, programAnswer, textResponse, scriptBinding } = turn;
1565
1503
  const responseParts = [];
1566
1504
  let analysisText = "";
1567
1505
  const hasProgramAnswer = programAnswer && programAnswer.trim().length > 0;
@@ -3491,7 +3429,6 @@ var MAX_TOKENS_COMPONENT_MATCHING = 8192;
3491
3429
  var MAX_TOKENS_CLASSIFICATION = 1500;
3492
3430
  var MAX_TOKENS_ADAPTATION = 8192;
3493
3431
  var MAX_TOKENS_TEXT_RESPONSE = 4e3;
3494
- var MAX_TOKENS_NEXT_QUESTIONS = 1200;
3495
3432
  var MAX_ROWS_FETCHED = 50;
3496
3433
  var MAX_ROWS_TO_LLM = 10;
3497
3434
  var LLM_SAMPLE_ROWS = 10;
@@ -5864,7 +5801,6 @@ You receive TWO key inputs:
5864
5801
  3. **Additional visualizations**: Based on the analysis text and EXECUTED_TOOLS data, generate additional visualizations that show different aspects of the data (e.g., if the answer is a KPI total, add a breakdown chart and a detail table). Stay within the complexity limit above.
5865
5802
  4. **Generate props**: Use \`externalTool\` to reference the executed source tool. Get SQL from \`EXECUTED_TOOLS.parameters\` \u2014 reuse exact SQL when possible, write new SQL only when a different aggregation or grouping is needed.
5866
5803
  5. **Dashboard metadata**: Title (5-10 words) and description (1-2 sentences)
5867
- 6. **Actions**: Exactly 3 simple follow-up questions. Each question must be answerable by running a SQL query on the available data \u2014 no consulting, opinion, or "why" questions. Explore different dimensions of the data (different grouping, time range, filter, comparison). Use specific column names or values from the data when relevant. Keep questions short and direct \u2014 one sentence, one clear ask.
5868
5804
 
5869
5805
  ### Choosing Complexity
5870
5806
  Determine complexity from the analysis text and EXECUTED_TOOLS:
@@ -6078,8 +6014,7 @@ When using \`externalTool\`, use field names from the tool's \`outputSchema\` in
6078
6014
  "answerComponent": { ... } | null,
6079
6015
  "layoutTitle": "Dashboard title (5-10 words)",
6080
6016
  "layoutDescription": "Dashboard purpose (1-2 sentences)",
6081
- "matchedComponents": [ ... ],
6082
- "actions": ["Follow-up question 1?", "Follow-up question 2?", "Follow-up question 3?"]
6017
+ "matchedComponents": [ ... ]
6083
6018
  }
6084
6019
  \`\`\`
6085
6020
 
@@ -6194,52 +6129,6 @@ Example when hasAnswerComponent is true:
6194
6129
 
6195
6130
  Remember: Use this analysis for DynamicMarkdownBlock content and to understand what to visualize. Use EXECUTED_TOOLS (in system prompt) for SQL queries, toolIds, field names, and data shapes.
6196
6131
  ---`
6197
- },
6198
- "actions": {
6199
- system: `You are a data analyst suggesting follow-up questions. The questions will be used to query data sources via SQL \u2014 they must be simple, useful, and answerable from the data.
6200
-
6201
- **Rules:**
6202
- - Keep questions short and simple \u2014 one clear ask per question
6203
- - Questions MUST be answerable by querying the available data columns (SQL queries)
6204
- - Suggest different slices of the same data: by time period, by category, by route, top/bottom N, trends, comparisons
6205
- - Avoid repeating topics already covered in the conversation
6206
- - NEVER suggest questions about: root causes, recommendations, process changes, staffing, business decisions, or anything requiring human judgment
6207
- - NEVER ask "why" questions \u2014 only "what", "which", "how much", "how does X compare to Y"
6208
-
6209
- ---
6210
-
6211
- ## CONTEXT (for this specific request)
6212
-
6213
- ### Previous Conversation
6214
- {{CONVERSATION_HISTORY}}`,
6215
- user: `Current Date and Time: {{CURRENT_DATETIME}}
6216
-
6217
- Given the following context:
6218
-
6219
- Latest User Question: {{ORIGINAL_USER_PROMPT}}
6220
-
6221
- Current Component:
6222
- {{COMPONENT_INFO}}
6223
-
6224
- {{COMPONENT_DATA}}
6225
-
6226
- Generate a JSON array of exactly 3 simple follow-up questions. Each question should:
6227
- 1. Be answerable by running a SQL query on the available data \u2014 no consulting or opinion questions
6228
- 2. Explore a different dimension or slice of the data (different grouping, time range, filter, comparison)
6229
- 3. NOT repeat topics already covered in the conversation
6230
- 4. Be short and direct \u2014 one sentence, one clear ask
6231
- 5. Use specific column names or values from the data when relevant
6232
-
6233
- Format your response as a JSON object with this structure:
6234
- {
6235
- "nextQuestions": [
6236
- "Question 1?",
6237
- "Question 2?",
6238
- ...
6239
- ]
6240
- }
6241
-
6242
- Return ONLY valid JSON.`
6243
6132
  },
6244
6133
  "category-classification": {
6245
6134
  system: `You categorize user questions and identify required data source tools. Respond with ONLY valid JSON.
@@ -6405,7 +6294,7 @@ Your task is to:
6405
6294
  ## Component Structure Handling
6406
6295
 
6407
6296
  ### For Single Components:
6408
- - Modify props directly (config, actions, query, filters, etc.)
6297
+ - Modify props directly (config, query, filters, etc.)
6409
6298
 
6410
6299
  ### For MultiComponentContainer:
6411
6300
  The component will have structure:
@@ -6418,8 +6307,7 @@ The component will have structure:
6418
6307
  "components": [...], // Array of nested components - ADAPT EACH ONE
6419
6308
  "title": "...", // Container title - UPDATE based on new question
6420
6309
  "description": "..." // Container description - UPDATE based on new question
6421
- },
6422
- "actions": [...] // ADAPT actions if needed
6310
+ }
6423
6311
  }
6424
6312
  }
6425
6313
  \`\`\`
@@ -6431,7 +6319,6 @@ When adapting MultiComponentContainer:
6431
6319
  - Adapt its query parameters (WHERE clauses, LIMIT, ORDER BY, filters, date ranges)
6432
6320
  - Update its title/description to match the new context
6433
6321
  - Update its config settings (colors, sorting, grouping, metrics)
6434
- - Update \`actions\` if the new question requires different actions
6435
6322
 
6436
6323
  ## Important Guidelines:
6437
6324
  - Keep the same component type (don't change KPICard to LineChart)
@@ -6504,8 +6391,7 @@ When adapting queries, follow the database-specific rules below:
6504
6391
  "type": "component_type",
6505
6392
  "description": "updated_description",
6506
6393
  "props": {
6507
- "config": { },
6508
- "actions": []
6394
+ "config": { }
6509
6395
  }
6510
6396
  },
6511
6397
  "adaptedTextResponse": "The adapted text response with updated values matching the new question...",
@@ -6562,8 +6448,7 @@ When adapting queries, follow the database-specific rules below:
6562
6448
  }
6563
6449
  }
6564
6450
  ]
6565
- },
6566
- "actions": []
6451
+ }
6567
6452
  }
6568
6453
  },
6569
6454
  "adaptedTextResponse": "The adapted text response with entity names, IDs, and references updated to match the new question. Numeric values replaced with placeholders.",
@@ -6631,13 +6516,12 @@ When adapting SQL queries, preserve the table and column names from the original
6631
6516
 
6632
6517
  1. **Analyze the difference** between the original question and the current question
6633
6518
  2. **Identify what data needs to change**:
6634
- - For single components: adapt the query/config/actions
6519
+ - For single components: adapt the query/config
6635
6520
  - For MultiComponentContainer: adapt the container title/description AND each nested component's parameters
6636
6521
 
6637
6522
  3. **Modify the parameters**:
6638
6523
  - **Container level** (if MultiComponentContainer):
6639
6524
  - Update \`title\` and \`description\` to reflect the new user question
6640
- - Update \`actions\` if needed
6641
6525
 
6642
6526
  - **For each component** (single or nested in container):
6643
6527
  - Identify what it shows (sales, revenue, inventory, etc.)
@@ -8156,16 +8040,9 @@ Return JSON. Shape each component per the section above (markdown uses \`props.c
8156
8040
  { "componentId": "<the answerComponent, repeated as the FIRST entry>", "componentName": "...", "sourceIndex": 0, "props": { "title": "...", "config": { "xAxisKey": "...", "yAxisKey": "..." } } },
8157
8041
  { "componentId": "...", "componentName": "DynamicMarkdownBlock", "props": { "content": "## Recommendation\\n\\n- key point\\n- key point" } },
8158
8042
  { "componentId": "...", "componentName": "DynamicDataTable", "sourceIndex": 0, "props": { "title": "...", "config": { "columns": [ { "key": "<exact data column>", "label": "<Heading>" } ] } } }
8159
- ],
8160
- "actions": [
8161
- { "question": "<follow-up question 1>" },
8162
- { "question": "<follow-up question 2>" },
8163
- { "question": "<follow-up question 3>" }
8164
8043
  ]
8165
8044
  }
8166
8045
 
8167
- Also produce **exactly 3 \`actions\`** \u2014 short, specific follow-up questions a user would naturally ask next, grounded in THIS dashboard's data and analysis (reference the actual entities, metrics, or findings shown \u2014 e.g. a district, a gap, a time window). They must be answerable from the same data domain. Do NOT ask generic questions ("tell me more"); make each one a concrete next step the data supports.
8168
-
8169
8046
  ---
8170
8047
 
8171
8048
  ## CONTEXT (for this specific request)
@@ -9951,14 +9828,6 @@ function ensurePostgresLimit(query, defaultLimit, maxLimit, hadSemicolon) {
9951
9828
  }
9952
9829
  return trimmedQuery;
9953
9830
  }
9954
- function convertQuestionsToActions(questions) {
9955
- return questions.map((question, index) => ({
9956
- id: `action_${index}_${Date.now()}`,
9957
- name: question,
9958
- type: "next_question",
9959
- question
9960
- }));
9961
- }
9962
9831
  function validateAndFixSqlQuery(query, dbType) {
9963
9832
  if (!query || query.trim().length === 0) {
9964
9833
  return { query, fixed: false, fixes: [] };
@@ -13384,7 +13253,7 @@ var DEFAULT_AGENT_CONFIG = {
13384
13253
  // will use the provider's default model
13385
13254
  maxRetries: 2,
13386
13255
  // 2 retries = 3 total query attempts (1 initial + 2 retries for SQL errors)
13387
- maxIterations: 15
13256
+ maxIterations: 20
13388
13257
  // schema search (2-3) + query attempts (2) + write_script/execute_script (2-3) + write_analysis (up to 3) + LLM responses + final
13389
13258
  };
13390
13259
 
@@ -14195,6 +14064,9 @@ function parseEditPrefix(rawPrompt) {
14195
14064
  if (!match) return { isExplicitEdit: false, prompt: rawPrompt };
14196
14065
  return { isExplicitEdit: true, prompt: rawPrompt.slice(match[0].length) };
14197
14066
  }
14067
+ function hasExplicitEditPrefix(prompt) {
14068
+ return EDIT_PREFIX_RE.test(prompt);
14069
+ }
14198
14070
  var MAX_FAILURE_RATE = 0.2;
14199
14071
  var PROMPT_HISTORY_SEARCH_LIMIT = 20;
14200
14072
  var PROMPT_HISTORY_SIMILARITY_THRESHOLD = 0.5;
@@ -14251,10 +14123,11 @@ var ScriptMatcher = class {
14251
14123
  traceEntry.sent.userPrompt = userPrompt;
14252
14124
  const promptHistoryMatches = await this.searchPromptHistory(userPrompt);
14253
14125
  const candidates = [];
14254
- for (const binding of activeBindings || []) {
14255
- const recipe = await this.store.get(binding.recipeId);
14256
- if (recipe) candidates.push({ recipe, binding });
14257
- else logger.warn(`[ScriptMatcher] Bound recipe "${binding.recipeId}" no longer in store \u2014 dropped from edit candidates`);
14126
+ const mostRecentBinding = activeBindings?.[0];
14127
+ if (mostRecentBinding) {
14128
+ const recipe = await this.store.get(mostRecentBinding.recipeId);
14129
+ if (recipe) candidates.push({ recipe, binding: mostRecentBinding });
14130
+ else logger.warn(`[ScriptMatcher] Bound recipe "${mostRecentBinding.recipeId}" no longer in store \u2014 no edit candidate this turn`);
14258
14131
  }
14259
14132
  const candidateById = new Map(candidates.map((c) => [c.recipe.id, c]));
14260
14133
  traceEntry.sent.activeBindingCount = candidates.length;
@@ -14314,11 +14187,6 @@ var ScriptMatcher = class {
14314
14187
  } else if (candidates.length === 0) {
14315
14188
  logger.info(`[ScriptMatcher] 'edit' coerced to 'none' (no script-backed answer in this thread to edit)`);
14316
14189
  tier = "none";
14317
- } else if (!candidateById.has(response?.scriptId)) {
14318
- logger.warn(
14319
- `[ScriptMatcher] 'edit' coerced to 'none' \u2014 matcher targeted "${response?.scriptId}", which is not one of this thread's editable scripts [${candidates.map((c) => c.recipe.id).join(", ")}]. Refusing to edit a script the user hasn't run here.`
14320
- );
14321
- tier = "none";
14322
14190
  } else if (!response?.editInstruction || !String(response.editInstruction).trim()) {
14323
14191
  logger.warn(`[ScriptMatcher] 'edit' coerced to 'none' \u2014 matcher returned no editInstruction`);
14324
14192
  tier = "none";
@@ -14326,35 +14194,45 @@ var ScriptMatcher = class {
14326
14194
  }
14327
14195
  const reasoning = response?.reasoning || "unknown";
14328
14196
  traceEntry.received.tier = tier;
14329
- if (tier === "none" || !response?.scriptId || response.scriptId === "none") {
14197
+ if (tier === "none") {
14330
14198
  logger.info(`[ScriptMatcher] No match. Reason: ${reasoning}`);
14331
14199
  return null;
14332
14200
  }
14333
- const recipe = candidateById.get(response.scriptId)?.recipe ?? await this.store.get(response.scriptId);
14334
- if (!recipe) {
14335
- logger.warn(`[ScriptMatcher] LLM returned unknown script ID: "${response.scriptId}"`);
14336
- traceEntry.received.error = `LLM returned unknown script ID: "${response.scriptId}"`;
14337
- return null;
14338
- }
14339
14201
  if (tier === "edit") {
14202
+ const target = candidates[0];
14203
+ if (response?.scriptId && response.scriptId !== target.recipe.id) {
14204
+ logger.info(
14205
+ `[ScriptMatcher] Explicit edit \u2014 matcher suggested "${response.scriptId}", overridden to the most recent script "${target.recipe.id}" ("${target.recipe.name}") per the always-most-recent policy.`
14206
+ );
14207
+ }
14340
14208
  const editInstruction = String(response.editInstruction).trim();
14341
14209
  const editTarget = String(response.editTarget || "").toLowerCase() === "display" ? "display" : "data";
14342
- logger.info(`[ScriptMatcher] EDIT [${editTarget}] "${recipe.name}": ${editInstruction} | Reason: ${reasoning}`);
14210
+ logger.info(`[ScriptMatcher] EDIT [${editTarget}] "${target.recipe.name}": ${editInstruction} | Reason: ${reasoning}`);
14343
14211
  return {
14344
- recipe,
14212
+ recipe: target.recipe,
14345
14213
  tier: "edit",
14346
14214
  editTarget,
14347
14215
  similarity: 1,
14348
14216
  confidence: "high",
14349
- // Carry the chosen candidate's params so the edited script re-runs on
14350
- // the same scope the user was looking at, not on bare defaults.
14351
- extractedParams: candidateById.get(response.scriptId)?.binding.params || {},
14217
+ // Carry the target's own params so the edited script re-runs on the
14218
+ // same scope the user was looking at, not on bare defaults.
14219
+ extractedParams: target.binding.params || {},
14352
14220
  mentions: parseMentions(response.mentions),
14353
14221
  entityTypes: parseEntityTypes(response.entityTypes),
14354
14222
  editInstruction,
14355
14223
  reasoning
14356
14224
  };
14357
14225
  }
14226
+ if (!response?.scriptId || response.scriptId === "none") {
14227
+ logger.info(`[ScriptMatcher] No match. Reason: ${reasoning}`);
14228
+ return null;
14229
+ }
14230
+ const recipe = candidateById.get(response.scriptId)?.recipe ?? await this.store.get(response.scriptId);
14231
+ if (!recipe) {
14232
+ logger.warn(`[ScriptMatcher] LLM returned unknown script ID: "${response.scriptId}"`);
14233
+ traceEntry.received.error = `LLM returned unknown script ID: "${response.scriptId}"`;
14234
+ return null;
14235
+ }
14358
14236
  const declaredParamNames = new Set(recipe.parameters.map((p) => p.name));
14359
14237
  const inventedParamKeys = Object.keys(response.params || {}).filter((k) => !declaredParamNames.has(k));
14360
14238
  if (inventedParamKeys.length > 0) {
@@ -14474,41 +14352,41 @@ ${paramList}`;
14474
14352
  }).join("\n\n");
14475
14353
  }
14476
14354
  /**
14477
- * The recent script-backed answers in this thread — the bounded set an edit
14478
- * may target. Rendered as its own prompt section (never merged into the
14479
- * ranked catalog) so the `edit` rules have an unambiguous referent set, and
14480
- * numbered newest-first so the prompt's "prefer the most recent when the
14481
- * instruction is ambiguous" tie-break has something to point at.
14355
+ * The most recent script-backed answer in this thread — the one an `edit`
14356
+ * targets. Rendered as its own prompt section (never merged into the ranked
14357
+ * catalog) so the `edit` rules have an unambiguous referent.
14358
+ *
14359
+ * `candidates` holds at most one entry (see doMatch) — `edit` always means
14360
+ * "the answer I just got", so there is nothing else to show here.
14482
14361
  *
14483
- * Each entry carries the QUESTION that produced it plus the columns it
14484
- * returned — that is what lets the matcher resolve "use the mode for the WSP
14485
- * one" instead of blindly taking the newest.
14362
+ * Carries the QUESTION that produced it plus the columns it returned — that
14363
+ * is what lets the matcher resolve "use the mode for the WSP one" against
14364
+ * this one script's own context.
14486
14365
  */
14487
14366
  buildActiveScriptBlock(candidates) {
14488
- const blocks = candidates.map(({ recipe, binding }, idx) => {
14489
- const paramList = this.formatParamList(recipe.parameters);
14490
- const lines = [
14491
- `${idx + 1}. [${recipe.id}] "${recipe.name}"${idx === 0 ? " \u2190 most recent" : ""}`,
14492
- ` ${recipe.intentDescription}`
14493
- ];
14494
- if (binding.userPrompt) lines.push(` Answered the question: "${binding.userPrompt}"`);
14495
- if (binding.answerSummary) {
14496
- const trimmed = binding.answerSummary.length > 1e3 ? binding.answerSummary.slice(0, 1e3) + "...[truncated]" : binding.answerSummary;
14497
- lines.push(` Last answer: ${trimmed.replace(/\n/g, "\n ")}`);
14498
- }
14499
- if (binding.columns?.length) lines.push(` Columns it returned: ${binding.columns.join(", ")}`);
14500
- if (binding.params && Object.keys(binding.params).length > 0) {
14501
- lines.push(` Ran with: ${JSON.stringify(binding.params)}`);
14502
- }
14503
- lines.push(" Parameters:", paramList);
14504
- return lines.join("\n");
14505
- });
14367
+ const target = candidates[0];
14368
+ if (!target) return "";
14369
+ const { recipe, binding } = target;
14370
+ const paramList = this.formatParamList(recipe.parameters);
14371
+ const lines = [
14372
+ `[${recipe.id}] "${recipe.name}"`,
14373
+ `${recipe.intentDescription}`
14374
+ ];
14375
+ if (binding.userPrompt) lines.push(`Answered the question: "${binding.userPrompt}"`);
14376
+ if (binding.answerSummary) {
14377
+ const trimmed = binding.answerSummary.length > 1e3 ? binding.answerSummary.slice(0, 1e3) + "...[truncated]" : binding.answerSummary;
14378
+ lines.push(`Last answer: ${trimmed}`);
14379
+ }
14380
+ if (binding.columns?.length) lines.push(`Columns it returned: ${binding.columns.join(", ")}`);
14381
+ if (binding.params && Object.keys(binding.params).length > 0) {
14382
+ lines.push(`Ran with: ${JSON.stringify(binding.params)}`);
14383
+ }
14384
+ lines.push("Parameters:", paramList);
14506
14385
  return [
14507
- "### EDITABLE SCRIPTS \u2014 answers already given in THIS conversation (newest first)",
14508
- "An `edit` may target ONLY one of these. When the instruction does not clearly",
14509
- "name which one, choose #1 (the most recent).",
14386
+ "### EDITABLE SCRIPT \u2014 the answer just given in THIS conversation",
14387
+ "An `edit` always targets this script.",
14510
14388
  "",
14511
- blocks.join("\n\n")
14389
+ lines.join("\n")
14512
14390
  ].join("\n");
14513
14391
  }
14514
14392
  };
@@ -14849,7 +14727,7 @@ async function generateScriptComponents(params) {
14849
14727
  const queries = scriptResult.executedQueries;
14850
14728
  if (!queries || queries.length === 0) {
14851
14729
  logger.warn(`[ScriptComponentGen] No query data available \u2014 returning empty`);
14852
- return { components: [], layoutTitle: "", layoutDescription: "", actions: [], componentSpecs: [] };
14730
+ return { components: [], layoutTitle: "", layoutDescription: "", componentSpecs: [] };
14853
14731
  }
14854
14732
  logger.info(`[ScriptComponentGen] Starting | ${queries.length} queries | ${availableComponents.length} available components`);
14855
14733
  const columnsByIndex = queries.map((q) => {
@@ -14936,7 +14814,7 @@ ${sampleData}
14936
14814
  logger.logLLMPrompt("scriptComponentGen:response", "user", JSON.stringify(response, null, 2));
14937
14815
  if (!response || !response.components || !Array.isArray(response.components)) {
14938
14816
  logger.warn(`[ScriptComponentGen] LLM returned invalid response`);
14939
- return { components: [], layoutTitle: "", layoutDescription: "", actions: [], componentSpecs: [] };
14817
+ return { components: [], layoutTitle: "", layoutDescription: "", componentSpecs: [] };
14940
14818
  }
14941
14819
  const layoutTitle = response.layoutTitle || "Dashboard";
14942
14820
  const layoutDescription = response.layoutDescription || "";
@@ -14991,23 +14869,16 @@ ${sampleData}
14991
14869
  }
14992
14870
  }
14993
14871
  logger.info(`[ScriptComponentGen] Generated ${matchedComponents.length} components`);
14994
- const actions = (response.actions || []).map((a, idx) => ({
14995
- id: `action_${idx}_${Date.now()}`,
14996
- name: a.name || a.question || "",
14997
- type: "next_question",
14998
- question: a.question || a.name || ""
14999
- }));
15000
14872
  return {
15001
14873
  components: matchedComponents,
15002
14874
  layoutTitle,
15003
14875
  layoutDescription,
15004
- actions,
15005
14876
  componentSpecs
15006
14877
  };
15007
14878
  } catch (error) {
15008
14879
  const msg = error instanceof Error ? error.message : String(error);
15009
14880
  logger.error(`[ScriptComponentGen] Failed: ${msg}`);
15010
- return { components: [], layoutTitle: "", layoutDescription: "", actions: [], componentSpecs: [] };
14881
+ return { components: [], layoutTitle: "", layoutDescription: "", componentSpecs: [] };
15011
14882
  }
15012
14883
  }
15013
14884
  async function summarizeToMarkdown(analysis, apiKey, model) {
@@ -16065,15 +15936,15 @@ var BaseLLM = class {
16065
15936
  return false;
16066
15937
  }
16067
15938
  /**
16068
- * Match components from text response suggestions and generate follow-up questions
15939
+ * Match components from text response suggestions
16069
15940
  * Takes a text response with component suggestions (c1:type format) and matches with available components
16070
- * Also generates title, description, and intelligent follow-up questions (actions) based on the analysis
15941
+ * Also generates title and description based on the analysis
16071
15942
  * All components are placed in a default MultiComponentContainer layout
16072
15943
  * @param analysisContent - The text response containing component suggestions
16073
15944
  * @param components - List of available components
16074
15945
  * @param apiKey - Optional API key
16075
15946
  * @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
16076
- * @returns Object containing matched components, layout title/description, and follow-up actions
15947
+ * @returns Object containing matched components and layout title/description
16077
15948
  */
16078
15949
  async matchComponentsFromAnalysis(analysisContent, components, userPrompt, apiKey, componentStreamCallback, deferredTools, executedTools, collections, userId) {
16079
15950
  const methodStartTime = Date.now();
@@ -16337,8 +16208,6 @@ ${executedToolsText}`);
16337
16208
  logger.info(`[${this.getProviderName()}] ${idx + 1}. ${comp.componentType} (${comp.componentName}) - ${comp.originalSuggestion || "N/A"}`);
16338
16209
  });
16339
16210
  logger.file("\n=============================\nFull LLM response:", JSON.stringify(result, null, 2));
16340
- const rawActions = result.actions || [];
16341
- const actions = convertQuestionsToActions(rawActions);
16342
16211
  const finalComponents = matchedComponents.map((mc) => {
16343
16212
  const originalComponent = components.find((c) => c.name === mc.componentName);
16344
16213
  if (!originalComponent) {
@@ -16381,12 +16250,11 @@ ${executedToolsText}`);
16381
16250
  logger.error(`[${this.getProviderName()}] Skipping query validation - database execute function not available`);
16382
16251
  }
16383
16252
  const methodDuration = Date.now() - methodStartTime;
16384
- logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration}ms | components: ${validatedComponents.length} | actions: ${actions.length}`);
16253
+ logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration}ms | components: ${validatedComponents.length}`);
16385
16254
  return {
16386
16255
  components: validatedComponents,
16387
16256
  layoutTitle,
16388
- layoutDescription,
16389
- actions
16257
+ layoutDescription
16390
16258
  };
16391
16259
  } catch (error) {
16392
16260
  const methodDuration = Date.now() - methodStartTime;
@@ -16395,8 +16263,7 @@ ${executedToolsText}`);
16395
16263
  return {
16396
16264
  components: [],
16397
16265
  layoutTitle: "Dashboard",
16398
- layoutDescription: "Failed to generate dashboard",
16399
- actions: []
16266
+ layoutDescription: "Failed to generate dashboard"
16400
16267
  };
16401
16268
  }
16402
16269
  }
@@ -16435,8 +16302,6 @@ ${executedToolsText}`);
16435
16302
  });
16436
16303
  logger.logLLMPrompt("classifyQuestionCategory", "system", extractPromptText(prompts.system));
16437
16304
  logger.logLLMPrompt("classifyQuestionCategory", "user", extractPromptText(prompts.user));
16438
- logger.logLLMPrompt("generateNextQuestions", "system", extractPromptText(prompts.system));
16439
- logger.logLLMPrompt("generateNextQuestions", "user", extractPromptText(prompts.user));
16440
16305
  const result = await LLM.stream(
16441
16306
  {
16442
16307
  sys: prompts.system,
@@ -16789,7 +16654,6 @@ ${executedToolsText}`);
16789
16654
  data: {
16790
16655
  text: textResponse,
16791
16656
  // Include the streamed text showing all attempts
16792
- actions: [],
16793
16657
  method: `${this.getProviderName()}-text-response-max-attempts`
16794
16658
  }
16795
16659
  };
@@ -16802,21 +16666,8 @@ ${executedToolsText}`);
16802
16666
  let matchedComponents = [];
16803
16667
  let layoutTitle = "Dashboard";
16804
16668
  let layoutDescription = "Multi-component dashboard";
16805
- let actions = [];
16806
16669
  if (category === "general") {
16807
16670
  logger.info(`[${this.getProviderName()}] General category - wrapping text response in DynamicMarkdownBlock`);
16808
- const nextQuestions = await this.generateNextQuestions(
16809
- userPrompt,
16810
- null,
16811
- // no component
16812
- void 0,
16813
- // no component data
16814
- apiKey,
16815
- conversationHistory,
16816
- textResponse
16817
- // pass text response as context
16818
- );
16819
- actions = convertQuestionsToActions(nextQuestions);
16820
16671
  const markdownContent2 = textResponse.replace(/<DashboardComponents>[\s\S]*?<\/DashboardComponents>/g, "").trim();
16821
16672
  matchedComponents = [{
16822
16673
  id: "dynamic-markdown-block",
@@ -16867,7 +16718,6 @@ ${executedToolsText}`);
16867
16718
  matchedComponents = matchResult.components;
16868
16719
  layoutTitle = matchResult.layoutTitle;
16869
16720
  layoutDescription = matchResult.layoutDescription;
16870
- actions = matchResult.actions;
16871
16721
  }
16872
16722
  let container_componet = null;
16873
16723
  if (matchedComponents.length > 0) {
@@ -16881,19 +16731,17 @@ ${executedToolsText}`);
16881
16731
  title: layoutTitle,
16882
16732
  description: layoutDescription,
16883
16733
  components: matchedComponents
16884
- },
16885
- actions
16734
+ }
16886
16735
  }
16887
16736
  };
16888
16737
  }
16889
16738
  const methodDuration = Date.now() - methodStartTime;
16890
- logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration}ms | result: success | components: ${matchedComponents.length} | actions: ${actions.length}`);
16739
+ logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration}ms | result: success | components: ${matchedComponents.length}`);
16891
16740
  return {
16892
16741
  success: true,
16893
16742
  data: {
16894
16743
  text: textResponse,
16895
16744
  component: container_componet,
16896
- actions,
16897
16745
  method: `${this.getProviderName()}-text-response`
16898
16746
  },
16899
16747
  errors: []
@@ -16915,7 +16763,6 @@ ${executedToolsText}`);
16915
16763
  errors,
16916
16764
  data: {
16917
16765
  text: "I apologize, but I encountered an error while processing your question. Please try rephrasing or ask something else.",
16918
- actions: [],
16919
16766
  method: `${this.getProviderName()}-text-response-error`
16920
16767
  }
16921
16768
  };
@@ -16957,7 +16804,6 @@ ${executedToolsText}`);
16957
16804
  data: {
16958
16805
  text: cachedTextResponse,
16959
16806
  component: null,
16960
- actions: conversationMatch.uiBlock?.actions || [],
16961
16807
  reasoning: `Exact match from previous general conversation`,
16962
16808
  method: `${this.getProviderName()}-semantic-match-general`,
16963
16809
  semanticSimilarity: conversationMatch.similarity
@@ -16975,13 +16821,11 @@ ${executedToolsText}`);
16975
16821
  logger.info(`[${this.getProviderName()}] Streaming cached text response to frontend`);
16976
16822
  streamCallback(cachedTextResponse);
16977
16823
  }
16978
- const cachedActions = conversationMatch.uiBlock?.actions || [];
16979
16824
  return {
16980
16825
  success: true,
16981
16826
  data: {
16982
16827
  text: cachedTextResponse,
16983
16828
  component,
16984
- actions: cachedActions,
16985
16829
  reasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,
16986
16830
  method: `${this.getProviderName()}-semantic-match-exact`,
16987
16831
  semanticSimilarity: conversationMatch.similarity
@@ -17006,13 +16850,11 @@ ${executedToolsText}`);
17006
16850
  logger.info(`[${this.getProviderName()}] Streaming ${adaptResult.adaptedTextResponse ? "adapted" : "cached"} text response to frontend`);
17007
16851
  streamCallback(textResponseToUse);
17008
16852
  }
17009
- const cachedActions = conversationMatch.uiBlock?.actions || [];
17010
16853
  return {
17011
16854
  success: true,
17012
16855
  data: {
17013
16856
  text: textResponseToUse,
17014
16857
  component: adaptResult.adaptedComponent,
17015
- actions: cachedActions,
17016
16858
  reasoning: `Adapted from previous conversation: ${originalPrompt}`,
17017
16859
  method: `${this.getProviderName()}-semantic-match`,
17018
16860
  semanticSimilarity: conversationMatch.similarity,
@@ -17103,67 +16945,6 @@ ${executedToolsText}`);
17103
16945
  };
17104
16946
  }
17105
16947
  }
17106
- /**
17107
- * Generate next questions that the user might ask based on the original prompt and generated component
17108
- * This helps provide intelligent suggestions for follow-up queries
17109
- * For general/conversational questions without components, pass textResponse instead
17110
- */
17111
- async generateNextQuestions(originalUserPrompt, component, componentData, apiKey, conversationHistory, textResponse, signal) {
17112
- const methodStartTime = Date.now();
17113
- const methodName = "generateNextQuestions";
17114
- const promptPreview = originalUserPrompt.substring(0, 50) + (originalUserPrompt.length > 50 ? "..." : "");
17115
- logger.info(`[${this.getProviderName()}] [TIMING] START ${methodName} | model: ${this.getModelForTask("simple")} | prompt: "${promptPreview}"`);
17116
- try {
17117
- let component_info;
17118
- if (component) {
17119
- component_info = `
17120
- Component Name: ${component.name}
17121
- Component Type: ${component.type}
17122
- Component Description: ${component.description || "No description"}
17123
- Component Props: ${component.props ? JSON.stringify(component.props, null, 2) : "No props"}
17124
- `;
17125
- } else if (textResponse) {
17126
- component_info = `
17127
- Response Type: Text/Conversational Response
17128
- Response Content: ${textResponse.substring(0, 1e3)}${textResponse.length > 1e3 ? "..." : ""}
17129
- `;
17130
- } else {
17131
- component_info = "No component or response context available";
17132
- }
17133
- const component_data = componentData ? `Component Data: ${JSON.stringify(componentData, null, 2)}` : "";
17134
- const prompts = await promptLoader.loadPrompts("actions", {
17135
- ORIGINAL_USER_PROMPT: originalUserPrompt,
17136
- COMPONENT_INFO: component_info,
17137
- COMPONENT_DATA: component_data,
17138
- CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
17139
- CURRENT_DATETIME: getCurrentDateTimeForPrompt()
17140
- });
17141
- const result = await LLM.stream(
17142
- {
17143
- sys: prompts.system,
17144
- user: prompts.user
17145
- },
17146
- {
17147
- model: this.getModelForTask("simple"),
17148
- maxTokens: MAX_TOKENS_NEXT_QUESTIONS,
17149
- temperature: 0,
17150
- apiKey: this.getApiKey(apiKey),
17151
- signal
17152
- },
17153
- true
17154
- // Parse as JSON
17155
- );
17156
- const nextQuestions = result.nextQuestions || [];
17157
- const methodDuration = Date.now() - methodStartTime;
17158
- logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration}ms | questions: ${nextQuestions.length}`);
17159
- return nextQuestions;
17160
- } catch (error) {
17161
- const methodDuration = Date.now() - methodStartTime;
17162
- const errorMsg = error instanceof Error ? error.message : String(error);
17163
- logger.error(`[${this.getProviderName()}] [TIMING] FAILED ${methodName} in ${methodDuration}ms | error: ${errorMsg}`);
17164
- return [];
17165
- }
17166
- }
17167
16948
  };
17168
16949
 
17169
16950
  // src/userResponse/anthropic.ts
@@ -17488,7 +17269,6 @@ var get_agent_user_response = async (prompt, components, anthropicApiKey, groqAp
17488
17269
  data: {
17489
17270
  text: cachedTextResponse,
17490
17271
  component: rehydratedComponent,
17491
- actions: conversationMatch.uiBlock?.actions || [],
17492
17272
  reasoning: `Exact match from previous conversation`,
17493
17273
  method: `${provider}-agent-exact-match`,
17494
17274
  semanticSimilarity: 1,
@@ -17587,9 +17367,14 @@ var get_agent_user_response = async (prompt, components, anthropicApiKey, groqAp
17587
17367
  logger.info(`[AgentFlow] Bound recipe ${directReplay.recipeId} no longer in store \u2014 falling back to ScriptMatcher LLM`);
17588
17368
  }
17589
17369
  }
17590
- if (!scriptMatch && process.env.SA_SKIP_SCRIPT_MATCH !== "true") {
17370
+ const explicitEdit = hasExplicitEditPrefix(prompt);
17371
+ if (!scriptMatch && (process.env.SA_SKIP_SCRIPT_MATCH !== "true" || explicitEdit)) {
17591
17372
  const scriptMatcher = new ScriptMatcher(scriptStore, { collections, userId, trace: runTrace });
17592
17373
  scriptMatch = await scriptMatcher.match(prompt, apiKey, sourceAgentModel, signal, activeBindings);
17374
+ if (scriptMatch && scriptMatch.tier !== "edit" && process.env.SA_SKIP_SCRIPT_MATCH === "true") {
17375
+ logger.info(`[AgentFlow] Matcher returned '${scriptMatch.tier}' for an "edit :"-prefixed prompt under SA_SKIP_SCRIPT_MATCH=true \u2014 discarding (only an actual edit is let through this opt-out)`);
17376
+ scriptMatch = null;
17377
+ }
17593
17378
  } else if (!scriptMatch) {
17594
17379
  logger.info("[AgentFlow] ScriptMatcher skipped (SA_SKIP_SCRIPT_MATCH=true) \u2014 proceeding with fresh generation");
17595
17380
  }
@@ -17743,7 +17528,6 @@ ${JSON.stringify(preview, null, 2)}
17743
17528
  let matchedComponents2 = [];
17744
17529
  let layoutTitle2 = "Dashboard";
17745
17530
  let layoutDescription2 = "Multi-component dashboard";
17746
- let actions2 = [];
17747
17531
  if (components && components.length > 0 && scriptExecutedTools.length > 0) {
17748
17532
  logger.info(`[AgentFlow] Script flow \u2014 generating components (lightweight)`);
17749
17533
  if (streamBuffer.hasCallback()) {
@@ -17852,7 +17636,6 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${scriptMatch
17852
17636
  matchedComponents2 = compResult.components;
17853
17637
  layoutTitle2 = compResult.layoutTitle;
17854
17638
  layoutDescription2 = compResult.layoutDescription;
17855
- actions2 = compResult.actions;
17856
17639
  if (compResult.componentSpecs.length > 0) {
17857
17640
  try {
17858
17641
  scriptMatch.recipe.components = compResult.componentSpecs;
@@ -17919,15 +17702,10 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${scriptMatch
17919
17702
  description: layoutDescription2,
17920
17703
  components: securedComponents2,
17921
17704
  ...Object.keys(queryMap2).length > 0 && { _queryMap: queryMap2 }
17922
- },
17923
- actions: actions2
17705
+ }
17924
17706
  }
17925
17707
  };
17926
17708
  }
17927
- actions2 = [];
17928
- if (containerComponent2) {
17929
- containerComponent2.props.actions = [];
17930
- }
17931
17709
  const elapsedTime2 = Date.now() - startTime;
17932
17710
  logger.info(`[AgentFlow] Script flow complete | ${scriptResult.executedQueries.length} queries | ${matchedComponents2.length} components | ${elapsedTime2}ms`);
17933
17711
  return {
@@ -17936,7 +17714,6 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${scriptMatch
17936
17714
  text: scriptTextResponse,
17937
17715
  ...replayProgramAnswer ? { programAnswer: replayProgramAnswer } : {},
17938
17716
  component: containerComponent2,
17939
- actions: actions2,
17940
17717
  method: isDisplayEdit ? `${provider}-script-display-edit` : `${provider}-script-response`,
17941
17718
  // Bind the answer to the replayed recipe so a follow-up
17942
17719
  // ("use mode instead") can edit THIS script.
@@ -18057,7 +17834,6 @@ BEGIN NOW. Your VERY FIRST action MUST be a \`write_script\` tool call containin
18057
17834
  data: {
18058
17835
  text: "",
18059
17836
  component: workflowComponent,
18060
- actions: [],
18061
17837
  method: `${provider}-agent-workflow`,
18062
17838
  ...runTrace ? { trace: runTrace } : {}
18063
17839
  },
@@ -18113,7 +17889,6 @@ BEGIN NOW. Your VERY FIRST action MUST be a \`write_script\` tool call containin
18113
17889
  let matchedComponents = [];
18114
17890
  let layoutTitle = "Dashboard";
18115
17891
  let layoutDescription = "Multi-component dashboard";
18116
- let actions = [];
18117
17892
  let authoredComponentSpecs = [];
18118
17893
  if (!hasExecutedTools) {
18119
17894
  logger.info(`[AgentFlow] No tools executed \u2014 general question, wrapping in DynamicMarkdownBlock`);
@@ -18267,7 +18042,6 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${carriedRequ
18267
18042
  matchedComponents = compResult.components;
18268
18043
  layoutTitle = compResult.layoutTitle;
18269
18044
  layoutDescription = compResult.layoutDescription;
18270
- actions = compResult.actions;
18271
18045
  authoredComponentSpecs = compResult.componentSpecs;
18272
18046
  usedLightweight = true;
18273
18047
  logger.info(`[AgentFlow] Lightweight component gen succeeded \u2014 ${matchedComponents.length} components`);
@@ -18319,13 +18093,10 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${carriedRequ
18319
18093
  components: securedComponents,
18320
18094
  // Persist queryId → SQL mapping so cached responses can re-register queries
18321
18095
  ...Object.keys(queryMap).length > 0 && { _queryMap: queryMap }
18322
- },
18323
- actions
18096
+ }
18324
18097
  }
18325
18098
  };
18326
18099
  }
18327
- if (containerComponent) {
18328
- }
18329
18100
  if (agentResponse.savedScript && editContext) {
18330
18101
  try {
18331
18102
  const authored = agentResponse.savedScript;
@@ -18452,7 +18223,6 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${carriedRequ
18452
18223
  ${programAnswer}` : textResponse,
18453
18224
  ...programAnswer ? { programAnswer } : {},
18454
18225
  component: containerComponent,
18455
- actions,
18456
18226
  method: editContext ? `${provider}-script-edit-response` : `${provider}-agent-response`,
18457
18227
  ...scriptBinding ? { scriptBinding } : {},
18458
18228
  ...noDataAnswer ? { noDataAnswer: true } : {},
@@ -18838,10 +18608,12 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
18838
18608
  const requestStartTime = Date.now();
18839
18609
  logger.info(`Starting user prompt request with ${components.length} components`);
18840
18610
  const conversationScriptStore = new ScriptStore({ collections, projectId: process.env.SUPERATOM_PROJECT_ID || "" });
18611
+ const getRecentForContext = collections?.["user-conversations"]?.["getRecentForContext"];
18841
18612
  const conversationHistory = await thread.getConversationContext(
18842
18613
  CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS,
18843
18614
  existingUiBlockId,
18844
- async (recipeId, version) => (await conversationScriptStore.getVersion(recipeId, version))?.scriptBody ?? null
18615
+ async (recipeId, version) => (await conversationScriptStore.getVersion(recipeId, version))?.scriptBody ?? null,
18616
+ getRecentForContext && userId && threadId ? async (limit) => (await getRecentForContext({ userId, threadId, limit }))?.data ?? [] : void 0
18845
18617
  );
18846
18618
  const MAX_EDIT_CANDIDATES = 5;
18847
18619
  let activeScriptBindings = thread.getScriptBindings(MAX_EDIT_CANDIDATES, existingUiBlockId);
@@ -18866,7 +18638,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
18866
18638
  `[UserPromptRequest] ${activeScriptBindings.length} editable script(s) in thread: ` + activeScriptBindings.map((b) => b.name || b.recipeId).join(", ")
18867
18639
  );
18868
18640
  }
18869
- const uiBlock = new UIBlock(prompt, {}, {}, [], existingUiBlockId, null);
18641
+ const uiBlock = new UIBlock(prompt, {}, {}, existingUiBlockId, null);
18870
18642
  thread.addUIBlock(uiBlock);
18871
18643
  logger.info(`Registered UIBlock (early): ${existingUiBlockId} in Thread: ${threadId}`);
18872
18644
  const abortController = new AbortController();
@@ -19054,7 +18826,6 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19054
18826
  }
19055
18827
  let component = null;
19056
18828
  let textResponse = null;
19057
- let actions = [];
19058
18829
  if (userResponse.data) {
19059
18830
  if (typeof userResponse.data === "object") {
19060
18831
  if ("component" in userResponse.data) {
@@ -19065,9 +18836,6 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19065
18836
  } else if ("textResponse" in userResponse.data) {
19066
18837
  textResponse = userResponse.data.textResponse;
19067
18838
  }
19068
- if ("actions" in userResponse.data) {
19069
- actions = userResponse.data.actions || [];
19070
- }
19071
18839
  }
19072
18840
  }
19073
18841
  let finalTextResponse = responseMode === "text" && accumulatedStreamResponse ? accumulatedStreamResponse : textResponse;
@@ -19085,10 +18853,6 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19085
18853
  }
19086
18854
  const programAnswer = userResponse.data?.programAnswer;
19087
18855
  if (programAnswer) uiBlock.setProgramAnswer(programAnswer);
19088
- if (actions.length > 0) {
19089
- uiBlock.setActions(actions);
19090
- logger.info(`Stored ${actions.length} actions in UIBlock: ${uiBlockId}`);
19091
- }
19092
18856
  logger.info(`Completed UIBlock: ${uiBlockId} in Thread: ${threadId}`);
19093
18857
  let savedConversationId;
19094
18858
  let savedResponse;
@@ -19354,229 +19118,6 @@ function sendResponse(id, res, sendMessage, clientId) {
19354
19118
  sendMessage(response);
19355
19119
  }
19356
19120
 
19357
- // src/userResponse/next-questions.ts
19358
- async function generateNextQuestions(originalUserPrompt, component, componentData, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, conversationHistory) {
19359
- try {
19360
- logger.debug("[generateNextQuestions] Starting next questions generation");
19361
- logger.debug(`[generateNextQuestions] User prompt: "${originalUserPrompt?.substring(0, 50)}..."`);
19362
- logger.debug(`[generateNextQuestions] Component: ${component?.name || "unknown"} (${component?.type || "unknown"})`);
19363
- logger.debug(`[generateNextQuestions] Component data available: ${componentData ? "yes" : "no"}`);
19364
- const providers = llmProviders || ["anthropic", "gemini", "openai", "groq"];
19365
- logger.info(`[generateNextQuestions] Using LLM providers: [${providers.join(", ")}]`);
19366
- if (conversationHistory && conversationHistory.length > 0) {
19367
- const exchangeCount = conversationHistory.split("\n").filter((l) => l.startsWith("Q")).length;
19368
- logger.debug(`[generateNextQuestions] Using conversation history with ${exchangeCount} previous exchanges`);
19369
- } else {
19370
- logger.debug("[generateNextQuestions] No conversation history available");
19371
- }
19372
- for (let i = 0; i < providers.length; i++) {
19373
- const provider = providers[i];
19374
- const isLastProvider = i === providers.length - 1;
19375
- try {
19376
- logger.info(`[generateNextQuestions] Attempting provider: ${provider} (${i + 1}/${providers.length})`);
19377
- let result = [];
19378
- if (provider === "groq") {
19379
- logger.debug("[generateNextQuestions] Using Groq LLM for next questions");
19380
- result = await groqLLM.generateNextQuestions(
19381
- originalUserPrompt,
19382
- component,
19383
- componentData,
19384
- groqApiKey,
19385
- conversationHistory
19386
- );
19387
- } else if (provider === "gemini") {
19388
- logger.debug("[generateNextQuestions] Using Gemini LLM for next questions");
19389
- result = await geminiLLM.generateNextQuestions(
19390
- originalUserPrompt,
19391
- component,
19392
- componentData,
19393
- geminiApiKey,
19394
- conversationHistory
19395
- );
19396
- } else if (provider === "openai") {
19397
- logger.debug("[generateNextQuestions] Using OpenAI LLM for next questions");
19398
- result = await openaiLLM.generateNextQuestions(
19399
- originalUserPrompt,
19400
- component,
19401
- componentData,
19402
- openaiApiKey,
19403
- conversationHistory
19404
- );
19405
- } else {
19406
- logger.debug("[generateNextQuestions] Using Anthropic LLM for next questions");
19407
- result = await anthropicLLM.generateNextQuestions(
19408
- originalUserPrompt,
19409
- component,
19410
- componentData,
19411
- anthropicApiKey,
19412
- conversationHistory
19413
- );
19414
- }
19415
- if (result && result.length > 0) {
19416
- logger.info(`[generateNextQuestions] Successfully generated ${result.length} questions with ${provider}`);
19417
- logger.debug(`[generateNextQuestions] Questions: ${JSON.stringify(result)}`);
19418
- return result;
19419
- }
19420
- logger.warn(`[generateNextQuestions] No questions generated from ${provider}${!isLastProvider ? ", trying next provider..." : ""}`);
19421
- } catch (providerError) {
19422
- const errorMsg = providerError instanceof Error ? providerError.message : String(providerError);
19423
- logger.error(`[generateNextQuestions] Provider ${provider} failed: ${errorMsg}`);
19424
- logger.debug(`[generateNextQuestions] Provider error details:`, providerError);
19425
- if (!isLastProvider) {
19426
- logger.info(`[generateNextQuestions] Provider ${provider} failed, trying next provider...`);
19427
- }
19428
- continue;
19429
- }
19430
- }
19431
- logger.warn("[generateNextQuestions] All providers failed or returned no questions");
19432
- return [];
19433
- } catch (error) {
19434
- const errorMsg = error instanceof Error ? error.message : String(error);
19435
- const errorStack = error instanceof Error ? error.stack : void 0;
19436
- logger.error(`[generateNextQuestions] Error generating next questions: ${errorMsg}`);
19437
- logger.debug("[generateNextQuestions] Error stack trace:", errorStack);
19438
- return [];
19439
- }
19440
- }
19441
-
19442
- // src/handlers/actions-request.ts
19443
- async function handleActionsRequest(data, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders) {
19444
- try {
19445
- logger.debug("[ACTIONS_REQ] Parsing incoming actions request");
19446
- const actionsRequest = ActionsRequestMessageSchema.parse(data);
19447
- const { id, payload } = actionsRequest;
19448
- const { SA_RUNTIME } = payload;
19449
- const wsId = actionsRequest.from.id || "unknown";
19450
- logger.info(`[ACTIONS_REQ ${id}] Processing actions request from client: ${wsId}`);
19451
- logger.debug(`[ACTIONS_REQ ${id}] Request payload:`, JSON.stringify(payload, null, 2).substring(0, 200));
19452
- if (!SA_RUNTIME) {
19453
- logger.error(`[ACTIONS_REQ ${id}] SA_RUNTIME missing from request`);
19454
- sendResponse2(id, {
19455
- success: false,
19456
- error: "SA_RUNTIME with threadId and uiBlockId is required"
19457
- }, sendMessage, wsId);
19458
- return;
19459
- }
19460
- const uiBlockId = SA_RUNTIME.uiBlockId;
19461
- const threadId = SA_RUNTIME.threadId;
19462
- logger.debug(`[ACTIONS_REQ ${id}] SA_RUNTIME validated - threadId: ${threadId}, uiBlockId: ${uiBlockId}`);
19463
- const threadManager = ThreadManager.getInstance();
19464
- const thread = threadManager.getThread(threadId);
19465
- if (!thread) {
19466
- logger.error(`[ACTIONS_REQ ${id}] Thread '${threadId}' not found`);
19467
- sendResponse2(id, {
19468
- success: false,
19469
- error: `Thread '${threadId}' not found`
19470
- }, sendMessage, wsId);
19471
- return;
19472
- }
19473
- logger.debug(`[ACTIONS_REQ ${id}] Thread found with ${thread.getUIBlocks().length} UIBlocks`);
19474
- logger.debug(`[ACTIONS_REQ ${id}] Retrieving UIBlock: ${uiBlockId}`);
19475
- const uiBlock = thread.getUIBlock(uiBlockId);
19476
- if (!uiBlock) {
19477
- logger.error(`[ACTIONS_REQ ${id}] UIBlock '${uiBlockId}' not found in thread '${threadId}'`);
19478
- sendResponse2(id, {
19479
- success: false,
19480
- error: `UIBlock '${uiBlockId}' not found in thread '${threadId}'`
19481
- }, sendMessage, wsId);
19482
- return;
19483
- }
19484
- logger.info(`[ACTIONS_REQ ${id}] UIBlock retrieved successfully`);
19485
- logger.debug(`[ACTIONS_REQ ${id}] Extracting data from UIBlock`);
19486
- const userQuestion = uiBlock.getUserQuestion();
19487
- const component = uiBlock.getComponentMetadata();
19488
- const componentData = uiBlock.getComponentData();
19489
- logger.debug(`[ACTIONS_REQ ${id}] User question: "${userQuestion?.substring(0, 50)}..."`);
19490
- logger.debug(`[ACTIONS_REQ ${id}] Component: ${component?.name || "unknown"} (${component?.type || "unknown"})`);
19491
- logger.debug(`[ACTIONS_REQ ${id}] Component data available: ${componentData ? "yes" : "no"}`);
19492
- logger.debug(`[ACTIONS_REQ ${id}] Extracting conversation history (max ${CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS} blocks)`);
19493
- const conversationHistory = await thread.getConversationContext(CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS, uiBlockId);
19494
- const historyLineCount = conversationHistory.split("\n").filter((l) => l.trim()).length;
19495
- logger.info(`[ACTIONS_REQ ${id}] Conversation history extracted: ${historyLineCount} lines`);
19496
- logger.debug(`[ACTIONS_REQ ${id}] Conversation history preview:
19497
- ${conversationHistory.substring(0, 200)}...`);
19498
- logger.info(`[ACTIONS_REQ ${id}] Generating actions for UIBlock: ${uiBlockId}, component: ${component?.name || "unknown"}`);
19499
- logger.debug(`[ACTIONS_REQ ${id}] Checking if actions are already cached`);
19500
- const startTime = Date.now();
19501
- const actions = await uiBlock.getOrFetchActions(async () => {
19502
- logger.info(`[ACTIONS_REQ ${id}] Actions not cached, generating new actions...`);
19503
- logger.info(`[ACTIONS_REQ ${id}] Starting next questions generation with ${llmProviders?.join(", ") || "default"} providers`);
19504
- const nextQuestions = await generateNextQuestions(
19505
- userQuestion,
19506
- component,
19507
- componentData,
19508
- anthropicApiKey,
19509
- groqApiKey,
19510
- geminiApiKey,
19511
- openaiApiKey,
19512
- llmProviders,
19513
- conversationHistory
19514
- );
19515
- logger.info(`[ACTIONS_REQ ${id}] Generated ${nextQuestions.length} questions`);
19516
- logger.debug(`[ACTIONS_REQ ${id}] Questions: ${JSON.stringify(nextQuestions)}`);
19517
- logger.debug(`[ACTIONS_REQ ${id}] Converting questions to actions format`);
19518
- const convertedActions = nextQuestions.map((question, index) => ({
19519
- id: `action_${index}_${Date.now()}`,
19520
- name: question,
19521
- type: "next_question",
19522
- question
19523
- }));
19524
- logger.debug(`[ACTIONS_REQ ${id}] Converted ${convertedActions.length} actions`);
19525
- return convertedActions;
19526
- });
19527
- const processingTime = Date.now() - startTime;
19528
- logger.info(`[ACTIONS_REQ ${id}] Actions retrieved in ${processingTime}ms - ${actions.length} actions total`);
19529
- if (actions.length > 0) {
19530
- logger.info(`[ACTIONS_REQ ${id}] Generated ${actions.length} follow-up questions successfully`);
19531
- logger.debug(`[ACTIONS_REQ ${id}] Actions: ${actions.map((a) => a.name).join(", ")}`);
19532
- } else {
19533
- logger.warn(`[ACTIONS_REQ ${id}] No actions generated`);
19534
- }
19535
- logger.debug(`[ACTIONS_REQ ${id}] Sending successful response to client`);
19536
- sendResponse2(id, {
19537
- success: true,
19538
- data: {
19539
- actions,
19540
- componentName: component?.name,
19541
- componentId: component?.id,
19542
- uiBlockId,
19543
- threadId
19544
- }
19545
- }, sendMessage, wsId);
19546
- logger.info(`[ACTIONS_REQ ${id}] \u2713 Actions request completed successfully`);
19547
- } catch (error) {
19548
- const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
19549
- const errorStack = error instanceof Error ? error.stack : void 0;
19550
- logger.error(`[ACTIONS_REQ] Failed to handle actions request: ${errorMessage}`);
19551
- logger.debug(`[ACTIONS_REQ] Error stack trace:`, errorStack);
19552
- sendResponse2(null, {
19553
- success: false,
19554
- error: errorMessage
19555
- }, sendMessage);
19556
- logger.info("[ACTIONS_REQ] \u2717 Actions request completed with errors");
19557
- }
19558
- }
19559
- function sendResponse2(id, res, sendMessage, clientId) {
19560
- const response = {
19561
- id: id || "unknown",
19562
- type: "ACTIONS_RES",
19563
- from: { type: "data-agent" },
19564
- to: {
19565
- type: "runtime",
19566
- id: clientId
19567
- },
19568
- payload: {
19569
- ...res
19570
- }
19571
- };
19572
- logger.debug(`[ACTIONS_RES ${id || "unknown"}] Sending ${res.success ? "successful" : "failed"} response to client`);
19573
- logger.debug(`[ACTIONS_RES ${id || "unknown"}] Response payload size: ${JSON.stringify(response).length} bytes`);
19574
- if (res.data?.actions) {
19575
- logger.debug(`[ACTIONS_RES ${id || "unknown"}] Sending ${res.data.actions.length} actions`);
19576
- }
19577
- sendMessage(response);
19578
- }
19579
-
19580
19121
  // src/handlers/components-list-response.ts
19581
19122
  async function handleComponentListResponse(data, storeComponents, collections) {
19582
19123
  try {
@@ -19651,7 +19192,7 @@ async function handleUsersRequest(data, collections, sendMessage) {
19651
19192
  const limit = requestData?.limit;
19652
19193
  const sort = requestData?.sort;
19653
19194
  if (from.type !== "admin" && operation !== "getOne" && operation !== "getAll" && operation !== "query") {
19654
- sendResponse3(id, {
19195
+ sendResponse2(id, {
19655
19196
  success: false,
19656
19197
  error: "Unauthorized: Only admin can manage users"
19657
19198
  }, sendMessage, from.id);
@@ -19679,14 +19220,14 @@ async function handleUsersRequest(data, collections, sendMessage) {
19679
19220
  await handleQuery(id, filters, limit, sort, executeCollection, userManager, sendMessage, from.id);
19680
19221
  break;
19681
19222
  default:
19682
- sendResponse3(id, {
19223
+ sendResponse2(id, {
19683
19224
  success: false,
19684
19225
  error: `Unknown operation: ${operation}`
19685
19226
  }, sendMessage, from.id);
19686
19227
  }
19687
19228
  } catch (error) {
19688
19229
  logger.error("Failed to handle users request:", error);
19689
- sendResponse3(null, {
19230
+ sendResponse2(null, {
19690
19231
  success: false,
19691
19232
  error: error instanceof Error ? error.message : "Unknown error occurred"
19692
19233
  }, sendMessage);
@@ -19695,14 +19236,14 @@ async function handleUsersRequest(data, collections, sendMessage) {
19695
19236
  async function handleCreate(id, userData, executeCollection, userManager, sendMessage, clientId) {
19696
19237
  const { username, email, password, fullname, role, userInfo } = userData;
19697
19238
  if (!username || username.trim().length === 0) {
19698
- sendResponse3(id, {
19239
+ sendResponse2(id, {
19699
19240
  success: false,
19700
19241
  error: "Username is required and cannot be empty"
19701
19242
  }, sendMessage, clientId);
19702
19243
  return;
19703
19244
  }
19704
19245
  if (!password || password.trim().length === 0) {
19705
- sendResponse3(id, {
19246
+ sendResponse2(id, {
19706
19247
  success: false,
19707
19248
  error: "Password is required and cannot be empty"
19708
19249
  }, sendMessage, clientId);
@@ -19711,7 +19252,7 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
19711
19252
  if (email && email.trim().length > 0) {
19712
19253
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
19713
19254
  if (!emailRegex.test(email)) {
19714
- sendResponse3(id, {
19255
+ sendResponse2(id, {
19715
19256
  success: false,
19716
19257
  error: "Invalid email format"
19717
19258
  }, sendMessage, clientId);
@@ -19729,7 +19270,7 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
19729
19270
  });
19730
19271
  if (result && result.success) {
19731
19272
  logger.info(`[DB] User created successfully: ${username}`);
19732
- sendResponse3(id, {
19273
+ sendResponse2(id, {
19733
19274
  success: true,
19734
19275
  data: {
19735
19276
  id: result.data?.id,
@@ -19747,14 +19288,14 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
19747
19288
  }
19748
19289
  try {
19749
19290
  if (userManager.userExists(username)) {
19750
- sendResponse3(id, {
19291
+ sendResponse2(id, {
19751
19292
  success: false,
19752
19293
  error: `User '${username}' already exists`
19753
19294
  }, sendMessage, clientId);
19754
19295
  return;
19755
19296
  }
19756
19297
  if (email && userManager.getUserByEmail(email)) {
19757
- sendResponse3(id, {
19298
+ sendResponse2(id, {
19758
19299
  success: false,
19759
19300
  error: `User with email '${email}' already exists`
19760
19301
  }, sendMessage, clientId);
@@ -19775,7 +19316,7 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
19775
19316
  }
19776
19317
  const newUser = userManager.createUser(newUserData);
19777
19318
  logger.info(`[FILE] User '${username}' created successfully`);
19778
- sendResponse3(id, {
19319
+ sendResponse2(id, {
19779
19320
  success: true,
19780
19321
  data: {
19781
19322
  username: newUser.username,
@@ -19786,7 +19327,7 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
19786
19327
  }
19787
19328
  }, sendMessage, clientId);
19788
19329
  } catch (error) {
19789
- sendResponse3(id, {
19330
+ sendResponse2(id, {
19790
19331
  success: false,
19791
19332
  error: error instanceof Error ? error.message : "Failed to create user"
19792
19333
  }, sendMessage, clientId);
@@ -19795,7 +19336,7 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
19795
19336
  async function handleUpdate(id, numericId, userData, executeCollection, userManager, sendMessage, clientId) {
19796
19337
  const { username, email, password, fullname, role, userInfo } = userData;
19797
19338
  if (!numericId && !username) {
19798
- sendResponse3(id, {
19339
+ sendResponse2(id, {
19799
19340
  success: false,
19800
19341
  error: "User ID or username is required"
19801
19342
  }, sendMessage, clientId);
@@ -19814,7 +19355,7 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19814
19355
  });
19815
19356
  if (result && result.success) {
19816
19357
  logger.info(`[DB] User updated successfully, ID: ${numericId}`);
19817
- sendResponse3(id, {
19358
+ sendResponse2(id, {
19818
19359
  success: true,
19819
19360
  data: {
19820
19361
  id: result.data?.id,
@@ -19832,14 +19373,14 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19832
19373
  }
19833
19374
  }
19834
19375
  if (!username || username.trim().length === 0) {
19835
- sendResponse3(id, {
19376
+ sendResponse2(id, {
19836
19377
  success: false,
19837
19378
  error: "Username is required for file-based storage update"
19838
19379
  }, sendMessage, clientId);
19839
19380
  return;
19840
19381
  }
19841
19382
  if (!userManager.userExists(username)) {
19842
- sendResponse3(id, {
19383
+ sendResponse2(id, {
19843
19384
  success: false,
19844
19385
  error: `User '${username}' not found`
19845
19386
  }, sendMessage, clientId);
@@ -19850,7 +19391,7 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19850
19391
  if (email.trim().length > 0) {
19851
19392
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
19852
19393
  if (!emailRegex.test(email)) {
19853
- sendResponse3(id, {
19394
+ sendResponse2(id, {
19854
19395
  success: false,
19855
19396
  error: "Invalid email format"
19856
19397
  }, sendMessage, clientId);
@@ -19858,7 +19399,7 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19858
19399
  }
19859
19400
  const existingUser = userManager.getUserByEmail(email);
19860
19401
  if (existingUser && existingUser.username !== username) {
19861
- sendResponse3(id, {
19402
+ sendResponse2(id, {
19862
19403
  success: false,
19863
19404
  error: `Email '${email}' is already used by another user`
19864
19405
  }, sendMessage, clientId);
@@ -19879,7 +19420,7 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19879
19420
  updates.role = role.trim().length > 0 ? role.trim() : void 0;
19880
19421
  }
19881
19422
  if (Object.keys(updates).length === 0) {
19882
- sendResponse3(id, {
19423
+ sendResponse2(id, {
19883
19424
  success: false,
19884
19425
  error: "No fields to update. Please provide at least one field to update."
19885
19426
  }, sendMessage, clientId);
@@ -19888,7 +19429,7 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19888
19429
  try {
19889
19430
  const updatedUser = userManager.updateUser(username, updates);
19890
19431
  logger.info(`[FILE] User '${username}' updated successfully`);
19891
- sendResponse3(id, {
19432
+ sendResponse2(id, {
19892
19433
  success: true,
19893
19434
  data: {
19894
19435
  username: updatedUser.username,
@@ -19899,7 +19440,7 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19899
19440
  }
19900
19441
  }, sendMessage, clientId);
19901
19442
  } catch (error) {
19902
- sendResponse3(id, {
19443
+ sendResponse2(id, {
19903
19444
  success: false,
19904
19445
  error: error instanceof Error ? error.message : "Failed to update user"
19905
19446
  }, sendMessage, clientId);
@@ -19907,7 +19448,7 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19907
19448
  }
19908
19449
  async function handleDelete(id, numericId, username, executeCollection, userManager, sendMessage, clientId) {
19909
19450
  if (!numericId && !username) {
19910
- sendResponse3(id, {
19451
+ sendResponse2(id, {
19911
19452
  success: false,
19912
19453
  error: "User ID or username is required"
19913
19454
  }, sendMessage, clientId);
@@ -19918,7 +19459,7 @@ async function handleDelete(id, numericId, username, executeCollection, userMana
19918
19459
  const result = await executeCollection("users", "delete", { id: numericId });
19919
19460
  if (result && result.success) {
19920
19461
  logger.info(`[DB] User deleted successfully, ID: ${numericId}`);
19921
- sendResponse3(id, {
19462
+ sendResponse2(id, {
19922
19463
  success: true,
19923
19464
  data: {
19924
19465
  id: numericId,
@@ -19933,14 +19474,14 @@ async function handleDelete(id, numericId, username, executeCollection, userMana
19933
19474
  }
19934
19475
  }
19935
19476
  if (!username || username.trim().length === 0) {
19936
- sendResponse3(id, {
19477
+ sendResponse2(id, {
19937
19478
  success: false,
19938
19479
  error: "Username is required for file-based storage delete"
19939
19480
  }, sendMessage, clientId);
19940
19481
  return;
19941
19482
  }
19942
19483
  if (!userManager.userExists(username)) {
19943
- sendResponse3(id, {
19484
+ sendResponse2(id, {
19944
19485
  success: false,
19945
19486
  error: `User '${username}' not found`
19946
19487
  }, sendMessage, clientId);
@@ -19948,14 +19489,14 @@ async function handleDelete(id, numericId, username, executeCollection, userMana
19948
19489
  }
19949
19490
  const deleted = userManager.deleteUser(username);
19950
19491
  if (!deleted) {
19951
- sendResponse3(id, {
19492
+ sendResponse2(id, {
19952
19493
  success: false,
19953
19494
  error: `Failed to delete user '${username}'`
19954
19495
  }, sendMessage, clientId);
19955
19496
  return;
19956
19497
  }
19957
19498
  logger.info(`[FILE] User '${username}' deleted successfully`);
19958
- sendResponse3(id, {
19499
+ sendResponse2(id, {
19959
19500
  success: true,
19960
19501
  data: {
19961
19502
  username,
@@ -19978,7 +19519,7 @@ async function handleGetAll(id, executeCollection, userManager, sendMessage, cli
19978
19519
  updatedAt: user.updatedAt
19979
19520
  }));
19980
19521
  logger.info(`[DB] Retrieved ${result.count} users`);
19981
- sendResponse3(id, {
19522
+ sendResponse2(id, {
19982
19523
  success: true,
19983
19524
  data: {
19984
19525
  users: sanitizedUsers2,
@@ -20000,7 +19541,7 @@ async function handleGetAll(id, executeCollection, userManager, sendMessage, cli
20000
19541
  wsIds: user.wsIds || []
20001
19542
  }));
20002
19543
  logger.info(`[FILE] Retrieved ${sanitizedUsers.length} users`);
20003
- sendResponse3(id, {
19544
+ sendResponse2(id, {
20004
19545
  success: true,
20005
19546
  data: {
20006
19547
  users: sanitizedUsers,
@@ -20011,7 +19552,7 @@ async function handleGetAll(id, executeCollection, userManager, sendMessage, cli
20011
19552
  }
20012
19553
  async function handleGetOne(id, numericId, username, executeCollection, userManager, sendMessage, clientId) {
20013
19554
  if (!numericId && !username) {
20014
- sendResponse3(id, {
19555
+ sendResponse2(id, {
20015
19556
  success: false,
20016
19557
  error: "User ID or username is required"
20017
19558
  }, sendMessage, clientId);
@@ -20032,7 +19573,7 @@ async function handleGetOne(id, numericId, username, executeCollection, userMana
20032
19573
  updatedAt: result.data?.updatedAt
20033
19574
  };
20034
19575
  logger.info(`[DB] Retrieved user ID: ${numericId}`);
20035
- sendResponse3(id, {
19576
+ sendResponse2(id, {
20036
19577
  success: true,
20037
19578
  data: {
20038
19579
  user: sanitizedUser2,
@@ -20046,14 +19587,14 @@ async function handleGetOne(id, numericId, username, executeCollection, userMana
20046
19587
  }
20047
19588
  }
20048
19589
  if (!username || username.trim().length === 0) {
20049
- sendResponse3(id, {
19590
+ sendResponse2(id, {
20050
19591
  success: false,
20051
19592
  error: "Username is required for file-based storage lookup"
20052
19593
  }, sendMessage, clientId);
20053
19594
  return;
20054
19595
  }
20055
19596
  if (!userManager.userExists(username)) {
20056
- sendResponse3(id, {
19597
+ sendResponse2(id, {
20057
19598
  success: false,
20058
19599
  error: `User '${username}' not found`
20059
19600
  }, sendMessage, clientId);
@@ -20068,7 +19609,7 @@ async function handleGetOne(id, numericId, username, executeCollection, userMana
20068
19609
  wsIds: user.wsIds || []
20069
19610
  };
20070
19611
  logger.info(`[FILE] Retrieved user: ${username}`);
20071
- sendResponse3(id, {
19612
+ sendResponse2(id, {
20072
19613
  success: true,
20073
19614
  data: {
20074
19615
  user: sanitizedUser,
@@ -20095,7 +19636,7 @@ async function handleQuery(id, filters, limit, sort, executeCollection, userMana
20095
19636
  updatedAt: user.updatedAt
20096
19637
  }));
20097
19638
  logger.info(`[DB] Query returned ${result.count} users`);
20098
- sendResponse3(id, {
19639
+ sendResponse2(id, {
20099
19640
  success: true,
20100
19641
  data: {
20101
19642
  users: sanitizedUsers2,
@@ -20118,7 +19659,7 @@ async function handleQuery(id, filters, limit, sort, executeCollection, userMana
20118
19659
  wsIds: user.wsIds || []
20119
19660
  }));
20120
19661
  logger.info(`[FILE] Retrieved ${sanitizedUsers.length} users (all - no query filter)`);
20121
- sendResponse3(id, {
19662
+ sendResponse2(id, {
20122
19663
  success: true,
20123
19664
  data: {
20124
19665
  users: sanitizedUsers,
@@ -20127,7 +19668,7 @@ async function handleQuery(id, filters, limit, sort, executeCollection, userMana
20127
19668
  }
20128
19669
  }, sendMessage, clientId);
20129
19670
  }
20130
- function sendResponse3(id, res, sendMessage, clientId) {
19671
+ function sendResponse2(id, res, sendMessage, clientId) {
20131
19672
  const response = {
20132
19673
  id: id || "unknown",
20133
19674
  type: "USERS_RES",
@@ -20183,7 +19724,7 @@ async function handleDashboardsRequest(data, collections, sendMessage) {
20183
19724
  const sort = requestData?.sort;
20184
19725
  const readOnlyOperations = ["query", "getAll", "getOne"];
20185
19726
  if (!readOnlyOperations.includes(operation) && from.type !== "admin") {
20186
- sendResponse4(id, {
19727
+ sendResponse3(id, {
20187
19728
  success: false,
20188
19729
  error: "Unauthorized: Only admin can manage dashboards"
20189
19730
  }, sendMessage, from.id);
@@ -20211,14 +19752,14 @@ async function handleDashboardsRequest(data, collections, sendMessage) {
20211
19752
  await handleQuery2(id, filters, limit, sort, executeCollection, dashboardManager2, sendMessage, from.id);
20212
19753
  break;
20213
19754
  default:
20214
- sendResponse4(id, {
19755
+ sendResponse3(id, {
20215
19756
  success: false,
20216
19757
  error: `Unknown operation: ${operation}`
20217
19758
  }, sendMessage, from.id);
20218
19759
  }
20219
19760
  } catch (error) {
20220
19761
  logger.error("Failed to handle dashboards request:", error);
20221
- sendResponse4(null, {
19762
+ sendResponse3(null, {
20222
19763
  success: false,
20223
19764
  error: error instanceof Error ? error.message : "Unknown error occurred"
20224
19765
  }, sendMessage);
@@ -20226,14 +19767,14 @@ async function handleDashboardsRequest(data, collections, sendMessage) {
20226
19767
  }
20227
19768
  async function handleCreate2(id, dashboardId, dashboard, projectId, name, description, published, createdBy, allowedUsers, executeCollection, dashboardManager2, sendMessage, clientId) {
20228
19769
  if (!dashboardId || dashboardId.trim().length === 0) {
20229
- sendResponse4(id, {
19770
+ sendResponse3(id, {
20230
19771
  success: false,
20231
19772
  error: "Dashboard ID is required and cannot be empty"
20232
19773
  }, sendMessage, clientId);
20233
19774
  return;
20234
19775
  }
20235
19776
  if (!projectId) {
20236
- sendResponse4(id, {
19777
+ sendResponse3(id, {
20237
19778
  success: false,
20238
19779
  error: "Project ID is required"
20239
19780
  }, sendMessage, clientId);
@@ -20252,7 +19793,7 @@ async function handleCreate2(id, dashboardId, dashboard, projectId, name, descri
20252
19793
  });
20253
19794
  if (result && result.success) {
20254
19795
  logger.info(`[DB] Dashboard created successfully, ID: ${result.data?.id}`);
20255
- sendResponse4(id, {
19796
+ sendResponse3(id, {
20256
19797
  success: true,
20257
19798
  data: {
20258
19799
  id: result.data?.id,
@@ -20272,7 +19813,7 @@ async function handleCreate2(id, dashboardId, dashboard, projectId, name, descri
20272
19813
  }
20273
19814
  const createdDashboard = dashboardManager2.createDashboard(dashboardId, dashboard);
20274
19815
  logger.info(`[FILE] Dashboard '${dashboardId}' created successfully`);
20275
- sendResponse4(id, {
19816
+ sendResponse3(id, {
20276
19817
  success: true,
20277
19818
  data: {
20278
19819
  dashboardId,
@@ -20281,7 +19822,7 @@ async function handleCreate2(id, dashboardId, dashboard, projectId, name, descri
20281
19822
  }
20282
19823
  }, sendMessage, clientId);
20283
19824
  } catch (error) {
20284
- sendResponse4(id, {
19825
+ sendResponse3(id, {
20285
19826
  success: false,
20286
19827
  error: error instanceof Error ? error.message : "Failed to create dashboard"
20287
19828
  }, sendMessage, clientId);
@@ -20289,7 +19830,7 @@ async function handleCreate2(id, dashboardId, dashboard, projectId, name, descri
20289
19830
  }
20290
19831
  async function handleUpdate2(id, numericId, dashboardId, dashboard, name, description, published, updatedBy, allowedUsers, executeCollection, dashboardManager2, sendMessage, clientId) {
20291
19832
  if (!numericId) {
20292
- sendResponse4(id, {
19833
+ sendResponse3(id, {
20293
19834
  success: false,
20294
19835
  error: "Dashboard ID is required"
20295
19836
  }, sendMessage, clientId);
@@ -20307,7 +19848,7 @@ async function handleUpdate2(id, numericId, dashboardId, dashboard, name, descri
20307
19848
  });
20308
19849
  if (result && result.success) {
20309
19850
  logger.info(`[DB] Dashboard updated successfully, ID: ${numericId}`);
20310
- sendResponse4(id, {
19851
+ sendResponse3(id, {
20311
19852
  success: true,
20312
19853
  data: {
20313
19854
  id: numericId,
@@ -20325,14 +19866,14 @@ async function handleUpdate2(id, numericId, dashboardId, dashboard, name, descri
20325
19866
  try {
20326
19867
  const updatedDashboard = dashboardManager2.updateDashboard(fileStorageId, dashboard);
20327
19868
  if (!updatedDashboard) {
20328
- sendResponse4(id, {
19869
+ sendResponse3(id, {
20329
19870
  success: false,
20330
19871
  error: `Dashboard '${fileStorageId}' not found`
20331
19872
  }, sendMessage, clientId);
20332
19873
  return;
20333
19874
  }
20334
19875
  logger.info(`[FILE] Dashboard '${fileStorageId}' updated successfully`);
20335
- sendResponse4(id, {
19876
+ sendResponse3(id, {
20336
19877
  success: true,
20337
19878
  data: {
20338
19879
  id: numericId,
@@ -20342,7 +19883,7 @@ async function handleUpdate2(id, numericId, dashboardId, dashboard, name, descri
20342
19883
  }
20343
19884
  }, sendMessage, clientId);
20344
19885
  } catch (error) {
20345
- sendResponse4(id, {
19886
+ sendResponse3(id, {
20346
19887
  success: false,
20347
19888
  error: error instanceof Error ? error.message : "Failed to update dashboard"
20348
19889
  }, sendMessage, clientId);
@@ -20350,7 +19891,7 @@ async function handleUpdate2(id, numericId, dashboardId, dashboard, name, descri
20350
19891
  }
20351
19892
  async function handleDelete2(id, numericId, dashboardId, executeCollection, dashboardManager2, sendMessage, clientId) {
20352
19893
  if (!numericId) {
20353
- sendResponse4(id, {
19894
+ sendResponse3(id, {
20354
19895
  success: false,
20355
19896
  error: "Dashboard ID is required"
20356
19897
  }, sendMessage, clientId);
@@ -20360,7 +19901,7 @@ async function handleDelete2(id, numericId, dashboardId, executeCollection, dash
20360
19901
  const result = await executeCollection("dashboards", "delete", { id: numericId });
20361
19902
  if (result && result.success) {
20362
19903
  logger.info(`[DB] Dashboard deleted successfully, ID: ${numericId}`);
20363
- sendResponse4(id, {
19904
+ sendResponse3(id, {
20364
19905
  success: true,
20365
19906
  data: {
20366
19907
  id: numericId,
@@ -20375,14 +19916,14 @@ async function handleDelete2(id, numericId, dashboardId, executeCollection, dash
20375
19916
  const fileStorageId = dashboardId || String(numericId);
20376
19917
  const deleted = dashboardManager2.deleteDashboard(fileStorageId);
20377
19918
  if (!deleted) {
20378
- sendResponse4(id, {
19919
+ sendResponse3(id, {
20379
19920
  success: false,
20380
19921
  error: `Dashboard '${fileStorageId}' not found`
20381
19922
  }, sendMessage, clientId);
20382
19923
  return;
20383
19924
  }
20384
19925
  logger.info(`[FILE] Dashboard '${fileStorageId}' deleted successfully`);
20385
- sendResponse4(id, {
19926
+ sendResponse3(id, {
20386
19927
  success: true,
20387
19928
  data: {
20388
19929
  id: numericId,
@@ -20396,7 +19937,7 @@ async function handleGetAll2(id, executeCollection, dashboardManager2, sendMessa
20396
19937
  const result = await executeCollection("dashboards", "getAll", {});
20397
19938
  if (result && result.success) {
20398
19939
  logger.info(`[DB] Retrieved ${result.count} dashboards`);
20399
- sendResponse4(id, {
19940
+ sendResponse3(id, {
20400
19941
  success: true,
20401
19942
  data: {
20402
19943
  dashboards: result.data,
@@ -20411,7 +19952,7 @@ async function handleGetAll2(id, executeCollection, dashboardManager2, sendMessa
20411
19952
  }
20412
19953
  const dashboards = dashboardManager2.getAllDashboards();
20413
19954
  logger.info(`[FILE] Retrieved ${dashboards.length} dashboards`);
20414
- sendResponse4(id, {
19955
+ sendResponse3(id, {
20415
19956
  success: true,
20416
19957
  data: {
20417
19958
  dashboards,
@@ -20422,7 +19963,7 @@ async function handleGetAll2(id, executeCollection, dashboardManager2, sendMessa
20422
19963
  }
20423
19964
  async function handleGetOne2(id, numericId, dashboardId, executeCollection, dashboardManager2, sendMessage, clientId) {
20424
19965
  if (!numericId) {
20425
- sendResponse4(id, {
19966
+ sendResponse3(id, {
20426
19967
  success: false,
20427
19968
  error: "Dashboard ID is required"
20428
19969
  }, sendMessage, clientId);
@@ -20432,7 +19973,7 @@ async function handleGetOne2(id, numericId, dashboardId, executeCollection, dash
20432
19973
  const result = await executeCollection("dashboards", "getOne", { id: numericId });
20433
19974
  if (result && result.success) {
20434
19975
  logger.info(`[DB] Retrieved dashboard ID: ${numericId}`);
20435
- sendResponse4(id, {
19976
+ sendResponse3(id, {
20436
19977
  success: true,
20437
19978
  data: {
20438
19979
  id: numericId,
@@ -20449,14 +19990,14 @@ async function handleGetOne2(id, numericId, dashboardId, executeCollection, dash
20449
19990
  const fileStorageId = dashboardId || String(numericId);
20450
19991
  const dashboard = dashboardManager2.getDashboard(fileStorageId);
20451
19992
  if (!dashboard) {
20452
- sendResponse4(id, {
19993
+ sendResponse3(id, {
20453
19994
  success: false,
20454
19995
  error: `Dashboard '${fileStorageId}' not found`
20455
19996
  }, sendMessage, clientId);
20456
19997
  return;
20457
19998
  }
20458
19999
  logger.info(`[FILE] Retrieved dashboard: ${fileStorageId}`);
20459
- sendResponse4(id, {
20000
+ sendResponse3(id, {
20460
20001
  success: true,
20461
20002
  data: {
20462
20003
  id: numericId,
@@ -20475,7 +20016,7 @@ async function handleQuery2(id, filters, limit, sort, executeCollection, dashboa
20475
20016
  });
20476
20017
  if (result && result.success) {
20477
20018
  logger.info(`[DB] Query returned ${result.count} dashboards`);
20478
- sendResponse4(id, {
20019
+ sendResponse3(id, {
20479
20020
  success: true,
20480
20021
  data: {
20481
20022
  dashboards: result.data,
@@ -20490,7 +20031,7 @@ async function handleQuery2(id, filters, limit, sort, executeCollection, dashboa
20490
20031
  }
20491
20032
  const dashboards = dashboardManager2.getAllDashboards();
20492
20033
  logger.info(`[FILE] Retrieved ${dashboards.length} dashboards (all - no query filter)`);
20493
- sendResponse4(id, {
20034
+ sendResponse3(id, {
20494
20035
  success: true,
20495
20036
  data: {
20496
20037
  dashboards,
@@ -20499,7 +20040,7 @@ async function handleQuery2(id, filters, limit, sort, executeCollection, dashboa
20499
20040
  }
20500
20041
  }, sendMessage, clientId);
20501
20042
  }
20502
- function sendResponse4(id, res, sendMessage, clientId) {
20043
+ function sendResponse3(id, res, sendMessage, clientId) {
20503
20044
  const response = {
20504
20045
  id: id || "unknown",
20505
20046
  type: "DASHBOARDS_RES",
@@ -20554,7 +20095,7 @@ async function handleReportsRequest(data, collections, sendMessage) {
20554
20095
  const sort = requestData?.sort;
20555
20096
  const readOnlyOperations = ["query", "getAll", "getOne"];
20556
20097
  if (!readOnlyOperations.includes(operation) && from.type !== "admin") {
20557
- sendResponse5(id, {
20098
+ sendResponse4(id, {
20558
20099
  success: false,
20559
20100
  error: "Unauthorized: Only admin can manage reports"
20560
20101
  }, sendMessage, from.id);
@@ -20582,14 +20123,14 @@ async function handleReportsRequest(data, collections, sendMessage) {
20582
20123
  await handleQuery3(id, filters, limit, sort, executeCollection, reportManager2, sendMessage, from.id);
20583
20124
  break;
20584
20125
  default:
20585
- sendResponse5(id, {
20126
+ sendResponse4(id, {
20586
20127
  success: false,
20587
20128
  error: `Unknown operation: ${operation}`
20588
20129
  }, sendMessage, from.id);
20589
20130
  }
20590
20131
  } catch (error) {
20591
20132
  logger.error("Failed to handle reports request:", error);
20592
- sendResponse5(null, {
20133
+ sendResponse4(null, {
20593
20134
  success: false,
20594
20135
  error: error instanceof Error ? error.message : "Unknown error occurred"
20595
20136
  }, sendMessage);
@@ -20597,14 +20138,14 @@ async function handleReportsRequest(data, collections, sendMessage) {
20597
20138
  }
20598
20139
  async function handleCreate3(id, reportId, report, projectId, name, description, published, createdBy, executeCollection, reportManager2, sendMessage, clientId) {
20599
20140
  if (!reportId || reportId.trim().length === 0) {
20600
- sendResponse5(id, {
20141
+ sendResponse4(id, {
20601
20142
  success: false,
20602
20143
  error: "Report ID is required and cannot be empty"
20603
20144
  }, sendMessage, clientId);
20604
20145
  return;
20605
20146
  }
20606
20147
  if (!projectId) {
20607
- sendResponse5(id, {
20148
+ sendResponse4(id, {
20608
20149
  success: false,
20609
20150
  error: "Project ID is required"
20610
20151
  }, sendMessage, clientId);
@@ -20622,7 +20163,7 @@ async function handleCreate3(id, reportId, report, projectId, name, description,
20622
20163
  });
20623
20164
  if (result && result.success) {
20624
20165
  logger.info(`[DB] Report created successfully, ID: ${result.data?.id}`);
20625
- sendResponse5(id, {
20166
+ sendResponse4(id, {
20626
20167
  success: true,
20627
20168
  data: {
20628
20169
  id: result.data?.id,
@@ -20642,7 +20183,7 @@ async function handleCreate3(id, reportId, report, projectId, name, description,
20642
20183
  }
20643
20184
  const createdReport = reportManager2.createReport(reportId, report);
20644
20185
  logger.info(`[FILE] Report '${reportId}' created successfully`);
20645
- sendResponse5(id, {
20186
+ sendResponse4(id, {
20646
20187
  success: true,
20647
20188
  data: {
20648
20189
  reportId,
@@ -20651,7 +20192,7 @@ async function handleCreate3(id, reportId, report, projectId, name, description,
20651
20192
  }
20652
20193
  }, sendMessage, clientId);
20653
20194
  } catch (error) {
20654
- sendResponse5(id, {
20195
+ sendResponse4(id, {
20655
20196
  success: false,
20656
20197
  error: error instanceof Error ? error.message : "Failed to create report"
20657
20198
  }, sendMessage, clientId);
@@ -20659,7 +20200,7 @@ async function handleCreate3(id, reportId, report, projectId, name, description,
20659
20200
  }
20660
20201
  async function handleUpdate3(id, numericId, reportId, report, name, description, published, updatedBy, executeCollection, reportManager2, sendMessage, clientId) {
20661
20202
  if (!numericId) {
20662
- sendResponse5(id, {
20203
+ sendResponse4(id, {
20663
20204
  success: false,
20664
20205
  error: "Report ID is required"
20665
20206
  }, sendMessage, clientId);
@@ -20676,7 +20217,7 @@ async function handleUpdate3(id, numericId, reportId, report, name, description,
20676
20217
  });
20677
20218
  if (result && result.success) {
20678
20219
  logger.info(`[DB] Report updated successfully, ID: ${numericId}`);
20679
- sendResponse5(id, {
20220
+ sendResponse4(id, {
20680
20221
  success: true,
20681
20222
  data: {
20682
20223
  id: numericId,
@@ -20694,14 +20235,14 @@ async function handleUpdate3(id, numericId, reportId, report, name, description,
20694
20235
  try {
20695
20236
  const updatedReport = reportManager2.updateReport(fileStorageId, report);
20696
20237
  if (!updatedReport) {
20697
- sendResponse5(id, {
20238
+ sendResponse4(id, {
20698
20239
  success: false,
20699
20240
  error: `Report '${fileStorageId}' not found`
20700
20241
  }, sendMessage, clientId);
20701
20242
  return;
20702
20243
  }
20703
20244
  logger.info(`[FILE] Report '${fileStorageId}' updated successfully`);
20704
- sendResponse5(id, {
20245
+ sendResponse4(id, {
20705
20246
  success: true,
20706
20247
  data: {
20707
20248
  id: numericId,
@@ -20711,7 +20252,7 @@ async function handleUpdate3(id, numericId, reportId, report, name, description,
20711
20252
  }
20712
20253
  }, sendMessage, clientId);
20713
20254
  } catch (error) {
20714
- sendResponse5(id, {
20255
+ sendResponse4(id, {
20715
20256
  success: false,
20716
20257
  error: error instanceof Error ? error.message : "Failed to update report"
20717
20258
  }, sendMessage, clientId);
@@ -20719,7 +20260,7 @@ async function handleUpdate3(id, numericId, reportId, report, name, description,
20719
20260
  }
20720
20261
  async function handleDelete3(id, numericId, reportId, executeCollection, reportManager2, sendMessage, clientId) {
20721
20262
  if (!numericId) {
20722
- sendResponse5(id, {
20263
+ sendResponse4(id, {
20723
20264
  success: false,
20724
20265
  error: "Report ID is required"
20725
20266
  }, sendMessage, clientId);
@@ -20729,7 +20270,7 @@ async function handleDelete3(id, numericId, reportId, executeCollection, reportM
20729
20270
  const result = await executeCollection("reports", "delete", { id: numericId });
20730
20271
  if (result && result.success) {
20731
20272
  logger.info(`[DB] Report deleted successfully, ID: ${numericId}`);
20732
- sendResponse5(id, {
20273
+ sendResponse4(id, {
20733
20274
  success: true,
20734
20275
  data: {
20735
20276
  id: numericId,
@@ -20744,14 +20285,14 @@ async function handleDelete3(id, numericId, reportId, executeCollection, reportM
20744
20285
  const fileStorageId = reportId || String(numericId);
20745
20286
  const deleted = reportManager2.deleteReport(fileStorageId);
20746
20287
  if (!deleted) {
20747
- sendResponse5(id, {
20288
+ sendResponse4(id, {
20748
20289
  success: false,
20749
20290
  error: `Report '${fileStorageId}' not found`
20750
20291
  }, sendMessage, clientId);
20751
20292
  return;
20752
20293
  }
20753
20294
  logger.info(`[FILE] Report '${fileStorageId}' deleted successfully`);
20754
- sendResponse5(id, {
20295
+ sendResponse4(id, {
20755
20296
  success: true,
20756
20297
  data: {
20757
20298
  id: numericId,
@@ -20765,7 +20306,7 @@ async function handleGetAll3(id, executeCollection, reportManager2, sendMessage,
20765
20306
  const result = await executeCollection("reports", "getAll", {});
20766
20307
  if (result && result.success) {
20767
20308
  logger.info(`[DB] Retrieved ${result.count} reports`);
20768
- sendResponse5(id, {
20309
+ sendResponse4(id, {
20769
20310
  success: true,
20770
20311
  data: {
20771
20312
  reports: result.data,
@@ -20780,7 +20321,7 @@ async function handleGetAll3(id, executeCollection, reportManager2, sendMessage,
20780
20321
  }
20781
20322
  const reports = reportManager2.getAllReports();
20782
20323
  logger.info(`[FILE] Retrieved ${reports.length} reports`);
20783
- sendResponse5(id, {
20324
+ sendResponse4(id, {
20784
20325
  success: true,
20785
20326
  data: {
20786
20327
  reports,
@@ -20791,7 +20332,7 @@ async function handleGetAll3(id, executeCollection, reportManager2, sendMessage,
20791
20332
  }
20792
20333
  async function handleGetOne3(id, numericId, reportId, executeCollection, reportManager2, sendMessage, clientId) {
20793
20334
  if (!numericId) {
20794
- sendResponse5(id, {
20335
+ sendResponse4(id, {
20795
20336
  success: false,
20796
20337
  error: "Report ID is required"
20797
20338
  }, sendMessage, clientId);
@@ -20801,7 +20342,7 @@ async function handleGetOne3(id, numericId, reportId, executeCollection, reportM
20801
20342
  const result = await executeCollection("reports", "getOne", { id: numericId });
20802
20343
  if (result && result.success) {
20803
20344
  logger.info(`[DB] Retrieved report ID: ${numericId}`);
20804
- sendResponse5(id, {
20345
+ sendResponse4(id, {
20805
20346
  success: true,
20806
20347
  data: {
20807
20348
  id: numericId,
@@ -20818,14 +20359,14 @@ async function handleGetOne3(id, numericId, reportId, executeCollection, reportM
20818
20359
  const fileStorageId = reportId || String(numericId);
20819
20360
  const report = reportManager2.getReport(fileStorageId);
20820
20361
  if (!report) {
20821
- sendResponse5(id, {
20362
+ sendResponse4(id, {
20822
20363
  success: false,
20823
20364
  error: `Report '${fileStorageId}' not found`
20824
20365
  }, sendMessage, clientId);
20825
20366
  return;
20826
20367
  }
20827
20368
  logger.info(`[FILE] Retrieved report: ${fileStorageId}`);
20828
- sendResponse5(id, {
20369
+ sendResponse4(id, {
20829
20370
  success: true,
20830
20371
  data: {
20831
20372
  id: numericId,
@@ -20844,7 +20385,7 @@ async function handleQuery3(id, filters, limit, sort, executeCollection, reportM
20844
20385
  });
20845
20386
  if (result && result.success) {
20846
20387
  logger.info(`[DB] Query returned ${result.count} reports`);
20847
- sendResponse5(id, {
20388
+ sendResponse4(id, {
20848
20389
  success: true,
20849
20390
  data: {
20850
20391
  reports: result.data,
@@ -20859,7 +20400,7 @@ async function handleQuery3(id, filters, limit, sort, executeCollection, reportM
20859
20400
  }
20860
20401
  const reports = reportManager2.getAllReports();
20861
20402
  logger.info(`[FILE] Retrieved ${reports.length} reports (all - no query filter)`);
20862
- sendResponse5(id, {
20403
+ sendResponse4(id, {
20863
20404
  success: true,
20864
20405
  data: {
20865
20406
  reports,
@@ -20868,7 +20409,7 @@ async function handleQuery3(id, filters, limit, sort, executeCollection, reportM
20868
20409
  }
20869
20410
  }, sendMessage, clientId);
20870
20411
  }
20871
- function sendResponse5(id, res, sendMessage, clientId) {
20412
+ function sendResponse4(id, res, sendMessage, clientId) {
20872
20413
  const response = {
20873
20414
  id: id || "unknown",
20874
20415
  type: "REPORTS_RES",
@@ -20909,7 +20450,7 @@ async function handleUIsRequest(data, collections, sendMessage) {
20909
20450
  const limit = requestData?.limit;
20910
20451
  const sort = requestData?.sort;
20911
20452
  if (from.type !== "admin") {
20912
- sendResponse6(id, {
20453
+ sendResponse5(id, {
20913
20454
  success: false,
20914
20455
  error: "Unauthorized: Only admin can manage UIs"
20915
20456
  }, sendMessage, from.id);
@@ -20936,14 +20477,14 @@ async function handleUIsRequest(data, collections, sendMessage) {
20936
20477
  await handleQuery4(id, filters, limit, sort, executeCollection, sendMessage, from.id);
20937
20478
  break;
20938
20479
  default:
20939
- sendResponse6(id, {
20480
+ sendResponse5(id, {
20940
20481
  success: false,
20941
20482
  error: `Unknown operation: ${operation}`
20942
20483
  }, sendMessage, from.id);
20943
20484
  }
20944
20485
  } catch (error) {
20945
20486
  logger.error("Failed to handle UIs request:", error);
20946
- sendResponse6(null, {
20487
+ sendResponse5(null, {
20947
20488
  success: false,
20948
20489
  error: error instanceof Error ? error.message : "Unknown error occurred"
20949
20490
  }, sendMessage);
@@ -20951,14 +20492,14 @@ async function handleUIsRequest(data, collections, sendMessage) {
20951
20492
  }
20952
20493
  async function handleCreate4(id, uiId, ui, projectId, name, description, createdBy, executeCollection, sendMessage, clientId) {
20953
20494
  if (!uiId || uiId.trim().length === 0) {
20954
- sendResponse6(id, {
20495
+ sendResponse5(id, {
20955
20496
  success: false,
20956
20497
  error: "UI ID is required and cannot be empty"
20957
20498
  }, sendMessage, clientId);
20958
20499
  return;
20959
20500
  }
20960
20501
  if (!projectId || projectId.trim().length === 0) {
20961
- sendResponse6(id, {
20502
+ sendResponse5(id, {
20962
20503
  success: false,
20963
20504
  error: "Project ID is required and cannot be empty"
20964
20505
  }, sendMessage, clientId);
@@ -20975,7 +20516,7 @@ async function handleCreate4(id, uiId, ui, projectId, name, description, created
20975
20516
  });
20976
20517
  if (result && result.success) {
20977
20518
  logger.info(`UI created successfully, ID: ${result.data?.id}`);
20978
- sendResponse6(id, {
20519
+ sendResponse5(id, {
20979
20520
  success: true,
20980
20521
  data: {
20981
20522
  id: result.data?.id,
@@ -20985,13 +20526,13 @@ async function handleCreate4(id, uiId, ui, projectId, name, description, created
20985
20526
  }
20986
20527
  }, sendMessage, clientId);
20987
20528
  } else {
20988
- sendResponse6(id, {
20529
+ sendResponse5(id, {
20989
20530
  success: false,
20990
20531
  error: "Failed to create UI"
20991
20532
  }, sendMessage, clientId);
20992
20533
  }
20993
20534
  } catch (error) {
20994
- sendResponse6(id, {
20535
+ sendResponse5(id, {
20995
20536
  success: false,
20996
20537
  error: error instanceof Error ? error.message : "Failed to create UI"
20997
20538
  }, sendMessage, clientId);
@@ -20999,7 +20540,7 @@ async function handleCreate4(id, uiId, ui, projectId, name, description, created
20999
20540
  }
21000
20541
  async function handleUpdate4(id, numericId, ui, name, description, updatedBy, executeCollection, sendMessage, clientId) {
21001
20542
  if (!numericId) {
21002
- sendResponse6(id, {
20543
+ sendResponse5(id, {
21003
20544
  success: false,
21004
20545
  error: "UI ID is required"
21005
20546
  }, sendMessage, clientId);
@@ -21015,7 +20556,7 @@ async function handleUpdate4(id, numericId, ui, name, description, updatedBy, ex
21015
20556
  });
21016
20557
  if (result && result.success) {
21017
20558
  logger.info(`UI updated successfully, ID: ${numericId}`);
21018
- sendResponse6(id, {
20559
+ sendResponse5(id, {
21019
20560
  success: true,
21020
20561
  data: {
21021
20562
  id: numericId,
@@ -21025,13 +20566,13 @@ async function handleUpdate4(id, numericId, ui, name, description, updatedBy, ex
21025
20566
  }
21026
20567
  }, sendMessage, clientId);
21027
20568
  } else {
21028
- sendResponse6(id, {
20569
+ sendResponse5(id, {
21029
20570
  success: false,
21030
20571
  error: "Failed to update UI"
21031
20572
  }, sendMessage, clientId);
21032
20573
  }
21033
20574
  } catch (error) {
21034
- sendResponse6(id, {
20575
+ sendResponse5(id, {
21035
20576
  success: false,
21036
20577
  error: error instanceof Error ? error.message : "Failed to update UI"
21037
20578
  }, sendMessage, clientId);
@@ -21039,7 +20580,7 @@ async function handleUpdate4(id, numericId, ui, name, description, updatedBy, ex
21039
20580
  }
21040
20581
  async function handleDelete4(id, numericId, executeCollection, sendMessage, clientId) {
21041
20582
  if (!numericId) {
21042
- sendResponse6(id, {
20583
+ sendResponse5(id, {
21043
20584
  success: false,
21044
20585
  error: "UI ID is required"
21045
20586
  }, sendMessage, clientId);
@@ -21049,7 +20590,7 @@ async function handleDelete4(id, numericId, executeCollection, sendMessage, clie
21049
20590
  const result = await executeCollection("uis", "delete", { id: numericId });
21050
20591
  if (result && result.success) {
21051
20592
  logger.info(`UI deleted successfully, ID: ${numericId}`);
21052
- sendResponse6(id, {
20593
+ sendResponse5(id, {
21053
20594
  success: true,
21054
20595
  data: {
21055
20596
  id: numericId,
@@ -21057,13 +20598,13 @@ async function handleDelete4(id, numericId, executeCollection, sendMessage, clie
21057
20598
  }
21058
20599
  }, sendMessage, clientId);
21059
20600
  } else {
21060
- sendResponse6(id, {
20601
+ sendResponse5(id, {
21061
20602
  success: false,
21062
20603
  error: "Failed to delete UI"
21063
20604
  }, sendMessage, clientId);
21064
20605
  }
21065
20606
  } catch (error) {
21066
- sendResponse6(id, {
20607
+ sendResponse5(id, {
21067
20608
  success: false,
21068
20609
  error: error instanceof Error ? error.message : "Failed to delete UI"
21069
20610
  }, sendMessage, clientId);
@@ -21074,7 +20615,7 @@ async function handleGetAll4(id, executeCollection, sendMessage, clientId) {
21074
20615
  const result = await executeCollection("uis", "getAll", {});
21075
20616
  if (result && result.success) {
21076
20617
  logger.info(`Retrieved ${result.count} UIs`);
21077
- sendResponse6(id, {
20618
+ sendResponse5(id, {
21078
20619
  success: true,
21079
20620
  data: {
21080
20621
  uis: result.data,
@@ -21083,13 +20624,13 @@ async function handleGetAll4(id, executeCollection, sendMessage, clientId) {
21083
20624
  }
21084
20625
  }, sendMessage, clientId);
21085
20626
  } else {
21086
- sendResponse6(id, {
20627
+ sendResponse5(id, {
21087
20628
  success: false,
21088
20629
  error: "Failed to get UIs"
21089
20630
  }, sendMessage, clientId);
21090
20631
  }
21091
20632
  } catch (error) {
21092
- sendResponse6(id, {
20633
+ sendResponse5(id, {
21093
20634
  success: false,
21094
20635
  error: error instanceof Error ? error.message : "Failed to get UIs"
21095
20636
  }, sendMessage, clientId);
@@ -21097,7 +20638,7 @@ async function handleGetAll4(id, executeCollection, sendMessage, clientId) {
21097
20638
  }
21098
20639
  async function handleGetOne4(id, numericId, executeCollection, sendMessage, clientId) {
21099
20640
  if (!numericId) {
21100
- sendResponse6(id, {
20641
+ sendResponse5(id, {
21101
20642
  success: false,
21102
20643
  error: "UI ID is required"
21103
20644
  }, sendMessage, clientId);
@@ -21107,7 +20648,7 @@ async function handleGetOne4(id, numericId, executeCollection, sendMessage, clie
21107
20648
  const result = await executeCollection("uis", "getOne", { id: numericId });
21108
20649
  if (result && result.success) {
21109
20650
  logger.info(`Retrieved UI ID: ${numericId}`);
21110
- sendResponse6(id, {
20651
+ sendResponse5(id, {
21111
20652
  success: true,
21112
20653
  data: {
21113
20654
  id: numericId,
@@ -21117,13 +20658,13 @@ async function handleGetOne4(id, numericId, executeCollection, sendMessage, clie
21117
20658
  }
21118
20659
  }, sendMessage, clientId);
21119
20660
  } else {
21120
- sendResponse6(id, {
20661
+ sendResponse5(id, {
21121
20662
  success: false,
21122
20663
  error: `UI not found`
21123
20664
  }, sendMessage, clientId);
21124
20665
  }
21125
20666
  } catch (error) {
21126
- sendResponse6(id, {
20667
+ sendResponse5(id, {
21127
20668
  success: false,
21128
20669
  error: error instanceof Error ? error.message : "Failed to get UI"
21129
20670
  }, sendMessage, clientId);
@@ -21138,7 +20679,7 @@ async function handleQuery4(id, filters, limit, sort, executeCollection, sendMes
21138
20679
  });
21139
20680
  if (result && result.success) {
21140
20681
  logger.info(`Query returned ${result.count} UIs`);
21141
- sendResponse6(id, {
20682
+ sendResponse5(id, {
21142
20683
  success: true,
21143
20684
  data: {
21144
20685
  uis: result.data,
@@ -21147,19 +20688,19 @@ async function handleQuery4(id, filters, limit, sort, executeCollection, sendMes
21147
20688
  }
21148
20689
  }, sendMessage, clientId);
21149
20690
  } else {
21150
- sendResponse6(id, {
20691
+ sendResponse5(id, {
21151
20692
  success: false,
21152
20693
  error: "Failed to query UIs"
21153
20694
  }, sendMessage, clientId);
21154
20695
  }
21155
20696
  } catch (error) {
21156
- sendResponse6(id, {
20697
+ sendResponse5(id, {
21157
20698
  success: false,
21158
20699
  error: error instanceof Error ? error.message : "Failed to query UIs"
21159
20700
  }, sendMessage, clientId);
21160
20701
  }
21161
20702
  }
21162
- function sendResponse6(id, res, sendMessage, clientId) {
20703
+ function sendResponse5(id, res, sendMessage, clientId) {
21163
20704
  const response = {
21164
20705
  id: id || "unknown",
21165
20706
  type: "UIS_RES",
@@ -21217,14 +20758,14 @@ async function handleBookmarksRequest(data, collections, sendMessage) {
21217
20758
  await handleQuery5(id, filters, limit, sort, executeCollection, sendMessage, from.id);
21218
20759
  break;
21219
20760
  default:
21220
- sendResponse7(id, {
20761
+ sendResponse6(id, {
21221
20762
  success: false,
21222
20763
  error: `Unknown operation: ${operation}`
21223
20764
  }, sendMessage, from.id);
21224
20765
  }
21225
20766
  } catch (error) {
21226
20767
  logger.error("Failed to handle bookmarks request:", error);
21227
- sendResponse7(null, {
20768
+ sendResponse6(null, {
21228
20769
  success: false,
21229
20770
  error: error instanceof Error ? error.message : "Unknown error occurred"
21230
20771
  }, sendMessage);
@@ -21232,14 +20773,14 @@ async function handleBookmarksRequest(data, collections, sendMessage) {
21232
20773
  }
21233
20774
  async function handleCreate5(id, userId, threadId, name, description, uiblock, executeCollection, sendMessage, clientId) {
21234
20775
  if (!userId) {
21235
- sendResponse7(id, {
20776
+ sendResponse6(id, {
21236
20777
  success: false,
21237
20778
  error: "userId is required"
21238
20779
  }, sendMessage, clientId);
21239
20780
  return;
21240
20781
  }
21241
20782
  if (!uiblock) {
21242
- sendResponse7(id, {
20783
+ sendResponse6(id, {
21243
20784
  success: false,
21244
20785
  error: "UIBlock data is required"
21245
20786
  }, sendMessage, clientId);
@@ -21247,14 +20788,14 @@ async function handleCreate5(id, userId, threadId, name, description, uiblock, e
21247
20788
  }
21248
20789
  try {
21249
20790
  const result = await executeCollection("bookmarks", "create", { userId, threadId, name, description, uiblock });
21250
- sendResponse7(id, {
20791
+ sendResponse6(id, {
21251
20792
  success: true,
21252
20793
  data: result.data,
21253
20794
  message: "Bookmark created successfully"
21254
20795
  }, sendMessage, clientId);
21255
20796
  logger.info(`Bookmark created: ID ${result.data.id}`);
21256
20797
  } catch (error) {
21257
- sendResponse7(id, {
20798
+ sendResponse6(id, {
21258
20799
  success: false,
21259
20800
  error: error instanceof Error ? error.message : "Failed to create bookmark"
21260
20801
  }, sendMessage, clientId);
@@ -21262,7 +20803,7 @@ async function handleCreate5(id, userId, threadId, name, description, uiblock, e
21262
20803
  }
21263
20804
  async function handleUpdate5(id, bookmarkId, threadId, name, description, uiblock, executeCollection, sendMessage, clientId) {
21264
20805
  if (!bookmarkId) {
21265
- sendResponse7(id, {
20806
+ sendResponse6(id, {
21266
20807
  success: false,
21267
20808
  error: "Bookmark ID is required"
21268
20809
  }, sendMessage, clientId);
@@ -21270,14 +20811,14 @@ async function handleUpdate5(id, bookmarkId, threadId, name, description, uibloc
21270
20811
  }
21271
20812
  try {
21272
20813
  const result = await executeCollection("bookmarks", "update", { id: bookmarkId, threadId, name, description, uiblock });
21273
- sendResponse7(id, {
20814
+ sendResponse6(id, {
21274
20815
  success: true,
21275
20816
  data: result.data,
21276
20817
  message: "Bookmark updated successfully"
21277
20818
  }, sendMessage, clientId);
21278
20819
  logger.info(`Bookmark updated: ID ${bookmarkId}`);
21279
20820
  } catch (error) {
21280
- sendResponse7(id, {
20821
+ sendResponse6(id, {
21281
20822
  success: false,
21282
20823
  error: error instanceof Error ? error.message : "Failed to update bookmark"
21283
20824
  }, sendMessage, clientId);
@@ -21285,7 +20826,7 @@ async function handleUpdate5(id, bookmarkId, threadId, name, description, uibloc
21285
20826
  }
21286
20827
  async function handleDelete5(id, bookmarkId, executeCollection, sendMessage, clientId) {
21287
20828
  if (!bookmarkId) {
21288
- sendResponse7(id, {
20829
+ sendResponse6(id, {
21289
20830
  success: false,
21290
20831
  error: "Bookmark ID is required"
21291
20832
  }, sendMessage, clientId);
@@ -21293,14 +20834,14 @@ async function handleDelete5(id, bookmarkId, executeCollection, sendMessage, cli
21293
20834
  }
21294
20835
  try {
21295
20836
  const result = await executeCollection("bookmarks", "delete", { id: bookmarkId });
21296
- sendResponse7(id, {
20837
+ sendResponse6(id, {
21297
20838
  success: true,
21298
20839
  data: result.data,
21299
20840
  message: "Bookmark deleted successfully"
21300
20841
  }, sendMessage, clientId);
21301
20842
  logger.info(`Bookmark deleted: ID ${bookmarkId}`);
21302
20843
  } catch (error) {
21303
- sendResponse7(id, {
20844
+ sendResponse6(id, {
21304
20845
  success: false,
21305
20846
  error: error instanceof Error ? error.message : "Failed to delete bookmark"
21306
20847
  }, sendMessage, clientId);
@@ -21309,7 +20850,7 @@ async function handleDelete5(id, bookmarkId, executeCollection, sendMessage, cli
21309
20850
  async function handleGetAll5(id, executeCollection, sendMessage, clientId) {
21310
20851
  try {
21311
20852
  const result = await executeCollection("bookmarks", "getAll", {});
21312
- sendResponse7(id, {
20853
+ sendResponse6(id, {
21313
20854
  success: true,
21314
20855
  data: result.data,
21315
20856
  count: result.count,
@@ -21317,7 +20858,7 @@ async function handleGetAll5(id, executeCollection, sendMessage, clientId) {
21317
20858
  }, sendMessage, clientId);
21318
20859
  logger.info(`Retrieved all bookmarks (count: ${result.count})`);
21319
20860
  } catch (error) {
21320
- sendResponse7(id, {
20861
+ sendResponse6(id, {
21321
20862
  success: false,
21322
20863
  error: error instanceof Error ? error.message : "Failed to get bookmarks"
21323
20864
  }, sendMessage, clientId);
@@ -21325,7 +20866,7 @@ async function handleGetAll5(id, executeCollection, sendMessage, clientId) {
21325
20866
  }
21326
20867
  async function handleGetOne5(id, bookmarkId, executeCollection, sendMessage, clientId) {
21327
20868
  if (!bookmarkId) {
21328
- sendResponse7(id, {
20869
+ sendResponse6(id, {
21329
20870
  success: false,
21330
20871
  error: "Bookmark ID is required"
21331
20872
  }, sendMessage, clientId);
@@ -21333,14 +20874,14 @@ async function handleGetOne5(id, bookmarkId, executeCollection, sendMessage, cli
21333
20874
  }
21334
20875
  try {
21335
20876
  const result = await executeCollection("bookmarks", "getOne", { id: bookmarkId });
21336
- sendResponse7(id, {
20877
+ sendResponse6(id, {
21337
20878
  success: true,
21338
20879
  data: result.data,
21339
20880
  message: `Retrieved bookmark ID ${bookmarkId}`
21340
20881
  }, sendMessage, clientId);
21341
20882
  logger.info(`Retrieved bookmark: ID ${bookmarkId}`);
21342
20883
  } catch (error) {
21343
- sendResponse7(id, {
20884
+ sendResponse6(id, {
21344
20885
  success: false,
21345
20886
  error: error instanceof Error ? error.message : "Failed to get bookmark"
21346
20887
  }, sendMessage, clientId);
@@ -21353,7 +20894,7 @@ async function handleQuery5(id, filters, limit, sort, executeCollection, sendMes
21353
20894
  limit,
21354
20895
  sort
21355
20896
  });
21356
- sendResponse7(id, {
20897
+ sendResponse6(id, {
21357
20898
  success: true,
21358
20899
  data: result.data,
21359
20900
  count: result.count,
@@ -21361,13 +20902,13 @@ async function handleQuery5(id, filters, limit, sort, executeCollection, sendMes
21361
20902
  }, sendMessage, clientId);
21362
20903
  logger.info(`Query returned ${result.count} bookmarks`);
21363
20904
  } catch (error) {
21364
- sendResponse7(id, {
20905
+ sendResponse6(id, {
21365
20906
  success: false,
21366
20907
  error: error instanceof Error ? error.message : "Failed to query bookmarks"
21367
20908
  }, sendMessage, clientId);
21368
20909
  }
21369
20910
  }
21370
- function sendResponse7(id, res, sendMessage, clientId) {
20911
+ function sendResponse6(id, res, sendMessage, clientId) {
21371
20912
  const response = {
21372
20913
  id: id || "unknown",
21373
20914
  type: "BOOKMARKS_RES",
@@ -21434,14 +20975,14 @@ async function handleArtifactsRequest(data, collections, sendMessage) {
21434
20975
  await handleQuery6(id, { filters, limit, offset, sort }, executeCollection, sendMessage, from.id);
21435
20976
  break;
21436
20977
  default:
21437
- sendResponse8(id, {
20978
+ sendResponse7(id, {
21438
20979
  success: false,
21439
20980
  error: `Unknown operation: ${operation}`
21440
20981
  }, sendMessage, from.id);
21441
20982
  }
21442
20983
  } catch (error) {
21443
20984
  logger.error("Failed to handle artifacts request:", error);
21444
- sendResponse8(null, {
20985
+ sendResponse7(null, {
21445
20986
  success: false,
21446
20987
  error: error instanceof Error ? error.message : "Unknown error occurred"
21447
20988
  }, sendMessage);
@@ -21449,7 +20990,7 @@ async function handleArtifactsRequest(data, collections, sendMessage) {
21449
20990
  }
21450
20991
  async function handleCreate6(id, name, createdBy, dsl, type, filters, status, executeCollection, sendMessage, clientId) {
21451
20992
  if (!name) {
21452
- sendResponse8(id, {
20993
+ sendResponse7(id, {
21453
20994
  success: false,
21454
20995
  error: "name is required"
21455
20996
  }, sendMessage, clientId);
@@ -21464,14 +21005,14 @@ async function handleCreate6(id, name, createdBy, dsl, type, filters, status, ex
21464
21005
  filters,
21465
21006
  status
21466
21007
  });
21467
- sendResponse8(id, {
21008
+ sendResponse7(id, {
21468
21009
  success: true,
21469
21010
  data: result.data,
21470
21011
  message: "Artifact created successfully"
21471
21012
  }, sendMessage, clientId);
21472
21013
  logger.info(`Artifact created: ID ${result.data.id}`);
21473
21014
  } catch (error) {
21474
- sendResponse8(id, {
21015
+ sendResponse7(id, {
21475
21016
  success: false,
21476
21017
  error: error instanceof Error ? error.message : "Failed to create artifact"
21477
21018
  }, sendMessage, clientId);
@@ -21479,7 +21020,7 @@ async function handleCreate6(id, name, createdBy, dsl, type, filters, status, ex
21479
21020
  }
21480
21021
  async function handleUpdate6(id, artifactId, name, dsl, type, filters, status, deleted, executeCollection, sendMessage, clientId) {
21481
21022
  if (!artifactId) {
21482
- sendResponse8(id, {
21023
+ sendResponse7(id, {
21483
21024
  success: false,
21484
21025
  error: "Artifact ID is required"
21485
21026
  }, sendMessage, clientId);
@@ -21487,14 +21028,14 @@ async function handleUpdate6(id, artifactId, name, dsl, type, filters, status, d
21487
21028
  }
21488
21029
  try {
21489
21030
  const result = await executeCollection("artifacts", "update", { id: artifactId, name, dsl, type, filters, status, deleted });
21490
- sendResponse8(id, {
21031
+ sendResponse7(id, {
21491
21032
  success: true,
21492
21033
  data: result.data,
21493
21034
  message: "Artifact updated successfully"
21494
21035
  }, sendMessage, clientId);
21495
21036
  logger.info(`Artifact updated: ID ${artifactId}`);
21496
21037
  } catch (error) {
21497
- sendResponse8(id, {
21038
+ sendResponse7(id, {
21498
21039
  success: false,
21499
21040
  error: error instanceof Error ? error.message : "Failed to update artifact"
21500
21041
  }, sendMessage, clientId);
@@ -21502,7 +21043,7 @@ async function handleUpdate6(id, artifactId, name, dsl, type, filters, status, d
21502
21043
  }
21503
21044
  async function handleDelete6(id, artifactId, executeCollection, sendMessage, clientId) {
21504
21045
  if (!artifactId) {
21505
- sendResponse8(id, {
21046
+ sendResponse7(id, {
21506
21047
  success: false,
21507
21048
  error: "Artifact ID is required"
21508
21049
  }, sendMessage, clientId);
@@ -21510,14 +21051,14 @@ async function handleDelete6(id, artifactId, executeCollection, sendMessage, cli
21510
21051
  }
21511
21052
  try {
21512
21053
  const result = await executeCollection("artifacts", "delete", { id: artifactId });
21513
- sendResponse8(id, {
21054
+ sendResponse7(id, {
21514
21055
  success: true,
21515
21056
  data: result.data,
21516
21057
  message: "Artifact deleted successfully"
21517
21058
  }, sendMessage, clientId);
21518
21059
  logger.info(`Artifact deleted: ID ${artifactId}`);
21519
21060
  } catch (error) {
21520
- sendResponse8(id, {
21061
+ sendResponse7(id, {
21521
21062
  success: false,
21522
21063
  error: error instanceof Error ? error.message : "Failed to delete artifact"
21523
21064
  }, sendMessage, clientId);
@@ -21526,7 +21067,7 @@ async function handleDelete6(id, artifactId, executeCollection, sendMessage, cli
21526
21067
  async function handleGetAll6(id, limit, executeCollection, sendMessage, clientId) {
21527
21068
  try {
21528
21069
  const result = await executeCollection("artifacts", "getAll", { limit });
21529
- sendResponse8(id, {
21070
+ sendResponse7(id, {
21530
21071
  success: true,
21531
21072
  data: result.data,
21532
21073
  count: result.count,
@@ -21534,7 +21075,7 @@ async function handleGetAll6(id, limit, executeCollection, sendMessage, clientId
21534
21075
  }, sendMessage, clientId);
21535
21076
  logger.info(`Retrieved all artifacts (count: ${result.count})`);
21536
21077
  } catch (error) {
21537
- sendResponse8(id, {
21078
+ sendResponse7(id, {
21538
21079
  success: false,
21539
21080
  error: error instanceof Error ? error.message : "Failed to get artifacts"
21540
21081
  }, sendMessage, clientId);
@@ -21542,7 +21083,7 @@ async function handleGetAll6(id, limit, executeCollection, sendMessage, clientId
21542
21083
  }
21543
21084
  async function handleGetOne6(id, artifactId, executeCollection, sendMessage, clientId) {
21544
21085
  if (!artifactId) {
21545
- sendResponse8(id, {
21086
+ sendResponse7(id, {
21546
21087
  success: false,
21547
21088
  error: "Artifact ID is required"
21548
21089
  }, sendMessage, clientId);
@@ -21550,14 +21091,14 @@ async function handleGetOne6(id, artifactId, executeCollection, sendMessage, cli
21550
21091
  }
21551
21092
  try {
21552
21093
  const result = await executeCollection("artifacts", "getOne", { id: artifactId });
21553
- sendResponse8(id, {
21094
+ sendResponse7(id, {
21554
21095
  success: true,
21555
21096
  data: result.data,
21556
21097
  message: `Retrieved artifact ID ${artifactId}`
21557
21098
  }, sendMessage, clientId);
21558
21099
  logger.info(`Retrieved artifact: ID ${artifactId}`);
21559
21100
  } catch (error) {
21560
- sendResponse8(id, {
21101
+ sendResponse7(id, {
21561
21102
  success: false,
21562
21103
  error: error instanceof Error ? error.message : "Failed to get artifact"
21563
21104
  }, sendMessage, clientId);
@@ -21574,7 +21115,7 @@ async function handleQuery6(id, queryParams, executeCollection, sendMessage, cli
21574
21115
  sort: queryParams.sort || "DESC"
21575
21116
  });
21576
21117
  logger.info("[SDK-NODEJS] handleQuery - executeCollection result count:", result.count);
21577
- sendResponse8(id, {
21118
+ sendResponse7(id, {
21578
21119
  success: true,
21579
21120
  data: result.data,
21580
21121
  count: result.count,
@@ -21582,13 +21123,13 @@ async function handleQuery6(id, queryParams, executeCollection, sendMessage, cli
21582
21123
  }, sendMessage, clientId);
21583
21124
  logger.info(`Query artifacts (count: ${result.count})`);
21584
21125
  } catch (error) {
21585
- sendResponse8(id, {
21126
+ sendResponse7(id, {
21586
21127
  success: false,
21587
21128
  error: error instanceof Error ? error.message : "Failed to query artifacts"
21588
21129
  }, sendMessage, clientId);
21589
21130
  }
21590
21131
  }
21591
- function sendResponse8(id, res, sendMessage, clientId) {
21132
+ function sendResponse7(id, res, sendMessage, clientId) {
21592
21133
  const response = {
21593
21134
  id: id || "unknown",
21594
21135
  type: "ARTIFACTS_RES",
@@ -21662,14 +21203,14 @@ async function handleKbNodesRequest(data, collections, sendMessage) {
21662
21203
  await handleGetTags(id, executeCollection, sendMessage, from.id);
21663
21204
  break;
21664
21205
  default:
21665
- sendResponse9(id, {
21206
+ sendResponse8(id, {
21666
21207
  success: false,
21667
21208
  error: `Unknown operation: ${operation}`
21668
21209
  }, sendMessage, from.id);
21669
21210
  }
21670
21211
  } catch (error) {
21671
21212
  logger.error("Failed to handle KB nodes request:", error);
21672
- sendResponse9(null, {
21213
+ sendResponse8(null, {
21673
21214
  success: false,
21674
21215
  error: error instanceof Error ? error.message : "Unknown error occurred"
21675
21216
  }, sendMessage);
@@ -21678,21 +21219,21 @@ async function handleKbNodesRequest(data, collections, sendMessage) {
21678
21219
  async function handleCreate7(id, nodeData, executeCollection, sendMessage, clientId) {
21679
21220
  const { title, content, category, tags, type, createdBy } = nodeData;
21680
21221
  if (!title || title.trim().length === 0) {
21681
- sendResponse9(id, {
21222
+ sendResponse8(id, {
21682
21223
  success: false,
21683
21224
  error: "Title is required and cannot be empty"
21684
21225
  }, sendMessage, clientId);
21685
21226
  return;
21686
21227
  }
21687
21228
  if (!content || content.trim().length === 0) {
21688
- sendResponse9(id, {
21229
+ sendResponse8(id, {
21689
21230
  success: false,
21690
21231
  error: "Content is required and cannot be empty"
21691
21232
  }, sendMessage, clientId);
21692
21233
  return;
21693
21234
  }
21694
21235
  if (!createdBy) {
21695
- sendResponse9(id, {
21236
+ sendResponse8(id, {
21696
21237
  success: false,
21697
21238
  error: "createdBy (user ID) is required"
21698
21239
  }, sendMessage, clientId);
@@ -21709,7 +21250,7 @@ async function handleCreate7(id, nodeData, executeCollection, sendMessage, clien
21709
21250
  });
21710
21251
  if (result && result.success) {
21711
21252
  logger.info(`[DB] KB node created successfully: ${title}`);
21712
- sendResponse9(id, {
21253
+ sendResponse8(id, {
21713
21254
  success: true,
21714
21255
  data: {
21715
21256
  ...result.data,
@@ -21718,13 +21259,13 @@ async function handleCreate7(id, nodeData, executeCollection, sendMessage, clien
21718
21259
  }, sendMessage, clientId);
21719
21260
  return;
21720
21261
  }
21721
- sendResponse9(id, {
21262
+ sendResponse8(id, {
21722
21263
  success: false,
21723
21264
  error: "Failed to create knowledge node"
21724
21265
  }, sendMessage, clientId);
21725
21266
  } catch (error) {
21726
21267
  logger.error("[DB] Failed to create KB node:", error);
21727
- sendResponse9(id, {
21268
+ sendResponse8(id, {
21728
21269
  success: false,
21729
21270
  error: error instanceof Error ? error.message : "Failed to create knowledge node"
21730
21271
  }, sendMessage, clientId);
@@ -21733,14 +21274,14 @@ async function handleCreate7(id, nodeData, executeCollection, sendMessage, clien
21733
21274
  async function handleUpdate7(id, nodeId, nodeData, executeCollection, sendMessage, clientId) {
21734
21275
  const { title, content, category, tags, type, updatedBy } = nodeData;
21735
21276
  if (!nodeId) {
21736
- sendResponse9(id, {
21277
+ sendResponse8(id, {
21737
21278
  success: false,
21738
21279
  error: "Knowledge node ID is required"
21739
21280
  }, sendMessage, clientId);
21740
21281
  return;
21741
21282
  }
21742
21283
  if (!updatedBy) {
21743
- sendResponse9(id, {
21284
+ sendResponse8(id, {
21744
21285
  success: false,
21745
21286
  error: "updatedBy (user ID) is required"
21746
21287
  }, sendMessage, clientId);
@@ -21758,7 +21299,7 @@ async function handleUpdate7(id, nodeId, nodeData, executeCollection, sendMessag
21758
21299
  });
21759
21300
  if (result && result.success) {
21760
21301
  logger.info(`[DB] KB node updated successfully, ID: ${nodeId}`);
21761
- sendResponse9(id, {
21302
+ sendResponse8(id, {
21762
21303
  success: true,
21763
21304
  data: {
21764
21305
  ...result.data,
@@ -21767,13 +21308,13 @@ async function handleUpdate7(id, nodeId, nodeData, executeCollection, sendMessag
21767
21308
  }, sendMessage, clientId);
21768
21309
  return;
21769
21310
  }
21770
- sendResponse9(id, {
21311
+ sendResponse8(id, {
21771
21312
  success: false,
21772
21313
  error: "Failed to update knowledge node"
21773
21314
  }, sendMessage, clientId);
21774
21315
  } catch (error) {
21775
21316
  logger.error("[DB] Failed to update KB node:", error);
21776
- sendResponse9(id, {
21317
+ sendResponse8(id, {
21777
21318
  success: false,
21778
21319
  error: error instanceof Error ? error.message : "Failed to update knowledge node"
21779
21320
  }, sendMessage, clientId);
@@ -21781,7 +21322,7 @@ async function handleUpdate7(id, nodeId, nodeData, executeCollection, sendMessag
21781
21322
  }
21782
21323
  async function handleDelete7(id, nodeId, executeCollection, sendMessage, clientId) {
21783
21324
  if (!nodeId) {
21784
- sendResponse9(id, {
21325
+ sendResponse8(id, {
21785
21326
  success: false,
21786
21327
  error: "Knowledge node ID is required"
21787
21328
  }, sendMessage, clientId);
@@ -21791,7 +21332,7 @@ async function handleDelete7(id, nodeId, executeCollection, sendMessage, clientI
21791
21332
  const result = await executeCollection("kbNodes", "delete", { id: nodeId });
21792
21333
  if (result && result.success) {
21793
21334
  logger.info(`[DB] KB node deleted successfully, ID: ${nodeId}`);
21794
- sendResponse9(id, {
21335
+ sendResponse8(id, {
21795
21336
  success: true,
21796
21337
  data: {
21797
21338
  id: nodeId,
@@ -21801,13 +21342,13 @@ async function handleDelete7(id, nodeId, executeCollection, sendMessage, clientI
21801
21342
  }, sendMessage, clientId);
21802
21343
  return;
21803
21344
  }
21804
- sendResponse9(id, {
21345
+ sendResponse8(id, {
21805
21346
  success: false,
21806
21347
  error: "Failed to delete knowledge node"
21807
21348
  }, sendMessage, clientId);
21808
21349
  } catch (error) {
21809
21350
  logger.error("[DB] Failed to delete KB node:", error);
21810
- sendResponse9(id, {
21351
+ sendResponse8(id, {
21811
21352
  success: false,
21812
21353
  error: error instanceof Error ? error.message : "Failed to delete knowledge node"
21813
21354
  }, sendMessage, clientId);
@@ -21821,7 +21362,7 @@ async function handleGetAll7(id, limit, offset, executeCollection, sendMessage,
21821
21362
  });
21822
21363
  if (result && result.success) {
21823
21364
  logger.info(`[DB] Retrieved ${result.count} KB nodes`);
21824
- sendResponse9(id, {
21365
+ sendResponse8(id, {
21825
21366
  success: true,
21826
21367
  data: {
21827
21368
  nodes: result.data,
@@ -21831,13 +21372,13 @@ async function handleGetAll7(id, limit, offset, executeCollection, sendMessage,
21831
21372
  }, sendMessage, clientId);
21832
21373
  return;
21833
21374
  }
21834
- sendResponse9(id, {
21375
+ sendResponse8(id, {
21835
21376
  success: false,
21836
21377
  error: "Failed to retrieve knowledge nodes"
21837
21378
  }, sendMessage, clientId);
21838
21379
  } catch (error) {
21839
21380
  logger.error("[DB] Failed to get all KB nodes:", error);
21840
- sendResponse9(id, {
21381
+ sendResponse8(id, {
21841
21382
  success: false,
21842
21383
  error: error instanceof Error ? error.message : "Failed to retrieve knowledge nodes"
21843
21384
  }, sendMessage, clientId);
@@ -21845,7 +21386,7 @@ async function handleGetAll7(id, limit, offset, executeCollection, sendMessage,
21845
21386
  }
21846
21387
  async function handleGetOne7(id, nodeId, executeCollection, sendMessage, clientId) {
21847
21388
  if (!nodeId) {
21848
- sendResponse9(id, {
21389
+ sendResponse8(id, {
21849
21390
  success: false,
21850
21391
  error: "Knowledge node ID is required"
21851
21392
  }, sendMessage, clientId);
@@ -21855,7 +21396,7 @@ async function handleGetOne7(id, nodeId, executeCollection, sendMessage, clientI
21855
21396
  const result = await executeCollection("kbNodes", "getOne", { id: nodeId });
21856
21397
  if (result && result.success) {
21857
21398
  logger.info(`[DB] Retrieved KB node ID: ${nodeId}`);
21858
- sendResponse9(id, {
21399
+ sendResponse8(id, {
21859
21400
  success: true,
21860
21401
  data: {
21861
21402
  node: result.data,
@@ -21864,13 +21405,13 @@ async function handleGetOne7(id, nodeId, executeCollection, sendMessage, clientI
21864
21405
  }, sendMessage, clientId);
21865
21406
  return;
21866
21407
  }
21867
- sendResponse9(id, {
21408
+ sendResponse8(id, {
21868
21409
  success: false,
21869
21410
  error: "Failed to retrieve knowledge node"
21870
21411
  }, sendMessage, clientId);
21871
21412
  } catch (error) {
21872
21413
  logger.error("[DB] Failed to get KB node:", error);
21873
- sendResponse9(id, {
21414
+ sendResponse8(id, {
21874
21415
  success: false,
21875
21416
  error: error instanceof Error ? error.message : "Failed to retrieve knowledge node"
21876
21417
  }, sendMessage, clientId);
@@ -21890,7 +21431,7 @@ async function handleSearch(id, searchParams, executeCollection, sendMessage, cl
21890
21431
  });
21891
21432
  if (result && result.success) {
21892
21433
  logger.info(`[DB] Search returned ${result.count} KB nodes`);
21893
- sendResponse9(id, {
21434
+ sendResponse8(id, {
21894
21435
  success: true,
21895
21436
  data: {
21896
21437
  nodes: result.data,
@@ -21900,13 +21441,13 @@ async function handleSearch(id, searchParams, executeCollection, sendMessage, cl
21900
21441
  }, sendMessage, clientId);
21901
21442
  return;
21902
21443
  }
21903
- sendResponse9(id, {
21444
+ sendResponse8(id, {
21904
21445
  success: false,
21905
21446
  error: "Failed to search knowledge nodes"
21906
21447
  }, sendMessage, clientId);
21907
21448
  } catch (error) {
21908
21449
  logger.error("[DB] Failed to search KB nodes:", error);
21909
- sendResponse9(id, {
21450
+ sendResponse8(id, {
21910
21451
  success: false,
21911
21452
  error: error instanceof Error ? error.message : "Failed to search knowledge nodes"
21912
21453
  }, sendMessage, clientId);
@@ -21914,7 +21455,7 @@ async function handleSearch(id, searchParams, executeCollection, sendMessage, cl
21914
21455
  }
21915
21456
  async function handleGetByCategory(id, category, limit, offset, executeCollection, sendMessage, clientId) {
21916
21457
  if (!category) {
21917
- sendResponse9(id, {
21458
+ sendResponse8(id, {
21918
21459
  success: false,
21919
21460
  error: "Category is required"
21920
21461
  }, sendMessage, clientId);
@@ -21928,7 +21469,7 @@ async function handleGetByCategory(id, category, limit, offset, executeCollectio
21928
21469
  });
21929
21470
  if (result && result.success) {
21930
21471
  logger.info(`[DB] Retrieved ${result.count} KB nodes for category: ${category}`);
21931
- sendResponse9(id, {
21472
+ sendResponse8(id, {
21932
21473
  success: true,
21933
21474
  data: {
21934
21475
  nodes: result.data,
@@ -21939,13 +21480,13 @@ async function handleGetByCategory(id, category, limit, offset, executeCollectio
21939
21480
  }, sendMessage, clientId);
21940
21481
  return;
21941
21482
  }
21942
- sendResponse9(id, {
21483
+ sendResponse8(id, {
21943
21484
  success: false,
21944
21485
  error: "Failed to retrieve knowledge nodes by category"
21945
21486
  }, sendMessage, clientId);
21946
21487
  } catch (error) {
21947
21488
  logger.error("[DB] Failed to get KB nodes by category:", error);
21948
- sendResponse9(id, {
21489
+ sendResponse8(id, {
21949
21490
  success: false,
21950
21491
  error: error instanceof Error ? error.message : "Failed to retrieve knowledge nodes by category"
21951
21492
  }, sendMessage, clientId);
@@ -21953,7 +21494,7 @@ async function handleGetByCategory(id, category, limit, offset, executeCollectio
21953
21494
  }
21954
21495
  async function handleGetByUser(id, userId, limit, offset, executeCollection, sendMessage, clientId) {
21955
21496
  if (!userId) {
21956
- sendResponse9(id, {
21497
+ sendResponse8(id, {
21957
21498
  success: false,
21958
21499
  error: "User ID is required"
21959
21500
  }, sendMessage, clientId);
@@ -21967,7 +21508,7 @@ async function handleGetByUser(id, userId, limit, offset, executeCollection, sen
21967
21508
  });
21968
21509
  if (result && result.success) {
21969
21510
  logger.info(`[DB] Retrieved ${result.count} KB nodes for user: ${userId}`);
21970
- sendResponse9(id, {
21511
+ sendResponse8(id, {
21971
21512
  success: true,
21972
21513
  data: {
21973
21514
  nodes: result.data,
@@ -21978,13 +21519,13 @@ async function handleGetByUser(id, userId, limit, offset, executeCollection, sen
21978
21519
  }, sendMessage, clientId);
21979
21520
  return;
21980
21521
  }
21981
- sendResponse9(id, {
21522
+ sendResponse8(id, {
21982
21523
  success: false,
21983
21524
  error: "Failed to retrieve knowledge nodes by user"
21984
21525
  }, sendMessage, clientId);
21985
21526
  } catch (error) {
21986
21527
  logger.error("[DB] Failed to get KB nodes by user:", error);
21987
- sendResponse9(id, {
21528
+ sendResponse8(id, {
21988
21529
  success: false,
21989
21530
  error: error instanceof Error ? error.message : "Failed to retrieve knowledge nodes by user"
21990
21531
  }, sendMessage, clientId);
@@ -21995,7 +21536,7 @@ async function handleGetCategories(id, executeCollection, sendMessage, clientId)
21995
21536
  const result = await executeCollection("kbNodes", "getCategories", {});
21996
21537
  if (result && result.success) {
21997
21538
  logger.info(`[DB] Retrieved ${result.count} categories`);
21998
- sendResponse9(id, {
21539
+ sendResponse8(id, {
21999
21540
  success: true,
22000
21541
  data: {
22001
21542
  categories: result.data,
@@ -22005,13 +21546,13 @@ async function handleGetCategories(id, executeCollection, sendMessage, clientId)
22005
21546
  }, sendMessage, clientId);
22006
21547
  return;
22007
21548
  }
22008
- sendResponse9(id, {
21549
+ sendResponse8(id, {
22009
21550
  success: false,
22010
21551
  error: "Failed to retrieve categories"
22011
21552
  }, sendMessage, clientId);
22012
21553
  } catch (error) {
22013
21554
  logger.error("[DB] Failed to get categories:", error);
22014
- sendResponse9(id, {
21555
+ sendResponse8(id, {
22015
21556
  success: false,
22016
21557
  error: error instanceof Error ? error.message : "Failed to retrieve categories"
22017
21558
  }, sendMessage, clientId);
@@ -22022,7 +21563,7 @@ async function handleGetTags(id, executeCollection, sendMessage, clientId) {
22022
21563
  const result = await executeCollection("kbNodes", "getTags", {});
22023
21564
  if (result && result.success) {
22024
21565
  logger.info(`[DB] Retrieved ${result.count} tags`);
22025
- sendResponse9(id, {
21566
+ sendResponse8(id, {
22026
21567
  success: true,
22027
21568
  data: {
22028
21569
  tags: result.data,
@@ -22032,19 +21573,19 @@ async function handleGetTags(id, executeCollection, sendMessage, clientId) {
22032
21573
  }, sendMessage, clientId);
22033
21574
  return;
22034
21575
  }
22035
- sendResponse9(id, {
21576
+ sendResponse8(id, {
22036
21577
  success: false,
22037
21578
  error: "Failed to retrieve tags"
22038
21579
  }, sendMessage, clientId);
22039
21580
  } catch (error) {
22040
21581
  logger.error("[DB] Failed to get tags:", error);
22041
- sendResponse9(id, {
21582
+ sendResponse8(id, {
22042
21583
  success: false,
22043
21584
  error: error instanceof Error ? error.message : "Failed to retrieve tags"
22044
21585
  }, sendMessage, clientId);
22045
21586
  }
22046
21587
  }
22047
- function sendResponse9(id, res, sendMessage, clientId) {
21588
+ function sendResponse8(id, res, sendMessage, clientId) {
22048
21589
  const response = {
22049
21590
  id: id || "unknown",
22050
21591
  type: "KB_NODES_RES",
@@ -22118,14 +21659,14 @@ async function handleMenusRequest(data, collections, sendMessage) {
22118
21659
  await handleReorder(id, items, executeCollection, sendMessage, from.id);
22119
21660
  break;
22120
21661
  default:
22121
- sendResponse10(id, {
21662
+ sendResponse9(id, {
22122
21663
  success: false,
22123
21664
  error: `Unknown operation: ${operation}`
22124
21665
  }, sendMessage, from.id);
22125
21666
  }
22126
21667
  } catch (error) {
22127
21668
  logger.error("Failed to handle menus request:", error);
22128
- sendResponse10(null, {
21669
+ sendResponse9(null, {
22129
21670
  success: false,
22130
21671
  error: error instanceof Error ? error.message : "Unknown error occurred"
22131
21672
  }, sendMessage);
@@ -22133,14 +21674,14 @@ async function handleMenusRequest(data, collections, sendMessage) {
22133
21674
  }
22134
21675
  async function handleCreate8(id, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, clientId) {
22135
21676
  if (!name) {
22136
- sendResponse10(id, {
21677
+ sendResponse9(id, {
22137
21678
  success: false,
22138
21679
  error: "name is required"
22139
21680
  }, sendMessage, clientId);
22140
21681
  return;
22141
21682
  }
22142
21683
  if (!componentName) {
22143
- sendResponse10(id, {
21684
+ sendResponse9(id, {
22144
21685
  success: false,
22145
21686
  error: "componentName is required"
22146
21687
  }, sendMessage, clientId);
@@ -22157,14 +21698,14 @@ async function handleCreate8(id, name, componentName, icon, userMessage, parentI
22157
21698
  props,
22158
21699
  isActive
22159
21700
  });
22160
- sendResponse10(id, {
21701
+ sendResponse9(id, {
22161
21702
  success: true,
22162
21703
  data: result.data,
22163
21704
  message: "Menu created successfully"
22164
21705
  }, sendMessage, clientId);
22165
21706
  logger.info(`Menu created: ID ${result.data?.id}`);
22166
21707
  } catch (error) {
22167
- sendResponse10(id, {
21708
+ sendResponse9(id, {
22168
21709
  success: false,
22169
21710
  error: error instanceof Error ? error.message : "Failed to create menu"
22170
21711
  }, sendMessage, clientId);
@@ -22172,7 +21713,7 @@ async function handleCreate8(id, name, componentName, icon, userMessage, parentI
22172
21713
  }
22173
21714
  async function handleUpdate8(id, menuId, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, clientId) {
22174
21715
  if (!menuId) {
22175
- sendResponse10(id, {
21716
+ sendResponse9(id, {
22176
21717
  success: false,
22177
21718
  error: "Menu ID is required"
22178
21719
  }, sendMessage, clientId);
@@ -22190,14 +21731,14 @@ async function handleUpdate8(id, menuId, name, componentName, icon, userMessage,
22190
21731
  props,
22191
21732
  isActive
22192
21733
  });
22193
- sendResponse10(id, {
21734
+ sendResponse9(id, {
22194
21735
  success: true,
22195
21736
  data: result.data,
22196
21737
  message: "Menu updated successfully"
22197
21738
  }, sendMessage, clientId);
22198
21739
  logger.info(`Menu updated: ID ${menuId}`);
22199
21740
  } catch (error) {
22200
- sendResponse10(id, {
21741
+ sendResponse9(id, {
22201
21742
  success: false,
22202
21743
  error: error instanceof Error ? error.message : "Failed to update menu"
22203
21744
  }, sendMessage, clientId);
@@ -22205,7 +21746,7 @@ async function handleUpdate8(id, menuId, name, componentName, icon, userMessage,
22205
21746
  }
22206
21747
  async function handleDelete8(id, menuId, executeCollection, sendMessage, clientId) {
22207
21748
  if (!menuId) {
22208
- sendResponse10(id, {
21749
+ sendResponse9(id, {
22209
21750
  success: false,
22210
21751
  error: "Menu ID is required"
22211
21752
  }, sendMessage, clientId);
@@ -22213,14 +21754,14 @@ async function handleDelete8(id, menuId, executeCollection, sendMessage, clientI
22213
21754
  }
22214
21755
  try {
22215
21756
  const result = await executeCollection("menus", "delete", { id: menuId });
22216
- sendResponse10(id, {
21757
+ sendResponse9(id, {
22217
21758
  success: true,
22218
21759
  data: result.data,
22219
21760
  message: "Menu deleted successfully"
22220
21761
  }, sendMessage, clientId);
22221
21762
  logger.info(`Menu deleted: ID ${menuId}`);
22222
21763
  } catch (error) {
22223
- sendResponse10(id, {
21764
+ sendResponse9(id, {
22224
21765
  success: false,
22225
21766
  error: error instanceof Error ? error.message : "Failed to delete menu"
22226
21767
  }, sendMessage, clientId);
@@ -22229,7 +21770,7 @@ async function handleDelete8(id, menuId, executeCollection, sendMessage, clientI
22229
21770
  async function handleGetAll8(id, executeCollection, sendMessage, clientId) {
22230
21771
  try {
22231
21772
  const result = await executeCollection("menus", "getAll", {});
22232
- sendResponse10(id, {
21773
+ sendResponse9(id, {
22233
21774
  success: true,
22234
21775
  data: result.data,
22235
21776
  count: result.count,
@@ -22237,7 +21778,7 @@ async function handleGetAll8(id, executeCollection, sendMessage, clientId) {
22237
21778
  }, sendMessage, clientId);
22238
21779
  logger.info(`Retrieved all menus (count: ${result.count})`);
22239
21780
  } catch (error) {
22240
- sendResponse10(id, {
21781
+ sendResponse9(id, {
22241
21782
  success: false,
22242
21783
  error: error instanceof Error ? error.message : "Failed to get menus"
22243
21784
  }, sendMessage, clientId);
@@ -22245,7 +21786,7 @@ async function handleGetAll8(id, executeCollection, sendMessage, clientId) {
22245
21786
  }
22246
21787
  async function handleGetOne8(id, menuId, executeCollection, sendMessage, clientId) {
22247
21788
  if (!menuId) {
22248
- sendResponse10(id, {
21789
+ sendResponse9(id, {
22249
21790
  success: false,
22250
21791
  error: "Menu ID is required"
22251
21792
  }, sendMessage, clientId);
@@ -22253,14 +21794,14 @@ async function handleGetOne8(id, menuId, executeCollection, sendMessage, clientI
22253
21794
  }
22254
21795
  try {
22255
21796
  const result = await executeCollection("menus", "getOne", { id: menuId });
22256
- sendResponse10(id, {
21797
+ sendResponse9(id, {
22257
21798
  success: true,
22258
21799
  data: result.data,
22259
21800
  message: `Retrieved menu ID ${menuId}`
22260
21801
  }, sendMessage, clientId);
22261
21802
  logger.info(`Retrieved menu: ID ${menuId}`);
22262
21803
  } catch (error) {
22263
- sendResponse10(id, {
21804
+ sendResponse9(id, {
22264
21805
  success: false,
22265
21806
  error: error instanceof Error ? error.message : "Failed to get menu"
22266
21807
  }, sendMessage, clientId);
@@ -22269,7 +21810,7 @@ async function handleGetOne8(id, menuId, executeCollection, sendMessage, clientI
22269
21810
  async function handleGetRootMenus(id, executeCollection, sendMessage, clientId) {
22270
21811
  try {
22271
21812
  const result = await executeCollection("menus", "getRootMenus", {});
22272
- sendResponse10(id, {
21813
+ sendResponse9(id, {
22273
21814
  success: true,
22274
21815
  data: result.data,
22275
21816
  count: result.count,
@@ -22277,7 +21818,7 @@ async function handleGetRootMenus(id, executeCollection, sendMessage, clientId)
22277
21818
  }, sendMessage, clientId);
22278
21819
  logger.info(`Retrieved root menus (count: ${result.count})`);
22279
21820
  } catch (error) {
22280
- sendResponse10(id, {
21821
+ sendResponse9(id, {
22281
21822
  success: false,
22282
21823
  error: error instanceof Error ? error.message : "Failed to get root menus"
22283
21824
  }, sendMessage, clientId);
@@ -22285,7 +21826,7 @@ async function handleGetRootMenus(id, executeCollection, sendMessage, clientId)
22285
21826
  }
22286
21827
  async function handleGetChildMenus(id, parentId, executeCollection, sendMessage, clientId) {
22287
21828
  if (parentId === void 0 || parentId === null) {
22288
- sendResponse10(id, {
21829
+ sendResponse9(id, {
22289
21830
  success: false,
22290
21831
  error: "parentId is required"
22291
21832
  }, sendMessage, clientId);
@@ -22293,7 +21834,7 @@ async function handleGetChildMenus(id, parentId, executeCollection, sendMessage,
22293
21834
  }
22294
21835
  try {
22295
21836
  const result = await executeCollection("menus", "getChildMenus", { parentId });
22296
- sendResponse10(id, {
21837
+ sendResponse9(id, {
22297
21838
  success: true,
22298
21839
  data: result.data,
22299
21840
  count: result.count,
@@ -22301,7 +21842,7 @@ async function handleGetChildMenus(id, parentId, executeCollection, sendMessage,
22301
21842
  }, sendMessage, clientId);
22302
21843
  logger.info(`Retrieved child menus for parent ${parentId} (count: ${result.count})`);
22303
21844
  } catch (error) {
22304
- sendResponse10(id, {
21845
+ sendResponse9(id, {
22305
21846
  success: false,
22306
21847
  error: error instanceof Error ? error.message : "Failed to get child menus"
22307
21848
  }, sendMessage, clientId);
@@ -22310,7 +21851,7 @@ async function handleGetChildMenus(id, parentId, executeCollection, sendMessage,
22310
21851
  async function handleGetHierarchy(id, executeCollection, sendMessage, clientId) {
22311
21852
  try {
22312
21853
  const result = await executeCollection("menus", "getHierarchy", {});
22313
- sendResponse10(id, {
21854
+ sendResponse9(id, {
22314
21855
  success: true,
22315
21856
  data: result.data,
22316
21857
  count: result.count,
@@ -22318,7 +21859,7 @@ async function handleGetHierarchy(id, executeCollection, sendMessage, clientId)
22318
21859
  }, sendMessage, clientId);
22319
21860
  logger.info(`Retrieved menus hierarchy (root count: ${result.count})`);
22320
21861
  } catch (error) {
22321
- sendResponse10(id, {
21862
+ sendResponse9(id, {
22322
21863
  success: false,
22323
21864
  error: error instanceof Error ? error.message : "Failed to get menus hierarchy"
22324
21865
  }, sendMessage, clientId);
@@ -22331,7 +21872,7 @@ async function handleQuery7(id, filters, limit, sort, executeCollection, sendMes
22331
21872
  limit,
22332
21873
  sort
22333
21874
  });
22334
- sendResponse10(id, {
21875
+ sendResponse9(id, {
22335
21876
  success: true,
22336
21877
  data: result.data,
22337
21878
  count: result.count,
@@ -22339,7 +21880,7 @@ async function handleQuery7(id, filters, limit, sort, executeCollection, sendMes
22339
21880
  }, sendMessage, clientId);
22340
21881
  logger.info(`Query returned ${result.count} menus`);
22341
21882
  } catch (error) {
22342
- sendResponse10(id, {
21883
+ sendResponse9(id, {
22343
21884
  success: false,
22344
21885
  error: error instanceof Error ? error.message : "Failed to query menus"
22345
21886
  }, sendMessage, clientId);
@@ -22347,7 +21888,7 @@ async function handleQuery7(id, filters, limit, sort, executeCollection, sendMes
22347
21888
  }
22348
21889
  async function handleReorder(id, items, executeCollection, sendMessage, clientId) {
22349
21890
  if (!items || !Array.isArray(items) || items.length === 0) {
22350
- sendResponse10(id, {
21891
+ sendResponse9(id, {
22351
21892
  success: false,
22352
21893
  error: "items array is required"
22353
21894
  }, sendMessage, clientId);
@@ -22355,20 +21896,20 @@ async function handleReorder(id, items, executeCollection, sendMessage, clientId
22355
21896
  }
22356
21897
  try {
22357
21898
  const result = await executeCollection("menus", "reorder", { items });
22358
- sendResponse10(id, {
21899
+ sendResponse9(id, {
22359
21900
  success: true,
22360
21901
  data: result.data,
22361
21902
  message: `Reordered ${items.length} menus successfully`
22362
21903
  }, sendMessage, clientId);
22363
21904
  logger.info(`Reordered ${items.length} menus`);
22364
21905
  } catch (error) {
22365
- sendResponse10(id, {
21906
+ sendResponse9(id, {
22366
21907
  success: false,
22367
21908
  error: error instanceof Error ? error.message : "Failed to reorder menus"
22368
21909
  }, sendMessage, clientId);
22369
21910
  }
22370
21911
  }
22371
- function sendResponse10(id, res, sendMessage, clientId) {
21912
+ function sendResponse9(id, res, sendMessage, clientId) {
22372
21913
  const response = {
22373
21914
  id: id || "unknown",
22374
21915
  type: "MENUS_RES",
@@ -24137,13 +23678,14 @@ async function runCodingAgent(agentId, options = {}) {
24137
23678
  const policy = def.session ?? {};
24138
23679
  const persistentWorkspace = policy.workspace === "persistent";
24139
23680
  const persistentSession = policy.scope === "persistent";
23681
+ const runAsJob = !(options.chat === true && def.mode === "task");
24140
23682
  const { key: scopeKey, dirName } = resolveScope(def, { userId: options.userId, threadId: options.threadId });
24141
23683
  const scopeDir = path9.join(agentDir, dirName);
24142
23684
  const dir = options.workspaceDir || (persistentWorkspace ? scopeDir : path9.join(scopeDir, "runs", runId));
24143
23685
  fs8.mkdirSync(dir, { recursive: true });
24144
23686
  if (persistentWorkspace && !options.workspaceDir) {
24145
23687
  fs8.mkdirSync(path9.join(dir, "memory"), { recursive: true });
24146
- await clearTransient(dir);
23688
+ if (runAsJob) await clearTransient(dir);
24147
23689
  }
24148
23690
  const lockKey = persistentWorkspace || persistentSession ? `${def.id}:${scopeKey}` : `dir:${dir}`;
24149
23691
  if (inFlight.has(lockKey)) {
@@ -24198,10 +23740,12 @@ async function runCodingAgent(agentId, options = {}) {
24198
23740
  };
24199
23741
  try {
24200
23742
  await installInstructions(def, ws);
24201
- if (def.prepare) await def.prepare(ws, input, ctx);
24202
- const outputPath = def.output ? ws.pathTo(def.output.file) : void 0;
23743
+ if (def.prepare && runAsJob) await def.prepare(ws, input, ctx);
23744
+ const outputPath = runAsJob && def.output ? ws.pathTo(def.output.file) : void 0;
24203
23745
  if (outputPath) await fsp.rm(outputPath, { force: true });
24204
- const prompt = options.prompt ?? (def.buildPrompt ? await def.buildPrompt(ws, input, ctx) : outputPath ? `Carry out the task described in AGENTS.md. Write your finished result to this exact absolute path: ${outputPath}` : "Carry out the task described in AGENTS.md.");
23746
+ const prompt = options.prompt ?? // buildPrompt may read what prepare() wrote, so it is only asked when
23747
+ // prepare() actually ran.
23748
+ (runAsJob && def.buildPrompt ? await def.buildPrompt(ws, input, ctx) : outputPath ? `Carry out the task described in AGENTS.md. Write your finished result to this exact absolute path: ${outputPath}` : "Carry out the task described in AGENTS.md.");
24205
23749
  const tools = { ...cfg.sharedTools ?? {}, ...def.tools ?? {} };
24206
23750
  const session = createCodingAgentSession(def.harness || cfg.harness, {
24207
23751
  cwd: dir,
@@ -24252,7 +23796,7 @@ async function runCodingAgent(agentId, options = {}) {
24252
23796
  return record;
24253
23797
  }
24254
23798
  const successStatus = result.status === "early" ? "early" : "completed";
24255
- if (!def.output) {
23799
+ if (!def.output || !runAsJob) {
24256
23800
  record.status = successStatus;
24257
23801
  return record;
24258
23802
  }
@@ -24281,7 +23825,7 @@ async function runCodingAgent(agentId, options = {}) {
24281
23825
  } finally {
24282
23826
  inFlight.delete(lockKey);
24283
23827
  logger.info(
24284
- `[CodingAgent:${def.id}] run=${runId} status=${record.status} ms=${record.ms} tokens=${record.usage.inputTokens}/${record.usage.outputTokens} tools=${record.usage.toolCalls}` + (record.applied ? ` applied="${record.applied.summary}"` : "") + (record.error ? ` error="${record.error}"` : "")
23828
+ `[CodingAgent:${def.id}] ${runAsJob ? "run" : "chat"}=${runId} status=${record.status} ms=${record.ms} tokens=${record.usage.inputTokens}/${record.usage.outputTokens} tools=${record.usage.toolCalls}` + (record.applied ? ` applied="${record.applied.summary}"` : "") + (record.error ? ` error="${record.error}"` : "")
24285
23829
  );
24286
23830
  if (!options.workspaceDir && !persistentWorkspace) await pruneRuns(path9.join(scopeDir, "runs"), cfg.keepRuns);
24287
23831
  }
@@ -24395,15 +23939,30 @@ console.log(${JSON.stringify(JSON.stringify(opts.sources, null, 2))});
24395
23939
  // src/codingAgent/triggers.ts
24396
23940
  var fs10 = __toESM(require("fs"));
24397
23941
  var path10 = __toESM(require("path"));
23942
+ var EVENT_BURST_CAP = 200;
23943
+ var capEvents = (events) => events.length > EVENT_BURST_CAP ? events.slice(-EVENT_BURST_CAP) : events;
24398
23944
  function statePath2(agentId) {
24399
23945
  return path10.join(getCodingAgentsConfig().runtimeDir, agentId, "_triggers.json");
24400
23946
  }
24401
23947
  function loadTriggerState(agentId) {
23948
+ let raw;
24402
23949
  try {
24403
- return JSON.parse(fs10.readFileSync(statePath2(agentId), "utf-8"));
23950
+ raw = JSON.parse(fs10.readFileSync(statePath2(agentId), "utf-8"));
24404
23951
  } catch {
24405
- return { counts: {} };
23952
+ return { counts: {}, pending: {} };
23953
+ }
23954
+ const counts = {};
23955
+ for (const [name, value] of Object.entries(raw?.counts ?? {})) {
23956
+ if (Array.isArray(value)) counts[name] = value;
23957
+ else if (typeof value === "number" && value > 0) counts[name] = Array.from({ length: value }, () => ({ name }));
23958
+ }
23959
+ const pending = {};
23960
+ if (raw?.pending && typeof raw.pending === "object" && !Array.isArray(raw.pending)) {
23961
+ for (const [key, value] of Object.entries(raw.pending)) {
23962
+ if (Array.isArray(value)) pending[key] = value;
23963
+ }
24406
23964
  }
23965
+ return { counts, pending, lastRunAt: raw?.lastRunAt };
24407
23966
  }
24408
23967
  function saveTriggerState(agentId, state) {
24409
23968
  try {
@@ -24417,6 +23976,7 @@ function saveTriggerState(agentId, state) {
24417
23976
  var asArray = (t) => !t ? [] : Array.isArray(t) ? t : [t];
24418
23977
  var intervals = /* @__PURE__ */ new Map();
24419
23978
  var debounces = /* @__PURE__ */ new Map();
23979
+ var bursts = /* @__PURE__ */ new Map();
24420
23980
  var firing = /* @__PURE__ */ new Set();
24421
23981
  var listeners = [];
24422
23982
  function onAgentRun(fn) {
@@ -24426,21 +23986,38 @@ function onAgentRun(fn) {
24426
23986
  if (i >= 0) listeners.splice(i, 1);
24427
23987
  };
24428
23988
  }
24429
- async function fire(agentId, reason, payload) {
23989
+ function inputFor(trigger, events) {
23990
+ const build = trigger?.buildInput;
23991
+ const lastPayload = () => events.length ? events[events.length - 1].payload : void 0;
23992
+ if (!build) return lastPayload();
23993
+ try {
23994
+ return build(events);
23995
+ } catch (err) {
23996
+ logger.error(`[CodingAgent] buildInput threw, falling back to the last payload: ${err?.message ?? err}`);
23997
+ return lastPayload();
23998
+ }
23999
+ }
24000
+ async function fire(agentId, triggerIndex, reason, events = []) {
24430
24001
  if (firing.has(agentId)) {
24431
- const st = loadTriggerState(agentId);
24432
- saveTriggerState(agentId, { ...st, pending: true });
24433
- logger.info(`[CodingAgent:${agentId}] ${reason} arrived mid-run \u2014 queued`);
24002
+ const st2 = loadTriggerState(agentId);
24003
+ const key = String(triggerIndex);
24004
+ saveTriggerState(agentId, {
24005
+ ...st2,
24006
+ pending: { ...st2.pending, [key]: capEvents([...st2.pending[key] ?? [], ...events]) }
24007
+ });
24008
+ logger.info(`[CodingAgent:${agentId}] ${reason} arrived mid-run \u2014 queued (${events.length} event(s))`);
24434
24009
  return;
24435
24010
  }
24436
24011
  firing.add(agentId);
24437
24012
  try {
24013
+ const trigger = asArray(getCodingAgent(agentId)?.trigger)[triggerIndex];
24014
+ const input = inputFor(trigger, events);
24438
24015
  logger.info(`[CodingAgent:${agentId}] triggered by ${reason}`);
24439
- const record = await runCodingAgent(agentId, { input: payload });
24440
- saveTriggerState(agentId, { ...loadTriggerState(agentId), lastRunAt: (/* @__PURE__ */ new Date()).toISOString(), pending: false });
24016
+ const record = await runCodingAgent(agentId, { input });
24017
+ saveTriggerState(agentId, { ...loadTriggerState(agentId), lastRunAt: (/* @__PURE__ */ new Date()).toISOString() });
24441
24018
  for (const fn of listeners) {
24442
24019
  try {
24443
- fn(record, { agentId, reason, payload });
24020
+ fn(record, { agentId, reason, events, input });
24444
24021
  } catch {
24445
24022
  }
24446
24023
  }
@@ -24448,9 +24025,13 @@ async function fire(agentId, reason, payload) {
24448
24025
  logger.error(`[CodingAgent:${agentId}] trigger run failed: ${err?.message ?? err}`);
24449
24026
  } finally {
24450
24027
  firing.delete(agentId);
24451
- if (loadTriggerState(agentId).pending) {
24452
- saveTriggerState(agentId, { ...loadTriggerState(agentId), pending: false });
24453
- void fire(agentId, "queued work from during the last run");
24028
+ }
24029
+ const st = loadTriggerState(agentId);
24030
+ const queued = Object.entries(st.pending);
24031
+ if (queued.length) {
24032
+ saveTriggerState(agentId, { ...st, pending: {} });
24033
+ for (const [index, evs] of queued) {
24034
+ await fire(agentId, Number(index), "queued work from during the last run", evs);
24454
24035
  }
24455
24036
  }
24456
24037
  }
@@ -24458,45 +24039,49 @@ function emitAgentEvent(event, payload) {
24458
24039
  for (const { id } of listCodingAgents()) {
24459
24040
  const def = getCodingAgent(id);
24460
24041
  if (!def) continue;
24461
- for (const trigger of asArray(def.trigger)) {
24042
+ asArray(def.trigger).forEach((trigger, index) => {
24462
24043
  if (trigger.type === "event") {
24463
24044
  const names = Array.isArray(trigger.on) ? trigger.on : [trigger.on];
24464
- if (!names.includes(event)) continue;
24045
+ if (!names.includes(event)) return;
24046
+ const arrived = { name: event, payload };
24465
24047
  if (!trigger.debounceMs) {
24466
- void fire(id, `event ${event}`, payload);
24467
- continue;
24048
+ void fire(id, index, `event ${event}`, [arrived]);
24049
+ return;
24468
24050
  }
24469
- const key = `${id}:${event}`;
24051
+ const key = `${id}:${index}`;
24052
+ bursts.set(key, capEvents([...bursts.get(key) ?? [], arrived]));
24470
24053
  const existing = debounces.get(key);
24471
24054
  if (existing) clearTimeout(existing);
24472
24055
  debounces.set(key, setTimeout(() => {
24473
24056
  debounces.delete(key);
24474
- void fire(id, `event ${event} (settled)`, payload);
24057
+ const batch = bursts.get(key) ?? [];
24058
+ bursts.delete(key);
24059
+ void fire(id, index, `event ${event} (settled, ${batch.length} event(s))`, batch);
24475
24060
  }, trigger.debounceMs));
24476
- continue;
24061
+ return;
24477
24062
  }
24478
24063
  if (trigger.type === "count" && trigger.on === event) {
24479
24064
  const state = loadTriggerState(id);
24480
- const next = (state.counts[event] ?? 0) + 1;
24481
- if (next < trigger.every) {
24482
- saveTriggerState(id, { ...state, counts: { ...state.counts, [event]: next } });
24483
- continue;
24065
+ const banked = capEvents([...state.counts[event] ?? [], { name: event, payload }]);
24066
+ if (banked.length < trigger.every) {
24067
+ saveTriggerState(id, { ...state, counts: { ...state.counts, [event]: banked } });
24068
+ return;
24484
24069
  }
24485
- saveTriggerState(id, { ...state, counts: { ...state.counts, [event]: 0 } });
24486
- void fire(id, `${trigger.every}x ${event}`, payload);
24070
+ saveTriggerState(id, { ...state, counts: { ...state.counts, [event]: [] } });
24071
+ void fire(id, index, `${trigger.every}x ${event}`, banked);
24487
24072
  }
24488
- }
24073
+ });
24489
24074
  }
24490
24075
  }
24491
24076
  function startAgentTriggers() {
24492
24077
  stopAgentTriggers();
24493
24078
  for (const { id } of listCodingAgents()) {
24494
24079
  const def = getCodingAgent(id);
24495
- for (const trigger of asArray(def?.trigger)) {
24496
- if (trigger.type !== "interval") continue;
24497
- intervals.set(id, setInterval(() => void fire(id, `interval ${trigger.everyMs}ms`), trigger.everyMs));
24080
+ asArray(def?.trigger).forEach((trigger, index) => {
24081
+ if (trigger.type !== "interval") return;
24082
+ intervals.set(`${id}:${index}`, setInterval(() => void fire(id, index, `interval ${trigger.everyMs}ms`), trigger.everyMs));
24498
24083
  logger.info(`[CodingAgent:${id}] interval trigger every ${trigger.everyMs}ms`);
24499
- }
24084
+ });
24500
24085
  }
24501
24086
  }
24502
24087
  function stopAgentTriggers() {
@@ -24504,6 +24089,7 @@ function stopAgentTriggers() {
24504
24089
  intervals.clear();
24505
24090
  for (const t of debounces.values()) clearTimeout(t);
24506
24091
  debounces.clear();
24092
+ bursts.clear();
24507
24093
  }
24508
24094
  function describeTriggers() {
24509
24095
  return listCodingAgents().map(({ id }) => {
@@ -24520,6 +24106,9 @@ function describeTriggers() {
24520
24106
  // src/codingAgent/collection.ts
24521
24107
  var fs11 = __toESM(require("fs"));
24522
24108
  var path11 = __toESM(require("path"));
24109
+ function isChattable(agent) {
24110
+ return agent.mode !== "task";
24111
+ }
24523
24112
  function registerCodingAgentCollection(sdk, config2 = {}) {
24524
24113
  const runtimeDir = config2.runtimeDir || process.env.CODING_AGENT_RUNTIME_DIR || path11.join(process.cwd(), ".coding-agent-runtime");
24525
24114
  const defaultHarness = config2.harness || process.env.CODING_AGENT_HARNESS || "codex";
@@ -24543,7 +24132,19 @@ function registerCodingAgentCollection(sdk, config2 = {}) {
24543
24132
  error: `Unknown agent "${agentId}". Available: ${listCodingAgents().map((a) => a.id).join(", ") || "(none registered)"}`
24544
24133
  };
24545
24134
  }
24135
+ if (!isChattable(def)) {
24136
+ return {
24137
+ success: false,
24138
+ error: `${def.title} runs as a scheduled task and is not available for chat.`
24139
+ };
24140
+ }
24546
24141
  const record = await runCodingAgent(agentId, {
24142
+ // chat:true is what stops a typed message being treated as a job. A
24143
+ // task agent's prepare()/output/apply() set work up and consume it, so
24144
+ // without this every conversational turn failed for not writing a
24145
+ // deliverable nobody asked for — and, for a batching agent, quietly ate
24146
+ // a batch of work on the way.
24147
+ chat: true,
24547
24148
  prompt,
24548
24149
  projectId,
24549
24150
  userId,
@@ -24563,7 +24164,10 @@ function registerCodingAgentCollection(sdk, config2 = {}) {
24563
24164
  sessionId: record.sessionId,
24564
24165
  ...record.output !== void 0 ? { output: record.output } : {},
24565
24166
  ...record.applied ? { applied: record.applied } : {},
24566
- ...record.error ? { error: record.error } : {}
24167
+ // A project-scoped agent serialises its runs, so a turn sent while it
24168
+ // is working is a normal outcome, not a fault. Say so in words a
24169
+ // person can act on.
24170
+ ...record.status === "skipped" ? { error: `${def.title} is in the middle of a run \u2014 try again in a moment.` } : record.error ? { error: record.error } : {}
24567
24171
  };
24568
24172
  }
24569
24173
  const cwd = path11.join(runtimeDir, "threads", threadId);
@@ -24610,7 +24214,10 @@ function registerCodingAgentCollection(sdk, config2 = {}) {
24610
24214
  }
24611
24215
  return { success: true };
24612
24216
  });
24613
- sdk.addCollection("coding-agent", "list", async () => ({ success: true, agents: listCodingAgents() }));
24217
+ sdk.addCollection("coding-agent", "list", async () => ({
24218
+ success: true,
24219
+ agents: listCodingAgents().map((a) => ({ ...a, chattable: isChattable(a) }))
24220
+ }));
24614
24221
  console.log(`\u2713 coding-agent collection registered (harness: ${defaultHarness})`);
24615
24222
  }
24616
24223
 
@@ -27744,11 +27351,6 @@ var SuperatomSDK = class {
27744
27351
  logger.error("Failed to handle user prompt abort request:", error);
27745
27352
  }
27746
27353
  break;
27747
- case "ACTIONS":
27748
- handleActionsRequest(parsed, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders).catch((error) => {
27749
- logger.error("Failed to handle actions request:", error);
27750
- });
27751
- break;
27752
27354
  case "USER_PROMPT_SUGGESTIONS_REQ":
27753
27355
  handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg), this.collections).catch((error) => {
27754
27356
  logger.error("Failed to handle user prompt suggestions request:", error);