@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.mjs CHANGED
@@ -316,8 +316,7 @@ var ComponentPropsSchema = z3.object({
316
316
  query: z3.string().or(z3.object({})).nullable().optional(),
317
317
  title: z3.string().optional(),
318
318
  description: z3.string().optional(),
319
- config: z3.record(z3.unknown()).optional(),
320
- actions: z3.array(z3.any()).optional()
319
+ config: z3.record(z3.unknown()).optional()
321
320
  }).passthrough();
322
321
  var ComponentSchema = z3.object({
323
322
  id: z3.string(),
@@ -431,19 +430,6 @@ var UILogsMessageSchema = z3.object({
431
430
  type: z3.literal("UI_LOGS"),
432
431
  payload: UILogsPayloadSchema
433
432
  });
434
- var ActionsRequestPayloadSchema = z3.object({
435
- userId: z3.string().optional(),
436
- SA_RUNTIME: z3.object({
437
- threadId: z3.string(),
438
- uiBlockId: z3.string()
439
- }).optional()
440
- });
441
- var ActionsRequestMessageSchema = z3.object({
442
- id: z3.string(),
443
- from: MessageParticipantSchema,
444
- type: z3.literal("ACTIONS"),
445
- payload: ActionsRequestPayloadSchema
446
- });
447
433
  var DashboardQueryFiltersSchema = z3.object({
448
434
  dashboardId: z3.string().optional(),
449
435
  projectId: z3.string().optional(),
@@ -553,8 +539,6 @@ var UIBlockSchema = z3.object({
553
539
  generatedComponentMetadata: ComponentSchema.optional(),
554
540
  // Actual field used by UIBlock class
555
541
  componentData: z3.record(z3.any()).optional(),
556
- actions: z3.array(z3.any()).optional(),
557
- isFetchingActions: z3.boolean().optional(),
558
542
  createdAt: z3.string().optional(),
559
543
  /**
560
544
  * Which script recipe produced this answer. Set whenever the turn was answered
@@ -1078,11 +1062,10 @@ var UIBlock = class {
1078
1062
  * @param userQuestion - The user's question or input
1079
1063
  * @param componentData - The component data object
1080
1064
  * @param generatedComponentMetadata - Optional metadata about the generated component
1081
- * @param actions - Optional array of available actions
1082
1065
  * @param id - Optional custom ID, generates UUID if not provided
1083
1066
  * @param textResponse - Optional text response from LLM
1084
1067
  */
1085
- constructor(userQuestion, componentData = {}, generatedComponentMetadata = {}, actions = [], id, textResponse = null) {
1068
+ constructor(userQuestion, componentData = {}, generatedComponentMetadata = {}, id, textResponse = null) {
1086
1069
  /**
1087
1070
  * Which script recipe produced this answer, when a script did. Read on the
1088
1071
  * NEXT turn so the user can say "use mode instead" and have the matcher
@@ -1094,7 +1077,6 @@ var UIBlock = class {
1094
1077
  this.userQuestion = userQuestion;
1095
1078
  this.componentData = componentData;
1096
1079
  this.generatedComponentMetadata = generatedComponentMetadata;
1097
- this.actions = actions;
1098
1080
  this.textResponse = textResponse;
1099
1081
  this.createdAt = /* @__PURE__ */ new Date();
1100
1082
  }
@@ -1223,76 +1205,6 @@ var UIBlock = class {
1223
1205
  setTextResponse(textResponse) {
1224
1206
  this.textResponse = textResponse;
1225
1207
  }
1226
- /**
1227
- * Get all actions (only if they are resolved, not if fetching)
1228
- */
1229
- getActions() {
1230
- return this.actions;
1231
- }
1232
- /**
1233
- * Get or fetch actions
1234
- * If actions don't exist or are a Promise, calls the generateFn and stores the promise
1235
- * If actions already exist, returns them
1236
- * @param generateFn - Async function to generate actions
1237
- * @returns Promise resolving to Action[]
1238
- */
1239
- async getOrFetchActions(generateFn) {
1240
- if (this.actions && !(this.actions instanceof Promise) && Array.isArray(this.actions) && this.actions.length > 0) {
1241
- return this.actions;
1242
- }
1243
- const fetchPromise = generateFn();
1244
- this.actions = fetchPromise;
1245
- try {
1246
- const resolvedActions = await fetchPromise;
1247
- logger.info(`Fetched ${resolvedActions.length} actions for UIBlock: ${this.id}`);
1248
- this.actions = resolvedActions;
1249
- return resolvedActions;
1250
- } catch (error) {
1251
- this.actions = null;
1252
- throw error;
1253
- }
1254
- }
1255
- /**
1256
- * Set or replace all actions
1257
- */
1258
- setActions(actions) {
1259
- this.actions = actions;
1260
- }
1261
- /**
1262
- * Add a single action (only if actions are resolved)
1263
- */
1264
- addAction(action) {
1265
- if (this.actions && Array.isArray(this.actions)) {
1266
- this.actions.push(action);
1267
- }
1268
- }
1269
- /**
1270
- * Add multiple actions (only if actions are resolved)
1271
- */
1272
- addActions(actions) {
1273
- if (this.actions && Array.isArray(this.actions)) {
1274
- this.actions.push(...actions);
1275
- }
1276
- }
1277
- /**
1278
- * Remove an action by ID (only if actions are resolved)
1279
- */
1280
- removeAction(actionId) {
1281
- if (this.actions && Array.isArray(this.actions)) {
1282
- const index = this.actions.findIndex((a) => a.id === actionId);
1283
- if (index > -1) {
1284
- this.actions.splice(index, 1);
1285
- return true;
1286
- }
1287
- }
1288
- return false;
1289
- }
1290
- /**
1291
- * Clear all actions
1292
- */
1293
- clearActions() {
1294
- this.actions = null;
1295
- }
1296
1208
  /**
1297
1209
  * Bind this block to the script recipe that produced its answer.
1298
1210
  */
@@ -1322,18 +1234,12 @@ var UIBlock = class {
1322
1234
  * Convert UIBlock to JSON-serializable object
1323
1235
  */
1324
1236
  toJSON() {
1325
- let actionsValue = null;
1326
- if (this.actions && !(this.actions instanceof Promise) && Array.isArray(this.actions)) {
1327
- actionsValue = this.actions;
1328
- }
1329
1237
  return {
1330
1238
  id: this.id,
1331
1239
  userQuestion: this.userQuestion,
1332
1240
  generatedComponentMetadata: this.generatedComponentMetadata,
1333
1241
  componentData: this.componentData,
1334
1242
  textResponse: this.textResponse,
1335
- actions: actionsValue,
1336
- isFetchingActions: this.actions instanceof Promise,
1337
1243
  createdAt: this.createdAt.toISOString(),
1338
1244
  ...this.scriptBinding ? { scriptBinding: this.scriptBinding } : {},
1339
1245
  ...this.programAnswer ? { programAnswer: this.programAnswer } : {}
@@ -1471,23 +1377,55 @@ var Thread = class {
1471
1377
  * since-edited) live body. Owned by the caller (needs a ScriptStore, which
1472
1378
  * Thread doesn't hold) — omit it and every turn falls back to the
1473
1379
  * no-script summary below.
1474
- */
1475
- async getConversationContext(limit = 5, currentUIBlockId, getScriptBody) {
1380
+ * @param fetchRecentFromDb When provided, this is now the SOURCE OF TRUTH
1381
+ * for history instead of this process's in-memory `uiblocks` map — reads
1382
+ * the persisted `user_conversations` rows (DB `response` jsonb shape, see
1383
+ * transformUIBlockForDB in conversation-saver.ts) via the caller's own
1384
+ * `user-conversations.getRecentForContext` collection. Rows come back
1385
+ * newest-first (already excluding status='aborted' — the query itself
1386
+ * filters that, matching what the in-memory path achieved via
1387
+ * thread.removeUIBlock() on abort). Fixes the standing gap where a backend
1388
+ * restart lost every thread's history (ThreadManager has no DB-backed
1389
+ * rehydration) — DB-backed history survives that, and is correct even if
1390
+ * a different process instance saved the row. Omit it and this falls back
1391
+ * to the in-memory map, for any caller not yet updated.
1392
+ */
1393
+ async getConversationContext(limit = 5, currentUIBlockId, getScriptBody, fetchRecentFromDb) {
1476
1394
  if (limit === 0) {
1477
1395
  return "";
1478
1396
  }
1479
- const allBlocks = Array.from(this.uiblocks.values()).filter((block) => !currentUIBlockId || block.getId() !== currentUIBlockId).sort((a, b) => a.getCreatedAt().getTime() - b.getCreatedAt().getTime());
1480
- if (allBlocks.length === 0) {
1397
+ let turns;
1398
+ if (fetchRecentFromDb) {
1399
+ const rows = await fetchRecentFromDb(limit);
1400
+ turns = rows.slice().reverse().map((row) => {
1401
+ const r = row.response || {};
1402
+ return {
1403
+ question: row.userprompt || r.user_prompt || "",
1404
+ metadata: r.component || {},
1405
+ programAnswer: r.programAnswer || null,
1406
+ textResponse: r.analysis || "",
1407
+ scriptBinding: r.scriptBinding || null
1408
+ };
1409
+ });
1410
+ } else {
1411
+ const allBlocks = Array.from(this.uiblocks.values()).filter((block) => !currentUIBlockId || block.getId() !== currentUIBlockId).sort((a, b) => a.getCreatedAt().getTime() - b.getCreatedAt().getTime());
1412
+ if (allBlocks.length === 0) {
1413
+ return "";
1414
+ }
1415
+ turns = allBlocks.slice(-limit).map((block) => ({
1416
+ question: block.getUserQuestion(),
1417
+ metadata: block.getComponentMetadata(),
1418
+ programAnswer: block.getProgramAnswer(),
1419
+ textResponse: block.getTextResponse(),
1420
+ scriptBinding: block.getScriptBinding()
1421
+ }));
1422
+ }
1423
+ if (turns.length === 0) {
1481
1424
  return "";
1482
1425
  }
1483
- const recentBlocks = allBlocks.slice(-limit);
1484
1426
  const contextLines = [];
1485
- for (const block of recentBlocks) {
1486
- const question = block.getUserQuestion();
1487
- const metadata = block.getComponentMetadata();
1488
- const programAnswer = block.getProgramAnswer();
1489
- const textResponse = block.getTextResponse();
1490
- const scriptBinding = block.getScriptBinding();
1427
+ for (const turn of turns) {
1428
+ const { question, metadata, programAnswer, textResponse, scriptBinding } = turn;
1491
1429
  const responseParts = [];
1492
1430
  let analysisText = "";
1493
1431
  const hasProgramAnswer = programAnswer && programAnswer.trim().length > 0;
@@ -3417,7 +3355,6 @@ var MAX_TOKENS_COMPONENT_MATCHING = 8192;
3417
3355
  var MAX_TOKENS_CLASSIFICATION = 1500;
3418
3356
  var MAX_TOKENS_ADAPTATION = 8192;
3419
3357
  var MAX_TOKENS_TEXT_RESPONSE = 4e3;
3420
- var MAX_TOKENS_NEXT_QUESTIONS = 1200;
3421
3358
  var MAX_ROWS_FETCHED = 50;
3422
3359
  var MAX_ROWS_TO_LLM = 10;
3423
3360
  var LLM_SAMPLE_ROWS = 10;
@@ -5790,7 +5727,6 @@ You receive TWO key inputs:
5790
5727
  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.
5791
5728
  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.
5792
5729
  5. **Dashboard metadata**: Title (5-10 words) and description (1-2 sentences)
5793
- 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.
5794
5730
 
5795
5731
  ### Choosing Complexity
5796
5732
  Determine complexity from the analysis text and EXECUTED_TOOLS:
@@ -6004,8 +5940,7 @@ When using \`externalTool\`, use field names from the tool's \`outputSchema\` in
6004
5940
  "answerComponent": { ... } | null,
6005
5941
  "layoutTitle": "Dashboard title (5-10 words)",
6006
5942
  "layoutDescription": "Dashboard purpose (1-2 sentences)",
6007
- "matchedComponents": [ ... ],
6008
- "actions": ["Follow-up question 1?", "Follow-up question 2?", "Follow-up question 3?"]
5943
+ "matchedComponents": [ ... ]
6009
5944
  }
6010
5945
  \`\`\`
6011
5946
 
@@ -6120,52 +6055,6 @@ Example when hasAnswerComponent is true:
6120
6055
 
6121
6056
  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.
6122
6057
  ---`
6123
- },
6124
- "actions": {
6125
- 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.
6126
-
6127
- **Rules:**
6128
- - Keep questions short and simple \u2014 one clear ask per question
6129
- - Questions MUST be answerable by querying the available data columns (SQL queries)
6130
- - Suggest different slices of the same data: by time period, by category, by route, top/bottom N, trends, comparisons
6131
- - Avoid repeating topics already covered in the conversation
6132
- - NEVER suggest questions about: root causes, recommendations, process changes, staffing, business decisions, or anything requiring human judgment
6133
- - NEVER ask "why" questions \u2014 only "what", "which", "how much", "how does X compare to Y"
6134
-
6135
- ---
6136
-
6137
- ## CONTEXT (for this specific request)
6138
-
6139
- ### Previous Conversation
6140
- {{CONVERSATION_HISTORY}}`,
6141
- user: `Current Date and Time: {{CURRENT_DATETIME}}
6142
-
6143
- Given the following context:
6144
-
6145
- Latest User Question: {{ORIGINAL_USER_PROMPT}}
6146
-
6147
- Current Component:
6148
- {{COMPONENT_INFO}}
6149
-
6150
- {{COMPONENT_DATA}}
6151
-
6152
- Generate a JSON array of exactly 3 simple follow-up questions. Each question should:
6153
- 1. Be answerable by running a SQL query on the available data \u2014 no consulting or opinion questions
6154
- 2. Explore a different dimension or slice of the data (different grouping, time range, filter, comparison)
6155
- 3. NOT repeat topics already covered in the conversation
6156
- 4. Be short and direct \u2014 one sentence, one clear ask
6157
- 5. Use specific column names or values from the data when relevant
6158
-
6159
- Format your response as a JSON object with this structure:
6160
- {
6161
- "nextQuestions": [
6162
- "Question 1?",
6163
- "Question 2?",
6164
- ...
6165
- ]
6166
- }
6167
-
6168
- Return ONLY valid JSON.`
6169
6058
  },
6170
6059
  "category-classification": {
6171
6060
  system: `You categorize user questions and identify required data source tools. Respond with ONLY valid JSON.
@@ -6331,7 +6220,7 @@ Your task is to:
6331
6220
  ## Component Structure Handling
6332
6221
 
6333
6222
  ### For Single Components:
6334
- - Modify props directly (config, actions, query, filters, etc.)
6223
+ - Modify props directly (config, query, filters, etc.)
6335
6224
 
6336
6225
  ### For MultiComponentContainer:
6337
6226
  The component will have structure:
@@ -6344,8 +6233,7 @@ The component will have structure:
6344
6233
  "components": [...], // Array of nested components - ADAPT EACH ONE
6345
6234
  "title": "...", // Container title - UPDATE based on new question
6346
6235
  "description": "..." // Container description - UPDATE based on new question
6347
- },
6348
- "actions": [...] // ADAPT actions if needed
6236
+ }
6349
6237
  }
6350
6238
  }
6351
6239
  \`\`\`
@@ -6357,7 +6245,6 @@ When adapting MultiComponentContainer:
6357
6245
  - Adapt its query parameters (WHERE clauses, LIMIT, ORDER BY, filters, date ranges)
6358
6246
  - Update its title/description to match the new context
6359
6247
  - Update its config settings (colors, sorting, grouping, metrics)
6360
- - Update \`actions\` if the new question requires different actions
6361
6248
 
6362
6249
  ## Important Guidelines:
6363
6250
  - Keep the same component type (don't change KPICard to LineChart)
@@ -6430,8 +6317,7 @@ When adapting queries, follow the database-specific rules below:
6430
6317
  "type": "component_type",
6431
6318
  "description": "updated_description",
6432
6319
  "props": {
6433
- "config": { },
6434
- "actions": []
6320
+ "config": { }
6435
6321
  }
6436
6322
  },
6437
6323
  "adaptedTextResponse": "The adapted text response with updated values matching the new question...",
@@ -6488,8 +6374,7 @@ When adapting queries, follow the database-specific rules below:
6488
6374
  }
6489
6375
  }
6490
6376
  ]
6491
- },
6492
- "actions": []
6377
+ }
6493
6378
  }
6494
6379
  },
6495
6380
  "adaptedTextResponse": "The adapted text response with entity names, IDs, and references updated to match the new question. Numeric values replaced with placeholders.",
@@ -6557,13 +6442,12 @@ When adapting SQL queries, preserve the table and column names from the original
6557
6442
 
6558
6443
  1. **Analyze the difference** between the original question and the current question
6559
6444
  2. **Identify what data needs to change**:
6560
- - For single components: adapt the query/config/actions
6445
+ - For single components: adapt the query/config
6561
6446
  - For MultiComponentContainer: adapt the container title/description AND each nested component's parameters
6562
6447
 
6563
6448
  3. **Modify the parameters**:
6564
6449
  - **Container level** (if MultiComponentContainer):
6565
6450
  - Update \`title\` and \`description\` to reflect the new user question
6566
- - Update \`actions\` if needed
6567
6451
 
6568
6452
  - **For each component** (single or nested in container):
6569
6453
  - Identify what it shows (sales, revenue, inventory, etc.)
@@ -8082,16 +7966,9 @@ Return JSON. Shape each component per the section above (markdown uses \`props.c
8082
7966
  { "componentId": "<the answerComponent, repeated as the FIRST entry>", "componentName": "...", "sourceIndex": 0, "props": { "title": "...", "config": { "xAxisKey": "...", "yAxisKey": "..." } } },
8083
7967
  { "componentId": "...", "componentName": "DynamicMarkdownBlock", "props": { "content": "## Recommendation\\n\\n- key point\\n- key point" } },
8084
7968
  { "componentId": "...", "componentName": "DynamicDataTable", "sourceIndex": 0, "props": { "title": "...", "config": { "columns": [ { "key": "<exact data column>", "label": "<Heading>" } ] } } }
8085
- ],
8086
- "actions": [
8087
- { "question": "<follow-up question 1>" },
8088
- { "question": "<follow-up question 2>" },
8089
- { "question": "<follow-up question 3>" }
8090
7969
  ]
8091
7970
  }
8092
7971
 
8093
- 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.
8094
-
8095
7972
  ---
8096
7973
 
8097
7974
  ## CONTEXT (for this specific request)
@@ -9877,14 +9754,6 @@ function ensurePostgresLimit(query, defaultLimit, maxLimit, hadSemicolon) {
9877
9754
  }
9878
9755
  return trimmedQuery;
9879
9756
  }
9880
- function convertQuestionsToActions(questions) {
9881
- return questions.map((question, index) => ({
9882
- id: `action_${index}_${Date.now()}`,
9883
- name: question,
9884
- type: "next_question",
9885
- question
9886
- }));
9887
- }
9888
9757
  function validateAndFixSqlQuery(query, dbType) {
9889
9758
  if (!query || query.trim().length === 0) {
9890
9759
  return { query, fixed: false, fixes: [] };
@@ -13310,7 +13179,7 @@ var DEFAULT_AGENT_CONFIG = {
13310
13179
  // will use the provider's default model
13311
13180
  maxRetries: 2,
13312
13181
  // 2 retries = 3 total query attempts (1 initial + 2 retries for SQL errors)
13313
- maxIterations: 15
13182
+ maxIterations: 20
13314
13183
  // schema search (2-3) + query attempts (2) + write_script/execute_script (2-3) + write_analysis (up to 3) + LLM responses + final
13315
13184
  };
13316
13185
 
@@ -14121,6 +13990,9 @@ function parseEditPrefix(rawPrompt) {
14121
13990
  if (!match) return { isExplicitEdit: false, prompt: rawPrompt };
14122
13991
  return { isExplicitEdit: true, prompt: rawPrompt.slice(match[0].length) };
14123
13992
  }
13993
+ function hasExplicitEditPrefix(prompt) {
13994
+ return EDIT_PREFIX_RE.test(prompt);
13995
+ }
14124
13996
  var MAX_FAILURE_RATE = 0.2;
14125
13997
  var PROMPT_HISTORY_SEARCH_LIMIT = 20;
14126
13998
  var PROMPT_HISTORY_SIMILARITY_THRESHOLD = 0.5;
@@ -14177,10 +14049,11 @@ var ScriptMatcher = class {
14177
14049
  traceEntry.sent.userPrompt = userPrompt;
14178
14050
  const promptHistoryMatches = await this.searchPromptHistory(userPrompt);
14179
14051
  const candidates = [];
14180
- for (const binding of activeBindings || []) {
14181
- const recipe = await this.store.get(binding.recipeId);
14182
- if (recipe) candidates.push({ recipe, binding });
14183
- else logger.warn(`[ScriptMatcher] Bound recipe "${binding.recipeId}" no longer in store \u2014 dropped from edit candidates`);
14052
+ const mostRecentBinding = activeBindings?.[0];
14053
+ if (mostRecentBinding) {
14054
+ const recipe = await this.store.get(mostRecentBinding.recipeId);
14055
+ if (recipe) candidates.push({ recipe, binding: mostRecentBinding });
14056
+ else logger.warn(`[ScriptMatcher] Bound recipe "${mostRecentBinding.recipeId}" no longer in store \u2014 no edit candidate this turn`);
14184
14057
  }
14185
14058
  const candidateById = new Map(candidates.map((c) => [c.recipe.id, c]));
14186
14059
  traceEntry.sent.activeBindingCount = candidates.length;
@@ -14240,11 +14113,6 @@ var ScriptMatcher = class {
14240
14113
  } else if (candidates.length === 0) {
14241
14114
  logger.info(`[ScriptMatcher] 'edit' coerced to 'none' (no script-backed answer in this thread to edit)`);
14242
14115
  tier = "none";
14243
- } else if (!candidateById.has(response?.scriptId)) {
14244
- logger.warn(
14245
- `[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.`
14246
- );
14247
- tier = "none";
14248
14116
  } else if (!response?.editInstruction || !String(response.editInstruction).trim()) {
14249
14117
  logger.warn(`[ScriptMatcher] 'edit' coerced to 'none' \u2014 matcher returned no editInstruction`);
14250
14118
  tier = "none";
@@ -14252,35 +14120,45 @@ var ScriptMatcher = class {
14252
14120
  }
14253
14121
  const reasoning = response?.reasoning || "unknown";
14254
14122
  traceEntry.received.tier = tier;
14255
- if (tier === "none" || !response?.scriptId || response.scriptId === "none") {
14123
+ if (tier === "none") {
14256
14124
  logger.info(`[ScriptMatcher] No match. Reason: ${reasoning}`);
14257
14125
  return null;
14258
14126
  }
14259
- const recipe = candidateById.get(response.scriptId)?.recipe ?? await this.store.get(response.scriptId);
14260
- if (!recipe) {
14261
- logger.warn(`[ScriptMatcher] LLM returned unknown script ID: "${response.scriptId}"`);
14262
- traceEntry.received.error = `LLM returned unknown script ID: "${response.scriptId}"`;
14263
- return null;
14264
- }
14265
14127
  if (tier === "edit") {
14128
+ const target = candidates[0];
14129
+ if (response?.scriptId && response.scriptId !== target.recipe.id) {
14130
+ logger.info(
14131
+ `[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.`
14132
+ );
14133
+ }
14266
14134
  const editInstruction = String(response.editInstruction).trim();
14267
14135
  const editTarget = String(response.editTarget || "").toLowerCase() === "display" ? "display" : "data";
14268
- logger.info(`[ScriptMatcher] EDIT [${editTarget}] "${recipe.name}": ${editInstruction} | Reason: ${reasoning}`);
14136
+ logger.info(`[ScriptMatcher] EDIT [${editTarget}] "${target.recipe.name}": ${editInstruction} | Reason: ${reasoning}`);
14269
14137
  return {
14270
- recipe,
14138
+ recipe: target.recipe,
14271
14139
  tier: "edit",
14272
14140
  editTarget,
14273
14141
  similarity: 1,
14274
14142
  confidence: "high",
14275
- // Carry the chosen candidate's params so the edited script re-runs on
14276
- // the same scope the user was looking at, not on bare defaults.
14277
- extractedParams: candidateById.get(response.scriptId)?.binding.params || {},
14143
+ // Carry the target's own params so the edited script re-runs on the
14144
+ // same scope the user was looking at, not on bare defaults.
14145
+ extractedParams: target.binding.params || {},
14278
14146
  mentions: parseMentions(response.mentions),
14279
14147
  entityTypes: parseEntityTypes(response.entityTypes),
14280
14148
  editInstruction,
14281
14149
  reasoning
14282
14150
  };
14283
14151
  }
14152
+ if (!response?.scriptId || response.scriptId === "none") {
14153
+ logger.info(`[ScriptMatcher] No match. Reason: ${reasoning}`);
14154
+ return null;
14155
+ }
14156
+ const recipe = candidateById.get(response.scriptId)?.recipe ?? await this.store.get(response.scriptId);
14157
+ if (!recipe) {
14158
+ logger.warn(`[ScriptMatcher] LLM returned unknown script ID: "${response.scriptId}"`);
14159
+ traceEntry.received.error = `LLM returned unknown script ID: "${response.scriptId}"`;
14160
+ return null;
14161
+ }
14284
14162
  const declaredParamNames = new Set(recipe.parameters.map((p) => p.name));
14285
14163
  const inventedParamKeys = Object.keys(response.params || {}).filter((k) => !declaredParamNames.has(k));
14286
14164
  if (inventedParamKeys.length > 0) {
@@ -14400,41 +14278,41 @@ ${paramList}`;
14400
14278
  }).join("\n\n");
14401
14279
  }
14402
14280
  /**
14403
- * The recent script-backed answers in this thread — the bounded set an edit
14404
- * may target. Rendered as its own prompt section (never merged into the
14405
- * ranked catalog) so the `edit` rules have an unambiguous referent set, and
14406
- * numbered newest-first so the prompt's "prefer the most recent when the
14407
- * instruction is ambiguous" tie-break has something to point at.
14281
+ * The most recent script-backed answer in this thread — the one an `edit`
14282
+ * targets. Rendered as its own prompt section (never merged into the ranked
14283
+ * catalog) so the `edit` rules have an unambiguous referent.
14284
+ *
14285
+ * `candidates` holds at most one entry (see doMatch) — `edit` always means
14286
+ * "the answer I just got", so there is nothing else to show here.
14408
14287
  *
14409
- * Each entry carries the QUESTION that produced it plus the columns it
14410
- * returned — that is what lets the matcher resolve "use the mode for the WSP
14411
- * one" instead of blindly taking the newest.
14288
+ * Carries the QUESTION that produced it plus the columns it returned — that
14289
+ * is what lets the matcher resolve "use the mode for the WSP one" against
14290
+ * this one script's own context.
14412
14291
  */
14413
14292
  buildActiveScriptBlock(candidates) {
14414
- const blocks = candidates.map(({ recipe, binding }, idx) => {
14415
- const paramList = this.formatParamList(recipe.parameters);
14416
- const lines = [
14417
- `${idx + 1}. [${recipe.id}] "${recipe.name}"${idx === 0 ? " \u2190 most recent" : ""}`,
14418
- ` ${recipe.intentDescription}`
14419
- ];
14420
- if (binding.userPrompt) lines.push(` Answered the question: "${binding.userPrompt}"`);
14421
- if (binding.answerSummary) {
14422
- const trimmed = binding.answerSummary.length > 1e3 ? binding.answerSummary.slice(0, 1e3) + "...[truncated]" : binding.answerSummary;
14423
- lines.push(` Last answer: ${trimmed.replace(/\n/g, "\n ")}`);
14424
- }
14425
- if (binding.columns?.length) lines.push(` Columns it returned: ${binding.columns.join(", ")}`);
14426
- if (binding.params && Object.keys(binding.params).length > 0) {
14427
- lines.push(` Ran with: ${JSON.stringify(binding.params)}`);
14428
- }
14429
- lines.push(" Parameters:", paramList);
14430
- return lines.join("\n");
14431
- });
14293
+ const target = candidates[0];
14294
+ if (!target) return "";
14295
+ const { recipe, binding } = target;
14296
+ const paramList = this.formatParamList(recipe.parameters);
14297
+ const lines = [
14298
+ `[${recipe.id}] "${recipe.name}"`,
14299
+ `${recipe.intentDescription}`
14300
+ ];
14301
+ if (binding.userPrompt) lines.push(`Answered the question: "${binding.userPrompt}"`);
14302
+ if (binding.answerSummary) {
14303
+ const trimmed = binding.answerSummary.length > 1e3 ? binding.answerSummary.slice(0, 1e3) + "...[truncated]" : binding.answerSummary;
14304
+ lines.push(`Last answer: ${trimmed}`);
14305
+ }
14306
+ if (binding.columns?.length) lines.push(`Columns it returned: ${binding.columns.join(", ")}`);
14307
+ if (binding.params && Object.keys(binding.params).length > 0) {
14308
+ lines.push(`Ran with: ${JSON.stringify(binding.params)}`);
14309
+ }
14310
+ lines.push("Parameters:", paramList);
14432
14311
  return [
14433
- "### EDITABLE SCRIPTS \u2014 answers already given in THIS conversation (newest first)",
14434
- "An `edit` may target ONLY one of these. When the instruction does not clearly",
14435
- "name which one, choose #1 (the most recent).",
14312
+ "### EDITABLE SCRIPT \u2014 the answer just given in THIS conversation",
14313
+ "An `edit` always targets this script.",
14436
14314
  "",
14437
- blocks.join("\n\n")
14315
+ lines.join("\n")
14438
14316
  ].join("\n");
14439
14317
  }
14440
14318
  };
@@ -14775,7 +14653,7 @@ async function generateScriptComponents(params) {
14775
14653
  const queries = scriptResult.executedQueries;
14776
14654
  if (!queries || queries.length === 0) {
14777
14655
  logger.warn(`[ScriptComponentGen] No query data available \u2014 returning empty`);
14778
- return { components: [], layoutTitle: "", layoutDescription: "", actions: [], componentSpecs: [] };
14656
+ return { components: [], layoutTitle: "", layoutDescription: "", componentSpecs: [] };
14779
14657
  }
14780
14658
  logger.info(`[ScriptComponentGen] Starting | ${queries.length} queries | ${availableComponents.length} available components`);
14781
14659
  const columnsByIndex = queries.map((q) => {
@@ -14862,7 +14740,7 @@ ${sampleData}
14862
14740
  logger.logLLMPrompt("scriptComponentGen:response", "user", JSON.stringify(response, null, 2));
14863
14741
  if (!response || !response.components || !Array.isArray(response.components)) {
14864
14742
  logger.warn(`[ScriptComponentGen] LLM returned invalid response`);
14865
- return { components: [], layoutTitle: "", layoutDescription: "", actions: [], componentSpecs: [] };
14743
+ return { components: [], layoutTitle: "", layoutDescription: "", componentSpecs: [] };
14866
14744
  }
14867
14745
  const layoutTitle = response.layoutTitle || "Dashboard";
14868
14746
  const layoutDescription = response.layoutDescription || "";
@@ -14917,23 +14795,16 @@ ${sampleData}
14917
14795
  }
14918
14796
  }
14919
14797
  logger.info(`[ScriptComponentGen] Generated ${matchedComponents.length} components`);
14920
- const actions = (response.actions || []).map((a, idx) => ({
14921
- id: `action_${idx}_${Date.now()}`,
14922
- name: a.name || a.question || "",
14923
- type: "next_question",
14924
- question: a.question || a.name || ""
14925
- }));
14926
14798
  return {
14927
14799
  components: matchedComponents,
14928
14800
  layoutTitle,
14929
14801
  layoutDescription,
14930
- actions,
14931
14802
  componentSpecs
14932
14803
  };
14933
14804
  } catch (error) {
14934
14805
  const msg = error instanceof Error ? error.message : String(error);
14935
14806
  logger.error(`[ScriptComponentGen] Failed: ${msg}`);
14936
- return { components: [], layoutTitle: "", layoutDescription: "", actions: [], componentSpecs: [] };
14807
+ return { components: [], layoutTitle: "", layoutDescription: "", componentSpecs: [] };
14937
14808
  }
14938
14809
  }
14939
14810
  async function summarizeToMarkdown(analysis, apiKey, model) {
@@ -15991,15 +15862,15 @@ var BaseLLM = class {
15991
15862
  return false;
15992
15863
  }
15993
15864
  /**
15994
- * Match components from text response suggestions and generate follow-up questions
15865
+ * Match components from text response suggestions
15995
15866
  * Takes a text response with component suggestions (c1:type format) and matches with available components
15996
- * Also generates title, description, and intelligent follow-up questions (actions) based on the analysis
15867
+ * Also generates title and description based on the analysis
15997
15868
  * All components are placed in a default MultiComponentContainer layout
15998
15869
  * @param analysisContent - The text response containing component suggestions
15999
15870
  * @param components - List of available components
16000
15871
  * @param apiKey - Optional API key
16001
15872
  * @param componentStreamCallback - Optional callback to stream primary KPI component as soon as it's identified
16002
- * @returns Object containing matched components, layout title/description, and follow-up actions
15873
+ * @returns Object containing matched components and layout title/description
16003
15874
  */
16004
15875
  async matchComponentsFromAnalysis(analysisContent, components, userPrompt, apiKey, componentStreamCallback, deferredTools, executedTools, collections, userId) {
16005
15876
  const methodStartTime = Date.now();
@@ -16263,8 +16134,6 @@ ${executedToolsText}`);
16263
16134
  logger.info(`[${this.getProviderName()}] ${idx + 1}. ${comp.componentType} (${comp.componentName}) - ${comp.originalSuggestion || "N/A"}`);
16264
16135
  });
16265
16136
  logger.file("\n=============================\nFull LLM response:", JSON.stringify(result, null, 2));
16266
- const rawActions = result.actions || [];
16267
- const actions = convertQuestionsToActions(rawActions);
16268
16137
  const finalComponents = matchedComponents.map((mc) => {
16269
16138
  const originalComponent = components.find((c) => c.name === mc.componentName);
16270
16139
  if (!originalComponent) {
@@ -16307,12 +16176,11 @@ ${executedToolsText}`);
16307
16176
  logger.error(`[${this.getProviderName()}] Skipping query validation - database execute function not available`);
16308
16177
  }
16309
16178
  const methodDuration = Date.now() - methodStartTime;
16310
- logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration}ms | components: ${validatedComponents.length} | actions: ${actions.length}`);
16179
+ logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration}ms | components: ${validatedComponents.length}`);
16311
16180
  return {
16312
16181
  components: validatedComponents,
16313
16182
  layoutTitle,
16314
- layoutDescription,
16315
- actions
16183
+ layoutDescription
16316
16184
  };
16317
16185
  } catch (error) {
16318
16186
  const methodDuration = Date.now() - methodStartTime;
@@ -16321,8 +16189,7 @@ ${executedToolsText}`);
16321
16189
  return {
16322
16190
  components: [],
16323
16191
  layoutTitle: "Dashboard",
16324
- layoutDescription: "Failed to generate dashboard",
16325
- actions: []
16192
+ layoutDescription: "Failed to generate dashboard"
16326
16193
  };
16327
16194
  }
16328
16195
  }
@@ -16361,8 +16228,6 @@ ${executedToolsText}`);
16361
16228
  });
16362
16229
  logger.logLLMPrompt("classifyQuestionCategory", "system", extractPromptText(prompts.system));
16363
16230
  logger.logLLMPrompt("classifyQuestionCategory", "user", extractPromptText(prompts.user));
16364
- logger.logLLMPrompt("generateNextQuestions", "system", extractPromptText(prompts.system));
16365
- logger.logLLMPrompt("generateNextQuestions", "user", extractPromptText(prompts.user));
16366
16231
  const result = await LLM.stream(
16367
16232
  {
16368
16233
  sys: prompts.system,
@@ -16715,7 +16580,6 @@ ${executedToolsText}`);
16715
16580
  data: {
16716
16581
  text: textResponse,
16717
16582
  // Include the streamed text showing all attempts
16718
- actions: [],
16719
16583
  method: `${this.getProviderName()}-text-response-max-attempts`
16720
16584
  }
16721
16585
  };
@@ -16728,21 +16592,8 @@ ${executedToolsText}`);
16728
16592
  let matchedComponents = [];
16729
16593
  let layoutTitle = "Dashboard";
16730
16594
  let layoutDescription = "Multi-component dashboard";
16731
- let actions = [];
16732
16595
  if (category === "general") {
16733
16596
  logger.info(`[${this.getProviderName()}] General category - wrapping text response in DynamicMarkdownBlock`);
16734
- const nextQuestions = await this.generateNextQuestions(
16735
- userPrompt,
16736
- null,
16737
- // no component
16738
- void 0,
16739
- // no component data
16740
- apiKey,
16741
- conversationHistory,
16742
- textResponse
16743
- // pass text response as context
16744
- );
16745
- actions = convertQuestionsToActions(nextQuestions);
16746
16597
  const markdownContent2 = textResponse.replace(/<DashboardComponents>[\s\S]*?<\/DashboardComponents>/g, "").trim();
16747
16598
  matchedComponents = [{
16748
16599
  id: "dynamic-markdown-block",
@@ -16793,7 +16644,6 @@ ${executedToolsText}`);
16793
16644
  matchedComponents = matchResult.components;
16794
16645
  layoutTitle = matchResult.layoutTitle;
16795
16646
  layoutDescription = matchResult.layoutDescription;
16796
- actions = matchResult.actions;
16797
16647
  }
16798
16648
  let container_componet = null;
16799
16649
  if (matchedComponents.length > 0) {
@@ -16807,19 +16657,17 @@ ${executedToolsText}`);
16807
16657
  title: layoutTitle,
16808
16658
  description: layoutDescription,
16809
16659
  components: matchedComponents
16810
- },
16811
- actions
16660
+ }
16812
16661
  }
16813
16662
  };
16814
16663
  }
16815
16664
  const methodDuration = Date.now() - methodStartTime;
16816
- logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration}ms | result: success | components: ${matchedComponents.length} | actions: ${actions.length}`);
16665
+ logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration}ms | result: success | components: ${matchedComponents.length}`);
16817
16666
  return {
16818
16667
  success: true,
16819
16668
  data: {
16820
16669
  text: textResponse,
16821
16670
  component: container_componet,
16822
- actions,
16823
16671
  method: `${this.getProviderName()}-text-response`
16824
16672
  },
16825
16673
  errors: []
@@ -16841,7 +16689,6 @@ ${executedToolsText}`);
16841
16689
  errors,
16842
16690
  data: {
16843
16691
  text: "I apologize, but I encountered an error while processing your question. Please try rephrasing or ask something else.",
16844
- actions: [],
16845
16692
  method: `${this.getProviderName()}-text-response-error`
16846
16693
  }
16847
16694
  };
@@ -16883,7 +16730,6 @@ ${executedToolsText}`);
16883
16730
  data: {
16884
16731
  text: cachedTextResponse,
16885
16732
  component: null,
16886
- actions: conversationMatch.uiBlock?.actions || [],
16887
16733
  reasoning: `Exact match from previous general conversation`,
16888
16734
  method: `${this.getProviderName()}-semantic-match-general`,
16889
16735
  semanticSimilarity: conversationMatch.similarity
@@ -16901,13 +16747,11 @@ ${executedToolsText}`);
16901
16747
  logger.info(`[${this.getProviderName()}] Streaming cached text response to frontend`);
16902
16748
  streamCallback(cachedTextResponse);
16903
16749
  }
16904
- const cachedActions = conversationMatch.uiBlock?.actions || [];
16905
16750
  return {
16906
16751
  success: true,
16907
16752
  data: {
16908
16753
  text: cachedTextResponse,
16909
16754
  component,
16910
- actions: cachedActions,
16911
16755
  reasoning: `Exact match from previous conversation (${(conversationMatch.similarity * 100).toFixed(2)}% similarity)`,
16912
16756
  method: `${this.getProviderName()}-semantic-match-exact`,
16913
16757
  semanticSimilarity: conversationMatch.similarity
@@ -16932,13 +16776,11 @@ ${executedToolsText}`);
16932
16776
  logger.info(`[${this.getProviderName()}] Streaming ${adaptResult.adaptedTextResponse ? "adapted" : "cached"} text response to frontend`);
16933
16777
  streamCallback(textResponseToUse);
16934
16778
  }
16935
- const cachedActions = conversationMatch.uiBlock?.actions || [];
16936
16779
  return {
16937
16780
  success: true,
16938
16781
  data: {
16939
16782
  text: textResponseToUse,
16940
16783
  component: adaptResult.adaptedComponent,
16941
- actions: cachedActions,
16942
16784
  reasoning: `Adapted from previous conversation: ${originalPrompt}`,
16943
16785
  method: `${this.getProviderName()}-semantic-match`,
16944
16786
  semanticSimilarity: conversationMatch.similarity,
@@ -17029,67 +16871,6 @@ ${executedToolsText}`);
17029
16871
  };
17030
16872
  }
17031
16873
  }
17032
- /**
17033
- * Generate next questions that the user might ask based on the original prompt and generated component
17034
- * This helps provide intelligent suggestions for follow-up queries
17035
- * For general/conversational questions without components, pass textResponse instead
17036
- */
17037
- async generateNextQuestions(originalUserPrompt, component, componentData, apiKey, conversationHistory, textResponse, signal) {
17038
- const methodStartTime = Date.now();
17039
- const methodName = "generateNextQuestions";
17040
- const promptPreview = originalUserPrompt.substring(0, 50) + (originalUserPrompt.length > 50 ? "..." : "");
17041
- logger.info(`[${this.getProviderName()}] [TIMING] START ${methodName} | model: ${this.getModelForTask("simple")} | prompt: "${promptPreview}"`);
17042
- try {
17043
- let component_info;
17044
- if (component) {
17045
- component_info = `
17046
- Component Name: ${component.name}
17047
- Component Type: ${component.type}
17048
- Component Description: ${component.description || "No description"}
17049
- Component Props: ${component.props ? JSON.stringify(component.props, null, 2) : "No props"}
17050
- `;
17051
- } else if (textResponse) {
17052
- component_info = `
17053
- Response Type: Text/Conversational Response
17054
- Response Content: ${textResponse.substring(0, 1e3)}${textResponse.length > 1e3 ? "..." : ""}
17055
- `;
17056
- } else {
17057
- component_info = "No component or response context available";
17058
- }
17059
- const component_data = componentData ? `Component Data: ${JSON.stringify(componentData, null, 2)}` : "";
17060
- const prompts = await promptLoader.loadPrompts("actions", {
17061
- ORIGINAL_USER_PROMPT: originalUserPrompt,
17062
- COMPONENT_INFO: component_info,
17063
- COMPONENT_DATA: component_data,
17064
- CONVERSATION_HISTORY: conversationHistory || "No previous conversation",
17065
- CURRENT_DATETIME: getCurrentDateTimeForPrompt()
17066
- });
17067
- const result = await LLM.stream(
17068
- {
17069
- sys: prompts.system,
17070
- user: prompts.user
17071
- },
17072
- {
17073
- model: this.getModelForTask("simple"),
17074
- maxTokens: MAX_TOKENS_NEXT_QUESTIONS,
17075
- temperature: 0,
17076
- apiKey: this.getApiKey(apiKey),
17077
- signal
17078
- },
17079
- true
17080
- // Parse as JSON
17081
- );
17082
- const nextQuestions = result.nextQuestions || [];
17083
- const methodDuration = Date.now() - methodStartTime;
17084
- logger.info(`[${this.getProviderName()}] [TIMING] DONE ${methodName} in ${methodDuration}ms | questions: ${nextQuestions.length}`);
17085
- return nextQuestions;
17086
- } catch (error) {
17087
- const methodDuration = Date.now() - methodStartTime;
17088
- const errorMsg = error instanceof Error ? error.message : String(error);
17089
- logger.error(`[${this.getProviderName()}] [TIMING] FAILED ${methodName} in ${methodDuration}ms | error: ${errorMsg}`);
17090
- return [];
17091
- }
17092
- }
17093
16874
  };
17094
16875
 
17095
16876
  // src/userResponse/anthropic.ts
@@ -17414,7 +17195,6 @@ var get_agent_user_response = async (prompt, components, anthropicApiKey, groqAp
17414
17195
  data: {
17415
17196
  text: cachedTextResponse,
17416
17197
  component: rehydratedComponent,
17417
- actions: conversationMatch.uiBlock?.actions || [],
17418
17198
  reasoning: `Exact match from previous conversation`,
17419
17199
  method: `${provider}-agent-exact-match`,
17420
17200
  semanticSimilarity: 1,
@@ -17513,9 +17293,14 @@ var get_agent_user_response = async (prompt, components, anthropicApiKey, groqAp
17513
17293
  logger.info(`[AgentFlow] Bound recipe ${directReplay.recipeId} no longer in store \u2014 falling back to ScriptMatcher LLM`);
17514
17294
  }
17515
17295
  }
17516
- if (!scriptMatch && process.env.SA_SKIP_SCRIPT_MATCH !== "true") {
17296
+ const explicitEdit = hasExplicitEditPrefix(prompt);
17297
+ if (!scriptMatch && (process.env.SA_SKIP_SCRIPT_MATCH !== "true" || explicitEdit)) {
17517
17298
  const scriptMatcher = new ScriptMatcher(scriptStore, { collections, userId, trace: runTrace });
17518
17299
  scriptMatch = await scriptMatcher.match(prompt, apiKey, sourceAgentModel, signal, activeBindings);
17300
+ if (scriptMatch && scriptMatch.tier !== "edit" && process.env.SA_SKIP_SCRIPT_MATCH === "true") {
17301
+ 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)`);
17302
+ scriptMatch = null;
17303
+ }
17519
17304
  } else if (!scriptMatch) {
17520
17305
  logger.info("[AgentFlow] ScriptMatcher skipped (SA_SKIP_SCRIPT_MATCH=true) \u2014 proceeding with fresh generation");
17521
17306
  }
@@ -17669,7 +17454,6 @@ ${JSON.stringify(preview, null, 2)}
17669
17454
  let matchedComponents2 = [];
17670
17455
  let layoutTitle2 = "Dashboard";
17671
17456
  let layoutDescription2 = "Multi-component dashboard";
17672
- let actions2 = [];
17673
17457
  if (components && components.length > 0 && scriptExecutedTools.length > 0) {
17674
17458
  logger.info(`[AgentFlow] Script flow \u2014 generating components (lightweight)`);
17675
17459
  if (streamBuffer.hasCallback()) {
@@ -17778,7 +17562,6 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${scriptMatch
17778
17562
  matchedComponents2 = compResult.components;
17779
17563
  layoutTitle2 = compResult.layoutTitle;
17780
17564
  layoutDescription2 = compResult.layoutDescription;
17781
- actions2 = compResult.actions;
17782
17565
  if (compResult.componentSpecs.length > 0) {
17783
17566
  try {
17784
17567
  scriptMatch.recipe.components = compResult.componentSpecs;
@@ -17845,15 +17628,10 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${scriptMatch
17845
17628
  description: layoutDescription2,
17846
17629
  components: securedComponents2,
17847
17630
  ...Object.keys(queryMap2).length > 0 && { _queryMap: queryMap2 }
17848
- },
17849
- actions: actions2
17631
+ }
17850
17632
  }
17851
17633
  };
17852
17634
  }
17853
- actions2 = [];
17854
- if (containerComponent2) {
17855
- containerComponent2.props.actions = [];
17856
- }
17857
17635
  const elapsedTime2 = Date.now() - startTime;
17858
17636
  logger.info(`[AgentFlow] Script flow complete | ${scriptResult.executedQueries.length} queries | ${matchedComponents2.length} components | ${elapsedTime2}ms`);
17859
17637
  return {
@@ -17862,7 +17640,6 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${scriptMatch
17862
17640
  text: scriptTextResponse,
17863
17641
  ...replayProgramAnswer ? { programAnswer: replayProgramAnswer } : {},
17864
17642
  component: containerComponent2,
17865
- actions: actions2,
17866
17643
  method: isDisplayEdit ? `${provider}-script-display-edit` : `${provider}-script-response`,
17867
17644
  // Bind the answer to the replayed recipe so a follow-up
17868
17645
  // ("use mode instead") can edit THIS script.
@@ -17983,7 +17760,6 @@ BEGIN NOW. Your VERY FIRST action MUST be a \`write_script\` tool call containin
17983
17760
  data: {
17984
17761
  text: "",
17985
17762
  component: workflowComponent,
17986
- actions: [],
17987
17763
  method: `${provider}-agent-workflow`,
17988
17764
  ...runTrace ? { trace: runTrace } : {}
17989
17765
  },
@@ -18039,7 +17815,6 @@ BEGIN NOW. Your VERY FIRST action MUST be a \`write_script\` tool call containin
18039
17815
  let matchedComponents = [];
18040
17816
  let layoutTitle = "Dashboard";
18041
17817
  let layoutDescription = "Multi-component dashboard";
18042
- let actions = [];
18043
17818
  let authoredComponentSpecs = [];
18044
17819
  if (!hasExecutedTools) {
18045
17820
  logger.info(`[AgentFlow] No tools executed \u2014 general question, wrapping in DynamicMarkdownBlock`);
@@ -18193,7 +17968,6 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${carriedRequ
18193
17968
  matchedComponents = compResult.components;
18194
17969
  layoutTitle = compResult.layoutTitle;
18195
17970
  layoutDescription = compResult.layoutDescription;
18196
- actions = compResult.actions;
18197
17971
  authoredComponentSpecs = compResult.componentSpecs;
18198
17972
  usedLightweight = true;
18199
17973
  logger.info(`[AgentFlow] Lightweight component gen succeeded \u2014 ${matchedComponents.length} components`);
@@ -18245,13 +18019,10 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${carriedRequ
18245
18019
  components: securedComponents,
18246
18020
  // Persist queryId → SQL mapping so cached responses can re-register queries
18247
18021
  ...Object.keys(queryMap).length > 0 && { _queryMap: queryMap }
18248
- },
18249
- actions
18022
+ }
18250
18023
  }
18251
18024
  };
18252
18025
  }
18253
- if (containerComponent) {
18254
- }
18255
18026
  if (agentResponse.savedScript && editContext) {
18256
18027
  try {
18257
18028
  const authored = agentResponse.savedScript;
@@ -18378,7 +18149,6 @@ RENDERING REQUIREMENT (overrides the default choice of component): ${carriedRequ
18378
18149
  ${programAnswer}` : textResponse,
18379
18150
  ...programAnswer ? { programAnswer } : {},
18380
18151
  component: containerComponent,
18381
- actions,
18382
18152
  method: editContext ? `${provider}-script-edit-response` : `${provider}-agent-response`,
18383
18153
  ...scriptBinding ? { scriptBinding } : {},
18384
18154
  ...noDataAnswer ? { noDataAnswer: true } : {},
@@ -18764,10 +18534,12 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
18764
18534
  const requestStartTime = Date.now();
18765
18535
  logger.info(`Starting user prompt request with ${components.length} components`);
18766
18536
  const conversationScriptStore = new ScriptStore({ collections, projectId: process.env.SUPERATOM_PROJECT_ID || "" });
18537
+ const getRecentForContext = collections?.["user-conversations"]?.["getRecentForContext"];
18767
18538
  const conversationHistory = await thread.getConversationContext(
18768
18539
  CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS,
18769
18540
  existingUiBlockId,
18770
- async (recipeId, version) => (await conversationScriptStore.getVersion(recipeId, version))?.scriptBody ?? null
18541
+ async (recipeId, version) => (await conversationScriptStore.getVersion(recipeId, version))?.scriptBody ?? null,
18542
+ getRecentForContext && userId && threadId ? async (limit) => (await getRecentForContext({ userId, threadId, limit }))?.data ?? [] : void 0
18771
18543
  );
18772
18544
  const MAX_EDIT_CANDIDATES = 5;
18773
18545
  let activeScriptBindings = thread.getScriptBindings(MAX_EDIT_CANDIDATES, existingUiBlockId);
@@ -18792,7 +18564,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
18792
18564
  `[UserPromptRequest] ${activeScriptBindings.length} editable script(s) in thread: ` + activeScriptBindings.map((b) => b.name || b.recipeId).join(", ")
18793
18565
  );
18794
18566
  }
18795
- const uiBlock = new UIBlock(prompt, {}, {}, [], existingUiBlockId, null);
18567
+ const uiBlock = new UIBlock(prompt, {}, {}, existingUiBlockId, null);
18796
18568
  thread.addUIBlock(uiBlock);
18797
18569
  logger.info(`Registered UIBlock (early): ${existingUiBlockId} in Thread: ${threadId}`);
18798
18570
  const abortController = new AbortController();
@@ -18980,7 +18752,6 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
18980
18752
  }
18981
18753
  let component = null;
18982
18754
  let textResponse = null;
18983
- let actions = [];
18984
18755
  if (userResponse.data) {
18985
18756
  if (typeof userResponse.data === "object") {
18986
18757
  if ("component" in userResponse.data) {
@@ -18991,9 +18762,6 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
18991
18762
  } else if ("textResponse" in userResponse.data) {
18992
18763
  textResponse = userResponse.data.textResponse;
18993
18764
  }
18994
- if ("actions" in userResponse.data) {
18995
- actions = userResponse.data.actions || [];
18996
- }
18997
18765
  }
18998
18766
  }
18999
18767
  let finalTextResponse = responseMode === "text" && accumulatedStreamResponse ? accumulatedStreamResponse : textResponse;
@@ -19011,10 +18779,6 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19011
18779
  }
19012
18780
  const programAnswer = userResponse.data?.programAnswer;
19013
18781
  if (programAnswer) uiBlock.setProgramAnswer(programAnswer);
19014
- if (actions.length > 0) {
19015
- uiBlock.setActions(actions);
19016
- logger.info(`Stored ${actions.length} actions in UIBlock: ${uiBlockId}`);
19017
- }
19018
18782
  logger.info(`Completed UIBlock: ${uiBlockId} in Thread: ${threadId}`);
19019
18783
  let savedConversationId;
19020
18784
  let savedResponse;
@@ -19280,229 +19044,6 @@ function sendResponse(id, res, sendMessage, clientId) {
19280
19044
  sendMessage(response);
19281
19045
  }
19282
19046
 
19283
- // src/userResponse/next-questions.ts
19284
- async function generateNextQuestions(originalUserPrompt, component, componentData, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders, conversationHistory) {
19285
- try {
19286
- logger.debug("[generateNextQuestions] Starting next questions generation");
19287
- logger.debug(`[generateNextQuestions] User prompt: "${originalUserPrompt?.substring(0, 50)}..."`);
19288
- logger.debug(`[generateNextQuestions] Component: ${component?.name || "unknown"} (${component?.type || "unknown"})`);
19289
- logger.debug(`[generateNextQuestions] Component data available: ${componentData ? "yes" : "no"}`);
19290
- const providers = llmProviders || ["anthropic", "gemini", "openai", "groq"];
19291
- logger.info(`[generateNextQuestions] Using LLM providers: [${providers.join(", ")}]`);
19292
- if (conversationHistory && conversationHistory.length > 0) {
19293
- const exchangeCount = conversationHistory.split("\n").filter((l) => l.startsWith("Q")).length;
19294
- logger.debug(`[generateNextQuestions] Using conversation history with ${exchangeCount} previous exchanges`);
19295
- } else {
19296
- logger.debug("[generateNextQuestions] No conversation history available");
19297
- }
19298
- for (let i = 0; i < providers.length; i++) {
19299
- const provider = providers[i];
19300
- const isLastProvider = i === providers.length - 1;
19301
- try {
19302
- logger.info(`[generateNextQuestions] Attempting provider: ${provider} (${i + 1}/${providers.length})`);
19303
- let result = [];
19304
- if (provider === "groq") {
19305
- logger.debug("[generateNextQuestions] Using Groq LLM for next questions");
19306
- result = await groqLLM.generateNextQuestions(
19307
- originalUserPrompt,
19308
- component,
19309
- componentData,
19310
- groqApiKey,
19311
- conversationHistory
19312
- );
19313
- } else if (provider === "gemini") {
19314
- logger.debug("[generateNextQuestions] Using Gemini LLM for next questions");
19315
- result = await geminiLLM.generateNextQuestions(
19316
- originalUserPrompt,
19317
- component,
19318
- componentData,
19319
- geminiApiKey,
19320
- conversationHistory
19321
- );
19322
- } else if (provider === "openai") {
19323
- logger.debug("[generateNextQuestions] Using OpenAI LLM for next questions");
19324
- result = await openaiLLM.generateNextQuestions(
19325
- originalUserPrompt,
19326
- component,
19327
- componentData,
19328
- openaiApiKey,
19329
- conversationHistory
19330
- );
19331
- } else {
19332
- logger.debug("[generateNextQuestions] Using Anthropic LLM for next questions");
19333
- result = await anthropicLLM.generateNextQuestions(
19334
- originalUserPrompt,
19335
- component,
19336
- componentData,
19337
- anthropicApiKey,
19338
- conversationHistory
19339
- );
19340
- }
19341
- if (result && result.length > 0) {
19342
- logger.info(`[generateNextQuestions] Successfully generated ${result.length} questions with ${provider}`);
19343
- logger.debug(`[generateNextQuestions] Questions: ${JSON.stringify(result)}`);
19344
- return result;
19345
- }
19346
- logger.warn(`[generateNextQuestions] No questions generated from ${provider}${!isLastProvider ? ", trying next provider..." : ""}`);
19347
- } catch (providerError) {
19348
- const errorMsg = providerError instanceof Error ? providerError.message : String(providerError);
19349
- logger.error(`[generateNextQuestions] Provider ${provider} failed: ${errorMsg}`);
19350
- logger.debug(`[generateNextQuestions] Provider error details:`, providerError);
19351
- if (!isLastProvider) {
19352
- logger.info(`[generateNextQuestions] Provider ${provider} failed, trying next provider...`);
19353
- }
19354
- continue;
19355
- }
19356
- }
19357
- logger.warn("[generateNextQuestions] All providers failed or returned no questions");
19358
- return [];
19359
- } catch (error) {
19360
- const errorMsg = error instanceof Error ? error.message : String(error);
19361
- const errorStack = error instanceof Error ? error.stack : void 0;
19362
- logger.error(`[generateNextQuestions] Error generating next questions: ${errorMsg}`);
19363
- logger.debug("[generateNextQuestions] Error stack trace:", errorStack);
19364
- return [];
19365
- }
19366
- }
19367
-
19368
- // src/handlers/actions-request.ts
19369
- async function handleActionsRequest(data, sendMessage, anthropicApiKey, groqApiKey, geminiApiKey, openaiApiKey, llmProviders) {
19370
- try {
19371
- logger.debug("[ACTIONS_REQ] Parsing incoming actions request");
19372
- const actionsRequest = ActionsRequestMessageSchema.parse(data);
19373
- const { id, payload } = actionsRequest;
19374
- const { SA_RUNTIME } = payload;
19375
- const wsId = actionsRequest.from.id || "unknown";
19376
- logger.info(`[ACTIONS_REQ ${id}] Processing actions request from client: ${wsId}`);
19377
- logger.debug(`[ACTIONS_REQ ${id}] Request payload:`, JSON.stringify(payload, null, 2).substring(0, 200));
19378
- if (!SA_RUNTIME) {
19379
- logger.error(`[ACTIONS_REQ ${id}] SA_RUNTIME missing from request`);
19380
- sendResponse2(id, {
19381
- success: false,
19382
- error: "SA_RUNTIME with threadId and uiBlockId is required"
19383
- }, sendMessage, wsId);
19384
- return;
19385
- }
19386
- const uiBlockId = SA_RUNTIME.uiBlockId;
19387
- const threadId = SA_RUNTIME.threadId;
19388
- logger.debug(`[ACTIONS_REQ ${id}] SA_RUNTIME validated - threadId: ${threadId}, uiBlockId: ${uiBlockId}`);
19389
- const threadManager = ThreadManager.getInstance();
19390
- const thread = threadManager.getThread(threadId);
19391
- if (!thread) {
19392
- logger.error(`[ACTIONS_REQ ${id}] Thread '${threadId}' not found`);
19393
- sendResponse2(id, {
19394
- success: false,
19395
- error: `Thread '${threadId}' not found`
19396
- }, sendMessage, wsId);
19397
- return;
19398
- }
19399
- logger.debug(`[ACTIONS_REQ ${id}] Thread found with ${thread.getUIBlocks().length} UIBlocks`);
19400
- logger.debug(`[ACTIONS_REQ ${id}] Retrieving UIBlock: ${uiBlockId}`);
19401
- const uiBlock = thread.getUIBlock(uiBlockId);
19402
- if (!uiBlock) {
19403
- logger.error(`[ACTIONS_REQ ${id}] UIBlock '${uiBlockId}' not found in thread '${threadId}'`);
19404
- sendResponse2(id, {
19405
- success: false,
19406
- error: `UIBlock '${uiBlockId}' not found in thread '${threadId}'`
19407
- }, sendMessage, wsId);
19408
- return;
19409
- }
19410
- logger.info(`[ACTIONS_REQ ${id}] UIBlock retrieved successfully`);
19411
- logger.debug(`[ACTIONS_REQ ${id}] Extracting data from UIBlock`);
19412
- const userQuestion = uiBlock.getUserQuestion();
19413
- const component = uiBlock.getComponentMetadata();
19414
- const componentData = uiBlock.getComponentData();
19415
- logger.debug(`[ACTIONS_REQ ${id}] User question: "${userQuestion?.substring(0, 50)}..."`);
19416
- logger.debug(`[ACTIONS_REQ ${id}] Component: ${component?.name || "unknown"} (${component?.type || "unknown"})`);
19417
- logger.debug(`[ACTIONS_REQ ${id}] Component data available: ${componentData ? "yes" : "no"}`);
19418
- logger.debug(`[ACTIONS_REQ ${id}] Extracting conversation history (max ${CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS} blocks)`);
19419
- const conversationHistory = await thread.getConversationContext(CONTEXT_CONFIG.MAX_CONVERSATION_CONTEXT_BLOCKS, uiBlockId);
19420
- const historyLineCount = conversationHistory.split("\n").filter((l) => l.trim()).length;
19421
- logger.info(`[ACTIONS_REQ ${id}] Conversation history extracted: ${historyLineCount} lines`);
19422
- logger.debug(`[ACTIONS_REQ ${id}] Conversation history preview:
19423
- ${conversationHistory.substring(0, 200)}...`);
19424
- logger.info(`[ACTIONS_REQ ${id}] Generating actions for UIBlock: ${uiBlockId}, component: ${component?.name || "unknown"}`);
19425
- logger.debug(`[ACTIONS_REQ ${id}] Checking if actions are already cached`);
19426
- const startTime = Date.now();
19427
- const actions = await uiBlock.getOrFetchActions(async () => {
19428
- logger.info(`[ACTIONS_REQ ${id}] Actions not cached, generating new actions...`);
19429
- logger.info(`[ACTIONS_REQ ${id}] Starting next questions generation with ${llmProviders?.join(", ") || "default"} providers`);
19430
- const nextQuestions = await generateNextQuestions(
19431
- userQuestion,
19432
- component,
19433
- componentData,
19434
- anthropicApiKey,
19435
- groqApiKey,
19436
- geminiApiKey,
19437
- openaiApiKey,
19438
- llmProviders,
19439
- conversationHistory
19440
- );
19441
- logger.info(`[ACTIONS_REQ ${id}] Generated ${nextQuestions.length} questions`);
19442
- logger.debug(`[ACTIONS_REQ ${id}] Questions: ${JSON.stringify(nextQuestions)}`);
19443
- logger.debug(`[ACTIONS_REQ ${id}] Converting questions to actions format`);
19444
- const convertedActions = nextQuestions.map((question, index) => ({
19445
- id: `action_${index}_${Date.now()}`,
19446
- name: question,
19447
- type: "next_question",
19448
- question
19449
- }));
19450
- logger.debug(`[ACTIONS_REQ ${id}] Converted ${convertedActions.length} actions`);
19451
- return convertedActions;
19452
- });
19453
- const processingTime = Date.now() - startTime;
19454
- logger.info(`[ACTIONS_REQ ${id}] Actions retrieved in ${processingTime}ms - ${actions.length} actions total`);
19455
- if (actions.length > 0) {
19456
- logger.info(`[ACTIONS_REQ ${id}] Generated ${actions.length} follow-up questions successfully`);
19457
- logger.debug(`[ACTIONS_REQ ${id}] Actions: ${actions.map((a) => a.name).join(", ")}`);
19458
- } else {
19459
- logger.warn(`[ACTIONS_REQ ${id}] No actions generated`);
19460
- }
19461
- logger.debug(`[ACTIONS_REQ ${id}] Sending successful response to client`);
19462
- sendResponse2(id, {
19463
- success: true,
19464
- data: {
19465
- actions,
19466
- componentName: component?.name,
19467
- componentId: component?.id,
19468
- uiBlockId,
19469
- threadId
19470
- }
19471
- }, sendMessage, wsId);
19472
- logger.info(`[ACTIONS_REQ ${id}] \u2713 Actions request completed successfully`);
19473
- } catch (error) {
19474
- const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
19475
- const errorStack = error instanceof Error ? error.stack : void 0;
19476
- logger.error(`[ACTIONS_REQ] Failed to handle actions request: ${errorMessage}`);
19477
- logger.debug(`[ACTIONS_REQ] Error stack trace:`, errorStack);
19478
- sendResponse2(null, {
19479
- success: false,
19480
- error: errorMessage
19481
- }, sendMessage);
19482
- logger.info("[ACTIONS_REQ] \u2717 Actions request completed with errors");
19483
- }
19484
- }
19485
- function sendResponse2(id, res, sendMessage, clientId) {
19486
- const response = {
19487
- id: id || "unknown",
19488
- type: "ACTIONS_RES",
19489
- from: { type: "data-agent" },
19490
- to: {
19491
- type: "runtime",
19492
- id: clientId
19493
- },
19494
- payload: {
19495
- ...res
19496
- }
19497
- };
19498
- logger.debug(`[ACTIONS_RES ${id || "unknown"}] Sending ${res.success ? "successful" : "failed"} response to client`);
19499
- logger.debug(`[ACTIONS_RES ${id || "unknown"}] Response payload size: ${JSON.stringify(response).length} bytes`);
19500
- if (res.data?.actions) {
19501
- logger.debug(`[ACTIONS_RES ${id || "unknown"}] Sending ${res.data.actions.length} actions`);
19502
- }
19503
- sendMessage(response);
19504
- }
19505
-
19506
19047
  // src/handlers/components-list-response.ts
19507
19048
  async function handleComponentListResponse(data, storeComponents, collections) {
19508
19049
  try {
@@ -19577,7 +19118,7 @@ async function handleUsersRequest(data, collections, sendMessage) {
19577
19118
  const limit = requestData?.limit;
19578
19119
  const sort = requestData?.sort;
19579
19120
  if (from.type !== "admin" && operation !== "getOne" && operation !== "getAll" && operation !== "query") {
19580
- sendResponse3(id, {
19121
+ sendResponse2(id, {
19581
19122
  success: false,
19582
19123
  error: "Unauthorized: Only admin can manage users"
19583
19124
  }, sendMessage, from.id);
@@ -19605,14 +19146,14 @@ async function handleUsersRequest(data, collections, sendMessage) {
19605
19146
  await handleQuery(id, filters, limit, sort, executeCollection, userManager, sendMessage, from.id);
19606
19147
  break;
19607
19148
  default:
19608
- sendResponse3(id, {
19149
+ sendResponse2(id, {
19609
19150
  success: false,
19610
19151
  error: `Unknown operation: ${operation}`
19611
19152
  }, sendMessage, from.id);
19612
19153
  }
19613
19154
  } catch (error) {
19614
19155
  logger.error("Failed to handle users request:", error);
19615
- sendResponse3(null, {
19156
+ sendResponse2(null, {
19616
19157
  success: false,
19617
19158
  error: error instanceof Error ? error.message : "Unknown error occurred"
19618
19159
  }, sendMessage);
@@ -19621,14 +19162,14 @@ async function handleUsersRequest(data, collections, sendMessage) {
19621
19162
  async function handleCreate(id, userData, executeCollection, userManager, sendMessage, clientId) {
19622
19163
  const { username, email, password, fullname, role, userInfo } = userData;
19623
19164
  if (!username || username.trim().length === 0) {
19624
- sendResponse3(id, {
19165
+ sendResponse2(id, {
19625
19166
  success: false,
19626
19167
  error: "Username is required and cannot be empty"
19627
19168
  }, sendMessage, clientId);
19628
19169
  return;
19629
19170
  }
19630
19171
  if (!password || password.trim().length === 0) {
19631
- sendResponse3(id, {
19172
+ sendResponse2(id, {
19632
19173
  success: false,
19633
19174
  error: "Password is required and cannot be empty"
19634
19175
  }, sendMessage, clientId);
@@ -19637,7 +19178,7 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
19637
19178
  if (email && email.trim().length > 0) {
19638
19179
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
19639
19180
  if (!emailRegex.test(email)) {
19640
- sendResponse3(id, {
19181
+ sendResponse2(id, {
19641
19182
  success: false,
19642
19183
  error: "Invalid email format"
19643
19184
  }, sendMessage, clientId);
@@ -19655,7 +19196,7 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
19655
19196
  });
19656
19197
  if (result && result.success) {
19657
19198
  logger.info(`[DB] User created successfully: ${username}`);
19658
- sendResponse3(id, {
19199
+ sendResponse2(id, {
19659
19200
  success: true,
19660
19201
  data: {
19661
19202
  id: result.data?.id,
@@ -19673,14 +19214,14 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
19673
19214
  }
19674
19215
  try {
19675
19216
  if (userManager.userExists(username)) {
19676
- sendResponse3(id, {
19217
+ sendResponse2(id, {
19677
19218
  success: false,
19678
19219
  error: `User '${username}' already exists`
19679
19220
  }, sendMessage, clientId);
19680
19221
  return;
19681
19222
  }
19682
19223
  if (email && userManager.getUserByEmail(email)) {
19683
- sendResponse3(id, {
19224
+ sendResponse2(id, {
19684
19225
  success: false,
19685
19226
  error: `User with email '${email}' already exists`
19686
19227
  }, sendMessage, clientId);
@@ -19701,7 +19242,7 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
19701
19242
  }
19702
19243
  const newUser = userManager.createUser(newUserData);
19703
19244
  logger.info(`[FILE] User '${username}' created successfully`);
19704
- sendResponse3(id, {
19245
+ sendResponse2(id, {
19705
19246
  success: true,
19706
19247
  data: {
19707
19248
  username: newUser.username,
@@ -19712,7 +19253,7 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
19712
19253
  }
19713
19254
  }, sendMessage, clientId);
19714
19255
  } catch (error) {
19715
- sendResponse3(id, {
19256
+ sendResponse2(id, {
19716
19257
  success: false,
19717
19258
  error: error instanceof Error ? error.message : "Failed to create user"
19718
19259
  }, sendMessage, clientId);
@@ -19721,7 +19262,7 @@ async function handleCreate(id, userData, executeCollection, userManager, sendMe
19721
19262
  async function handleUpdate(id, numericId, userData, executeCollection, userManager, sendMessage, clientId) {
19722
19263
  const { username, email, password, fullname, role, userInfo } = userData;
19723
19264
  if (!numericId && !username) {
19724
- sendResponse3(id, {
19265
+ sendResponse2(id, {
19725
19266
  success: false,
19726
19267
  error: "User ID or username is required"
19727
19268
  }, sendMessage, clientId);
@@ -19740,7 +19281,7 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19740
19281
  });
19741
19282
  if (result && result.success) {
19742
19283
  logger.info(`[DB] User updated successfully, ID: ${numericId}`);
19743
- sendResponse3(id, {
19284
+ sendResponse2(id, {
19744
19285
  success: true,
19745
19286
  data: {
19746
19287
  id: result.data?.id,
@@ -19758,14 +19299,14 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19758
19299
  }
19759
19300
  }
19760
19301
  if (!username || username.trim().length === 0) {
19761
- sendResponse3(id, {
19302
+ sendResponse2(id, {
19762
19303
  success: false,
19763
19304
  error: "Username is required for file-based storage update"
19764
19305
  }, sendMessage, clientId);
19765
19306
  return;
19766
19307
  }
19767
19308
  if (!userManager.userExists(username)) {
19768
- sendResponse3(id, {
19309
+ sendResponse2(id, {
19769
19310
  success: false,
19770
19311
  error: `User '${username}' not found`
19771
19312
  }, sendMessage, clientId);
@@ -19776,7 +19317,7 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19776
19317
  if (email.trim().length > 0) {
19777
19318
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
19778
19319
  if (!emailRegex.test(email)) {
19779
- sendResponse3(id, {
19320
+ sendResponse2(id, {
19780
19321
  success: false,
19781
19322
  error: "Invalid email format"
19782
19323
  }, sendMessage, clientId);
@@ -19784,7 +19325,7 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19784
19325
  }
19785
19326
  const existingUser = userManager.getUserByEmail(email);
19786
19327
  if (existingUser && existingUser.username !== username) {
19787
- sendResponse3(id, {
19328
+ sendResponse2(id, {
19788
19329
  success: false,
19789
19330
  error: `Email '${email}' is already used by another user`
19790
19331
  }, sendMessage, clientId);
@@ -19805,7 +19346,7 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19805
19346
  updates.role = role.trim().length > 0 ? role.trim() : void 0;
19806
19347
  }
19807
19348
  if (Object.keys(updates).length === 0) {
19808
- sendResponse3(id, {
19349
+ sendResponse2(id, {
19809
19350
  success: false,
19810
19351
  error: "No fields to update. Please provide at least one field to update."
19811
19352
  }, sendMessage, clientId);
@@ -19814,7 +19355,7 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19814
19355
  try {
19815
19356
  const updatedUser = userManager.updateUser(username, updates);
19816
19357
  logger.info(`[FILE] User '${username}' updated successfully`);
19817
- sendResponse3(id, {
19358
+ sendResponse2(id, {
19818
19359
  success: true,
19819
19360
  data: {
19820
19361
  username: updatedUser.username,
@@ -19825,7 +19366,7 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19825
19366
  }
19826
19367
  }, sendMessage, clientId);
19827
19368
  } catch (error) {
19828
- sendResponse3(id, {
19369
+ sendResponse2(id, {
19829
19370
  success: false,
19830
19371
  error: error instanceof Error ? error.message : "Failed to update user"
19831
19372
  }, sendMessage, clientId);
@@ -19833,7 +19374,7 @@ async function handleUpdate(id, numericId, userData, executeCollection, userMana
19833
19374
  }
19834
19375
  async function handleDelete(id, numericId, username, executeCollection, userManager, sendMessage, clientId) {
19835
19376
  if (!numericId && !username) {
19836
- sendResponse3(id, {
19377
+ sendResponse2(id, {
19837
19378
  success: false,
19838
19379
  error: "User ID or username is required"
19839
19380
  }, sendMessage, clientId);
@@ -19844,7 +19385,7 @@ async function handleDelete(id, numericId, username, executeCollection, userMana
19844
19385
  const result = await executeCollection("users", "delete", { id: numericId });
19845
19386
  if (result && result.success) {
19846
19387
  logger.info(`[DB] User deleted successfully, ID: ${numericId}`);
19847
- sendResponse3(id, {
19388
+ sendResponse2(id, {
19848
19389
  success: true,
19849
19390
  data: {
19850
19391
  id: numericId,
@@ -19859,14 +19400,14 @@ async function handleDelete(id, numericId, username, executeCollection, userMana
19859
19400
  }
19860
19401
  }
19861
19402
  if (!username || username.trim().length === 0) {
19862
- sendResponse3(id, {
19403
+ sendResponse2(id, {
19863
19404
  success: false,
19864
19405
  error: "Username is required for file-based storage delete"
19865
19406
  }, sendMessage, clientId);
19866
19407
  return;
19867
19408
  }
19868
19409
  if (!userManager.userExists(username)) {
19869
- sendResponse3(id, {
19410
+ sendResponse2(id, {
19870
19411
  success: false,
19871
19412
  error: `User '${username}' not found`
19872
19413
  }, sendMessage, clientId);
@@ -19874,14 +19415,14 @@ async function handleDelete(id, numericId, username, executeCollection, userMana
19874
19415
  }
19875
19416
  const deleted = userManager.deleteUser(username);
19876
19417
  if (!deleted) {
19877
- sendResponse3(id, {
19418
+ sendResponse2(id, {
19878
19419
  success: false,
19879
19420
  error: `Failed to delete user '${username}'`
19880
19421
  }, sendMessage, clientId);
19881
19422
  return;
19882
19423
  }
19883
19424
  logger.info(`[FILE] User '${username}' deleted successfully`);
19884
- sendResponse3(id, {
19425
+ sendResponse2(id, {
19885
19426
  success: true,
19886
19427
  data: {
19887
19428
  username,
@@ -19904,7 +19445,7 @@ async function handleGetAll(id, executeCollection, userManager, sendMessage, cli
19904
19445
  updatedAt: user.updatedAt
19905
19446
  }));
19906
19447
  logger.info(`[DB] Retrieved ${result.count} users`);
19907
- sendResponse3(id, {
19448
+ sendResponse2(id, {
19908
19449
  success: true,
19909
19450
  data: {
19910
19451
  users: sanitizedUsers2,
@@ -19926,7 +19467,7 @@ async function handleGetAll(id, executeCollection, userManager, sendMessage, cli
19926
19467
  wsIds: user.wsIds || []
19927
19468
  }));
19928
19469
  logger.info(`[FILE] Retrieved ${sanitizedUsers.length} users`);
19929
- sendResponse3(id, {
19470
+ sendResponse2(id, {
19930
19471
  success: true,
19931
19472
  data: {
19932
19473
  users: sanitizedUsers,
@@ -19937,7 +19478,7 @@ async function handleGetAll(id, executeCollection, userManager, sendMessage, cli
19937
19478
  }
19938
19479
  async function handleGetOne(id, numericId, username, executeCollection, userManager, sendMessage, clientId) {
19939
19480
  if (!numericId && !username) {
19940
- sendResponse3(id, {
19481
+ sendResponse2(id, {
19941
19482
  success: false,
19942
19483
  error: "User ID or username is required"
19943
19484
  }, sendMessage, clientId);
@@ -19958,7 +19499,7 @@ async function handleGetOne(id, numericId, username, executeCollection, userMana
19958
19499
  updatedAt: result.data?.updatedAt
19959
19500
  };
19960
19501
  logger.info(`[DB] Retrieved user ID: ${numericId}`);
19961
- sendResponse3(id, {
19502
+ sendResponse2(id, {
19962
19503
  success: true,
19963
19504
  data: {
19964
19505
  user: sanitizedUser2,
@@ -19972,14 +19513,14 @@ async function handleGetOne(id, numericId, username, executeCollection, userMana
19972
19513
  }
19973
19514
  }
19974
19515
  if (!username || username.trim().length === 0) {
19975
- sendResponse3(id, {
19516
+ sendResponse2(id, {
19976
19517
  success: false,
19977
19518
  error: "Username is required for file-based storage lookup"
19978
19519
  }, sendMessage, clientId);
19979
19520
  return;
19980
19521
  }
19981
19522
  if (!userManager.userExists(username)) {
19982
- sendResponse3(id, {
19523
+ sendResponse2(id, {
19983
19524
  success: false,
19984
19525
  error: `User '${username}' not found`
19985
19526
  }, sendMessage, clientId);
@@ -19994,7 +19535,7 @@ async function handleGetOne(id, numericId, username, executeCollection, userMana
19994
19535
  wsIds: user.wsIds || []
19995
19536
  };
19996
19537
  logger.info(`[FILE] Retrieved user: ${username}`);
19997
- sendResponse3(id, {
19538
+ sendResponse2(id, {
19998
19539
  success: true,
19999
19540
  data: {
20000
19541
  user: sanitizedUser,
@@ -20021,7 +19562,7 @@ async function handleQuery(id, filters, limit, sort, executeCollection, userMana
20021
19562
  updatedAt: user.updatedAt
20022
19563
  }));
20023
19564
  logger.info(`[DB] Query returned ${result.count} users`);
20024
- sendResponse3(id, {
19565
+ sendResponse2(id, {
20025
19566
  success: true,
20026
19567
  data: {
20027
19568
  users: sanitizedUsers2,
@@ -20044,7 +19585,7 @@ async function handleQuery(id, filters, limit, sort, executeCollection, userMana
20044
19585
  wsIds: user.wsIds || []
20045
19586
  }));
20046
19587
  logger.info(`[FILE] Retrieved ${sanitizedUsers.length} users (all - no query filter)`);
20047
- sendResponse3(id, {
19588
+ sendResponse2(id, {
20048
19589
  success: true,
20049
19590
  data: {
20050
19591
  users: sanitizedUsers,
@@ -20053,7 +19594,7 @@ async function handleQuery(id, filters, limit, sort, executeCollection, userMana
20053
19594
  }
20054
19595
  }, sendMessage, clientId);
20055
19596
  }
20056
- function sendResponse3(id, res, sendMessage, clientId) {
19597
+ function sendResponse2(id, res, sendMessage, clientId) {
20057
19598
  const response = {
20058
19599
  id: id || "unknown",
20059
19600
  type: "USERS_RES",
@@ -20109,7 +19650,7 @@ async function handleDashboardsRequest(data, collections, sendMessage) {
20109
19650
  const sort = requestData?.sort;
20110
19651
  const readOnlyOperations = ["query", "getAll", "getOne"];
20111
19652
  if (!readOnlyOperations.includes(operation) && from.type !== "admin") {
20112
- sendResponse4(id, {
19653
+ sendResponse3(id, {
20113
19654
  success: false,
20114
19655
  error: "Unauthorized: Only admin can manage dashboards"
20115
19656
  }, sendMessage, from.id);
@@ -20137,14 +19678,14 @@ async function handleDashboardsRequest(data, collections, sendMessage) {
20137
19678
  await handleQuery2(id, filters, limit, sort, executeCollection, dashboardManager2, sendMessage, from.id);
20138
19679
  break;
20139
19680
  default:
20140
- sendResponse4(id, {
19681
+ sendResponse3(id, {
20141
19682
  success: false,
20142
19683
  error: `Unknown operation: ${operation}`
20143
19684
  }, sendMessage, from.id);
20144
19685
  }
20145
19686
  } catch (error) {
20146
19687
  logger.error("Failed to handle dashboards request:", error);
20147
- sendResponse4(null, {
19688
+ sendResponse3(null, {
20148
19689
  success: false,
20149
19690
  error: error instanceof Error ? error.message : "Unknown error occurred"
20150
19691
  }, sendMessage);
@@ -20152,14 +19693,14 @@ async function handleDashboardsRequest(data, collections, sendMessage) {
20152
19693
  }
20153
19694
  async function handleCreate2(id, dashboardId, dashboard, projectId, name, description, published, createdBy, allowedUsers, executeCollection, dashboardManager2, sendMessage, clientId) {
20154
19695
  if (!dashboardId || dashboardId.trim().length === 0) {
20155
- sendResponse4(id, {
19696
+ sendResponse3(id, {
20156
19697
  success: false,
20157
19698
  error: "Dashboard ID is required and cannot be empty"
20158
19699
  }, sendMessage, clientId);
20159
19700
  return;
20160
19701
  }
20161
19702
  if (!projectId) {
20162
- sendResponse4(id, {
19703
+ sendResponse3(id, {
20163
19704
  success: false,
20164
19705
  error: "Project ID is required"
20165
19706
  }, sendMessage, clientId);
@@ -20178,7 +19719,7 @@ async function handleCreate2(id, dashboardId, dashboard, projectId, name, descri
20178
19719
  });
20179
19720
  if (result && result.success) {
20180
19721
  logger.info(`[DB] Dashboard created successfully, ID: ${result.data?.id}`);
20181
- sendResponse4(id, {
19722
+ sendResponse3(id, {
20182
19723
  success: true,
20183
19724
  data: {
20184
19725
  id: result.data?.id,
@@ -20198,7 +19739,7 @@ async function handleCreate2(id, dashboardId, dashboard, projectId, name, descri
20198
19739
  }
20199
19740
  const createdDashboard = dashboardManager2.createDashboard(dashboardId, dashboard);
20200
19741
  logger.info(`[FILE] Dashboard '${dashboardId}' created successfully`);
20201
- sendResponse4(id, {
19742
+ sendResponse3(id, {
20202
19743
  success: true,
20203
19744
  data: {
20204
19745
  dashboardId,
@@ -20207,7 +19748,7 @@ async function handleCreate2(id, dashboardId, dashboard, projectId, name, descri
20207
19748
  }
20208
19749
  }, sendMessage, clientId);
20209
19750
  } catch (error) {
20210
- sendResponse4(id, {
19751
+ sendResponse3(id, {
20211
19752
  success: false,
20212
19753
  error: error instanceof Error ? error.message : "Failed to create dashboard"
20213
19754
  }, sendMessage, clientId);
@@ -20215,7 +19756,7 @@ async function handleCreate2(id, dashboardId, dashboard, projectId, name, descri
20215
19756
  }
20216
19757
  async function handleUpdate2(id, numericId, dashboardId, dashboard, name, description, published, updatedBy, allowedUsers, executeCollection, dashboardManager2, sendMessage, clientId) {
20217
19758
  if (!numericId) {
20218
- sendResponse4(id, {
19759
+ sendResponse3(id, {
20219
19760
  success: false,
20220
19761
  error: "Dashboard ID is required"
20221
19762
  }, sendMessage, clientId);
@@ -20233,7 +19774,7 @@ async function handleUpdate2(id, numericId, dashboardId, dashboard, name, descri
20233
19774
  });
20234
19775
  if (result && result.success) {
20235
19776
  logger.info(`[DB] Dashboard updated successfully, ID: ${numericId}`);
20236
- sendResponse4(id, {
19777
+ sendResponse3(id, {
20237
19778
  success: true,
20238
19779
  data: {
20239
19780
  id: numericId,
@@ -20251,14 +19792,14 @@ async function handleUpdate2(id, numericId, dashboardId, dashboard, name, descri
20251
19792
  try {
20252
19793
  const updatedDashboard = dashboardManager2.updateDashboard(fileStorageId, dashboard);
20253
19794
  if (!updatedDashboard) {
20254
- sendResponse4(id, {
19795
+ sendResponse3(id, {
20255
19796
  success: false,
20256
19797
  error: `Dashboard '${fileStorageId}' not found`
20257
19798
  }, sendMessage, clientId);
20258
19799
  return;
20259
19800
  }
20260
19801
  logger.info(`[FILE] Dashboard '${fileStorageId}' updated successfully`);
20261
- sendResponse4(id, {
19802
+ sendResponse3(id, {
20262
19803
  success: true,
20263
19804
  data: {
20264
19805
  id: numericId,
@@ -20268,7 +19809,7 @@ async function handleUpdate2(id, numericId, dashboardId, dashboard, name, descri
20268
19809
  }
20269
19810
  }, sendMessage, clientId);
20270
19811
  } catch (error) {
20271
- sendResponse4(id, {
19812
+ sendResponse3(id, {
20272
19813
  success: false,
20273
19814
  error: error instanceof Error ? error.message : "Failed to update dashboard"
20274
19815
  }, sendMessage, clientId);
@@ -20276,7 +19817,7 @@ async function handleUpdate2(id, numericId, dashboardId, dashboard, name, descri
20276
19817
  }
20277
19818
  async function handleDelete2(id, numericId, dashboardId, executeCollection, dashboardManager2, sendMessage, clientId) {
20278
19819
  if (!numericId) {
20279
- sendResponse4(id, {
19820
+ sendResponse3(id, {
20280
19821
  success: false,
20281
19822
  error: "Dashboard ID is required"
20282
19823
  }, sendMessage, clientId);
@@ -20286,7 +19827,7 @@ async function handleDelete2(id, numericId, dashboardId, executeCollection, dash
20286
19827
  const result = await executeCollection("dashboards", "delete", { id: numericId });
20287
19828
  if (result && result.success) {
20288
19829
  logger.info(`[DB] Dashboard deleted successfully, ID: ${numericId}`);
20289
- sendResponse4(id, {
19830
+ sendResponse3(id, {
20290
19831
  success: true,
20291
19832
  data: {
20292
19833
  id: numericId,
@@ -20301,14 +19842,14 @@ async function handleDelete2(id, numericId, dashboardId, executeCollection, dash
20301
19842
  const fileStorageId = dashboardId || String(numericId);
20302
19843
  const deleted = dashboardManager2.deleteDashboard(fileStorageId);
20303
19844
  if (!deleted) {
20304
- sendResponse4(id, {
19845
+ sendResponse3(id, {
20305
19846
  success: false,
20306
19847
  error: `Dashboard '${fileStorageId}' not found`
20307
19848
  }, sendMessage, clientId);
20308
19849
  return;
20309
19850
  }
20310
19851
  logger.info(`[FILE] Dashboard '${fileStorageId}' deleted successfully`);
20311
- sendResponse4(id, {
19852
+ sendResponse3(id, {
20312
19853
  success: true,
20313
19854
  data: {
20314
19855
  id: numericId,
@@ -20322,7 +19863,7 @@ async function handleGetAll2(id, executeCollection, dashboardManager2, sendMessa
20322
19863
  const result = await executeCollection("dashboards", "getAll", {});
20323
19864
  if (result && result.success) {
20324
19865
  logger.info(`[DB] Retrieved ${result.count} dashboards`);
20325
- sendResponse4(id, {
19866
+ sendResponse3(id, {
20326
19867
  success: true,
20327
19868
  data: {
20328
19869
  dashboards: result.data,
@@ -20337,7 +19878,7 @@ async function handleGetAll2(id, executeCollection, dashboardManager2, sendMessa
20337
19878
  }
20338
19879
  const dashboards = dashboardManager2.getAllDashboards();
20339
19880
  logger.info(`[FILE] Retrieved ${dashboards.length} dashboards`);
20340
- sendResponse4(id, {
19881
+ sendResponse3(id, {
20341
19882
  success: true,
20342
19883
  data: {
20343
19884
  dashboards,
@@ -20348,7 +19889,7 @@ async function handleGetAll2(id, executeCollection, dashboardManager2, sendMessa
20348
19889
  }
20349
19890
  async function handleGetOne2(id, numericId, dashboardId, executeCollection, dashboardManager2, sendMessage, clientId) {
20350
19891
  if (!numericId) {
20351
- sendResponse4(id, {
19892
+ sendResponse3(id, {
20352
19893
  success: false,
20353
19894
  error: "Dashboard ID is required"
20354
19895
  }, sendMessage, clientId);
@@ -20358,7 +19899,7 @@ async function handleGetOne2(id, numericId, dashboardId, executeCollection, dash
20358
19899
  const result = await executeCollection("dashboards", "getOne", { id: numericId });
20359
19900
  if (result && result.success) {
20360
19901
  logger.info(`[DB] Retrieved dashboard ID: ${numericId}`);
20361
- sendResponse4(id, {
19902
+ sendResponse3(id, {
20362
19903
  success: true,
20363
19904
  data: {
20364
19905
  id: numericId,
@@ -20375,14 +19916,14 @@ async function handleGetOne2(id, numericId, dashboardId, executeCollection, dash
20375
19916
  const fileStorageId = dashboardId || String(numericId);
20376
19917
  const dashboard = dashboardManager2.getDashboard(fileStorageId);
20377
19918
  if (!dashboard) {
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] Retrieved dashboard: ${fileStorageId}`);
20385
- sendResponse4(id, {
19926
+ sendResponse3(id, {
20386
19927
  success: true,
20387
19928
  data: {
20388
19929
  id: numericId,
@@ -20401,7 +19942,7 @@ async function handleQuery2(id, filters, limit, sort, executeCollection, dashboa
20401
19942
  });
20402
19943
  if (result && result.success) {
20403
19944
  logger.info(`[DB] Query returned ${result.count} dashboards`);
20404
- sendResponse4(id, {
19945
+ sendResponse3(id, {
20405
19946
  success: true,
20406
19947
  data: {
20407
19948
  dashboards: result.data,
@@ -20416,7 +19957,7 @@ async function handleQuery2(id, filters, limit, sort, executeCollection, dashboa
20416
19957
  }
20417
19958
  const dashboards = dashboardManager2.getAllDashboards();
20418
19959
  logger.info(`[FILE] Retrieved ${dashboards.length} dashboards (all - no query filter)`);
20419
- sendResponse4(id, {
19960
+ sendResponse3(id, {
20420
19961
  success: true,
20421
19962
  data: {
20422
19963
  dashboards,
@@ -20425,7 +19966,7 @@ async function handleQuery2(id, filters, limit, sort, executeCollection, dashboa
20425
19966
  }
20426
19967
  }, sendMessage, clientId);
20427
19968
  }
20428
- function sendResponse4(id, res, sendMessage, clientId) {
19969
+ function sendResponse3(id, res, sendMessage, clientId) {
20429
19970
  const response = {
20430
19971
  id: id || "unknown",
20431
19972
  type: "DASHBOARDS_RES",
@@ -20480,7 +20021,7 @@ async function handleReportsRequest(data, collections, sendMessage) {
20480
20021
  const sort = requestData?.sort;
20481
20022
  const readOnlyOperations = ["query", "getAll", "getOne"];
20482
20023
  if (!readOnlyOperations.includes(operation) && from.type !== "admin") {
20483
- sendResponse5(id, {
20024
+ sendResponse4(id, {
20484
20025
  success: false,
20485
20026
  error: "Unauthorized: Only admin can manage reports"
20486
20027
  }, sendMessage, from.id);
@@ -20508,14 +20049,14 @@ async function handleReportsRequest(data, collections, sendMessage) {
20508
20049
  await handleQuery3(id, filters, limit, sort, executeCollection, reportManager2, sendMessage, from.id);
20509
20050
  break;
20510
20051
  default:
20511
- sendResponse5(id, {
20052
+ sendResponse4(id, {
20512
20053
  success: false,
20513
20054
  error: `Unknown operation: ${operation}`
20514
20055
  }, sendMessage, from.id);
20515
20056
  }
20516
20057
  } catch (error) {
20517
20058
  logger.error("Failed to handle reports request:", error);
20518
- sendResponse5(null, {
20059
+ sendResponse4(null, {
20519
20060
  success: false,
20520
20061
  error: error instanceof Error ? error.message : "Unknown error occurred"
20521
20062
  }, sendMessage);
@@ -20523,14 +20064,14 @@ async function handleReportsRequest(data, collections, sendMessage) {
20523
20064
  }
20524
20065
  async function handleCreate3(id, reportId, report, projectId, name, description, published, createdBy, executeCollection, reportManager2, sendMessage, clientId) {
20525
20066
  if (!reportId || reportId.trim().length === 0) {
20526
- sendResponse5(id, {
20067
+ sendResponse4(id, {
20527
20068
  success: false,
20528
20069
  error: "Report ID is required and cannot be empty"
20529
20070
  }, sendMessage, clientId);
20530
20071
  return;
20531
20072
  }
20532
20073
  if (!projectId) {
20533
- sendResponse5(id, {
20074
+ sendResponse4(id, {
20534
20075
  success: false,
20535
20076
  error: "Project ID is required"
20536
20077
  }, sendMessage, clientId);
@@ -20548,7 +20089,7 @@ async function handleCreate3(id, reportId, report, projectId, name, description,
20548
20089
  });
20549
20090
  if (result && result.success) {
20550
20091
  logger.info(`[DB] Report created successfully, ID: ${result.data?.id}`);
20551
- sendResponse5(id, {
20092
+ sendResponse4(id, {
20552
20093
  success: true,
20553
20094
  data: {
20554
20095
  id: result.data?.id,
@@ -20568,7 +20109,7 @@ async function handleCreate3(id, reportId, report, projectId, name, description,
20568
20109
  }
20569
20110
  const createdReport = reportManager2.createReport(reportId, report);
20570
20111
  logger.info(`[FILE] Report '${reportId}' created successfully`);
20571
- sendResponse5(id, {
20112
+ sendResponse4(id, {
20572
20113
  success: true,
20573
20114
  data: {
20574
20115
  reportId,
@@ -20577,7 +20118,7 @@ async function handleCreate3(id, reportId, report, projectId, name, description,
20577
20118
  }
20578
20119
  }, sendMessage, clientId);
20579
20120
  } catch (error) {
20580
- sendResponse5(id, {
20121
+ sendResponse4(id, {
20581
20122
  success: false,
20582
20123
  error: error instanceof Error ? error.message : "Failed to create report"
20583
20124
  }, sendMessage, clientId);
@@ -20585,7 +20126,7 @@ async function handleCreate3(id, reportId, report, projectId, name, description,
20585
20126
  }
20586
20127
  async function handleUpdate3(id, numericId, reportId, report, name, description, published, updatedBy, executeCollection, reportManager2, sendMessage, clientId) {
20587
20128
  if (!numericId) {
20588
- sendResponse5(id, {
20129
+ sendResponse4(id, {
20589
20130
  success: false,
20590
20131
  error: "Report ID is required"
20591
20132
  }, sendMessage, clientId);
@@ -20602,7 +20143,7 @@ async function handleUpdate3(id, numericId, reportId, report, name, description,
20602
20143
  });
20603
20144
  if (result && result.success) {
20604
20145
  logger.info(`[DB] Report updated successfully, ID: ${numericId}`);
20605
- sendResponse5(id, {
20146
+ sendResponse4(id, {
20606
20147
  success: true,
20607
20148
  data: {
20608
20149
  id: numericId,
@@ -20620,14 +20161,14 @@ async function handleUpdate3(id, numericId, reportId, report, name, description,
20620
20161
  try {
20621
20162
  const updatedReport = reportManager2.updateReport(fileStorageId, report);
20622
20163
  if (!updatedReport) {
20623
- sendResponse5(id, {
20164
+ sendResponse4(id, {
20624
20165
  success: false,
20625
20166
  error: `Report '${fileStorageId}' not found`
20626
20167
  }, sendMessage, clientId);
20627
20168
  return;
20628
20169
  }
20629
20170
  logger.info(`[FILE] Report '${fileStorageId}' updated successfully`);
20630
- sendResponse5(id, {
20171
+ sendResponse4(id, {
20631
20172
  success: true,
20632
20173
  data: {
20633
20174
  id: numericId,
@@ -20637,7 +20178,7 @@ async function handleUpdate3(id, numericId, reportId, report, name, description,
20637
20178
  }
20638
20179
  }, sendMessage, clientId);
20639
20180
  } catch (error) {
20640
- sendResponse5(id, {
20181
+ sendResponse4(id, {
20641
20182
  success: false,
20642
20183
  error: error instanceof Error ? error.message : "Failed to update report"
20643
20184
  }, sendMessage, clientId);
@@ -20645,7 +20186,7 @@ async function handleUpdate3(id, numericId, reportId, report, name, description,
20645
20186
  }
20646
20187
  async function handleDelete3(id, numericId, reportId, executeCollection, reportManager2, sendMessage, clientId) {
20647
20188
  if (!numericId) {
20648
- sendResponse5(id, {
20189
+ sendResponse4(id, {
20649
20190
  success: false,
20650
20191
  error: "Report ID is required"
20651
20192
  }, sendMessage, clientId);
@@ -20655,7 +20196,7 @@ async function handleDelete3(id, numericId, reportId, executeCollection, reportM
20655
20196
  const result = await executeCollection("reports", "delete", { id: numericId });
20656
20197
  if (result && result.success) {
20657
20198
  logger.info(`[DB] Report deleted successfully, ID: ${numericId}`);
20658
- sendResponse5(id, {
20199
+ sendResponse4(id, {
20659
20200
  success: true,
20660
20201
  data: {
20661
20202
  id: numericId,
@@ -20670,14 +20211,14 @@ async function handleDelete3(id, numericId, reportId, executeCollection, reportM
20670
20211
  const fileStorageId = reportId || String(numericId);
20671
20212
  const deleted = reportManager2.deleteReport(fileStorageId);
20672
20213
  if (!deleted) {
20673
- sendResponse5(id, {
20214
+ sendResponse4(id, {
20674
20215
  success: false,
20675
20216
  error: `Report '${fileStorageId}' not found`
20676
20217
  }, sendMessage, clientId);
20677
20218
  return;
20678
20219
  }
20679
20220
  logger.info(`[FILE] Report '${fileStorageId}' deleted successfully`);
20680
- sendResponse5(id, {
20221
+ sendResponse4(id, {
20681
20222
  success: true,
20682
20223
  data: {
20683
20224
  id: numericId,
@@ -20691,7 +20232,7 @@ async function handleGetAll3(id, executeCollection, reportManager2, sendMessage,
20691
20232
  const result = await executeCollection("reports", "getAll", {});
20692
20233
  if (result && result.success) {
20693
20234
  logger.info(`[DB] Retrieved ${result.count} reports`);
20694
- sendResponse5(id, {
20235
+ sendResponse4(id, {
20695
20236
  success: true,
20696
20237
  data: {
20697
20238
  reports: result.data,
@@ -20706,7 +20247,7 @@ async function handleGetAll3(id, executeCollection, reportManager2, sendMessage,
20706
20247
  }
20707
20248
  const reports = reportManager2.getAllReports();
20708
20249
  logger.info(`[FILE] Retrieved ${reports.length} reports`);
20709
- sendResponse5(id, {
20250
+ sendResponse4(id, {
20710
20251
  success: true,
20711
20252
  data: {
20712
20253
  reports,
@@ -20717,7 +20258,7 @@ async function handleGetAll3(id, executeCollection, reportManager2, sendMessage,
20717
20258
  }
20718
20259
  async function handleGetOne3(id, numericId, reportId, executeCollection, reportManager2, sendMessage, clientId) {
20719
20260
  if (!numericId) {
20720
- sendResponse5(id, {
20261
+ sendResponse4(id, {
20721
20262
  success: false,
20722
20263
  error: "Report ID is required"
20723
20264
  }, sendMessage, clientId);
@@ -20727,7 +20268,7 @@ async function handleGetOne3(id, numericId, reportId, executeCollection, reportM
20727
20268
  const result = await executeCollection("reports", "getOne", { id: numericId });
20728
20269
  if (result && result.success) {
20729
20270
  logger.info(`[DB] Retrieved report ID: ${numericId}`);
20730
- sendResponse5(id, {
20271
+ sendResponse4(id, {
20731
20272
  success: true,
20732
20273
  data: {
20733
20274
  id: numericId,
@@ -20744,14 +20285,14 @@ async function handleGetOne3(id, numericId, reportId, executeCollection, reportM
20744
20285
  const fileStorageId = reportId || String(numericId);
20745
20286
  const report = reportManager2.getReport(fileStorageId);
20746
20287
  if (!report) {
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] Retrieved report: ${fileStorageId}`);
20754
- sendResponse5(id, {
20295
+ sendResponse4(id, {
20755
20296
  success: true,
20756
20297
  data: {
20757
20298
  id: numericId,
@@ -20770,7 +20311,7 @@ async function handleQuery3(id, filters, limit, sort, executeCollection, reportM
20770
20311
  });
20771
20312
  if (result && result.success) {
20772
20313
  logger.info(`[DB] Query returned ${result.count} reports`);
20773
- sendResponse5(id, {
20314
+ sendResponse4(id, {
20774
20315
  success: true,
20775
20316
  data: {
20776
20317
  reports: result.data,
@@ -20785,7 +20326,7 @@ async function handleQuery3(id, filters, limit, sort, executeCollection, reportM
20785
20326
  }
20786
20327
  const reports = reportManager2.getAllReports();
20787
20328
  logger.info(`[FILE] Retrieved ${reports.length} reports (all - no query filter)`);
20788
- sendResponse5(id, {
20329
+ sendResponse4(id, {
20789
20330
  success: true,
20790
20331
  data: {
20791
20332
  reports,
@@ -20794,7 +20335,7 @@ async function handleQuery3(id, filters, limit, sort, executeCollection, reportM
20794
20335
  }
20795
20336
  }, sendMessage, clientId);
20796
20337
  }
20797
- function sendResponse5(id, res, sendMessage, clientId) {
20338
+ function sendResponse4(id, res, sendMessage, clientId) {
20798
20339
  const response = {
20799
20340
  id: id || "unknown",
20800
20341
  type: "REPORTS_RES",
@@ -20835,7 +20376,7 @@ async function handleUIsRequest(data, collections, sendMessage) {
20835
20376
  const limit = requestData?.limit;
20836
20377
  const sort = requestData?.sort;
20837
20378
  if (from.type !== "admin") {
20838
- sendResponse6(id, {
20379
+ sendResponse5(id, {
20839
20380
  success: false,
20840
20381
  error: "Unauthorized: Only admin can manage UIs"
20841
20382
  }, sendMessage, from.id);
@@ -20862,14 +20403,14 @@ async function handleUIsRequest(data, collections, sendMessage) {
20862
20403
  await handleQuery4(id, filters, limit, sort, executeCollection, sendMessage, from.id);
20863
20404
  break;
20864
20405
  default:
20865
- sendResponse6(id, {
20406
+ sendResponse5(id, {
20866
20407
  success: false,
20867
20408
  error: `Unknown operation: ${operation}`
20868
20409
  }, sendMessage, from.id);
20869
20410
  }
20870
20411
  } catch (error) {
20871
20412
  logger.error("Failed to handle UIs request:", error);
20872
- sendResponse6(null, {
20413
+ sendResponse5(null, {
20873
20414
  success: false,
20874
20415
  error: error instanceof Error ? error.message : "Unknown error occurred"
20875
20416
  }, sendMessage);
@@ -20877,14 +20418,14 @@ async function handleUIsRequest(data, collections, sendMessage) {
20877
20418
  }
20878
20419
  async function handleCreate4(id, uiId, ui, projectId, name, description, createdBy, executeCollection, sendMessage, clientId) {
20879
20420
  if (!uiId || uiId.trim().length === 0) {
20880
- sendResponse6(id, {
20421
+ sendResponse5(id, {
20881
20422
  success: false,
20882
20423
  error: "UI ID is required and cannot be empty"
20883
20424
  }, sendMessage, clientId);
20884
20425
  return;
20885
20426
  }
20886
20427
  if (!projectId || projectId.trim().length === 0) {
20887
- sendResponse6(id, {
20428
+ sendResponse5(id, {
20888
20429
  success: false,
20889
20430
  error: "Project ID is required and cannot be empty"
20890
20431
  }, sendMessage, clientId);
@@ -20901,7 +20442,7 @@ async function handleCreate4(id, uiId, ui, projectId, name, description, created
20901
20442
  });
20902
20443
  if (result && result.success) {
20903
20444
  logger.info(`UI created successfully, ID: ${result.data?.id}`);
20904
- sendResponse6(id, {
20445
+ sendResponse5(id, {
20905
20446
  success: true,
20906
20447
  data: {
20907
20448
  id: result.data?.id,
@@ -20911,13 +20452,13 @@ async function handleCreate4(id, uiId, ui, projectId, name, description, created
20911
20452
  }
20912
20453
  }, sendMessage, clientId);
20913
20454
  } else {
20914
- sendResponse6(id, {
20455
+ sendResponse5(id, {
20915
20456
  success: false,
20916
20457
  error: "Failed to create UI"
20917
20458
  }, sendMessage, clientId);
20918
20459
  }
20919
20460
  } catch (error) {
20920
- sendResponse6(id, {
20461
+ sendResponse5(id, {
20921
20462
  success: false,
20922
20463
  error: error instanceof Error ? error.message : "Failed to create UI"
20923
20464
  }, sendMessage, clientId);
@@ -20925,7 +20466,7 @@ async function handleCreate4(id, uiId, ui, projectId, name, description, created
20925
20466
  }
20926
20467
  async function handleUpdate4(id, numericId, ui, name, description, updatedBy, executeCollection, sendMessage, clientId) {
20927
20468
  if (!numericId) {
20928
- sendResponse6(id, {
20469
+ sendResponse5(id, {
20929
20470
  success: false,
20930
20471
  error: "UI ID is required"
20931
20472
  }, sendMessage, clientId);
@@ -20941,7 +20482,7 @@ async function handleUpdate4(id, numericId, ui, name, description, updatedBy, ex
20941
20482
  });
20942
20483
  if (result && result.success) {
20943
20484
  logger.info(`UI updated successfully, ID: ${numericId}`);
20944
- sendResponse6(id, {
20485
+ sendResponse5(id, {
20945
20486
  success: true,
20946
20487
  data: {
20947
20488
  id: numericId,
@@ -20951,13 +20492,13 @@ async function handleUpdate4(id, numericId, ui, name, description, updatedBy, ex
20951
20492
  }
20952
20493
  }, sendMessage, clientId);
20953
20494
  } else {
20954
- sendResponse6(id, {
20495
+ sendResponse5(id, {
20955
20496
  success: false,
20956
20497
  error: "Failed to update UI"
20957
20498
  }, sendMessage, clientId);
20958
20499
  }
20959
20500
  } catch (error) {
20960
- sendResponse6(id, {
20501
+ sendResponse5(id, {
20961
20502
  success: false,
20962
20503
  error: error instanceof Error ? error.message : "Failed to update UI"
20963
20504
  }, sendMessage, clientId);
@@ -20965,7 +20506,7 @@ async function handleUpdate4(id, numericId, ui, name, description, updatedBy, ex
20965
20506
  }
20966
20507
  async function handleDelete4(id, numericId, executeCollection, sendMessage, clientId) {
20967
20508
  if (!numericId) {
20968
- sendResponse6(id, {
20509
+ sendResponse5(id, {
20969
20510
  success: false,
20970
20511
  error: "UI ID is required"
20971
20512
  }, sendMessage, clientId);
@@ -20975,7 +20516,7 @@ async function handleDelete4(id, numericId, executeCollection, sendMessage, clie
20975
20516
  const result = await executeCollection("uis", "delete", { id: numericId });
20976
20517
  if (result && result.success) {
20977
20518
  logger.info(`UI deleted successfully, ID: ${numericId}`);
20978
- sendResponse6(id, {
20519
+ sendResponse5(id, {
20979
20520
  success: true,
20980
20521
  data: {
20981
20522
  id: numericId,
@@ -20983,13 +20524,13 @@ async function handleDelete4(id, numericId, executeCollection, sendMessage, clie
20983
20524
  }
20984
20525
  }, sendMessage, clientId);
20985
20526
  } else {
20986
- sendResponse6(id, {
20527
+ sendResponse5(id, {
20987
20528
  success: false,
20988
20529
  error: "Failed to delete UI"
20989
20530
  }, sendMessage, clientId);
20990
20531
  }
20991
20532
  } catch (error) {
20992
- sendResponse6(id, {
20533
+ sendResponse5(id, {
20993
20534
  success: false,
20994
20535
  error: error instanceof Error ? error.message : "Failed to delete UI"
20995
20536
  }, sendMessage, clientId);
@@ -21000,7 +20541,7 @@ async function handleGetAll4(id, executeCollection, sendMessage, clientId) {
21000
20541
  const result = await executeCollection("uis", "getAll", {});
21001
20542
  if (result && result.success) {
21002
20543
  logger.info(`Retrieved ${result.count} UIs`);
21003
- sendResponse6(id, {
20544
+ sendResponse5(id, {
21004
20545
  success: true,
21005
20546
  data: {
21006
20547
  uis: result.data,
@@ -21009,13 +20550,13 @@ async function handleGetAll4(id, executeCollection, sendMessage, clientId) {
21009
20550
  }
21010
20551
  }, sendMessage, clientId);
21011
20552
  } else {
21012
- sendResponse6(id, {
20553
+ sendResponse5(id, {
21013
20554
  success: false,
21014
20555
  error: "Failed to get UIs"
21015
20556
  }, sendMessage, clientId);
21016
20557
  }
21017
20558
  } catch (error) {
21018
- sendResponse6(id, {
20559
+ sendResponse5(id, {
21019
20560
  success: false,
21020
20561
  error: error instanceof Error ? error.message : "Failed to get UIs"
21021
20562
  }, sendMessage, clientId);
@@ -21023,7 +20564,7 @@ async function handleGetAll4(id, executeCollection, sendMessage, clientId) {
21023
20564
  }
21024
20565
  async function handleGetOne4(id, numericId, executeCollection, sendMessage, clientId) {
21025
20566
  if (!numericId) {
21026
- sendResponse6(id, {
20567
+ sendResponse5(id, {
21027
20568
  success: false,
21028
20569
  error: "UI ID is required"
21029
20570
  }, sendMessage, clientId);
@@ -21033,7 +20574,7 @@ async function handleGetOne4(id, numericId, executeCollection, sendMessage, clie
21033
20574
  const result = await executeCollection("uis", "getOne", { id: numericId });
21034
20575
  if (result && result.success) {
21035
20576
  logger.info(`Retrieved UI ID: ${numericId}`);
21036
- sendResponse6(id, {
20577
+ sendResponse5(id, {
21037
20578
  success: true,
21038
20579
  data: {
21039
20580
  id: numericId,
@@ -21043,13 +20584,13 @@ async function handleGetOne4(id, numericId, executeCollection, sendMessage, clie
21043
20584
  }
21044
20585
  }, sendMessage, clientId);
21045
20586
  } else {
21046
- sendResponse6(id, {
20587
+ sendResponse5(id, {
21047
20588
  success: false,
21048
20589
  error: `UI not found`
21049
20590
  }, sendMessage, clientId);
21050
20591
  }
21051
20592
  } catch (error) {
21052
- sendResponse6(id, {
20593
+ sendResponse5(id, {
21053
20594
  success: false,
21054
20595
  error: error instanceof Error ? error.message : "Failed to get UI"
21055
20596
  }, sendMessage, clientId);
@@ -21064,7 +20605,7 @@ async function handleQuery4(id, filters, limit, sort, executeCollection, sendMes
21064
20605
  });
21065
20606
  if (result && result.success) {
21066
20607
  logger.info(`Query returned ${result.count} UIs`);
21067
- sendResponse6(id, {
20608
+ sendResponse5(id, {
21068
20609
  success: true,
21069
20610
  data: {
21070
20611
  uis: result.data,
@@ -21073,19 +20614,19 @@ async function handleQuery4(id, filters, limit, sort, executeCollection, sendMes
21073
20614
  }
21074
20615
  }, sendMessage, clientId);
21075
20616
  } else {
21076
- sendResponse6(id, {
20617
+ sendResponse5(id, {
21077
20618
  success: false,
21078
20619
  error: "Failed to query UIs"
21079
20620
  }, sendMessage, clientId);
21080
20621
  }
21081
20622
  } catch (error) {
21082
- sendResponse6(id, {
20623
+ sendResponse5(id, {
21083
20624
  success: false,
21084
20625
  error: error instanceof Error ? error.message : "Failed to query UIs"
21085
20626
  }, sendMessage, clientId);
21086
20627
  }
21087
20628
  }
21088
- function sendResponse6(id, res, sendMessage, clientId) {
20629
+ function sendResponse5(id, res, sendMessage, clientId) {
21089
20630
  const response = {
21090
20631
  id: id || "unknown",
21091
20632
  type: "UIS_RES",
@@ -21143,14 +20684,14 @@ async function handleBookmarksRequest(data, collections, sendMessage) {
21143
20684
  await handleQuery5(id, filters, limit, sort, executeCollection, sendMessage, from.id);
21144
20685
  break;
21145
20686
  default:
21146
- sendResponse7(id, {
20687
+ sendResponse6(id, {
21147
20688
  success: false,
21148
20689
  error: `Unknown operation: ${operation}`
21149
20690
  }, sendMessage, from.id);
21150
20691
  }
21151
20692
  } catch (error) {
21152
20693
  logger.error("Failed to handle bookmarks request:", error);
21153
- sendResponse7(null, {
20694
+ sendResponse6(null, {
21154
20695
  success: false,
21155
20696
  error: error instanceof Error ? error.message : "Unknown error occurred"
21156
20697
  }, sendMessage);
@@ -21158,14 +20699,14 @@ async function handleBookmarksRequest(data, collections, sendMessage) {
21158
20699
  }
21159
20700
  async function handleCreate5(id, userId, threadId, name, description, uiblock, executeCollection, sendMessage, clientId) {
21160
20701
  if (!userId) {
21161
- sendResponse7(id, {
20702
+ sendResponse6(id, {
21162
20703
  success: false,
21163
20704
  error: "userId is required"
21164
20705
  }, sendMessage, clientId);
21165
20706
  return;
21166
20707
  }
21167
20708
  if (!uiblock) {
21168
- sendResponse7(id, {
20709
+ sendResponse6(id, {
21169
20710
  success: false,
21170
20711
  error: "UIBlock data is required"
21171
20712
  }, sendMessage, clientId);
@@ -21173,14 +20714,14 @@ async function handleCreate5(id, userId, threadId, name, description, uiblock, e
21173
20714
  }
21174
20715
  try {
21175
20716
  const result = await executeCollection("bookmarks", "create", { userId, threadId, name, description, uiblock });
21176
- sendResponse7(id, {
20717
+ sendResponse6(id, {
21177
20718
  success: true,
21178
20719
  data: result.data,
21179
20720
  message: "Bookmark created successfully"
21180
20721
  }, sendMessage, clientId);
21181
20722
  logger.info(`Bookmark created: ID ${result.data.id}`);
21182
20723
  } catch (error) {
21183
- sendResponse7(id, {
20724
+ sendResponse6(id, {
21184
20725
  success: false,
21185
20726
  error: error instanceof Error ? error.message : "Failed to create bookmark"
21186
20727
  }, sendMessage, clientId);
@@ -21188,7 +20729,7 @@ async function handleCreate5(id, userId, threadId, name, description, uiblock, e
21188
20729
  }
21189
20730
  async function handleUpdate5(id, bookmarkId, threadId, name, description, uiblock, executeCollection, sendMessage, clientId) {
21190
20731
  if (!bookmarkId) {
21191
- sendResponse7(id, {
20732
+ sendResponse6(id, {
21192
20733
  success: false,
21193
20734
  error: "Bookmark ID is required"
21194
20735
  }, sendMessage, clientId);
@@ -21196,14 +20737,14 @@ async function handleUpdate5(id, bookmarkId, threadId, name, description, uibloc
21196
20737
  }
21197
20738
  try {
21198
20739
  const result = await executeCollection("bookmarks", "update", { id: bookmarkId, threadId, name, description, uiblock });
21199
- sendResponse7(id, {
20740
+ sendResponse6(id, {
21200
20741
  success: true,
21201
20742
  data: result.data,
21202
20743
  message: "Bookmark updated successfully"
21203
20744
  }, sendMessage, clientId);
21204
20745
  logger.info(`Bookmark updated: ID ${bookmarkId}`);
21205
20746
  } catch (error) {
21206
- sendResponse7(id, {
20747
+ sendResponse6(id, {
21207
20748
  success: false,
21208
20749
  error: error instanceof Error ? error.message : "Failed to update bookmark"
21209
20750
  }, sendMessage, clientId);
@@ -21211,7 +20752,7 @@ async function handleUpdate5(id, bookmarkId, threadId, name, description, uibloc
21211
20752
  }
21212
20753
  async function handleDelete5(id, bookmarkId, executeCollection, sendMessage, clientId) {
21213
20754
  if (!bookmarkId) {
21214
- sendResponse7(id, {
20755
+ sendResponse6(id, {
21215
20756
  success: false,
21216
20757
  error: "Bookmark ID is required"
21217
20758
  }, sendMessage, clientId);
@@ -21219,14 +20760,14 @@ async function handleDelete5(id, bookmarkId, executeCollection, sendMessage, cli
21219
20760
  }
21220
20761
  try {
21221
20762
  const result = await executeCollection("bookmarks", "delete", { id: bookmarkId });
21222
- sendResponse7(id, {
20763
+ sendResponse6(id, {
21223
20764
  success: true,
21224
20765
  data: result.data,
21225
20766
  message: "Bookmark deleted successfully"
21226
20767
  }, sendMessage, clientId);
21227
20768
  logger.info(`Bookmark deleted: ID ${bookmarkId}`);
21228
20769
  } catch (error) {
21229
- sendResponse7(id, {
20770
+ sendResponse6(id, {
21230
20771
  success: false,
21231
20772
  error: error instanceof Error ? error.message : "Failed to delete bookmark"
21232
20773
  }, sendMessage, clientId);
@@ -21235,7 +20776,7 @@ async function handleDelete5(id, bookmarkId, executeCollection, sendMessage, cli
21235
20776
  async function handleGetAll5(id, executeCollection, sendMessage, clientId) {
21236
20777
  try {
21237
20778
  const result = await executeCollection("bookmarks", "getAll", {});
21238
- sendResponse7(id, {
20779
+ sendResponse6(id, {
21239
20780
  success: true,
21240
20781
  data: result.data,
21241
20782
  count: result.count,
@@ -21243,7 +20784,7 @@ async function handleGetAll5(id, executeCollection, sendMessage, clientId) {
21243
20784
  }, sendMessage, clientId);
21244
20785
  logger.info(`Retrieved all bookmarks (count: ${result.count})`);
21245
20786
  } catch (error) {
21246
- sendResponse7(id, {
20787
+ sendResponse6(id, {
21247
20788
  success: false,
21248
20789
  error: error instanceof Error ? error.message : "Failed to get bookmarks"
21249
20790
  }, sendMessage, clientId);
@@ -21251,7 +20792,7 @@ async function handleGetAll5(id, executeCollection, sendMessage, clientId) {
21251
20792
  }
21252
20793
  async function handleGetOne5(id, bookmarkId, executeCollection, sendMessage, clientId) {
21253
20794
  if (!bookmarkId) {
21254
- sendResponse7(id, {
20795
+ sendResponse6(id, {
21255
20796
  success: false,
21256
20797
  error: "Bookmark ID is required"
21257
20798
  }, sendMessage, clientId);
@@ -21259,14 +20800,14 @@ async function handleGetOne5(id, bookmarkId, executeCollection, sendMessage, cli
21259
20800
  }
21260
20801
  try {
21261
20802
  const result = await executeCollection("bookmarks", "getOne", { id: bookmarkId });
21262
- sendResponse7(id, {
20803
+ sendResponse6(id, {
21263
20804
  success: true,
21264
20805
  data: result.data,
21265
20806
  message: `Retrieved bookmark ID ${bookmarkId}`
21266
20807
  }, sendMessage, clientId);
21267
20808
  logger.info(`Retrieved bookmark: ID ${bookmarkId}`);
21268
20809
  } catch (error) {
21269
- sendResponse7(id, {
20810
+ sendResponse6(id, {
21270
20811
  success: false,
21271
20812
  error: error instanceof Error ? error.message : "Failed to get bookmark"
21272
20813
  }, sendMessage, clientId);
@@ -21279,7 +20820,7 @@ async function handleQuery5(id, filters, limit, sort, executeCollection, sendMes
21279
20820
  limit,
21280
20821
  sort
21281
20822
  });
21282
- sendResponse7(id, {
20823
+ sendResponse6(id, {
21283
20824
  success: true,
21284
20825
  data: result.data,
21285
20826
  count: result.count,
@@ -21287,13 +20828,13 @@ async function handleQuery5(id, filters, limit, sort, executeCollection, sendMes
21287
20828
  }, sendMessage, clientId);
21288
20829
  logger.info(`Query returned ${result.count} bookmarks`);
21289
20830
  } catch (error) {
21290
- sendResponse7(id, {
20831
+ sendResponse6(id, {
21291
20832
  success: false,
21292
20833
  error: error instanceof Error ? error.message : "Failed to query bookmarks"
21293
20834
  }, sendMessage, clientId);
21294
20835
  }
21295
20836
  }
21296
- function sendResponse7(id, res, sendMessage, clientId) {
20837
+ function sendResponse6(id, res, sendMessage, clientId) {
21297
20838
  const response = {
21298
20839
  id: id || "unknown",
21299
20840
  type: "BOOKMARKS_RES",
@@ -21360,14 +20901,14 @@ async function handleArtifactsRequest(data, collections, sendMessage) {
21360
20901
  await handleQuery6(id, { filters, limit, offset, sort }, executeCollection, sendMessage, from.id);
21361
20902
  break;
21362
20903
  default:
21363
- sendResponse8(id, {
20904
+ sendResponse7(id, {
21364
20905
  success: false,
21365
20906
  error: `Unknown operation: ${operation}`
21366
20907
  }, sendMessage, from.id);
21367
20908
  }
21368
20909
  } catch (error) {
21369
20910
  logger.error("Failed to handle artifacts request:", error);
21370
- sendResponse8(null, {
20911
+ sendResponse7(null, {
21371
20912
  success: false,
21372
20913
  error: error instanceof Error ? error.message : "Unknown error occurred"
21373
20914
  }, sendMessage);
@@ -21375,7 +20916,7 @@ async function handleArtifactsRequest(data, collections, sendMessage) {
21375
20916
  }
21376
20917
  async function handleCreate6(id, name, createdBy, dsl, type, filters, status, executeCollection, sendMessage, clientId) {
21377
20918
  if (!name) {
21378
- sendResponse8(id, {
20919
+ sendResponse7(id, {
21379
20920
  success: false,
21380
20921
  error: "name is required"
21381
20922
  }, sendMessage, clientId);
@@ -21390,14 +20931,14 @@ async function handleCreate6(id, name, createdBy, dsl, type, filters, status, ex
21390
20931
  filters,
21391
20932
  status
21392
20933
  });
21393
- sendResponse8(id, {
20934
+ sendResponse7(id, {
21394
20935
  success: true,
21395
20936
  data: result.data,
21396
20937
  message: "Artifact created successfully"
21397
20938
  }, sendMessage, clientId);
21398
20939
  logger.info(`Artifact created: ID ${result.data.id}`);
21399
20940
  } catch (error) {
21400
- sendResponse8(id, {
20941
+ sendResponse7(id, {
21401
20942
  success: false,
21402
20943
  error: error instanceof Error ? error.message : "Failed to create artifact"
21403
20944
  }, sendMessage, clientId);
@@ -21405,7 +20946,7 @@ async function handleCreate6(id, name, createdBy, dsl, type, filters, status, ex
21405
20946
  }
21406
20947
  async function handleUpdate6(id, artifactId, name, dsl, type, filters, status, deleted, executeCollection, sendMessage, clientId) {
21407
20948
  if (!artifactId) {
21408
- sendResponse8(id, {
20949
+ sendResponse7(id, {
21409
20950
  success: false,
21410
20951
  error: "Artifact ID is required"
21411
20952
  }, sendMessage, clientId);
@@ -21413,14 +20954,14 @@ async function handleUpdate6(id, artifactId, name, dsl, type, filters, status, d
21413
20954
  }
21414
20955
  try {
21415
20956
  const result = await executeCollection("artifacts", "update", { id: artifactId, name, dsl, type, filters, status, deleted });
21416
- sendResponse8(id, {
20957
+ sendResponse7(id, {
21417
20958
  success: true,
21418
20959
  data: result.data,
21419
20960
  message: "Artifact updated successfully"
21420
20961
  }, sendMessage, clientId);
21421
20962
  logger.info(`Artifact updated: ID ${artifactId}`);
21422
20963
  } catch (error) {
21423
- sendResponse8(id, {
20964
+ sendResponse7(id, {
21424
20965
  success: false,
21425
20966
  error: error instanceof Error ? error.message : "Failed to update artifact"
21426
20967
  }, sendMessage, clientId);
@@ -21428,7 +20969,7 @@ async function handleUpdate6(id, artifactId, name, dsl, type, filters, status, d
21428
20969
  }
21429
20970
  async function handleDelete6(id, artifactId, executeCollection, sendMessage, clientId) {
21430
20971
  if (!artifactId) {
21431
- sendResponse8(id, {
20972
+ sendResponse7(id, {
21432
20973
  success: false,
21433
20974
  error: "Artifact ID is required"
21434
20975
  }, sendMessage, clientId);
@@ -21436,14 +20977,14 @@ async function handleDelete6(id, artifactId, executeCollection, sendMessage, cli
21436
20977
  }
21437
20978
  try {
21438
20979
  const result = await executeCollection("artifacts", "delete", { id: artifactId });
21439
- sendResponse8(id, {
20980
+ sendResponse7(id, {
21440
20981
  success: true,
21441
20982
  data: result.data,
21442
20983
  message: "Artifact deleted successfully"
21443
20984
  }, sendMessage, clientId);
21444
20985
  logger.info(`Artifact deleted: ID ${artifactId}`);
21445
20986
  } catch (error) {
21446
- sendResponse8(id, {
20987
+ sendResponse7(id, {
21447
20988
  success: false,
21448
20989
  error: error instanceof Error ? error.message : "Failed to delete artifact"
21449
20990
  }, sendMessage, clientId);
@@ -21452,7 +20993,7 @@ async function handleDelete6(id, artifactId, executeCollection, sendMessage, cli
21452
20993
  async function handleGetAll6(id, limit, executeCollection, sendMessage, clientId) {
21453
20994
  try {
21454
20995
  const result = await executeCollection("artifacts", "getAll", { limit });
21455
- sendResponse8(id, {
20996
+ sendResponse7(id, {
21456
20997
  success: true,
21457
20998
  data: result.data,
21458
20999
  count: result.count,
@@ -21460,7 +21001,7 @@ async function handleGetAll6(id, limit, executeCollection, sendMessage, clientId
21460
21001
  }, sendMessage, clientId);
21461
21002
  logger.info(`Retrieved all artifacts (count: ${result.count})`);
21462
21003
  } catch (error) {
21463
- sendResponse8(id, {
21004
+ sendResponse7(id, {
21464
21005
  success: false,
21465
21006
  error: error instanceof Error ? error.message : "Failed to get artifacts"
21466
21007
  }, sendMessage, clientId);
@@ -21468,7 +21009,7 @@ async function handleGetAll6(id, limit, executeCollection, sendMessage, clientId
21468
21009
  }
21469
21010
  async function handleGetOne6(id, artifactId, executeCollection, sendMessage, clientId) {
21470
21011
  if (!artifactId) {
21471
- sendResponse8(id, {
21012
+ sendResponse7(id, {
21472
21013
  success: false,
21473
21014
  error: "Artifact ID is required"
21474
21015
  }, sendMessage, clientId);
@@ -21476,14 +21017,14 @@ async function handleGetOne6(id, artifactId, executeCollection, sendMessage, cli
21476
21017
  }
21477
21018
  try {
21478
21019
  const result = await executeCollection("artifacts", "getOne", { id: artifactId });
21479
- sendResponse8(id, {
21020
+ sendResponse7(id, {
21480
21021
  success: true,
21481
21022
  data: result.data,
21482
21023
  message: `Retrieved artifact ID ${artifactId}`
21483
21024
  }, sendMessage, clientId);
21484
21025
  logger.info(`Retrieved artifact: ID ${artifactId}`);
21485
21026
  } catch (error) {
21486
- sendResponse8(id, {
21027
+ sendResponse7(id, {
21487
21028
  success: false,
21488
21029
  error: error instanceof Error ? error.message : "Failed to get artifact"
21489
21030
  }, sendMessage, clientId);
@@ -21500,7 +21041,7 @@ async function handleQuery6(id, queryParams, executeCollection, sendMessage, cli
21500
21041
  sort: queryParams.sort || "DESC"
21501
21042
  });
21502
21043
  logger.info("[SDK-NODEJS] handleQuery - executeCollection result count:", result.count);
21503
- sendResponse8(id, {
21044
+ sendResponse7(id, {
21504
21045
  success: true,
21505
21046
  data: result.data,
21506
21047
  count: result.count,
@@ -21508,13 +21049,13 @@ async function handleQuery6(id, queryParams, executeCollection, sendMessage, cli
21508
21049
  }, sendMessage, clientId);
21509
21050
  logger.info(`Query artifacts (count: ${result.count})`);
21510
21051
  } catch (error) {
21511
- sendResponse8(id, {
21052
+ sendResponse7(id, {
21512
21053
  success: false,
21513
21054
  error: error instanceof Error ? error.message : "Failed to query artifacts"
21514
21055
  }, sendMessage, clientId);
21515
21056
  }
21516
21057
  }
21517
- function sendResponse8(id, res, sendMessage, clientId) {
21058
+ function sendResponse7(id, res, sendMessage, clientId) {
21518
21059
  const response = {
21519
21060
  id: id || "unknown",
21520
21061
  type: "ARTIFACTS_RES",
@@ -21588,14 +21129,14 @@ async function handleKbNodesRequest(data, collections, sendMessage) {
21588
21129
  await handleGetTags(id, executeCollection, sendMessage, from.id);
21589
21130
  break;
21590
21131
  default:
21591
- sendResponse9(id, {
21132
+ sendResponse8(id, {
21592
21133
  success: false,
21593
21134
  error: `Unknown operation: ${operation}`
21594
21135
  }, sendMessage, from.id);
21595
21136
  }
21596
21137
  } catch (error) {
21597
21138
  logger.error("Failed to handle KB nodes request:", error);
21598
- sendResponse9(null, {
21139
+ sendResponse8(null, {
21599
21140
  success: false,
21600
21141
  error: error instanceof Error ? error.message : "Unknown error occurred"
21601
21142
  }, sendMessage);
@@ -21604,21 +21145,21 @@ async function handleKbNodesRequest(data, collections, sendMessage) {
21604
21145
  async function handleCreate7(id, nodeData, executeCollection, sendMessage, clientId) {
21605
21146
  const { title, content, category, tags, type, createdBy } = nodeData;
21606
21147
  if (!title || title.trim().length === 0) {
21607
- sendResponse9(id, {
21148
+ sendResponse8(id, {
21608
21149
  success: false,
21609
21150
  error: "Title is required and cannot be empty"
21610
21151
  }, sendMessage, clientId);
21611
21152
  return;
21612
21153
  }
21613
21154
  if (!content || content.trim().length === 0) {
21614
- sendResponse9(id, {
21155
+ sendResponse8(id, {
21615
21156
  success: false,
21616
21157
  error: "Content is required and cannot be empty"
21617
21158
  }, sendMessage, clientId);
21618
21159
  return;
21619
21160
  }
21620
21161
  if (!createdBy) {
21621
- sendResponse9(id, {
21162
+ sendResponse8(id, {
21622
21163
  success: false,
21623
21164
  error: "createdBy (user ID) is required"
21624
21165
  }, sendMessage, clientId);
@@ -21635,7 +21176,7 @@ async function handleCreate7(id, nodeData, executeCollection, sendMessage, clien
21635
21176
  });
21636
21177
  if (result && result.success) {
21637
21178
  logger.info(`[DB] KB node created successfully: ${title}`);
21638
- sendResponse9(id, {
21179
+ sendResponse8(id, {
21639
21180
  success: true,
21640
21181
  data: {
21641
21182
  ...result.data,
@@ -21644,13 +21185,13 @@ async function handleCreate7(id, nodeData, executeCollection, sendMessage, clien
21644
21185
  }, sendMessage, clientId);
21645
21186
  return;
21646
21187
  }
21647
- sendResponse9(id, {
21188
+ sendResponse8(id, {
21648
21189
  success: false,
21649
21190
  error: "Failed to create knowledge node"
21650
21191
  }, sendMessage, clientId);
21651
21192
  } catch (error) {
21652
21193
  logger.error("[DB] Failed to create KB node:", error);
21653
- sendResponse9(id, {
21194
+ sendResponse8(id, {
21654
21195
  success: false,
21655
21196
  error: error instanceof Error ? error.message : "Failed to create knowledge node"
21656
21197
  }, sendMessage, clientId);
@@ -21659,14 +21200,14 @@ async function handleCreate7(id, nodeData, executeCollection, sendMessage, clien
21659
21200
  async function handleUpdate7(id, nodeId, nodeData, executeCollection, sendMessage, clientId) {
21660
21201
  const { title, content, category, tags, type, updatedBy } = nodeData;
21661
21202
  if (!nodeId) {
21662
- sendResponse9(id, {
21203
+ sendResponse8(id, {
21663
21204
  success: false,
21664
21205
  error: "Knowledge node ID is required"
21665
21206
  }, sendMessage, clientId);
21666
21207
  return;
21667
21208
  }
21668
21209
  if (!updatedBy) {
21669
- sendResponse9(id, {
21210
+ sendResponse8(id, {
21670
21211
  success: false,
21671
21212
  error: "updatedBy (user ID) is required"
21672
21213
  }, sendMessage, clientId);
@@ -21684,7 +21225,7 @@ async function handleUpdate7(id, nodeId, nodeData, executeCollection, sendMessag
21684
21225
  });
21685
21226
  if (result && result.success) {
21686
21227
  logger.info(`[DB] KB node updated successfully, ID: ${nodeId}`);
21687
- sendResponse9(id, {
21228
+ sendResponse8(id, {
21688
21229
  success: true,
21689
21230
  data: {
21690
21231
  ...result.data,
@@ -21693,13 +21234,13 @@ async function handleUpdate7(id, nodeId, nodeData, executeCollection, sendMessag
21693
21234
  }, sendMessage, clientId);
21694
21235
  return;
21695
21236
  }
21696
- sendResponse9(id, {
21237
+ sendResponse8(id, {
21697
21238
  success: false,
21698
21239
  error: "Failed to update knowledge node"
21699
21240
  }, sendMessage, clientId);
21700
21241
  } catch (error) {
21701
21242
  logger.error("[DB] Failed to update KB node:", error);
21702
- sendResponse9(id, {
21243
+ sendResponse8(id, {
21703
21244
  success: false,
21704
21245
  error: error instanceof Error ? error.message : "Failed to update knowledge node"
21705
21246
  }, sendMessage, clientId);
@@ -21707,7 +21248,7 @@ async function handleUpdate7(id, nodeId, nodeData, executeCollection, sendMessag
21707
21248
  }
21708
21249
  async function handleDelete7(id, nodeId, executeCollection, sendMessage, clientId) {
21709
21250
  if (!nodeId) {
21710
- sendResponse9(id, {
21251
+ sendResponse8(id, {
21711
21252
  success: false,
21712
21253
  error: "Knowledge node ID is required"
21713
21254
  }, sendMessage, clientId);
@@ -21717,7 +21258,7 @@ async function handleDelete7(id, nodeId, executeCollection, sendMessage, clientI
21717
21258
  const result = await executeCollection("kbNodes", "delete", { id: nodeId });
21718
21259
  if (result && result.success) {
21719
21260
  logger.info(`[DB] KB node deleted successfully, ID: ${nodeId}`);
21720
- sendResponse9(id, {
21261
+ sendResponse8(id, {
21721
21262
  success: true,
21722
21263
  data: {
21723
21264
  id: nodeId,
@@ -21727,13 +21268,13 @@ async function handleDelete7(id, nodeId, executeCollection, sendMessage, clientI
21727
21268
  }, sendMessage, clientId);
21728
21269
  return;
21729
21270
  }
21730
- sendResponse9(id, {
21271
+ sendResponse8(id, {
21731
21272
  success: false,
21732
21273
  error: "Failed to delete knowledge node"
21733
21274
  }, sendMessage, clientId);
21734
21275
  } catch (error) {
21735
21276
  logger.error("[DB] Failed to delete KB node:", error);
21736
- sendResponse9(id, {
21277
+ sendResponse8(id, {
21737
21278
  success: false,
21738
21279
  error: error instanceof Error ? error.message : "Failed to delete knowledge node"
21739
21280
  }, sendMessage, clientId);
@@ -21747,7 +21288,7 @@ async function handleGetAll7(id, limit, offset, executeCollection, sendMessage,
21747
21288
  });
21748
21289
  if (result && result.success) {
21749
21290
  logger.info(`[DB] Retrieved ${result.count} KB nodes`);
21750
- sendResponse9(id, {
21291
+ sendResponse8(id, {
21751
21292
  success: true,
21752
21293
  data: {
21753
21294
  nodes: result.data,
@@ -21757,13 +21298,13 @@ async function handleGetAll7(id, limit, offset, executeCollection, sendMessage,
21757
21298
  }, sendMessage, clientId);
21758
21299
  return;
21759
21300
  }
21760
- sendResponse9(id, {
21301
+ sendResponse8(id, {
21761
21302
  success: false,
21762
21303
  error: "Failed to retrieve knowledge nodes"
21763
21304
  }, sendMessage, clientId);
21764
21305
  } catch (error) {
21765
21306
  logger.error("[DB] Failed to get all KB nodes:", error);
21766
- sendResponse9(id, {
21307
+ sendResponse8(id, {
21767
21308
  success: false,
21768
21309
  error: error instanceof Error ? error.message : "Failed to retrieve knowledge nodes"
21769
21310
  }, sendMessage, clientId);
@@ -21771,7 +21312,7 @@ async function handleGetAll7(id, limit, offset, executeCollection, sendMessage,
21771
21312
  }
21772
21313
  async function handleGetOne7(id, nodeId, executeCollection, sendMessage, clientId) {
21773
21314
  if (!nodeId) {
21774
- sendResponse9(id, {
21315
+ sendResponse8(id, {
21775
21316
  success: false,
21776
21317
  error: "Knowledge node ID is required"
21777
21318
  }, sendMessage, clientId);
@@ -21781,7 +21322,7 @@ async function handleGetOne7(id, nodeId, executeCollection, sendMessage, clientI
21781
21322
  const result = await executeCollection("kbNodes", "getOne", { id: nodeId });
21782
21323
  if (result && result.success) {
21783
21324
  logger.info(`[DB] Retrieved KB node ID: ${nodeId}`);
21784
- sendResponse9(id, {
21325
+ sendResponse8(id, {
21785
21326
  success: true,
21786
21327
  data: {
21787
21328
  node: result.data,
@@ -21790,13 +21331,13 @@ async function handleGetOne7(id, nodeId, executeCollection, sendMessage, clientI
21790
21331
  }, sendMessage, clientId);
21791
21332
  return;
21792
21333
  }
21793
- sendResponse9(id, {
21334
+ sendResponse8(id, {
21794
21335
  success: false,
21795
21336
  error: "Failed to retrieve knowledge node"
21796
21337
  }, sendMessage, clientId);
21797
21338
  } catch (error) {
21798
21339
  logger.error("[DB] Failed to get KB node:", error);
21799
- sendResponse9(id, {
21340
+ sendResponse8(id, {
21800
21341
  success: false,
21801
21342
  error: error instanceof Error ? error.message : "Failed to retrieve knowledge node"
21802
21343
  }, sendMessage, clientId);
@@ -21816,7 +21357,7 @@ async function handleSearch(id, searchParams, executeCollection, sendMessage, cl
21816
21357
  });
21817
21358
  if (result && result.success) {
21818
21359
  logger.info(`[DB] Search returned ${result.count} KB nodes`);
21819
- sendResponse9(id, {
21360
+ sendResponse8(id, {
21820
21361
  success: true,
21821
21362
  data: {
21822
21363
  nodes: result.data,
@@ -21826,13 +21367,13 @@ async function handleSearch(id, searchParams, executeCollection, sendMessage, cl
21826
21367
  }, sendMessage, clientId);
21827
21368
  return;
21828
21369
  }
21829
- sendResponse9(id, {
21370
+ sendResponse8(id, {
21830
21371
  success: false,
21831
21372
  error: "Failed to search knowledge nodes"
21832
21373
  }, sendMessage, clientId);
21833
21374
  } catch (error) {
21834
21375
  logger.error("[DB] Failed to search KB nodes:", error);
21835
- sendResponse9(id, {
21376
+ sendResponse8(id, {
21836
21377
  success: false,
21837
21378
  error: error instanceof Error ? error.message : "Failed to search knowledge nodes"
21838
21379
  }, sendMessage, clientId);
@@ -21840,7 +21381,7 @@ async function handleSearch(id, searchParams, executeCollection, sendMessage, cl
21840
21381
  }
21841
21382
  async function handleGetByCategory(id, category, limit, offset, executeCollection, sendMessage, clientId) {
21842
21383
  if (!category) {
21843
- sendResponse9(id, {
21384
+ sendResponse8(id, {
21844
21385
  success: false,
21845
21386
  error: "Category is required"
21846
21387
  }, sendMessage, clientId);
@@ -21854,7 +21395,7 @@ async function handleGetByCategory(id, category, limit, offset, executeCollectio
21854
21395
  });
21855
21396
  if (result && result.success) {
21856
21397
  logger.info(`[DB] Retrieved ${result.count} KB nodes for category: ${category}`);
21857
- sendResponse9(id, {
21398
+ sendResponse8(id, {
21858
21399
  success: true,
21859
21400
  data: {
21860
21401
  nodes: result.data,
@@ -21865,13 +21406,13 @@ async function handleGetByCategory(id, category, limit, offset, executeCollectio
21865
21406
  }, sendMessage, clientId);
21866
21407
  return;
21867
21408
  }
21868
- sendResponse9(id, {
21409
+ sendResponse8(id, {
21869
21410
  success: false,
21870
21411
  error: "Failed to retrieve knowledge nodes by category"
21871
21412
  }, sendMessage, clientId);
21872
21413
  } catch (error) {
21873
21414
  logger.error("[DB] Failed to get KB nodes by category:", error);
21874
- sendResponse9(id, {
21415
+ sendResponse8(id, {
21875
21416
  success: false,
21876
21417
  error: error instanceof Error ? error.message : "Failed to retrieve knowledge nodes by category"
21877
21418
  }, sendMessage, clientId);
@@ -21879,7 +21420,7 @@ async function handleGetByCategory(id, category, limit, offset, executeCollectio
21879
21420
  }
21880
21421
  async function handleGetByUser(id, userId, limit, offset, executeCollection, sendMessage, clientId) {
21881
21422
  if (!userId) {
21882
- sendResponse9(id, {
21423
+ sendResponse8(id, {
21883
21424
  success: false,
21884
21425
  error: "User ID is required"
21885
21426
  }, sendMessage, clientId);
@@ -21893,7 +21434,7 @@ async function handleGetByUser(id, userId, limit, offset, executeCollection, sen
21893
21434
  });
21894
21435
  if (result && result.success) {
21895
21436
  logger.info(`[DB] Retrieved ${result.count} KB nodes for user: ${userId}`);
21896
- sendResponse9(id, {
21437
+ sendResponse8(id, {
21897
21438
  success: true,
21898
21439
  data: {
21899
21440
  nodes: result.data,
@@ -21904,13 +21445,13 @@ async function handleGetByUser(id, userId, limit, offset, executeCollection, sen
21904
21445
  }, sendMessage, clientId);
21905
21446
  return;
21906
21447
  }
21907
- sendResponse9(id, {
21448
+ sendResponse8(id, {
21908
21449
  success: false,
21909
21450
  error: "Failed to retrieve knowledge nodes by user"
21910
21451
  }, sendMessage, clientId);
21911
21452
  } catch (error) {
21912
21453
  logger.error("[DB] Failed to get KB nodes by user:", error);
21913
- sendResponse9(id, {
21454
+ sendResponse8(id, {
21914
21455
  success: false,
21915
21456
  error: error instanceof Error ? error.message : "Failed to retrieve knowledge nodes by user"
21916
21457
  }, sendMessage, clientId);
@@ -21921,7 +21462,7 @@ async function handleGetCategories(id, executeCollection, sendMessage, clientId)
21921
21462
  const result = await executeCollection("kbNodes", "getCategories", {});
21922
21463
  if (result && result.success) {
21923
21464
  logger.info(`[DB] Retrieved ${result.count} categories`);
21924
- sendResponse9(id, {
21465
+ sendResponse8(id, {
21925
21466
  success: true,
21926
21467
  data: {
21927
21468
  categories: result.data,
@@ -21931,13 +21472,13 @@ async function handleGetCategories(id, executeCollection, sendMessage, clientId)
21931
21472
  }, sendMessage, clientId);
21932
21473
  return;
21933
21474
  }
21934
- sendResponse9(id, {
21475
+ sendResponse8(id, {
21935
21476
  success: false,
21936
21477
  error: "Failed to retrieve categories"
21937
21478
  }, sendMessage, clientId);
21938
21479
  } catch (error) {
21939
21480
  logger.error("[DB] Failed to get categories:", error);
21940
- sendResponse9(id, {
21481
+ sendResponse8(id, {
21941
21482
  success: false,
21942
21483
  error: error instanceof Error ? error.message : "Failed to retrieve categories"
21943
21484
  }, sendMessage, clientId);
@@ -21948,7 +21489,7 @@ async function handleGetTags(id, executeCollection, sendMessage, clientId) {
21948
21489
  const result = await executeCollection("kbNodes", "getTags", {});
21949
21490
  if (result && result.success) {
21950
21491
  logger.info(`[DB] Retrieved ${result.count} tags`);
21951
- sendResponse9(id, {
21492
+ sendResponse8(id, {
21952
21493
  success: true,
21953
21494
  data: {
21954
21495
  tags: result.data,
@@ -21958,19 +21499,19 @@ async function handleGetTags(id, executeCollection, sendMessage, clientId) {
21958
21499
  }, sendMessage, clientId);
21959
21500
  return;
21960
21501
  }
21961
- sendResponse9(id, {
21502
+ sendResponse8(id, {
21962
21503
  success: false,
21963
21504
  error: "Failed to retrieve tags"
21964
21505
  }, sendMessage, clientId);
21965
21506
  } catch (error) {
21966
21507
  logger.error("[DB] Failed to get tags:", error);
21967
- sendResponse9(id, {
21508
+ sendResponse8(id, {
21968
21509
  success: false,
21969
21510
  error: error instanceof Error ? error.message : "Failed to retrieve tags"
21970
21511
  }, sendMessage, clientId);
21971
21512
  }
21972
21513
  }
21973
- function sendResponse9(id, res, sendMessage, clientId) {
21514
+ function sendResponse8(id, res, sendMessage, clientId) {
21974
21515
  const response = {
21975
21516
  id: id || "unknown",
21976
21517
  type: "KB_NODES_RES",
@@ -22044,14 +21585,14 @@ async function handleMenusRequest(data, collections, sendMessage) {
22044
21585
  await handleReorder(id, items, executeCollection, sendMessage, from.id);
22045
21586
  break;
22046
21587
  default:
22047
- sendResponse10(id, {
21588
+ sendResponse9(id, {
22048
21589
  success: false,
22049
21590
  error: `Unknown operation: ${operation}`
22050
21591
  }, sendMessage, from.id);
22051
21592
  }
22052
21593
  } catch (error) {
22053
21594
  logger.error("Failed to handle menus request:", error);
22054
- sendResponse10(null, {
21595
+ sendResponse9(null, {
22055
21596
  success: false,
22056
21597
  error: error instanceof Error ? error.message : "Unknown error occurred"
22057
21598
  }, sendMessage);
@@ -22059,14 +21600,14 @@ async function handleMenusRequest(data, collections, sendMessage) {
22059
21600
  }
22060
21601
  async function handleCreate8(id, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, clientId) {
22061
21602
  if (!name) {
22062
- sendResponse10(id, {
21603
+ sendResponse9(id, {
22063
21604
  success: false,
22064
21605
  error: "name is required"
22065
21606
  }, sendMessage, clientId);
22066
21607
  return;
22067
21608
  }
22068
21609
  if (!componentName) {
22069
- sendResponse10(id, {
21610
+ sendResponse9(id, {
22070
21611
  success: false,
22071
21612
  error: "componentName is required"
22072
21613
  }, sendMessage, clientId);
@@ -22083,14 +21624,14 @@ async function handleCreate8(id, name, componentName, icon, userMessage, parentI
22083
21624
  props,
22084
21625
  isActive
22085
21626
  });
22086
- sendResponse10(id, {
21627
+ sendResponse9(id, {
22087
21628
  success: true,
22088
21629
  data: result.data,
22089
21630
  message: "Menu created successfully"
22090
21631
  }, sendMessage, clientId);
22091
21632
  logger.info(`Menu created: ID ${result.data?.id}`);
22092
21633
  } catch (error) {
22093
- sendResponse10(id, {
21634
+ sendResponse9(id, {
22094
21635
  success: false,
22095
21636
  error: error instanceof Error ? error.message : "Failed to create menu"
22096
21637
  }, sendMessage, clientId);
@@ -22098,7 +21639,7 @@ async function handleCreate8(id, name, componentName, icon, userMessage, parentI
22098
21639
  }
22099
21640
  async function handleUpdate8(id, menuId, name, componentName, icon, userMessage, parentId, sortOrder, props, isActive, executeCollection, sendMessage, clientId) {
22100
21641
  if (!menuId) {
22101
- sendResponse10(id, {
21642
+ sendResponse9(id, {
22102
21643
  success: false,
22103
21644
  error: "Menu ID is required"
22104
21645
  }, sendMessage, clientId);
@@ -22116,14 +21657,14 @@ async function handleUpdate8(id, menuId, name, componentName, icon, userMessage,
22116
21657
  props,
22117
21658
  isActive
22118
21659
  });
22119
- sendResponse10(id, {
21660
+ sendResponse9(id, {
22120
21661
  success: true,
22121
21662
  data: result.data,
22122
21663
  message: "Menu updated successfully"
22123
21664
  }, sendMessage, clientId);
22124
21665
  logger.info(`Menu updated: ID ${menuId}`);
22125
21666
  } catch (error) {
22126
- sendResponse10(id, {
21667
+ sendResponse9(id, {
22127
21668
  success: false,
22128
21669
  error: error instanceof Error ? error.message : "Failed to update menu"
22129
21670
  }, sendMessage, clientId);
@@ -22131,7 +21672,7 @@ async function handleUpdate8(id, menuId, name, componentName, icon, userMessage,
22131
21672
  }
22132
21673
  async function handleDelete8(id, menuId, executeCollection, sendMessage, clientId) {
22133
21674
  if (!menuId) {
22134
- sendResponse10(id, {
21675
+ sendResponse9(id, {
22135
21676
  success: false,
22136
21677
  error: "Menu ID is required"
22137
21678
  }, sendMessage, clientId);
@@ -22139,14 +21680,14 @@ async function handleDelete8(id, menuId, executeCollection, sendMessage, clientI
22139
21680
  }
22140
21681
  try {
22141
21682
  const result = await executeCollection("menus", "delete", { id: menuId });
22142
- sendResponse10(id, {
21683
+ sendResponse9(id, {
22143
21684
  success: true,
22144
21685
  data: result.data,
22145
21686
  message: "Menu deleted successfully"
22146
21687
  }, sendMessage, clientId);
22147
21688
  logger.info(`Menu deleted: ID ${menuId}`);
22148
21689
  } catch (error) {
22149
- sendResponse10(id, {
21690
+ sendResponse9(id, {
22150
21691
  success: false,
22151
21692
  error: error instanceof Error ? error.message : "Failed to delete menu"
22152
21693
  }, sendMessage, clientId);
@@ -22155,7 +21696,7 @@ async function handleDelete8(id, menuId, executeCollection, sendMessage, clientI
22155
21696
  async function handleGetAll8(id, executeCollection, sendMessage, clientId) {
22156
21697
  try {
22157
21698
  const result = await executeCollection("menus", "getAll", {});
22158
- sendResponse10(id, {
21699
+ sendResponse9(id, {
22159
21700
  success: true,
22160
21701
  data: result.data,
22161
21702
  count: result.count,
@@ -22163,7 +21704,7 @@ async function handleGetAll8(id, executeCollection, sendMessage, clientId) {
22163
21704
  }, sendMessage, clientId);
22164
21705
  logger.info(`Retrieved all menus (count: ${result.count})`);
22165
21706
  } catch (error) {
22166
- sendResponse10(id, {
21707
+ sendResponse9(id, {
22167
21708
  success: false,
22168
21709
  error: error instanceof Error ? error.message : "Failed to get menus"
22169
21710
  }, sendMessage, clientId);
@@ -22171,7 +21712,7 @@ async function handleGetAll8(id, executeCollection, sendMessage, clientId) {
22171
21712
  }
22172
21713
  async function handleGetOne8(id, menuId, executeCollection, sendMessage, clientId) {
22173
21714
  if (!menuId) {
22174
- sendResponse10(id, {
21715
+ sendResponse9(id, {
22175
21716
  success: false,
22176
21717
  error: "Menu ID is required"
22177
21718
  }, sendMessage, clientId);
@@ -22179,14 +21720,14 @@ async function handleGetOne8(id, menuId, executeCollection, sendMessage, clientI
22179
21720
  }
22180
21721
  try {
22181
21722
  const result = await executeCollection("menus", "getOne", { id: menuId });
22182
- sendResponse10(id, {
21723
+ sendResponse9(id, {
22183
21724
  success: true,
22184
21725
  data: result.data,
22185
21726
  message: `Retrieved menu ID ${menuId}`
22186
21727
  }, sendMessage, clientId);
22187
21728
  logger.info(`Retrieved menu: ID ${menuId}`);
22188
21729
  } catch (error) {
22189
- sendResponse10(id, {
21730
+ sendResponse9(id, {
22190
21731
  success: false,
22191
21732
  error: error instanceof Error ? error.message : "Failed to get menu"
22192
21733
  }, sendMessage, clientId);
@@ -22195,7 +21736,7 @@ async function handleGetOne8(id, menuId, executeCollection, sendMessage, clientI
22195
21736
  async function handleGetRootMenus(id, executeCollection, sendMessage, clientId) {
22196
21737
  try {
22197
21738
  const result = await executeCollection("menus", "getRootMenus", {});
22198
- sendResponse10(id, {
21739
+ sendResponse9(id, {
22199
21740
  success: true,
22200
21741
  data: result.data,
22201
21742
  count: result.count,
@@ -22203,7 +21744,7 @@ async function handleGetRootMenus(id, executeCollection, sendMessage, clientId)
22203
21744
  }, sendMessage, clientId);
22204
21745
  logger.info(`Retrieved root menus (count: ${result.count})`);
22205
21746
  } catch (error) {
22206
- sendResponse10(id, {
21747
+ sendResponse9(id, {
22207
21748
  success: false,
22208
21749
  error: error instanceof Error ? error.message : "Failed to get root menus"
22209
21750
  }, sendMessage, clientId);
@@ -22211,7 +21752,7 @@ async function handleGetRootMenus(id, executeCollection, sendMessage, clientId)
22211
21752
  }
22212
21753
  async function handleGetChildMenus(id, parentId, executeCollection, sendMessage, clientId) {
22213
21754
  if (parentId === void 0 || parentId === null) {
22214
- sendResponse10(id, {
21755
+ sendResponse9(id, {
22215
21756
  success: false,
22216
21757
  error: "parentId is required"
22217
21758
  }, sendMessage, clientId);
@@ -22219,7 +21760,7 @@ async function handleGetChildMenus(id, parentId, executeCollection, sendMessage,
22219
21760
  }
22220
21761
  try {
22221
21762
  const result = await executeCollection("menus", "getChildMenus", { parentId });
22222
- sendResponse10(id, {
21763
+ sendResponse9(id, {
22223
21764
  success: true,
22224
21765
  data: result.data,
22225
21766
  count: result.count,
@@ -22227,7 +21768,7 @@ async function handleGetChildMenus(id, parentId, executeCollection, sendMessage,
22227
21768
  }, sendMessage, clientId);
22228
21769
  logger.info(`Retrieved child menus for parent ${parentId} (count: ${result.count})`);
22229
21770
  } catch (error) {
22230
- sendResponse10(id, {
21771
+ sendResponse9(id, {
22231
21772
  success: false,
22232
21773
  error: error instanceof Error ? error.message : "Failed to get child menus"
22233
21774
  }, sendMessage, clientId);
@@ -22236,7 +21777,7 @@ async function handleGetChildMenus(id, parentId, executeCollection, sendMessage,
22236
21777
  async function handleGetHierarchy(id, executeCollection, sendMessage, clientId) {
22237
21778
  try {
22238
21779
  const result = await executeCollection("menus", "getHierarchy", {});
22239
- sendResponse10(id, {
21780
+ sendResponse9(id, {
22240
21781
  success: true,
22241
21782
  data: result.data,
22242
21783
  count: result.count,
@@ -22244,7 +21785,7 @@ async function handleGetHierarchy(id, executeCollection, sendMessage, clientId)
22244
21785
  }, sendMessage, clientId);
22245
21786
  logger.info(`Retrieved menus hierarchy (root count: ${result.count})`);
22246
21787
  } catch (error) {
22247
- sendResponse10(id, {
21788
+ sendResponse9(id, {
22248
21789
  success: false,
22249
21790
  error: error instanceof Error ? error.message : "Failed to get menus hierarchy"
22250
21791
  }, sendMessage, clientId);
@@ -22257,7 +21798,7 @@ async function handleQuery7(id, filters, limit, sort, executeCollection, sendMes
22257
21798
  limit,
22258
21799
  sort
22259
21800
  });
22260
- sendResponse10(id, {
21801
+ sendResponse9(id, {
22261
21802
  success: true,
22262
21803
  data: result.data,
22263
21804
  count: result.count,
@@ -22265,7 +21806,7 @@ async function handleQuery7(id, filters, limit, sort, executeCollection, sendMes
22265
21806
  }, sendMessage, clientId);
22266
21807
  logger.info(`Query returned ${result.count} menus`);
22267
21808
  } catch (error) {
22268
- sendResponse10(id, {
21809
+ sendResponse9(id, {
22269
21810
  success: false,
22270
21811
  error: error instanceof Error ? error.message : "Failed to query menus"
22271
21812
  }, sendMessage, clientId);
@@ -22273,7 +21814,7 @@ async function handleQuery7(id, filters, limit, sort, executeCollection, sendMes
22273
21814
  }
22274
21815
  async function handleReorder(id, items, executeCollection, sendMessage, clientId) {
22275
21816
  if (!items || !Array.isArray(items) || items.length === 0) {
22276
- sendResponse10(id, {
21817
+ sendResponse9(id, {
22277
21818
  success: false,
22278
21819
  error: "items array is required"
22279
21820
  }, sendMessage, clientId);
@@ -22281,20 +21822,20 @@ async function handleReorder(id, items, executeCollection, sendMessage, clientId
22281
21822
  }
22282
21823
  try {
22283
21824
  const result = await executeCollection("menus", "reorder", { items });
22284
- sendResponse10(id, {
21825
+ sendResponse9(id, {
22285
21826
  success: true,
22286
21827
  data: result.data,
22287
21828
  message: `Reordered ${items.length} menus successfully`
22288
21829
  }, sendMessage, clientId);
22289
21830
  logger.info(`Reordered ${items.length} menus`);
22290
21831
  } catch (error) {
22291
- sendResponse10(id, {
21832
+ sendResponse9(id, {
22292
21833
  success: false,
22293
21834
  error: error instanceof Error ? error.message : "Failed to reorder menus"
22294
21835
  }, sendMessage, clientId);
22295
21836
  }
22296
21837
  }
22297
- function sendResponse10(id, res, sendMessage, clientId) {
21838
+ function sendResponse9(id, res, sendMessage, clientId) {
22298
21839
  const response = {
22299
21840
  id: id || "unknown",
22300
21841
  type: "MENUS_RES",
@@ -24063,13 +23604,14 @@ async function runCodingAgent(agentId, options = {}) {
24063
23604
  const policy = def.session ?? {};
24064
23605
  const persistentWorkspace = policy.workspace === "persistent";
24065
23606
  const persistentSession = policy.scope === "persistent";
23607
+ const runAsJob = !(options.chat === true && def.mode === "task");
24066
23608
  const { key: scopeKey, dirName } = resolveScope(def, { userId: options.userId, threadId: options.threadId });
24067
23609
  const scopeDir = path9.join(agentDir, dirName);
24068
23610
  const dir = options.workspaceDir || (persistentWorkspace ? scopeDir : path9.join(scopeDir, "runs", runId));
24069
23611
  fs8.mkdirSync(dir, { recursive: true });
24070
23612
  if (persistentWorkspace && !options.workspaceDir) {
24071
23613
  fs8.mkdirSync(path9.join(dir, "memory"), { recursive: true });
24072
- await clearTransient(dir);
23614
+ if (runAsJob) await clearTransient(dir);
24073
23615
  }
24074
23616
  const lockKey = persistentWorkspace || persistentSession ? `${def.id}:${scopeKey}` : `dir:${dir}`;
24075
23617
  if (inFlight.has(lockKey)) {
@@ -24124,10 +23666,12 @@ async function runCodingAgent(agentId, options = {}) {
24124
23666
  };
24125
23667
  try {
24126
23668
  await installInstructions(def, ws);
24127
- if (def.prepare) await def.prepare(ws, input, ctx);
24128
- const outputPath = def.output ? ws.pathTo(def.output.file) : void 0;
23669
+ if (def.prepare && runAsJob) await def.prepare(ws, input, ctx);
23670
+ const outputPath = runAsJob && def.output ? ws.pathTo(def.output.file) : void 0;
24129
23671
  if (outputPath) await fsp.rm(outputPath, { force: true });
24130
- 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.");
23672
+ const prompt = options.prompt ?? // buildPrompt may read what prepare() wrote, so it is only asked when
23673
+ // prepare() actually ran.
23674
+ (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.");
24131
23675
  const tools = { ...cfg.sharedTools ?? {}, ...def.tools ?? {} };
24132
23676
  const session = createCodingAgentSession(def.harness || cfg.harness, {
24133
23677
  cwd: dir,
@@ -24178,7 +23722,7 @@ async function runCodingAgent(agentId, options = {}) {
24178
23722
  return record;
24179
23723
  }
24180
23724
  const successStatus = result.status === "early" ? "early" : "completed";
24181
- if (!def.output) {
23725
+ if (!def.output || !runAsJob) {
24182
23726
  record.status = successStatus;
24183
23727
  return record;
24184
23728
  }
@@ -24207,7 +23751,7 @@ async function runCodingAgent(agentId, options = {}) {
24207
23751
  } finally {
24208
23752
  inFlight.delete(lockKey);
24209
23753
  logger.info(
24210
- `[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}"` : "")
23754
+ `[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}"` : "")
24211
23755
  );
24212
23756
  if (!options.workspaceDir && !persistentWorkspace) await pruneRuns(path9.join(scopeDir, "runs"), cfg.keepRuns);
24213
23757
  }
@@ -24321,15 +23865,30 @@ console.log(${JSON.stringify(JSON.stringify(opts.sources, null, 2))});
24321
23865
  // src/codingAgent/triggers.ts
24322
23866
  import * as fs10 from "fs";
24323
23867
  import * as path10 from "path";
23868
+ var EVENT_BURST_CAP = 200;
23869
+ var capEvents = (events) => events.length > EVENT_BURST_CAP ? events.slice(-EVENT_BURST_CAP) : events;
24324
23870
  function statePath2(agentId) {
24325
23871
  return path10.join(getCodingAgentsConfig().runtimeDir, agentId, "_triggers.json");
24326
23872
  }
24327
23873
  function loadTriggerState(agentId) {
23874
+ let raw;
24328
23875
  try {
24329
- return JSON.parse(fs10.readFileSync(statePath2(agentId), "utf-8"));
23876
+ raw = JSON.parse(fs10.readFileSync(statePath2(agentId), "utf-8"));
24330
23877
  } catch {
24331
- return { counts: {} };
23878
+ return { counts: {}, pending: {} };
23879
+ }
23880
+ const counts = {};
23881
+ for (const [name, value] of Object.entries(raw?.counts ?? {})) {
23882
+ if (Array.isArray(value)) counts[name] = value;
23883
+ else if (typeof value === "number" && value > 0) counts[name] = Array.from({ length: value }, () => ({ name }));
23884
+ }
23885
+ const pending = {};
23886
+ if (raw?.pending && typeof raw.pending === "object" && !Array.isArray(raw.pending)) {
23887
+ for (const [key, value] of Object.entries(raw.pending)) {
23888
+ if (Array.isArray(value)) pending[key] = value;
23889
+ }
24332
23890
  }
23891
+ return { counts, pending, lastRunAt: raw?.lastRunAt };
24333
23892
  }
24334
23893
  function saveTriggerState(agentId, state) {
24335
23894
  try {
@@ -24343,6 +23902,7 @@ function saveTriggerState(agentId, state) {
24343
23902
  var asArray = (t) => !t ? [] : Array.isArray(t) ? t : [t];
24344
23903
  var intervals = /* @__PURE__ */ new Map();
24345
23904
  var debounces = /* @__PURE__ */ new Map();
23905
+ var bursts = /* @__PURE__ */ new Map();
24346
23906
  var firing = /* @__PURE__ */ new Set();
24347
23907
  var listeners = [];
24348
23908
  function onAgentRun(fn) {
@@ -24352,21 +23912,38 @@ function onAgentRun(fn) {
24352
23912
  if (i >= 0) listeners.splice(i, 1);
24353
23913
  };
24354
23914
  }
24355
- async function fire(agentId, reason, payload) {
23915
+ function inputFor(trigger, events) {
23916
+ const build = trigger?.buildInput;
23917
+ const lastPayload = () => events.length ? events[events.length - 1].payload : void 0;
23918
+ if (!build) return lastPayload();
23919
+ try {
23920
+ return build(events);
23921
+ } catch (err) {
23922
+ logger.error(`[CodingAgent] buildInput threw, falling back to the last payload: ${err?.message ?? err}`);
23923
+ return lastPayload();
23924
+ }
23925
+ }
23926
+ async function fire(agentId, triggerIndex, reason, events = []) {
24356
23927
  if (firing.has(agentId)) {
24357
- const st = loadTriggerState(agentId);
24358
- saveTriggerState(agentId, { ...st, pending: true });
24359
- logger.info(`[CodingAgent:${agentId}] ${reason} arrived mid-run \u2014 queued`);
23928
+ const st2 = loadTriggerState(agentId);
23929
+ const key = String(triggerIndex);
23930
+ saveTriggerState(agentId, {
23931
+ ...st2,
23932
+ pending: { ...st2.pending, [key]: capEvents([...st2.pending[key] ?? [], ...events]) }
23933
+ });
23934
+ logger.info(`[CodingAgent:${agentId}] ${reason} arrived mid-run \u2014 queued (${events.length} event(s))`);
24360
23935
  return;
24361
23936
  }
24362
23937
  firing.add(agentId);
24363
23938
  try {
23939
+ const trigger = asArray(getCodingAgent(agentId)?.trigger)[triggerIndex];
23940
+ const input = inputFor(trigger, events);
24364
23941
  logger.info(`[CodingAgent:${agentId}] triggered by ${reason}`);
24365
- const record = await runCodingAgent(agentId, { input: payload });
24366
- saveTriggerState(agentId, { ...loadTriggerState(agentId), lastRunAt: (/* @__PURE__ */ new Date()).toISOString(), pending: false });
23942
+ const record = await runCodingAgent(agentId, { input });
23943
+ saveTriggerState(agentId, { ...loadTriggerState(agentId), lastRunAt: (/* @__PURE__ */ new Date()).toISOString() });
24367
23944
  for (const fn of listeners) {
24368
23945
  try {
24369
- fn(record, { agentId, reason, payload });
23946
+ fn(record, { agentId, reason, events, input });
24370
23947
  } catch {
24371
23948
  }
24372
23949
  }
@@ -24374,9 +23951,13 @@ async function fire(agentId, reason, payload) {
24374
23951
  logger.error(`[CodingAgent:${agentId}] trigger run failed: ${err?.message ?? err}`);
24375
23952
  } finally {
24376
23953
  firing.delete(agentId);
24377
- if (loadTriggerState(agentId).pending) {
24378
- saveTriggerState(agentId, { ...loadTriggerState(agentId), pending: false });
24379
- void fire(agentId, "queued work from during the last run");
23954
+ }
23955
+ const st = loadTriggerState(agentId);
23956
+ const queued = Object.entries(st.pending);
23957
+ if (queued.length) {
23958
+ saveTriggerState(agentId, { ...st, pending: {} });
23959
+ for (const [index, evs] of queued) {
23960
+ await fire(agentId, Number(index), "queued work from during the last run", evs);
24380
23961
  }
24381
23962
  }
24382
23963
  }
@@ -24384,45 +23965,49 @@ function emitAgentEvent(event, payload) {
24384
23965
  for (const { id } of listCodingAgents()) {
24385
23966
  const def = getCodingAgent(id);
24386
23967
  if (!def) continue;
24387
- for (const trigger of asArray(def.trigger)) {
23968
+ asArray(def.trigger).forEach((trigger, index) => {
24388
23969
  if (trigger.type === "event") {
24389
23970
  const names = Array.isArray(trigger.on) ? trigger.on : [trigger.on];
24390
- if (!names.includes(event)) continue;
23971
+ if (!names.includes(event)) return;
23972
+ const arrived = { name: event, payload };
24391
23973
  if (!trigger.debounceMs) {
24392
- void fire(id, `event ${event}`, payload);
24393
- continue;
23974
+ void fire(id, index, `event ${event}`, [arrived]);
23975
+ return;
24394
23976
  }
24395
- const key = `${id}:${event}`;
23977
+ const key = `${id}:${index}`;
23978
+ bursts.set(key, capEvents([...bursts.get(key) ?? [], arrived]));
24396
23979
  const existing = debounces.get(key);
24397
23980
  if (existing) clearTimeout(existing);
24398
23981
  debounces.set(key, setTimeout(() => {
24399
23982
  debounces.delete(key);
24400
- void fire(id, `event ${event} (settled)`, payload);
23983
+ const batch = bursts.get(key) ?? [];
23984
+ bursts.delete(key);
23985
+ void fire(id, index, `event ${event} (settled, ${batch.length} event(s))`, batch);
24401
23986
  }, trigger.debounceMs));
24402
- continue;
23987
+ return;
24403
23988
  }
24404
23989
  if (trigger.type === "count" && trigger.on === event) {
24405
23990
  const state = loadTriggerState(id);
24406
- const next = (state.counts[event] ?? 0) + 1;
24407
- if (next < trigger.every) {
24408
- saveTriggerState(id, { ...state, counts: { ...state.counts, [event]: next } });
24409
- continue;
23991
+ const banked = capEvents([...state.counts[event] ?? [], { name: event, payload }]);
23992
+ if (banked.length < trigger.every) {
23993
+ saveTriggerState(id, { ...state, counts: { ...state.counts, [event]: banked } });
23994
+ return;
24410
23995
  }
24411
- saveTriggerState(id, { ...state, counts: { ...state.counts, [event]: 0 } });
24412
- void fire(id, `${trigger.every}x ${event}`, payload);
23996
+ saveTriggerState(id, { ...state, counts: { ...state.counts, [event]: [] } });
23997
+ void fire(id, index, `${trigger.every}x ${event}`, banked);
24413
23998
  }
24414
- }
23999
+ });
24415
24000
  }
24416
24001
  }
24417
24002
  function startAgentTriggers() {
24418
24003
  stopAgentTriggers();
24419
24004
  for (const { id } of listCodingAgents()) {
24420
24005
  const def = getCodingAgent(id);
24421
- for (const trigger of asArray(def?.trigger)) {
24422
- if (trigger.type !== "interval") continue;
24423
- intervals.set(id, setInterval(() => void fire(id, `interval ${trigger.everyMs}ms`), trigger.everyMs));
24006
+ asArray(def?.trigger).forEach((trigger, index) => {
24007
+ if (trigger.type !== "interval") return;
24008
+ intervals.set(`${id}:${index}`, setInterval(() => void fire(id, index, `interval ${trigger.everyMs}ms`), trigger.everyMs));
24424
24009
  logger.info(`[CodingAgent:${id}] interval trigger every ${trigger.everyMs}ms`);
24425
- }
24010
+ });
24426
24011
  }
24427
24012
  }
24428
24013
  function stopAgentTriggers() {
@@ -24430,6 +24015,7 @@ function stopAgentTriggers() {
24430
24015
  intervals.clear();
24431
24016
  for (const t of debounces.values()) clearTimeout(t);
24432
24017
  debounces.clear();
24018
+ bursts.clear();
24433
24019
  }
24434
24020
  function describeTriggers() {
24435
24021
  return listCodingAgents().map(({ id }) => {
@@ -24446,6 +24032,9 @@ function describeTriggers() {
24446
24032
  // src/codingAgent/collection.ts
24447
24033
  import * as fs11 from "fs";
24448
24034
  import * as path11 from "path";
24035
+ function isChattable(agent) {
24036
+ return agent.mode !== "task";
24037
+ }
24449
24038
  function registerCodingAgentCollection(sdk, config2 = {}) {
24450
24039
  const runtimeDir = config2.runtimeDir || process.env.CODING_AGENT_RUNTIME_DIR || path11.join(process.cwd(), ".coding-agent-runtime");
24451
24040
  const defaultHarness = config2.harness || process.env.CODING_AGENT_HARNESS || "codex";
@@ -24469,7 +24058,19 @@ function registerCodingAgentCollection(sdk, config2 = {}) {
24469
24058
  error: `Unknown agent "${agentId}". Available: ${listCodingAgents().map((a) => a.id).join(", ") || "(none registered)"}`
24470
24059
  };
24471
24060
  }
24061
+ if (!isChattable(def)) {
24062
+ return {
24063
+ success: false,
24064
+ error: `${def.title} runs as a scheduled task and is not available for chat.`
24065
+ };
24066
+ }
24472
24067
  const record = await runCodingAgent(agentId, {
24068
+ // chat:true is what stops a typed message being treated as a job. A
24069
+ // task agent's prepare()/output/apply() set work up and consume it, so
24070
+ // without this every conversational turn failed for not writing a
24071
+ // deliverable nobody asked for — and, for a batching agent, quietly ate
24072
+ // a batch of work on the way.
24073
+ chat: true,
24473
24074
  prompt,
24474
24075
  projectId,
24475
24076
  userId,
@@ -24489,7 +24090,10 @@ function registerCodingAgentCollection(sdk, config2 = {}) {
24489
24090
  sessionId: record.sessionId,
24490
24091
  ...record.output !== void 0 ? { output: record.output } : {},
24491
24092
  ...record.applied ? { applied: record.applied } : {},
24492
- ...record.error ? { error: record.error } : {}
24093
+ // A project-scoped agent serialises its runs, so a turn sent while it
24094
+ // is working is a normal outcome, not a fault. Say so in words a
24095
+ // person can act on.
24096
+ ...record.status === "skipped" ? { error: `${def.title} is in the middle of a run \u2014 try again in a moment.` } : record.error ? { error: record.error } : {}
24493
24097
  };
24494
24098
  }
24495
24099
  const cwd = path11.join(runtimeDir, "threads", threadId);
@@ -24536,7 +24140,10 @@ function registerCodingAgentCollection(sdk, config2 = {}) {
24536
24140
  }
24537
24141
  return { success: true };
24538
24142
  });
24539
- sdk.addCollection("coding-agent", "list", async () => ({ success: true, agents: listCodingAgents() }));
24143
+ sdk.addCollection("coding-agent", "list", async () => ({
24144
+ success: true,
24145
+ agents: listCodingAgents().map((a) => ({ ...a, chattable: isChattable(a) }))
24146
+ }));
24540
24147
  console.log(`\u2713 coding-agent collection registered (harness: ${defaultHarness})`);
24541
24148
  }
24542
24149
 
@@ -27670,11 +27277,6 @@ var SuperatomSDK = class {
27670
27277
  logger.error("Failed to handle user prompt abort request:", error);
27671
27278
  }
27672
27279
  break;
27673
- case "ACTIONS":
27674
- handleActionsRequest(parsed, (msg) => this.send(msg), this.anthropicApiKey, this.groqApiKey, this.geminiApiKey, this.openaiApiKey, this.llmProviders).catch((error) => {
27675
- logger.error("Failed to handle actions request:", error);
27676
- });
27677
- break;
27678
27280
  case "USER_PROMPT_SUGGESTIONS_REQ":
27679
27281
  handleUserPromptSuggestions(parsed, this.components, (msg) => this.send(msg), this.collections).catch((error) => {
27680
27282
  logger.error("Failed to handle user prompt suggestions request:", error);