@superatomai/sdk-node 0.0.65-dsp → 0.0.66-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.d.mts CHANGED
@@ -1257,6 +1257,10 @@ interface DBUIBlock {
1257
1257
  name?: string;
1258
1258
  columns?: string[];
1259
1259
  };
1260
+ /** Progress updates written while this answer was produced, in order. */
1261
+ narration?: NarrationUpdate[];
1262
+ /** How long the answer took, in milliseconds. */
1263
+ durationMs?: number;
1260
1264
  }
1261
1265
 
1262
1266
  /**
@@ -2113,14 +2117,49 @@ interface AnswerProviderContext {
2113
2117
  conversationHistory?: string;
2114
2118
  /** Stream user-facing prose. Do NOT stream tool/command output through this. */
2115
2119
  onStream?: (chunk: string) => void;
2120
+ /**
2121
+ * Send one narrator update to the client live, as its OWN message
2122
+ * (USER_PROMPT_NARRATION) — never into the answer stream, so it is not part of
2123
+ * the saved answer text. Every response mode. The saved copy travels
2124
+ * separately, as `data.narration`.
2125
+ */
2126
+ onNarration?: (update: {
2127
+ elapsedMs: number;
2128
+ text: string;
2129
+ }) => void;
2116
2130
  signal?: AbortSignal;
2117
2131
  }
2132
+ /**
2133
+ * One narrator tick while an answer was being produced: what the narrator was
2134
+ * given, and what it wrote. Returned as `data.narration` (an array, in order)
2135
+ * and saved with the answer as `response.narration`, unchanged. A UI shows the
2136
+ * `shown` entries; the rest are kept for judging the narrator against its input.
2137
+ */
2138
+ interface NarrationUpdate {
2139
+ /** Milliseconds since the question arrived. */
2140
+ elapsedMs: number;
2141
+ /** shown | skipped | dropped (refused by an output filter) | failed. */
2142
+ status?: 'shown' | 'skipped' | 'dropped' | 'failed';
2143
+ /** The update itself; null when nothing was shown. */
2144
+ text: string | null;
2145
+ /** Why an update was dropped or failed. */
2146
+ reason?: string;
2147
+ /**
2148
+ * What the narrator was given for this tick — the agent's notes, commands
2149
+ * with their output, queries with SQL and sample rows. Shape is the
2150
+ * deployment's; the SDK stores it as-is.
2151
+ */
2152
+ activity?: unknown[];
2153
+ }
2118
2154
  /**
2119
2155
  * An alternative to the built-in MainAgent/SourceAgent flow.
2120
2156
  *
2121
2157
  * Returns the same T_RESPONSE the built-in flow does, so everything downstream —
2122
2158
  * the UIBlock, streaming, abort, the conversation save, component rendering — is
2123
2159
  * unchanged and the two flows stay comparable.
2160
+ *
2161
+ * `data.narration` (NarrationUpdate[]) is optional and saved with the answer on
2162
+ * every outcome — success, error and abort — so return it on each of them.
2124
2163
  */
2125
2164
  type AnswerProvider = (ctx: AnswerProviderContext) => Promise<T_RESPONSE>;
2126
2165
  interface SuperatomSDKConfig {
@@ -3651,6 +3690,18 @@ declare class UIBlock {
3651
3690
  setTextResponse(textResponse: string | null): void;
3652
3691
  /** The program-generated half of the answer — see setProgramAnswer. */
3653
3692
  programAnswer?: string | null;
3693
+ /** Progress updates written while the answer was produced — see setNarration. */
3694
+ narration?: NarrationUpdate[] | null;
3695
+ /**
3696
+ * Progress updates a narrator wrote while this answer was being produced,
3697
+ * in order. Not part of the answer text: kept beside it so it is saved with
3698
+ * the answer it describes, and can be shown or left out on its own.
3699
+ */
3700
+ setNarration(updates: NarrationUpdate[] | null): void;
3701
+ getNarration(): NarrationUpdate[] | null;
3702
+ /** How long the answer took, from the request arriving to the flow returning. */
3703
+ durationMs?: number | null;
3704
+ setDurationMs(ms: number | null): void;
3654
3705
  /**
3655
3706
  * Bind this block to the script recipe that produced its answer.
3656
3707
  */
@@ -6089,4 +6140,4 @@ declare class SuperatomSDK {
6089
6140
  getConversationSimilarityThreshold(): number;
6090
6141
  }
6091
6142
 
6092
- export { ALL_COLUMN_KEYS, ANSWER_COMPONENT_NAMES, type AgentConfig, type AgentEvent, type AgentResponse, type AgentRunContext, type AgentRunHandlers, type AgentRunRecord, type AgentRunResult, type AgentTrigger, type AgentUsage, type AnswerProvider, type AnswerProviderContext, type ApplySummary, BM25L, type BM25LOptions, type BaseLLMConfig, type BuildTriggerInput, CATEGORY_KEYS, CONTEXT_CONFIG, type CapturedLog, CleanupService, type CodexSessionOptions, type CodingAgentCollectionConfig, type CodingAgentDefinition, type CodingAgentSession, type CodingAgentSessionOptions, type CodingAgentsConfig, type ColInfo, type ColType, type CollectionHandler, type CollectionOperation, type Component, type DBUIBlock, DEFAULT_AGENT_CONFIG, DEFAULT_FMT_CONFIG, type DashboardAgentCollectionConfig, type DatabaseType, type FindingCode, type Fmt, type FmtConfig, type Harness, type HybridSearchOptions, type IncomingMessage, type KbNodesQueryFilters, type KbNodesRequestPayload, LLM, type LLMUsageEntry, type LogLevel, MainAgent, type McpServerSpec, type Message, MissingRequestContextError, type ModelStrategy, NUMERIC_KEYS, type OutputContract, type OutputField, type OutputValidator, type Principal, type RequestContext, type RerankedResult, type RowFilter, type RunAgentOptions, STORAGE_CONFIG, type ScriptComponentSpec, ScriptMatcher, type ScriptParameter, type ScriptRecipe, type ScriptRecipeMetaRow, type ScriptRecipeStore, type ScriptResult, ScriptStore, type ScriptStoreOptions, type SelectedWorkflow, type SourcePolicy, type SpecToValidate, SuperatomSDK, type SuperatomSDKConfig, type T_RESPONSE, type TaskType, Thread, ThreadManager, type Tool$1 as Tool, type ToolOutputSchema, type TriggerEvent, type TriggerFireInfo, UIBlock, UILogCollector, type User, UserManager, type UsersData, type ValidationContext, type ValidationFinding, type WorkflowDescriptor, type Workspace, answerCatalogForBinding, answerComponents, anthropicLLM, assertReadOnlySql, bindContext, captureContext, clearContextTokens, contextTokenCount, createCodexSession, createCodingAgentSession, dashboardConversationHistory, dataFingerprint, describeContext, describeTriggers, emitAgentEvent, extractNamedExport, formatFindingsForAgent, geminiLLM, getCodingAgent, getCodingAgentsConfig, getRequestContext, groqLLM, hybridRerank, inferColumns, isUserContext, listCodingAgents, llmUsageLogger, logger, makeFmt, mintContextToken, normalizeScriptBody, onAgentRun, openaiLLM, policiesFromConfig, projectForDatasetBinding, queryCache, registerCodingAgentCollection, registerCodingAgents, registerDashboardAgentCollection, requireRequestContext, rerankChromaResults, rerankConversationResults, resolveContextToken, resolveScriptRecipeStore, revokeContextToken, runAsSystem, runAsUser, runCodingAgent, runScript, runWithContext, runWithMessageIdentity, startAgentTriggers, stopAgentTriggers, userPromptErrorLogger, validateComponentSpec, withCapturedContext, writeBridgeShims };
6143
+ export { ALL_COLUMN_KEYS, ANSWER_COMPONENT_NAMES, type AgentConfig, type AgentEvent, type AgentResponse, type AgentRunContext, type AgentRunHandlers, type AgentRunRecord, type AgentRunResult, type AgentTrigger, type AgentUsage, type AnswerProvider, type AnswerProviderContext, type ApplySummary, BM25L, type BM25LOptions, type BaseLLMConfig, type BuildTriggerInput, CATEGORY_KEYS, CONTEXT_CONFIG, type CapturedLog, CleanupService, type CodexSessionOptions, type CodingAgentCollectionConfig, type CodingAgentDefinition, type CodingAgentSession, type CodingAgentSessionOptions, type CodingAgentsConfig, type ColInfo, type ColType, type CollectionHandler, type CollectionOperation, type Component, type DBUIBlock, DEFAULT_AGENT_CONFIG, DEFAULT_FMT_CONFIG, type DashboardAgentCollectionConfig, type DatabaseType, type FindingCode, type Fmt, type FmtConfig, type Harness, type HybridSearchOptions, type IncomingMessage, type KbNodesQueryFilters, type KbNodesRequestPayload, LLM, type LLMUsageEntry, type LogLevel, MainAgent, type McpServerSpec, type Message, MissingRequestContextError, type ModelStrategy, NUMERIC_KEYS, type NarrationUpdate, type OutputContract, type OutputField, type OutputValidator, type Principal, type RequestContext, type RerankedResult, type RowFilter, type RunAgentOptions, STORAGE_CONFIG, type ScriptComponentSpec, ScriptMatcher, type ScriptParameter, type ScriptRecipe, type ScriptRecipeMetaRow, type ScriptRecipeStore, type ScriptResult, ScriptStore, type ScriptStoreOptions, type SelectedWorkflow, type SourcePolicy, type SpecToValidate, SuperatomSDK, type SuperatomSDKConfig, type T_RESPONSE, type TaskType, Thread, ThreadManager, type Tool$1 as Tool, type ToolOutputSchema, type TriggerEvent, type TriggerFireInfo, UIBlock, UILogCollector, type User, UserManager, type UsersData, type ValidationContext, type ValidationFinding, type WorkflowDescriptor, type Workspace, answerCatalogForBinding, answerComponents, anthropicLLM, assertReadOnlySql, bindContext, captureContext, clearContextTokens, contextTokenCount, createCodexSession, createCodingAgentSession, dashboardConversationHistory, dataFingerprint, describeContext, describeTriggers, emitAgentEvent, extractNamedExport, formatFindingsForAgent, geminiLLM, getCodingAgent, getCodingAgentsConfig, getRequestContext, groqLLM, hybridRerank, inferColumns, isUserContext, listCodingAgents, llmUsageLogger, logger, makeFmt, mintContextToken, normalizeScriptBody, onAgentRun, openaiLLM, policiesFromConfig, projectForDatasetBinding, queryCache, registerCodingAgentCollection, registerCodingAgents, registerDashboardAgentCollection, requireRequestContext, rerankChromaResults, rerankConversationResults, resolveContextToken, resolveScriptRecipeStore, revokeContextToken, runAsSystem, runAsUser, runCodingAgent, runScript, runWithContext, runWithMessageIdentity, startAgentTriggers, stopAgentTriggers, userPromptErrorLogger, validateComponentSpec, withCapturedContext, writeBridgeShims };
package/dist/index.d.ts CHANGED
@@ -1257,6 +1257,10 @@ interface DBUIBlock {
1257
1257
  name?: string;
1258
1258
  columns?: string[];
1259
1259
  };
1260
+ /** Progress updates written while this answer was produced, in order. */
1261
+ narration?: NarrationUpdate[];
1262
+ /** How long the answer took, in milliseconds. */
1263
+ durationMs?: number;
1260
1264
  }
1261
1265
 
1262
1266
  /**
@@ -2113,14 +2117,49 @@ interface AnswerProviderContext {
2113
2117
  conversationHistory?: string;
2114
2118
  /** Stream user-facing prose. Do NOT stream tool/command output through this. */
2115
2119
  onStream?: (chunk: string) => void;
2120
+ /**
2121
+ * Send one narrator update to the client live, as its OWN message
2122
+ * (USER_PROMPT_NARRATION) — never into the answer stream, so it is not part of
2123
+ * the saved answer text. Every response mode. The saved copy travels
2124
+ * separately, as `data.narration`.
2125
+ */
2126
+ onNarration?: (update: {
2127
+ elapsedMs: number;
2128
+ text: string;
2129
+ }) => void;
2116
2130
  signal?: AbortSignal;
2117
2131
  }
2132
+ /**
2133
+ * One narrator tick while an answer was being produced: what the narrator was
2134
+ * given, and what it wrote. Returned as `data.narration` (an array, in order)
2135
+ * and saved with the answer as `response.narration`, unchanged. A UI shows the
2136
+ * `shown` entries; the rest are kept for judging the narrator against its input.
2137
+ */
2138
+ interface NarrationUpdate {
2139
+ /** Milliseconds since the question arrived. */
2140
+ elapsedMs: number;
2141
+ /** shown | skipped | dropped (refused by an output filter) | failed. */
2142
+ status?: 'shown' | 'skipped' | 'dropped' | 'failed';
2143
+ /** The update itself; null when nothing was shown. */
2144
+ text: string | null;
2145
+ /** Why an update was dropped or failed. */
2146
+ reason?: string;
2147
+ /**
2148
+ * What the narrator was given for this tick — the agent's notes, commands
2149
+ * with their output, queries with SQL and sample rows. Shape is the
2150
+ * deployment's; the SDK stores it as-is.
2151
+ */
2152
+ activity?: unknown[];
2153
+ }
2118
2154
  /**
2119
2155
  * An alternative to the built-in MainAgent/SourceAgent flow.
2120
2156
  *
2121
2157
  * Returns the same T_RESPONSE the built-in flow does, so everything downstream —
2122
2158
  * the UIBlock, streaming, abort, the conversation save, component rendering — is
2123
2159
  * unchanged and the two flows stay comparable.
2160
+ *
2161
+ * `data.narration` (NarrationUpdate[]) is optional and saved with the answer on
2162
+ * every outcome — success, error and abort — so return it on each of them.
2124
2163
  */
2125
2164
  type AnswerProvider = (ctx: AnswerProviderContext) => Promise<T_RESPONSE>;
2126
2165
  interface SuperatomSDKConfig {
@@ -3651,6 +3690,18 @@ declare class UIBlock {
3651
3690
  setTextResponse(textResponse: string | null): void;
3652
3691
  /** The program-generated half of the answer — see setProgramAnswer. */
3653
3692
  programAnswer?: string | null;
3693
+ /** Progress updates written while the answer was produced — see setNarration. */
3694
+ narration?: NarrationUpdate[] | null;
3695
+ /**
3696
+ * Progress updates a narrator wrote while this answer was being produced,
3697
+ * in order. Not part of the answer text: kept beside it so it is saved with
3698
+ * the answer it describes, and can be shown or left out on its own.
3699
+ */
3700
+ setNarration(updates: NarrationUpdate[] | null): void;
3701
+ getNarration(): NarrationUpdate[] | null;
3702
+ /** How long the answer took, from the request arriving to the flow returning. */
3703
+ durationMs?: number | null;
3704
+ setDurationMs(ms: number | null): void;
3654
3705
  /**
3655
3706
  * Bind this block to the script recipe that produced its answer.
3656
3707
  */
@@ -6089,4 +6140,4 @@ declare class SuperatomSDK {
6089
6140
  getConversationSimilarityThreshold(): number;
6090
6141
  }
6091
6142
 
6092
- export { ALL_COLUMN_KEYS, ANSWER_COMPONENT_NAMES, type AgentConfig, type AgentEvent, type AgentResponse, type AgentRunContext, type AgentRunHandlers, type AgentRunRecord, type AgentRunResult, type AgentTrigger, type AgentUsage, type AnswerProvider, type AnswerProviderContext, type ApplySummary, BM25L, type BM25LOptions, type BaseLLMConfig, type BuildTriggerInput, CATEGORY_KEYS, CONTEXT_CONFIG, type CapturedLog, CleanupService, type CodexSessionOptions, type CodingAgentCollectionConfig, type CodingAgentDefinition, type CodingAgentSession, type CodingAgentSessionOptions, type CodingAgentsConfig, type ColInfo, type ColType, type CollectionHandler, type CollectionOperation, type Component, type DBUIBlock, DEFAULT_AGENT_CONFIG, DEFAULT_FMT_CONFIG, type DashboardAgentCollectionConfig, type DatabaseType, type FindingCode, type Fmt, type FmtConfig, type Harness, type HybridSearchOptions, type IncomingMessage, type KbNodesQueryFilters, type KbNodesRequestPayload, LLM, type LLMUsageEntry, type LogLevel, MainAgent, type McpServerSpec, type Message, MissingRequestContextError, type ModelStrategy, NUMERIC_KEYS, type OutputContract, type OutputField, type OutputValidator, type Principal, type RequestContext, type RerankedResult, type RowFilter, type RunAgentOptions, STORAGE_CONFIG, type ScriptComponentSpec, ScriptMatcher, type ScriptParameter, type ScriptRecipe, type ScriptRecipeMetaRow, type ScriptRecipeStore, type ScriptResult, ScriptStore, type ScriptStoreOptions, type SelectedWorkflow, type SourcePolicy, type SpecToValidate, SuperatomSDK, type SuperatomSDKConfig, type T_RESPONSE, type TaskType, Thread, ThreadManager, type Tool$1 as Tool, type ToolOutputSchema, type TriggerEvent, type TriggerFireInfo, UIBlock, UILogCollector, type User, UserManager, type UsersData, type ValidationContext, type ValidationFinding, type WorkflowDescriptor, type Workspace, answerCatalogForBinding, answerComponents, anthropicLLM, assertReadOnlySql, bindContext, captureContext, clearContextTokens, contextTokenCount, createCodexSession, createCodingAgentSession, dashboardConversationHistory, dataFingerprint, describeContext, describeTriggers, emitAgentEvent, extractNamedExport, formatFindingsForAgent, geminiLLM, getCodingAgent, getCodingAgentsConfig, getRequestContext, groqLLM, hybridRerank, inferColumns, isUserContext, listCodingAgents, llmUsageLogger, logger, makeFmt, mintContextToken, normalizeScriptBody, onAgentRun, openaiLLM, policiesFromConfig, projectForDatasetBinding, queryCache, registerCodingAgentCollection, registerCodingAgents, registerDashboardAgentCollection, requireRequestContext, rerankChromaResults, rerankConversationResults, resolveContextToken, resolveScriptRecipeStore, revokeContextToken, runAsSystem, runAsUser, runCodingAgent, runScript, runWithContext, runWithMessageIdentity, startAgentTriggers, stopAgentTriggers, userPromptErrorLogger, validateComponentSpec, withCapturedContext, writeBridgeShims };
6143
+ export { ALL_COLUMN_KEYS, ANSWER_COMPONENT_NAMES, type AgentConfig, type AgentEvent, type AgentResponse, type AgentRunContext, type AgentRunHandlers, type AgentRunRecord, type AgentRunResult, type AgentTrigger, type AgentUsage, type AnswerProvider, type AnswerProviderContext, type ApplySummary, BM25L, type BM25LOptions, type BaseLLMConfig, type BuildTriggerInput, CATEGORY_KEYS, CONTEXT_CONFIG, type CapturedLog, CleanupService, type CodexSessionOptions, type CodingAgentCollectionConfig, type CodingAgentDefinition, type CodingAgentSession, type CodingAgentSessionOptions, type CodingAgentsConfig, type ColInfo, type ColType, type CollectionHandler, type CollectionOperation, type Component, type DBUIBlock, DEFAULT_AGENT_CONFIG, DEFAULT_FMT_CONFIG, type DashboardAgentCollectionConfig, type DatabaseType, type FindingCode, type Fmt, type FmtConfig, type Harness, type HybridSearchOptions, type IncomingMessage, type KbNodesQueryFilters, type KbNodesRequestPayload, LLM, type LLMUsageEntry, type LogLevel, MainAgent, type McpServerSpec, type Message, MissingRequestContextError, type ModelStrategy, NUMERIC_KEYS, type NarrationUpdate, type OutputContract, type OutputField, type OutputValidator, type Principal, type RequestContext, type RerankedResult, type RowFilter, type RunAgentOptions, STORAGE_CONFIG, type ScriptComponentSpec, ScriptMatcher, type ScriptParameter, type ScriptRecipe, type ScriptRecipeMetaRow, type ScriptRecipeStore, type ScriptResult, ScriptStore, type ScriptStoreOptions, type SelectedWorkflow, type SourcePolicy, type SpecToValidate, SuperatomSDK, type SuperatomSDKConfig, type T_RESPONSE, type TaskType, Thread, ThreadManager, type Tool$1 as Tool, type ToolOutputSchema, type TriggerEvent, type TriggerFireInfo, UIBlock, UILogCollector, type User, UserManager, type UsersData, type ValidationContext, type ValidationFinding, type WorkflowDescriptor, type Workspace, answerCatalogForBinding, answerComponents, anthropicLLM, assertReadOnlySql, bindContext, captureContext, clearContextTokens, contextTokenCount, createCodexSession, createCodingAgentSession, dashboardConversationHistory, dataFingerprint, describeContext, describeTriggers, emitAgentEvent, extractNamedExport, formatFindingsForAgent, geminiLLM, getCodingAgent, getCodingAgentsConfig, getRequestContext, groqLLM, hybridRerank, inferColumns, isUserContext, listCodingAgents, llmUsageLogger, logger, makeFmt, mintContextToken, normalizeScriptBody, onAgentRun, openaiLLM, policiesFromConfig, projectForDatasetBinding, queryCache, registerCodingAgentCollection, registerCodingAgents, registerDashboardAgentCollection, requireRequestContext, rerankChromaResults, rerankConversationResults, resolveContextToken, resolveScriptRecipeStore, revokeContextToken, runAsSystem, runAsUser, runCodingAgent, runScript, runWithContext, runWithMessageIdentity, startAgentTriggers, stopAgentTriggers, userPromptErrorLogger, validateComponentSpec, withCapturedContext, writeBridgeShims };
package/dist/index.js CHANGED
@@ -1319,6 +1319,20 @@ var UIBlock = class {
1319
1319
  setTextResponse(textResponse) {
1320
1320
  this.textResponse = textResponse;
1321
1321
  }
1322
+ /**
1323
+ * Progress updates a narrator wrote while this answer was being produced,
1324
+ * in order. Not part of the answer text: kept beside it so it is saved with
1325
+ * the answer it describes, and can be shown or left out on its own.
1326
+ */
1327
+ setNarration(updates) {
1328
+ this.narration = updates && updates.length ? updates : null;
1329
+ }
1330
+ getNarration() {
1331
+ return this.narration ?? null;
1332
+ }
1333
+ setDurationMs(ms) {
1334
+ this.durationMs = typeof ms === "number" && Number.isFinite(ms) && ms >= 0 ? Math.round(ms) : null;
1335
+ }
1322
1336
  /**
1323
1337
  * Bind this block to the script recipe that produced its answer.
1324
1338
  */
@@ -1356,7 +1370,9 @@ var UIBlock = class {
1356
1370
  textResponse: this.textResponse,
1357
1371
  createdAt: this.createdAt.toISOString(),
1358
1372
  ...this.scriptBinding ? { scriptBinding: this.scriptBinding } : {},
1359
- ...this.programAnswer ? { programAnswer: this.programAnswer } : {}
1373
+ ...this.programAnswer ? { programAnswer: this.programAnswer } : {},
1374
+ ...this.narration ? { narration: this.narration } : {},
1375
+ ...this.durationMs != null ? { durationMs: this.durationMs } : {}
1360
1376
  };
1361
1377
  }
1362
1378
  };
@@ -19210,7 +19226,10 @@ function transformUIBlockForDB(uiblock, userPrompt, uiBlockId) {
19210
19226
  ...uiblock?.scriptBinding?.recipeId ? { scriptBinding: uiblock.scriptBinding } : {},
19211
19227
  // The program-generated half, stored verbatim so a reload can regenerate
19212
19228
  // just that portion of `analysis` and leave the narration alone.
19213
- ...uiblock?.programAnswer ? { programAnswer: uiblock.programAnswer } : {}
19229
+ ...uiblock?.programAnswer ? { programAnswer: uiblock.programAnswer } : {},
19230
+ // Beside the answer, not in it: `analysis` stays the answer text alone.
19231
+ ...Array.isArray(uiblock?.narration) && uiblock.narration.length ? { narration: uiblock.narration } : {},
19232
+ ...typeof uiblock?.durationMs === "number" ? { durationMs: uiblock.durationMs } : {}
19214
19233
  };
19215
19234
  }
19216
19235
  function hasTraceContent(trace) {
@@ -19518,6 +19537,20 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19518
19537
  }
19519
19538
  };
19520
19539
  }
19540
+ let narrationSeq = 0;
19541
+ const narrationCallback = (update) => {
19542
+ try {
19543
+ sendMessage({
19544
+ id: `narration_${existingUiBlockId}`,
19545
+ type: "USER_PROMPT_NARRATION",
19546
+ from: { type: "data-agent" },
19547
+ to: { type: "runtime", id: wsId },
19548
+ payload: { uiBlockId: existingUiBlockId, threadId, seq: narrationSeq++, ...update }
19549
+ });
19550
+ } catch (err) {
19551
+ logger.warn(`[UserPromptRequest] Narration send failed (WebSocket may be closed): ${err instanceof Error ? err.message : String(err)}`);
19552
+ }
19553
+ };
19521
19554
  let userResponse;
19522
19555
  try {
19523
19556
  const replayed = answerProvider ? (await replayExactMatch({ prompt, collections, userId, streamCallback, method: "custom-exact-match", startTime: Date.now() }))?.response : void 0;
@@ -19531,6 +19564,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19531
19564
  userConfig,
19532
19565
  conversationHistory,
19533
19566
  onStream: streamCallback,
19567
+ onNarration: narrationCallback,
19534
19568
  signal: abortController.signal
19535
19569
  }) : await get_agent_user_response(
19536
19570
  prompt,
@@ -19556,6 +19590,9 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19556
19590
  inFlightAborts.delete(existingUiBlockId);
19557
19591
  }
19558
19592
  logger.info("User prompt request completed");
19593
+ const narration = userResponse?.data?.narration;
19594
+ if (Array.isArray(narration) && narration.length) uiBlock.setNarration(narration);
19595
+ uiBlock.setDurationMs(Date.now() - requestStartTime);
19559
19596
  const uiBlockId = existingUiBlockId;
19560
19597
  const wasAborted = abortController.signal.aborted || !userResponse.success && Array.isArray(userResponse.errors) && userResponse.errors.includes("aborted");
19561
19598
  if (wasAborted) {
package/dist/index.mjs CHANGED
@@ -1213,6 +1213,20 @@ var UIBlock = class {
1213
1213
  setTextResponse(textResponse) {
1214
1214
  this.textResponse = textResponse;
1215
1215
  }
1216
+ /**
1217
+ * Progress updates a narrator wrote while this answer was being produced,
1218
+ * in order. Not part of the answer text: kept beside it so it is saved with
1219
+ * the answer it describes, and can be shown or left out on its own.
1220
+ */
1221
+ setNarration(updates) {
1222
+ this.narration = updates && updates.length ? updates : null;
1223
+ }
1224
+ getNarration() {
1225
+ return this.narration ?? null;
1226
+ }
1227
+ setDurationMs(ms) {
1228
+ this.durationMs = typeof ms === "number" && Number.isFinite(ms) && ms >= 0 ? Math.round(ms) : null;
1229
+ }
1216
1230
  /**
1217
1231
  * Bind this block to the script recipe that produced its answer.
1218
1232
  */
@@ -1250,7 +1264,9 @@ var UIBlock = class {
1250
1264
  textResponse: this.textResponse,
1251
1265
  createdAt: this.createdAt.toISOString(),
1252
1266
  ...this.scriptBinding ? { scriptBinding: this.scriptBinding } : {},
1253
- ...this.programAnswer ? { programAnswer: this.programAnswer } : {}
1267
+ ...this.programAnswer ? { programAnswer: this.programAnswer } : {},
1268
+ ...this.narration ? { narration: this.narration } : {},
1269
+ ...this.durationMs != null ? { durationMs: this.durationMs } : {}
1254
1270
  };
1255
1271
  }
1256
1272
  };
@@ -19104,7 +19120,10 @@ function transformUIBlockForDB(uiblock, userPrompt, uiBlockId) {
19104
19120
  ...uiblock?.scriptBinding?.recipeId ? { scriptBinding: uiblock.scriptBinding } : {},
19105
19121
  // The program-generated half, stored verbatim so a reload can regenerate
19106
19122
  // just that portion of `analysis` and leave the narration alone.
19107
- ...uiblock?.programAnswer ? { programAnswer: uiblock.programAnswer } : {}
19123
+ ...uiblock?.programAnswer ? { programAnswer: uiblock.programAnswer } : {},
19124
+ // Beside the answer, not in it: `analysis` stays the answer text alone.
19125
+ ...Array.isArray(uiblock?.narration) && uiblock.narration.length ? { narration: uiblock.narration } : {},
19126
+ ...typeof uiblock?.durationMs === "number" ? { durationMs: uiblock.durationMs } : {}
19108
19127
  };
19109
19128
  }
19110
19129
  function hasTraceContent(trace) {
@@ -19412,6 +19431,20 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19412
19431
  }
19413
19432
  };
19414
19433
  }
19434
+ let narrationSeq = 0;
19435
+ const narrationCallback = (update) => {
19436
+ try {
19437
+ sendMessage({
19438
+ id: `narration_${existingUiBlockId}`,
19439
+ type: "USER_PROMPT_NARRATION",
19440
+ from: { type: "data-agent" },
19441
+ to: { type: "runtime", id: wsId },
19442
+ payload: { uiBlockId: existingUiBlockId, threadId, seq: narrationSeq++, ...update }
19443
+ });
19444
+ } catch (err) {
19445
+ logger.warn(`[UserPromptRequest] Narration send failed (WebSocket may be closed): ${err instanceof Error ? err.message : String(err)}`);
19446
+ }
19447
+ };
19415
19448
  let userResponse;
19416
19449
  try {
19417
19450
  const replayed = answerProvider ? (await replayExactMatch({ prompt, collections, userId, streamCallback, method: "custom-exact-match", startTime: Date.now() }))?.response : void 0;
@@ -19425,6 +19458,7 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19425
19458
  userConfig,
19426
19459
  conversationHistory,
19427
19460
  onStream: streamCallback,
19461
+ onNarration: narrationCallback,
19428
19462
  signal: abortController.signal
19429
19463
  }) : await get_agent_user_response(
19430
19464
  prompt,
@@ -19450,6 +19484,9 @@ var get_user_request = async (data, components, sendMessage, anthropicApiKey, gr
19450
19484
  inFlightAborts.delete(existingUiBlockId);
19451
19485
  }
19452
19486
  logger.info("User prompt request completed");
19487
+ const narration = userResponse?.data?.narration;
19488
+ if (Array.isArray(narration) && narration.length) uiBlock.setNarration(narration);
19489
+ uiBlock.setDurationMs(Date.now() - requestStartTime);
19453
19490
  const uiBlockId = existingUiBlockId;
19454
19491
  const wasAborted = abortController.signal.aborted || !userResponse.success && Array.isArray(userResponse.errors) && userResponse.errors.includes("aborted");
19455
19492
  if (wasAborted) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superatomai/sdk-node",
3
- "version": "0.0.65-dsp",
3
+ "version": "0.0.66-dsp",
4
4
  "description": "Node.js TypeScript SDK for Superatom",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",