@inkeep/agents-run-api 0.0.0-dev-20250920002849 → 0.0.0-dev-20250924193535

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.cjs +86 -217
  2. package/dist/index.js +87 -218
  3. package/package.json +4 -2
package/dist/index.cjs CHANGED
@@ -27,6 +27,7 @@ var streaming = require('hono/streaming');
27
27
  var destr = require('destr');
28
28
  var traverse = require('traverse');
29
29
  var ai = require('ai');
30
+ var agentsSdk = require('@inkeep/agents-sdk');
30
31
  var anthropic = require('@ai-sdk/anthropic');
31
32
  var gateway = require('@ai-sdk/gateway');
32
33
  var google = require('@ai-sdk/google');
@@ -1929,68 +1930,52 @@ var GraphSession = class {
1929
1930
  }
1930
1931
  const now = Date.now();
1931
1932
  const elapsedTime = now - statusUpdateState.startTime;
1932
- let summaryToSend;
1933
- if (statusUpdateState.config.statusComponents && statusUpdateState.config.statusComponents.length > 0) {
1934
- const result = await this.generateStructuredStatusUpdate(
1935
- this.events.slice(statusUpdateState.lastEventCount),
1936
- elapsedTime,
1937
- statusUpdateState.config.statusComponents,
1938
- statusUpdateState.summarizerModel,
1939
- this.previousSummaries
1940
- );
1941
- if (result.summaries && result.summaries.length > 0) {
1942
- for (const summary of result.summaries) {
1943
- if (!summary || !summary.type || !summary.data || !summary.data.label || Object.keys(summary.data).length === 0) {
1944
- logger6.warn(
1945
- {
1946
- sessionId: this.sessionId,
1947
- summary
1948
- },
1949
- "Skipping empty or invalid structured operation"
1950
- );
1951
- continue;
1952
- }
1953
- const summaryToSend2 = {
1954
- type: summary.data.type || summary.type,
1955
- // Preserve the actual custom type from LLM
1956
- label: summary.data.label,
1957
- details: Object.fromEntries(
1958
- Object.entries(summary.data).filter(([key]) => !["label", "type"].includes(key))
1959
- )
1960
- };
1961
- await streamHelper.writeSummary(summaryToSend2);
1962
- }
1963
- const summaryTexts = result.summaries.map(
1964
- (summary) => JSON.stringify({ type: summary.type, data: summary.data })
1965
- );
1966
- this.previousSummaries.push(...summaryTexts);
1967
- if (this.statusUpdateState) {
1968
- this.statusUpdateState.lastUpdateTime = now;
1969
- this.statusUpdateState.lastEventCount = this.events.length;
1933
+ const statusComponents = statusUpdateState.config.statusComponents && statusUpdateState.config.statusComponents.length > 0 ? statusUpdateState.config.statusComponents : agentsSdk.defaultStatusSchemas;
1934
+ const result = await this.generateStructuredStatusUpdate(
1935
+ this.events.slice(statusUpdateState.lastEventCount),
1936
+ elapsedTime,
1937
+ statusComponents,
1938
+ statusUpdateState.summarizerModel,
1939
+ this.previousSummaries
1940
+ );
1941
+ if (result.summaries && result.summaries.length > 0) {
1942
+ for (const summary of result.summaries) {
1943
+ if (!summary || !summary.type || !summary.data || !summary.data.label || Object.keys(summary.data).length === 0) {
1944
+ logger6.warn(
1945
+ {
1946
+ sessionId: this.sessionId,
1947
+ summary
1948
+ },
1949
+ "Skipping empty or invalid structured operation"
1950
+ );
1951
+ continue;
1970
1952
  }
1971
- return;
1953
+ const summaryToSend = {
1954
+ type: summary.data.type || summary.type,
1955
+ // Preserve the actual custom type from LLM
1956
+ label: summary.data.label,
1957
+ details: Object.fromEntries(
1958
+ Object.entries(summary.data).filter(([key]) => !["label", "type"].includes(key))
1959
+ )
1960
+ };
1961
+ await streamHelper.writeSummary(summaryToSend);
1972
1962
  }
1973
- } else {
1974
- const summary = await this.generateProgressSummary(
1975
- this.events.slice(statusUpdateState.lastEventCount),
1976
- elapsedTime,
1977
- statusUpdateState.summarizerModel,
1978
- this.previousSummaries
1963
+ const summaryTexts = result.summaries.map(
1964
+ (summary) => JSON.stringify({ type: summary.type, data: summary.data })
1979
1965
  );
1980
- this.previousSummaries.push(summary);
1966
+ this.previousSummaries.push(...summaryTexts);
1967
+ if (this.statusUpdateState) {
1968
+ this.statusUpdateState.lastUpdateTime = now;
1969
+ this.statusUpdateState.lastEventCount = this.events.length;
1970
+ }
1971
+ return;
1981
1972
  }
1982
1973
  if (this.previousSummaries.length > 3) {
1983
1974
  this.previousSummaries.shift();
1984
1975
  }
1985
- {
1986
- logger6.warn(
1987
- {
1988
- sessionId: this.sessionId,
1989
- summaryToSend
1990
- },
1991
- "Skipping empty or invalid status update operation"
1992
- );
1993
- return;
1976
+ if (this.statusUpdateState) {
1977
+ this.statusUpdateState.lastUpdateTime = now;
1978
+ this.statusUpdateState.lastEventCount = this.events.length;
1994
1979
  }
1995
1980
  } catch (error) {
1996
1981
  logger6.error(
@@ -2071,106 +2056,6 @@ var GraphSession = class {
2071
2056
  this.statusUpdateState.updateLock = false;
2072
2057
  }
2073
2058
  }
2074
- /**
2075
- * Generate user-focused progress summary hiding internal operations
2076
- */
2077
- async generateProgressSummary(newEvents, elapsedTime, summarizerModel, previousSummaries = []) {
2078
- return tracer.startActiveSpan(
2079
- "graph_session.generate_progress_summary",
2080
- {
2081
- attributes: {
2082
- "graph_session.id": this.sessionId,
2083
- "events.count": newEvents.length,
2084
- "elapsed_time.seconds": Math.round(elapsedTime / 1e3),
2085
- "llm.model": summarizerModel?.model,
2086
- "previous_summaries.count": previousSummaries.length
2087
- }
2088
- },
2089
- async (span) => {
2090
- try {
2091
- const userVisibleActivities = this.extractUserVisibleActivities(newEvents);
2092
- let conversationContext = "";
2093
- if (this.tenantId && this.projectId) {
2094
- try {
2095
- const conversationHistory = await getFormattedConversationHistory({
2096
- tenantId: this.tenantId,
2097
- projectId: this.projectId,
2098
- conversationId: this.sessionId,
2099
- options: {
2100
- limit: 10,
2101
- // Get recent conversation context
2102
- maxOutputTokens: 2e3
2103
- },
2104
- filters: {}
2105
- });
2106
- conversationContext = conversationHistory.trim() ? `
2107
- User's Question/Context:
2108
- ${conversationHistory}
2109
- ` : "";
2110
- } catch (error) {
2111
- logger6.warn(
2112
- { sessionId: this.sessionId, error },
2113
- "Failed to fetch conversation history for status update"
2114
- );
2115
- }
2116
- }
2117
- const previousSummaryContext = previousSummaries.length > 0 ? `
2118
- Previous updates provided to user:
2119
- ${previousSummaries.map((s, i) => `${i + 1}. ${s}`).join("\n")}
2120
- ` : "";
2121
- const basePrompt = `Generate a meaningful status update that tells the user what specific information or result was just found/achieved.${conversationContext}${previousSummaries.length > 0 ? `
2122
- ${previousSummaryContext}` : ""}
2123
-
2124
- Activities:
2125
- ${userVisibleActivities.join("\n") || "No New Activities"}
2126
-
2127
- Create a short 3-5 word label describing the ACTUAL finding. Use sentence case (only capitalize the first word and proper nouns). Examples: "Found admin permissions needed", "Identified three channel types", "OAuth token required".
2128
-
2129
- ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
2130
- const prompt = basePrompt;
2131
- let modelToUse = summarizerModel;
2132
- if (!summarizerModel?.model?.trim()) {
2133
- if (!this.statusUpdateState?.baseModel?.model?.trim()) {
2134
- throw new Error(
2135
- "Either summarizer or base model is required for progress summary generation. Please configure models at the project level."
2136
- );
2137
- }
2138
- modelToUse = this.statusUpdateState.baseModel;
2139
- }
2140
- if (!modelToUse) {
2141
- throw new Error("No model configuration available");
2142
- }
2143
- const model = ModelFactory.createModel(modelToUse);
2144
- const { text } = await ai.generateText({
2145
- model,
2146
- prompt,
2147
- experimental_telemetry: {
2148
- isEnabled: true,
2149
- functionId: `status_update_${this.sessionId}`,
2150
- recordInputs: true,
2151
- recordOutputs: true,
2152
- metadata: {
2153
- operation: "progress_summary_generation",
2154
- sessionId: this.sessionId
2155
- }
2156
- }
2157
- });
2158
- span.setAttributes({
2159
- "summary.length": text.trim().length,
2160
- "user_activities.count": userVisibleActivities.length
2161
- });
2162
- span.setStatus({ code: api.SpanStatusCode.OK });
2163
- return text.trim();
2164
- } catch (error) {
2165
- agentsCore.setSpanWithError(span, error);
2166
- logger6.error({ error }, "Failed to generate summary, using fallback");
2167
- return this.generateFallbackSummary(newEvents, elapsedTime);
2168
- } finally {
2169
- span.end();
2170
- }
2171
- }
2172
- );
2173
- }
2174
2059
  /**
2175
2060
  * Generate structured status update using configured data components
2176
2061
  */
@@ -2249,17 +2134,45 @@ Rules:
2249
2134
  - Fill in data for relevant components only
2250
2135
  - Use 'no_relevant_updates' if nothing substantially new to report. DO NOT WRITE LABELS OR USE OTHER COMPONENTS IF YOU USE THIS COMPONENT.
2251
2136
  - Never repeat previous values, make every update EXTREMELY unique. If you cannot do that the update is not worth mentioning.
2252
- - Labels MUST be short 3-5 word phrases with ACTUAL information discovered. NEVER MAKE UP SOMETHING WITHOUT BACKING IT UP WITH ACTUAL INFORMATION.
2137
+ - Labels MUST be short 3-7 word phrases with ACTUAL information discovered. NEVER MAKE UP SOMETHING WITHOUT BACKING IT UP WITH ACTUAL INFORMATION.
2253
2138
  - Use sentence case: only capitalize the first word and proper nouns (e.g., "Admin permissions required", not "Admin Permissions Required"). ALWAYS capitalize the first word of the label.
2254
2139
  - DO NOT use action words like "Searching", "Processing", "Analyzing" - state what was FOUND
2255
2140
  - Include specific details, numbers, requirements, or insights discovered
2256
2141
  - Examples: "Admin permissions required", "Three OAuth steps found", "Token expires daily"
2257
- - You are ONE unified AI system - NEVER mention agents, transfers, delegations, or routing
2258
- - CRITICAL: NEVER use the words "transfer", "delegation", "agent", "routing", "artifact", or any internal system terminology in labels or any names of agents, tools, or systems.
2259
- - Present all operations as seamless actions by a single system
2260
- - Anonymize all internal operations so that the information appears descriptive and USER FRIENDLY. HIDE ALL INTERNAL OPERATIONS!
2261
- - Bad examples: "Transferring to search agent", "continuing transfer to qa agent", "Delegating task", "Routing request", "Processing request", "Artifact found", "Artifact saved", or not using the no_relevant_updates
2262
- - Good examples: "Slack bot needs admin privileges", "Found 3-step OAuth flow required", "Channel limit is 500 per workspace", or use the no_relevant_updates component if nothing new to report.
2142
+
2143
+ CRITICAL - HIDE ALL INTERNAL SYSTEM OPERATIONS:
2144
+ - You are ONE unified AI system presenting results to the user
2145
+ - ABSOLUTELY FORBIDDEN WORDS/PHRASES: "transfer", "transferring", "delegation", "delegating", "delegate", "agent", "routing", "route", "artifact", "saving artifact", "stored artifact", "artifact saved", "continuing", "passing to", "handing off", "switching to"
2146
+ - NEVER reveal internal architecture: No mentions of different agents, components, systems, or modules working together
2147
+ - NEVER mention artifact operations: Users don't need to know about data being saved, stored, or organized internally
2148
+ - NEVER describe handoffs or transitions: Present everything as one seamless operation
2149
+ - If you see "transfer", "delegation_sent", "delegation_returned", or "artifact_saved" events - IGNORE THEM or translate to user-facing information only
2150
+ - Focus ONLY on actual discoveries, findings, and results that matter to the user
2151
+
2152
+ - Bad examples:
2153
+ * "Transferring to search agent"
2154
+ * "Delegating research task"
2155
+ * "Routing to QA specialist"
2156
+ * "Artifact saved successfully"
2157
+ * "Storing results for later"
2158
+ * "Passing request to tool handler"
2159
+ * "Continuing with analysis"
2160
+ * "Handing off to processor"
2161
+ - Good examples:
2162
+ * "Slack bot needs admin privileges"
2163
+ * "Found 3-step OAuth flow required"
2164
+ * "Channel limit is 500 per workspace"
2165
+ * Use no_relevant_updates if nothing new to report
2166
+
2167
+ CRITICAL ANTI-HALLUCINATION RULES:
2168
+ - NEVER MAKE UP SOMETHING WITHOUT BACKING IT UP WITH ACTUAL INFORMATION. EVERY SINGLE UPDATE MUST BE BACKED UP WITH ACTUAL INFORMATION.
2169
+ - DO NOT MAKE UP PEOPLE, NAMES, PLACES, THINGS, ORGANIZATIONS, OR INFORMATION. IT IS OBVIOUS WHEN A PERSON/ENTITY DOES NOT EXIST.
2170
+ - Only report facts that are EXPLICITLY mentioned in the activities or tool results
2171
+ - If you don't have concrete information about something, DO NOT mention it
2172
+ - Never invent names like "John Doe", "Alice", "Bob", or any other placeholder names
2173
+ - Never create fictional companies, products, or services
2174
+ - If a tool returned no results or an error, DO NOT pretend it found something
2175
+ - Every detail in your status update must be traceable back to the actual activities provided
2263
2176
 
2264
2177
  REMEMBER YOU CAN ONLY USE 'no_relevant_updates' ALONE! IT CANNOT BE CONCATENATED WITH OTHER STATUS UPDATES!
2265
2178
 
@@ -2332,7 +2245,7 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
2332
2245
  }
2333
2246
  return z5.z.object({
2334
2247
  label: z5.z.string().describe(
2335
- 'A short 3-5 word phrase, that is a descriptive label for the update component. This Label must be EXTREMELY unique to represent the UNIQUE update we are providing. The ACTUAL finding or result, not the action. What specific information was discovered? (e.g., "Slack requires OAuth 2.0 setup", "Found 5 integration methods", "API rate limit is 100/minute"). Include the actual detail or insight, not just that you searched or processed.'
2248
+ 'A short 3-5 word phrase, that is a descriptive label for the update component. This Label must be EXTREMELY unique to represent the UNIQUE update we are providing. The ACTUAL finding or result, not the action. What specific information was discovered? (e.g., "Slack requires OAuth 2.0 setup", "Found 5 integration methods", "API rate limit is 100/minute"). Include the actual detail or insight, not just that you searched or processed. CRITICAL: Only use facts explicitly found in the activities - NEVER invent names, people, organizations, or details that are not present in the actual tool results.'
2336
2249
  )
2337
2250
  });
2338
2251
  }
@@ -2342,7 +2255,7 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
2342
2255
  buildZodSchemaFromJson(jsonSchema) {
2343
2256
  const properties = {};
2344
2257
  properties["label"] = z5.z.string().describe(
2345
- 'A short 3-5 word phrase, that is a descriptive label for the update component. This Label must be EXTREMELY unique to represent the UNIQUE update we are providing. The SPECIFIC finding, result, or insight discovered (e.g., "Slack bot needs workspace admin role", "Found ingestion requires 3 steps", "Channel history limited to 10k messages"). State the ACTUAL information found, not that you searched. What did you LEARN or DISCOVER? What specific detail is now known?'
2258
+ 'A short 3-5 word phrase, that is a descriptive label for the update component. This Label must be EXTREMELY unique to represent the UNIQUE update we are providing. The SPECIFIC finding, result, or insight discovered (e.g., "Slack bot needs workspace admin role", "Found ingestion requires 3 steps", "Channel history limited to 10k messages"). State the ACTUAL information found, not that you searched. What did you LEARN or DISCOVER? What specific detail is now known? CRITICAL: Only use facts explicitly found in the activities - NEVER invent names, people, organizations, or details that are not present in the actual tool results.'
2346
2259
  );
2347
2260
  for (const [key, value] of Object.entries(jsonSchema.properties)) {
2348
2261
  let zodType;
@@ -2419,41 +2332,12 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
2419
2332
  );
2420
2333
  break;
2421
2334
  }
2422
- case "transfer": {
2423
- const data = event.data;
2424
- activities.push(
2425
- `\u{1F504} **Continuing**: ${data.reason || "Processing request"}
2426
- ${data.context ? `Context: ${JSON.stringify(data.context, null, 2)}` : ""}`
2427
- );
2335
+ // INTERNAL OPERATIONS - DO NOT EXPOSE TO STATUS UPDATES
2336
+ case "transfer":
2337
+ case "delegation_sent":
2338
+ case "delegation_returned":
2339
+ case "artifact_saved":
2428
2340
  break;
2429
- }
2430
- case "delegation_sent": {
2431
- const data = event.data;
2432
- activities.push(
2433
- `\u{1F4E4} **Processing**: ${data.taskDescription}
2434
- ${data.context ? `Context: ${JSON.stringify(data.context, null, 2)}` : ""}`
2435
- );
2436
- break;
2437
- }
2438
- case "delegation_returned": {
2439
- const data = event.data;
2440
- activities.push(
2441
- `\u{1F4E5} **Completed subtask**
2442
- Result: ${JSON.stringify(data.result, null, 2)}`
2443
- );
2444
- break;
2445
- }
2446
- case "artifact_saved": {
2447
- const data = event.data;
2448
- activities.push(
2449
- `\u{1F4BE} **Artifact Saved**: ${data.artifactType}
2450
- ID: ${data.artifactId}
2451
- Task: ${data.taskId}
2452
- ${data.summaryData ? `Summary: ${data.summaryData}` : ""}
2453
- ${data.fullData ? `Full Data: ${data.fullData}` : ""}`
2454
- );
2455
- break;
2456
- }
2457
2341
  case "agent_reasoning": {
2458
2342
  const data = event.data;
2459
2343
  activities.push(
@@ -2478,21 +2362,6 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
2478
2362
  }
2479
2363
  return activities;
2480
2364
  }
2481
- /**
2482
- * Generate fallback summary when LLM fails
2483
- */
2484
- generateFallbackSummary(events, elapsedTime) {
2485
- const timeStr = Math.round(elapsedTime / 1e3);
2486
- const toolCalls = events.filter((e) => e.eventType === "tool_execution").length;
2487
- const artifacts = events.filter((e) => e.eventType === "artifact_saved").length;
2488
- if (artifacts > 0) {
2489
- return `Generated ${artifacts} result${artifacts > 1 ? "s" : ""} so far (${timeStr}s elapsed)`;
2490
- } else if (toolCalls > 0) {
2491
- return `Used ${toolCalls} tool${toolCalls > 1 ? "s" : ""} to gather information (${timeStr}s elapsed)`;
2492
- } else {
2493
- return `Processing your request... (${timeStr}s elapsed)`;
2494
- }
2495
- }
2496
2365
  /**
2497
2366
  * Process a single artifact to generate name and description using conversation context
2498
2367
  */
@@ -3246,7 +3115,7 @@ var _IncrementalStreamParser = class _IncrementalStreamParser {
3246
3115
  await this.streamPart(part);
3247
3116
  }
3248
3117
  if (this.pendingTextBuffer) {
3249
- const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
3118
+ const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/artifact:ref>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
3250
3119
  if (cleanedText) {
3251
3120
  this.collectedParts.push({
3252
3121
  kind: "text",
@@ -3324,7 +3193,7 @@ var _IncrementalStreamParser = class _IncrementalStreamParser {
3324
3193
  if (part.kind === "text" && part.text) {
3325
3194
  this.pendingTextBuffer += part.text;
3326
3195
  if (!this.artifactParser.hasIncompleteArtifact(this.pendingTextBuffer)) {
3327
- const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
3196
+ const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/artifact:ref>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
3328
3197
  if (cleanedText) {
3329
3198
  await this.streamHelper.streamText(cleanedText, 50);
3330
3199
  }
@@ -3332,7 +3201,7 @@ var _IncrementalStreamParser = class _IncrementalStreamParser {
3332
3201
  }
3333
3202
  } else if (part.kind === "data" && part.data) {
3334
3203
  if (this.pendingTextBuffer) {
3335
- const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
3204
+ const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/artifact:ref>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
3336
3205
  if (cleanedText) {
3337
3206
  await this.streamHelper.streamText(cleanedText, 50);
3338
3207
  }
@@ -7319,7 +7188,7 @@ var _VercelDataStreamHelper = class _VercelDataStreamHelper {
7319
7188
  __publicField(this, "queuedEvents", []);
7320
7189
  // Timing tracking for text sequences (text-end to text-start gap)
7321
7190
  __publicField(this, "lastTextEndTimestamp", 0);
7322
- __publicField(this, "TEXT_GAP_THRESHOLD", 50);
7191
+ __publicField(this, "TEXT_GAP_THRESHOLD", 2e3);
7323
7192
  // milliseconds - if gap between text sequences is less than this, queue operations
7324
7193
  // Connection management and forced cleanup
7325
7194
  __publicField(this, "connectionDropTimer");
package/dist/index.js CHANGED
@@ -23,7 +23,8 @@ import { streamSSE, stream } from 'hono/streaming';
23
23
  import { nanoid } from 'nanoid';
24
24
  import destr from 'destr';
25
25
  import traverse from 'traverse';
26
- import { createUIMessageStream, JsonToSseTransformStream, parsePartialJson, generateText, generateObject, tool, streamText, streamObject } from 'ai';
26
+ import { createUIMessageStream, JsonToSseTransformStream, parsePartialJson, generateObject, tool, streamText, generateText, streamObject } from 'ai';
27
+ import { defaultStatusSchemas } from '@inkeep/agents-sdk';
27
28
  import { createAnthropic, anthropic } from '@ai-sdk/anthropic';
28
29
  import { createGateway, gateway } from '@ai-sdk/gateway';
29
30
  import { createGoogleGenerativeAI, google } from '@ai-sdk/google';
@@ -1654,68 +1655,52 @@ var GraphSession = class {
1654
1655
  }
1655
1656
  const now = Date.now();
1656
1657
  const elapsedTime = now - statusUpdateState.startTime;
1657
- let summaryToSend;
1658
- if (statusUpdateState.config.statusComponents && statusUpdateState.config.statusComponents.length > 0) {
1659
- const result = await this.generateStructuredStatusUpdate(
1660
- this.events.slice(statusUpdateState.lastEventCount),
1661
- elapsedTime,
1662
- statusUpdateState.config.statusComponents,
1663
- statusUpdateState.summarizerModel,
1664
- this.previousSummaries
1665
- );
1666
- if (result.summaries && result.summaries.length > 0) {
1667
- for (const summary of result.summaries) {
1668
- if (!summary || !summary.type || !summary.data || !summary.data.label || Object.keys(summary.data).length === 0) {
1669
- logger6.warn(
1670
- {
1671
- sessionId: this.sessionId,
1672
- summary
1673
- },
1674
- "Skipping empty or invalid structured operation"
1675
- );
1676
- continue;
1677
- }
1678
- const summaryToSend2 = {
1679
- type: summary.data.type || summary.type,
1680
- // Preserve the actual custom type from LLM
1681
- label: summary.data.label,
1682
- details: Object.fromEntries(
1683
- Object.entries(summary.data).filter(([key]) => !["label", "type"].includes(key))
1684
- )
1685
- };
1686
- await streamHelper.writeSummary(summaryToSend2);
1687
- }
1688
- const summaryTexts = result.summaries.map(
1689
- (summary) => JSON.stringify({ type: summary.type, data: summary.data })
1690
- );
1691
- this.previousSummaries.push(...summaryTexts);
1692
- if (this.statusUpdateState) {
1693
- this.statusUpdateState.lastUpdateTime = now;
1694
- this.statusUpdateState.lastEventCount = this.events.length;
1658
+ const statusComponents = statusUpdateState.config.statusComponents && statusUpdateState.config.statusComponents.length > 0 ? statusUpdateState.config.statusComponents : defaultStatusSchemas;
1659
+ const result = await this.generateStructuredStatusUpdate(
1660
+ this.events.slice(statusUpdateState.lastEventCount),
1661
+ elapsedTime,
1662
+ statusComponents,
1663
+ statusUpdateState.summarizerModel,
1664
+ this.previousSummaries
1665
+ );
1666
+ if (result.summaries && result.summaries.length > 0) {
1667
+ for (const summary of result.summaries) {
1668
+ if (!summary || !summary.type || !summary.data || !summary.data.label || Object.keys(summary.data).length === 0) {
1669
+ logger6.warn(
1670
+ {
1671
+ sessionId: this.sessionId,
1672
+ summary
1673
+ },
1674
+ "Skipping empty or invalid structured operation"
1675
+ );
1676
+ continue;
1695
1677
  }
1696
- return;
1678
+ const summaryToSend = {
1679
+ type: summary.data.type || summary.type,
1680
+ // Preserve the actual custom type from LLM
1681
+ label: summary.data.label,
1682
+ details: Object.fromEntries(
1683
+ Object.entries(summary.data).filter(([key]) => !["label", "type"].includes(key))
1684
+ )
1685
+ };
1686
+ await streamHelper.writeSummary(summaryToSend);
1697
1687
  }
1698
- } else {
1699
- const summary = await this.generateProgressSummary(
1700
- this.events.slice(statusUpdateState.lastEventCount),
1701
- elapsedTime,
1702
- statusUpdateState.summarizerModel,
1703
- this.previousSummaries
1688
+ const summaryTexts = result.summaries.map(
1689
+ (summary) => JSON.stringify({ type: summary.type, data: summary.data })
1704
1690
  );
1705
- this.previousSummaries.push(summary);
1691
+ this.previousSummaries.push(...summaryTexts);
1692
+ if (this.statusUpdateState) {
1693
+ this.statusUpdateState.lastUpdateTime = now;
1694
+ this.statusUpdateState.lastEventCount = this.events.length;
1695
+ }
1696
+ return;
1706
1697
  }
1707
1698
  if (this.previousSummaries.length > 3) {
1708
1699
  this.previousSummaries.shift();
1709
1700
  }
1710
- {
1711
- logger6.warn(
1712
- {
1713
- sessionId: this.sessionId,
1714
- summaryToSend
1715
- },
1716
- "Skipping empty or invalid status update operation"
1717
- );
1718
- return;
1701
+ if (this.statusUpdateState) {
1702
+ this.statusUpdateState.lastUpdateTime = now;
1703
+ this.statusUpdateState.lastEventCount = this.events.length;
1719
1704
  }
1720
1705
  } catch (error) {
1721
1706
  logger6.error(
@@ -1796,106 +1781,6 @@ var GraphSession = class {
1796
1781
  this.statusUpdateState.updateLock = false;
1797
1782
  }
1798
1783
  }
1799
- /**
1800
- * Generate user-focused progress summary hiding internal operations
1801
- */
1802
- async generateProgressSummary(newEvents, elapsedTime, summarizerModel, previousSummaries = []) {
1803
- return tracer.startActiveSpan(
1804
- "graph_session.generate_progress_summary",
1805
- {
1806
- attributes: {
1807
- "graph_session.id": this.sessionId,
1808
- "events.count": newEvents.length,
1809
- "elapsed_time.seconds": Math.round(elapsedTime / 1e3),
1810
- "llm.model": summarizerModel?.model,
1811
- "previous_summaries.count": previousSummaries.length
1812
- }
1813
- },
1814
- async (span) => {
1815
- try {
1816
- const userVisibleActivities = this.extractUserVisibleActivities(newEvents);
1817
- let conversationContext = "";
1818
- if (this.tenantId && this.projectId) {
1819
- try {
1820
- const conversationHistory = await getFormattedConversationHistory({
1821
- tenantId: this.tenantId,
1822
- projectId: this.projectId,
1823
- conversationId: this.sessionId,
1824
- options: {
1825
- limit: 10,
1826
- // Get recent conversation context
1827
- maxOutputTokens: 2e3
1828
- },
1829
- filters: {}
1830
- });
1831
- conversationContext = conversationHistory.trim() ? `
1832
- User's Question/Context:
1833
- ${conversationHistory}
1834
- ` : "";
1835
- } catch (error) {
1836
- logger6.warn(
1837
- { sessionId: this.sessionId, error },
1838
- "Failed to fetch conversation history for status update"
1839
- );
1840
- }
1841
- }
1842
- const previousSummaryContext = previousSummaries.length > 0 ? `
1843
- Previous updates provided to user:
1844
- ${previousSummaries.map((s, i) => `${i + 1}. ${s}`).join("\n")}
1845
- ` : "";
1846
- const basePrompt = `Generate a meaningful status update that tells the user what specific information or result was just found/achieved.${conversationContext}${previousSummaries.length > 0 ? `
1847
- ${previousSummaryContext}` : ""}
1848
-
1849
- Activities:
1850
- ${userVisibleActivities.join("\n") || "No New Activities"}
1851
-
1852
- Create a short 3-5 word label describing the ACTUAL finding. Use sentence case (only capitalize the first word and proper nouns). Examples: "Found admin permissions needed", "Identified three channel types", "OAuth token required".
1853
-
1854
- ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
1855
- const prompt = basePrompt;
1856
- let modelToUse = summarizerModel;
1857
- if (!summarizerModel?.model?.trim()) {
1858
- if (!this.statusUpdateState?.baseModel?.model?.trim()) {
1859
- throw new Error(
1860
- "Either summarizer or base model is required for progress summary generation. Please configure models at the project level."
1861
- );
1862
- }
1863
- modelToUse = this.statusUpdateState.baseModel;
1864
- }
1865
- if (!modelToUse) {
1866
- throw new Error("No model configuration available");
1867
- }
1868
- const model = ModelFactory.createModel(modelToUse);
1869
- const { text } = await generateText({
1870
- model,
1871
- prompt,
1872
- experimental_telemetry: {
1873
- isEnabled: true,
1874
- functionId: `status_update_${this.sessionId}`,
1875
- recordInputs: true,
1876
- recordOutputs: true,
1877
- metadata: {
1878
- operation: "progress_summary_generation",
1879
- sessionId: this.sessionId
1880
- }
1881
- }
1882
- });
1883
- span.setAttributes({
1884
- "summary.length": text.trim().length,
1885
- "user_activities.count": userVisibleActivities.length
1886
- });
1887
- span.setStatus({ code: SpanStatusCode.OK });
1888
- return text.trim();
1889
- } catch (error) {
1890
- setSpanWithError(span, error);
1891
- logger6.error({ error }, "Failed to generate summary, using fallback");
1892
- return this.generateFallbackSummary(newEvents, elapsedTime);
1893
- } finally {
1894
- span.end();
1895
- }
1896
- }
1897
- );
1898
- }
1899
1784
  /**
1900
1785
  * Generate structured status update using configured data components
1901
1786
  */
@@ -1974,17 +1859,45 @@ Rules:
1974
1859
  - Fill in data for relevant components only
1975
1860
  - Use 'no_relevant_updates' if nothing substantially new to report. DO NOT WRITE LABELS OR USE OTHER COMPONENTS IF YOU USE THIS COMPONENT.
1976
1861
  - Never repeat previous values, make every update EXTREMELY unique. If you cannot do that the update is not worth mentioning.
1977
- - Labels MUST be short 3-5 word phrases with ACTUAL information discovered. NEVER MAKE UP SOMETHING WITHOUT BACKING IT UP WITH ACTUAL INFORMATION.
1862
+ - Labels MUST be short 3-7 word phrases with ACTUAL information discovered. NEVER MAKE UP SOMETHING WITHOUT BACKING IT UP WITH ACTUAL INFORMATION.
1978
1863
  - Use sentence case: only capitalize the first word and proper nouns (e.g., "Admin permissions required", not "Admin Permissions Required"). ALWAYS capitalize the first word of the label.
1979
1864
  - DO NOT use action words like "Searching", "Processing", "Analyzing" - state what was FOUND
1980
1865
  - Include specific details, numbers, requirements, or insights discovered
1981
1866
  - Examples: "Admin permissions required", "Three OAuth steps found", "Token expires daily"
1982
- - You are ONE unified AI system - NEVER mention agents, transfers, delegations, or routing
1983
- - CRITICAL: NEVER use the words "transfer", "delegation", "agent", "routing", "artifact", or any internal system terminology in labels or any names of agents, tools, or systems.
1984
- - Present all operations as seamless actions by a single system
1985
- - Anonymize all internal operations so that the information appears descriptive and USER FRIENDLY. HIDE ALL INTERNAL OPERATIONS!
1986
- - Bad examples: "Transferring to search agent", "continuing transfer to qa agent", "Delegating task", "Routing request", "Processing request", "Artifact found", "Artifact saved", or not using the no_relevant_updates
1987
- - Good examples: "Slack bot needs admin privileges", "Found 3-step OAuth flow required", "Channel limit is 500 per workspace", or use the no_relevant_updates component if nothing new to report.
1867
+
1868
+ CRITICAL - HIDE ALL INTERNAL SYSTEM OPERATIONS:
1869
+ - You are ONE unified AI system presenting results to the user
1870
+ - ABSOLUTELY FORBIDDEN WORDS/PHRASES: "transfer", "transferring", "delegation", "delegating", "delegate", "agent", "routing", "route", "artifact", "saving artifact", "stored artifact", "artifact saved", "continuing", "passing to", "handing off", "switching to"
1871
+ - NEVER reveal internal architecture: No mentions of different agents, components, systems, or modules working together
1872
+ - NEVER mention artifact operations: Users don't need to know about data being saved, stored, or organized internally
1873
+ - NEVER describe handoffs or transitions: Present everything as one seamless operation
1874
+ - If you see "transfer", "delegation_sent", "delegation_returned", or "artifact_saved" events - IGNORE THEM or translate to user-facing information only
1875
+ - Focus ONLY on actual discoveries, findings, and results that matter to the user
1876
+
1877
+ - Bad examples:
1878
+ * "Transferring to search agent"
1879
+ * "Delegating research task"
1880
+ * "Routing to QA specialist"
1881
+ * "Artifact saved successfully"
1882
+ * "Storing results for later"
1883
+ * "Passing request to tool handler"
1884
+ * "Continuing with analysis"
1885
+ * "Handing off to processor"
1886
+ - Good examples:
1887
+ * "Slack bot needs admin privileges"
1888
+ * "Found 3-step OAuth flow required"
1889
+ * "Channel limit is 500 per workspace"
1890
+ * Use no_relevant_updates if nothing new to report
1891
+
1892
+ CRITICAL ANTI-HALLUCINATION RULES:
1893
+ - NEVER MAKE UP SOMETHING WITHOUT BACKING IT UP WITH ACTUAL INFORMATION. EVERY SINGLE UPDATE MUST BE BACKED UP WITH ACTUAL INFORMATION.
1894
+ - DO NOT MAKE UP PEOPLE, NAMES, PLACES, THINGS, ORGANIZATIONS, OR INFORMATION. IT IS OBVIOUS WHEN A PERSON/ENTITY DOES NOT EXIST.
1895
+ - Only report facts that are EXPLICITLY mentioned in the activities or tool results
1896
+ - If you don't have concrete information about something, DO NOT mention it
1897
+ - Never invent names like "John Doe", "Alice", "Bob", or any other placeholder names
1898
+ - Never create fictional companies, products, or services
1899
+ - If a tool returned no results or an error, DO NOT pretend it found something
1900
+ - Every detail in your status update must be traceable back to the actual activities provided
1988
1901
 
1989
1902
  REMEMBER YOU CAN ONLY USE 'no_relevant_updates' ALONE! IT CANNOT BE CONCATENATED WITH OTHER STATUS UPDATES!
1990
1903
 
@@ -2057,7 +1970,7 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
2057
1970
  }
2058
1971
  return z.object({
2059
1972
  label: z.string().describe(
2060
- 'A short 3-5 word phrase, that is a descriptive label for the update component. This Label must be EXTREMELY unique to represent the UNIQUE update we are providing. The ACTUAL finding or result, not the action. What specific information was discovered? (e.g., "Slack requires OAuth 2.0 setup", "Found 5 integration methods", "API rate limit is 100/minute"). Include the actual detail or insight, not just that you searched or processed.'
1973
+ 'A short 3-5 word phrase, that is a descriptive label for the update component. This Label must be EXTREMELY unique to represent the UNIQUE update we are providing. The ACTUAL finding or result, not the action. What specific information was discovered? (e.g., "Slack requires OAuth 2.0 setup", "Found 5 integration methods", "API rate limit is 100/minute"). Include the actual detail or insight, not just that you searched or processed. CRITICAL: Only use facts explicitly found in the activities - NEVER invent names, people, organizations, or details that are not present in the actual tool results.'
2061
1974
  )
2062
1975
  });
2063
1976
  }
@@ -2067,7 +1980,7 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
2067
1980
  buildZodSchemaFromJson(jsonSchema) {
2068
1981
  const properties = {};
2069
1982
  properties["label"] = z.string().describe(
2070
- 'A short 3-5 word phrase, that is a descriptive label for the update component. This Label must be EXTREMELY unique to represent the UNIQUE update we are providing. The SPECIFIC finding, result, or insight discovered (e.g., "Slack bot needs workspace admin role", "Found ingestion requires 3 steps", "Channel history limited to 10k messages"). State the ACTUAL information found, not that you searched. What did you LEARN or DISCOVER? What specific detail is now known?'
1983
+ 'A short 3-5 word phrase, that is a descriptive label for the update component. This Label must be EXTREMELY unique to represent the UNIQUE update we are providing. The SPECIFIC finding, result, or insight discovered (e.g., "Slack bot needs workspace admin role", "Found ingestion requires 3 steps", "Channel history limited to 10k messages"). State the ACTUAL information found, not that you searched. What did you LEARN or DISCOVER? What specific detail is now known? CRITICAL: Only use facts explicitly found in the activities - NEVER invent names, people, organizations, or details that are not present in the actual tool results.'
2071
1984
  );
2072
1985
  for (const [key, value] of Object.entries(jsonSchema.properties)) {
2073
1986
  let zodType;
@@ -2144,41 +2057,12 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
2144
2057
  );
2145
2058
  break;
2146
2059
  }
2147
- case "transfer": {
2148
- const data = event.data;
2149
- activities.push(
2150
- `\u{1F504} **Continuing**: ${data.reason || "Processing request"}
2151
- ${data.context ? `Context: ${JSON.stringify(data.context, null, 2)}` : ""}`
2152
- );
2060
+ // INTERNAL OPERATIONS - DO NOT EXPOSE TO STATUS UPDATES
2061
+ case "transfer":
2062
+ case "delegation_sent":
2063
+ case "delegation_returned":
2064
+ case "artifact_saved":
2153
2065
  break;
2154
- }
2155
- case "delegation_sent": {
2156
- const data = event.data;
2157
- activities.push(
2158
- `\u{1F4E4} **Processing**: ${data.taskDescription}
2159
- ${data.context ? `Context: ${JSON.stringify(data.context, null, 2)}` : ""}`
2160
- );
2161
- break;
2162
- }
2163
- case "delegation_returned": {
2164
- const data = event.data;
2165
- activities.push(
2166
- `\u{1F4E5} **Completed subtask**
2167
- Result: ${JSON.stringify(data.result, null, 2)}`
2168
- );
2169
- break;
2170
- }
2171
- case "artifact_saved": {
2172
- const data = event.data;
2173
- activities.push(
2174
- `\u{1F4BE} **Artifact Saved**: ${data.artifactType}
2175
- ID: ${data.artifactId}
2176
- Task: ${data.taskId}
2177
- ${data.summaryData ? `Summary: ${data.summaryData}` : ""}
2178
- ${data.fullData ? `Full Data: ${data.fullData}` : ""}`
2179
- );
2180
- break;
2181
- }
2182
2066
  case "agent_reasoning": {
2183
2067
  const data = event.data;
2184
2068
  activities.push(
@@ -2203,21 +2087,6 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
2203
2087
  }
2204
2088
  return activities;
2205
2089
  }
2206
- /**
2207
- * Generate fallback summary when LLM fails
2208
- */
2209
- generateFallbackSummary(events, elapsedTime) {
2210
- const timeStr = Math.round(elapsedTime / 1e3);
2211
- const toolCalls = events.filter((e) => e.eventType === "tool_execution").length;
2212
- const artifacts = events.filter((e) => e.eventType === "artifact_saved").length;
2213
- if (artifacts > 0) {
2214
- return `Generated ${artifacts} result${artifacts > 1 ? "s" : ""} so far (${timeStr}s elapsed)`;
2215
- } else if (toolCalls > 0) {
2216
- return `Used ${toolCalls} tool${toolCalls > 1 ? "s" : ""} to gather information (${timeStr}s elapsed)`;
2217
- } else {
2218
- return `Processing your request... (${timeStr}s elapsed)`;
2219
- }
2220
- }
2221
2090
  /**
2222
2091
  * Process a single artifact to generate name and description using conversation context
2223
2092
  */
@@ -2968,7 +2837,7 @@ var _IncrementalStreamParser = class _IncrementalStreamParser {
2968
2837
  await this.streamPart(part);
2969
2838
  }
2970
2839
  if (this.pendingTextBuffer) {
2971
- const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
2840
+ const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/artifact:ref>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
2972
2841
  if (cleanedText) {
2973
2842
  this.collectedParts.push({
2974
2843
  kind: "text",
@@ -3046,7 +2915,7 @@ var _IncrementalStreamParser = class _IncrementalStreamParser {
3046
2915
  if (part.kind === "text" && part.text) {
3047
2916
  this.pendingTextBuffer += part.text;
3048
2917
  if (!this.artifactParser.hasIncompleteArtifact(this.pendingTextBuffer)) {
3049
- const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
2918
+ const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/artifact:ref>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
3050
2919
  if (cleanedText) {
3051
2920
  await this.streamHelper.streamText(cleanedText, 50);
3052
2921
  }
@@ -3054,7 +2923,7 @@ var _IncrementalStreamParser = class _IncrementalStreamParser {
3054
2923
  }
3055
2924
  } else if (part.kind === "data" && part.data) {
3056
2925
  if (this.pendingTextBuffer) {
3057
- const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
2926
+ const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/artifact:ref>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
3058
2927
  if (cleanedText) {
3059
2928
  await this.streamHelper.streamText(cleanedText, 50);
3060
2929
  }
@@ -7028,7 +6897,7 @@ var _VercelDataStreamHelper = class _VercelDataStreamHelper {
7028
6897
  __publicField(this, "queuedEvents", []);
7029
6898
  // Timing tracking for text sequences (text-end to text-start gap)
7030
6899
  __publicField(this, "lastTextEndTimestamp", 0);
7031
- __publicField(this, "TEXT_GAP_THRESHOLD", 50);
6900
+ __publicField(this, "TEXT_GAP_THRESHOLD", 2e3);
7032
6901
  // milliseconds - if gap between text sequences is less than this, queue operations
7033
6902
  // Connection management and forced cleanup
7034
6903
  __publicField(this, "connectionDropTimer");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkeep/agents-run-api",
3
- "version": "0.0.0-dev-20250920002849",
3
+ "version": "0.0.0-dev-20250924193535",
4
4
  "description": "Agents Run API for Inkeep Agent Framework - handles chat, agent execution, and streaming",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -44,10 +44,12 @@
44
44
  "jmespath": "^0.16.0",
45
45
  "keytar": "^7.9.0",
46
46
  "nanoid": "^5.1.5",
47
+ "pino": "^9.11.0",
47
48
  "traverse": "^0.6.11",
48
49
  "ts-pattern": "^5.7.1",
49
50
  "zod": "^4.1.5",
50
- "@inkeep/agents-core": "^0.0.0-dev-20250920002849"
51
+ "@inkeep/agents-sdk": "^0.0.0-dev-20250924193535",
52
+ "@inkeep/agents-core": "^0.0.0-dev-20250924193535"
51
53
  },
52
54
  "devDependencies": {
53
55
  "@hono/vite-dev-server": "^0.20.1",