@inkeep/agents-run-api 0.3.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-5RGAMXUL.js +55 -0
- package/dist/{chunk-7PHUFKNP.js → chunk-HIGMADTA.js} +3 -6
- package/dist/chunk-PKBMQBKP.js +5 -0
- package/dist/{conversations-WDOIWO7W.js → conversations-OVETKXSP.js} +1 -1
- package/dist/index.cjs +182 -283
- package/dist/index.js +142 -289
- package/dist/instrumentation.cjs +63 -0
- package/dist/instrumentation.d.cts +15 -0
- package/dist/instrumentation.d.ts +15 -0
- package/dist/instrumentation.js +1 -0
- package/package.json +11 -4
package/dist/index.cjs
CHANGED
|
@@ -5,6 +5,13 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var agentsCore = require('@inkeep/agents-core');
|
|
6
6
|
var z5 = require('zod');
|
|
7
7
|
var nanoid = require('nanoid');
|
|
8
|
+
var otel = require('@hono/otel');
|
|
9
|
+
var zodOpenapi = require('@hono/zod-openapi');
|
|
10
|
+
var api = require('@opentelemetry/api');
|
|
11
|
+
var hono = require('hono');
|
|
12
|
+
var cors = require('hono/cors');
|
|
13
|
+
var httpException = require('hono/http-exception');
|
|
14
|
+
var requestId = require('hono/request-id');
|
|
8
15
|
var autoInstrumentationsNode = require('@opentelemetry/auto-instrumentations-node');
|
|
9
16
|
var baggageSpanProcessor = require('@opentelemetry/baggage-span-processor');
|
|
10
17
|
var contextAsyncHooks = require('@opentelemetry/context-async-hooks');
|
|
@@ -14,13 +21,6 @@ var resources = require('@opentelemetry/resources');
|
|
|
14
21
|
var sdkNode = require('@opentelemetry/sdk-node');
|
|
15
22
|
var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
|
|
16
23
|
var semanticConventions = require('@opentelemetry/semantic-conventions');
|
|
17
|
-
var otel = require('@hono/otel');
|
|
18
|
-
var zodOpenapi = require('@hono/zod-openapi');
|
|
19
|
-
var api = require('@opentelemetry/api');
|
|
20
|
-
var hono = require('hono');
|
|
21
|
-
var cors = require('hono/cors');
|
|
22
|
-
var httpException = require('hono/http-exception');
|
|
23
|
-
var requestId = require('hono/request-id');
|
|
24
24
|
var factory = require('hono/factory');
|
|
25
25
|
var swaggerUi = require('@hono/swagger-ui');
|
|
26
26
|
var streaming = require('hono/streaming');
|
|
@@ -28,8 +28,10 @@ var destr = require('destr');
|
|
|
28
28
|
var traverse = require('traverse');
|
|
29
29
|
var ai = require('ai');
|
|
30
30
|
var anthropic = require('@ai-sdk/anthropic');
|
|
31
|
+
var gateway = require('@ai-sdk/gateway');
|
|
31
32
|
var google = require('@ai-sdk/google');
|
|
32
33
|
var openai = require('@ai-sdk/openai');
|
|
34
|
+
var aiSdkProvider = require('@openrouter/ai-sdk-provider');
|
|
33
35
|
var jmespath = require('jmespath');
|
|
34
36
|
var mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
35
37
|
var streamableHttp_js = require('@modelcontextprotocol/sdk/server/streamableHttp.js');
|
|
@@ -67,8 +69,7 @@ var init_env = __esm({
|
|
|
67
69
|
NANGO_SECRET_KEY: z5.z.string().optional(),
|
|
68
70
|
OPENAI_API_KEY: z5.z.string().optional(),
|
|
69
71
|
ANTHROPIC_API_KEY: z5.z.string(),
|
|
70
|
-
INKEEP_AGENTS_RUN_API_BYPASS_SECRET: z5.z.string().optional()
|
|
71
|
-
OTEL_MAX_EXPORT_BATCH_SIZE: z5.z.coerce.number().optional()
|
|
72
|
+
INKEEP_AGENTS_RUN_API_BYPASS_SECRET: z5.z.string().optional()
|
|
72
73
|
});
|
|
73
74
|
parseEnv = () => {
|
|
74
75
|
try {
|
|
@@ -282,48 +283,48 @@ var init_conversations = __esm({
|
|
|
282
283
|
init_dbClient();
|
|
283
284
|
}
|
|
284
285
|
});
|
|
285
|
-
|
|
286
|
-
// src/instrumentation.ts
|
|
287
|
-
init_env();
|
|
288
|
-
var maxExportBatchSize = env.OTEL_MAX_EXPORT_BATCH_SIZE ?? (env.ENVIRONMENT === "development" ? 1 : 512);
|
|
289
286
|
var otlpExporter = new exporterTraceOtlpHttp.OTLPTraceExporter();
|
|
290
|
-
var
|
|
291
|
-
|
|
292
|
-
});
|
|
293
|
-
var resource = resources.resourceFromAttributes({
|
|
287
|
+
var defaultBatchProcessor = new sdkTraceBase.BatchSpanProcessor(otlpExporter);
|
|
288
|
+
var defaultResource = resources.resourceFromAttributes({
|
|
294
289
|
[semanticConventions.ATTR_SERVICE_NAME]: "inkeep-agents-run-api"
|
|
295
290
|
});
|
|
296
|
-
var
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
"@opentelemetry/instrumentation-http": {
|
|
306
|
-
enabled: true,
|
|
307
|
-
requestHook: (span, request) => {
|
|
308
|
-
const url = request?.url ?? request?.path;
|
|
309
|
-
if (!url) return;
|
|
310
|
-
const u = new URL(url, "http://localhost");
|
|
311
|
-
span.updateName(`${request?.method || "UNKNOWN"} ${u.pathname}`);
|
|
312
|
-
}
|
|
313
|
-
},
|
|
314
|
-
"@opentelemetry/instrumentation-undici": {
|
|
315
|
-
requestHook: (span) => {
|
|
316
|
-
const method = span.attributes?.["http.request.method"];
|
|
317
|
-
const host = span.attributes?.["server.address"];
|
|
318
|
-
const path = span.attributes?.["url.path"];
|
|
319
|
-
if (method && path)
|
|
320
|
-
span.updateName(host ? `${method} ${host}${path}` : `${method} ${path}`);
|
|
321
|
-
}
|
|
291
|
+
var defaultInstrumentations = [
|
|
292
|
+
autoInstrumentationsNode.getNodeAutoInstrumentations({
|
|
293
|
+
"@opentelemetry/instrumentation-http": {
|
|
294
|
+
enabled: true,
|
|
295
|
+
requestHook: (span, request) => {
|
|
296
|
+
const url = request?.url ?? request?.path;
|
|
297
|
+
if (!url) return;
|
|
298
|
+
const u = new URL(url, "http://localhost");
|
|
299
|
+
span.updateName(`${request?.method || "UNKNOWN"} ${u.pathname}`);
|
|
322
300
|
}
|
|
323
|
-
}
|
|
324
|
-
|
|
301
|
+
},
|
|
302
|
+
"@opentelemetry/instrumentation-undici": {
|
|
303
|
+
requestHook: (span) => {
|
|
304
|
+
const method = span.attributes?.["http.request.method"];
|
|
305
|
+
const host = span.attributes?.["server.address"];
|
|
306
|
+
const path = span.attributes?.["url.path"];
|
|
307
|
+
if (method && path)
|
|
308
|
+
span.updateName(host ? `${method} ${host}${path}` : `${method} ${path}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
})
|
|
312
|
+
];
|
|
313
|
+
var defaultSpanProcessors = [
|
|
314
|
+
new baggageSpanProcessor.BaggageSpanProcessor(baggageSpanProcessor.ALLOW_ALL_BAGGAGE_KEYS),
|
|
315
|
+
defaultBatchProcessor
|
|
316
|
+
];
|
|
317
|
+
var defaultContextManager = new contextAsyncHooks.AsyncLocalStorageContextManager();
|
|
318
|
+
var defaultTextMapPropagator = new core.CompositePropagator({
|
|
319
|
+
propagators: [new core.W3CTraceContextPropagator(), new core.W3CBaggagePropagator()]
|
|
320
|
+
});
|
|
321
|
+
new sdkNode.NodeSDK({
|
|
322
|
+
resource: defaultResource,
|
|
323
|
+
contextManager: defaultContextManager,
|
|
324
|
+
textMapPropagator: defaultTextMapPropagator,
|
|
325
|
+
spanProcessors: defaultSpanProcessors,
|
|
326
|
+
instrumentations: defaultInstrumentations
|
|
325
327
|
});
|
|
326
|
-
sdk.start();
|
|
327
328
|
init_dbClient();
|
|
328
329
|
init_env();
|
|
329
330
|
|
|
@@ -1398,6 +1399,17 @@ __publicField(_ArtifactReferenceSchema, "ARTIFACT_PROPS_SCHEMA", {
|
|
|
1398
1399
|
required: ["artifact_id", "task_id"]
|
|
1399
1400
|
});
|
|
1400
1401
|
var ArtifactReferenceSchema = _ArtifactReferenceSchema;
|
|
1402
|
+
|
|
1403
|
+
// src/utils/default-status-schemas.ts
|
|
1404
|
+
var retrieveStatusSchema = {
|
|
1405
|
+
type: "retrieve",
|
|
1406
|
+
description: 'Use this when the system found or retrieved specific information from searches, queries, or lookups. ONLY report ACTUAL findings that appear explicitly in the tool results - never make up data, names, numbers, or details. The label must state the SPECIFIC discovery (e.g., "Found 3 authentication methods", "Database contains 500 records", "API supports JSON format") not the act of searching. Every detail must be traceable to actual tool output. NEVER invent placeholder names, fictional data, or information not present in the activities.'
|
|
1407
|
+
};
|
|
1408
|
+
var actionStatusSchema = {
|
|
1409
|
+
type: "action",
|
|
1410
|
+
description: 'Use this when the system executed a tool or performed an operation that modified state or had side effects. ONLY report ACTUAL tool executions and their results as they appear in the tool outputs - never make up tool names, parameters, or outcomes. The label must describe what specific action was performed and its concrete result based on actual tool execution data. DO NOT make up examples like "Ran test suite with X passes" unless a test suite was ACTUALLY run and reported X passes. DO NOT say "Executed database query" unless a database query was ACTUALLY executed. Only report what literally happened. NEVER invent tool names, execution results, or details not explicitly present in the tool execution activities. If a tool failed, report the actual failure, not imagined success.'
|
|
1411
|
+
};
|
|
1412
|
+
var defaultStatusSchemas = [retrieveStatusSchema, actionStatusSchema];
|
|
1401
1413
|
var logger5 = agentsCore.getLogger("ModelFactory");
|
|
1402
1414
|
var _ModelFactory = class _ModelFactory {
|
|
1403
1415
|
/**
|
|
@@ -1411,6 +1423,18 @@ var _ModelFactory = class _ModelFactory {
|
|
|
1411
1423
|
return openai.createOpenAI(config);
|
|
1412
1424
|
case "google":
|
|
1413
1425
|
return google.createGoogleGenerativeAI(config);
|
|
1426
|
+
case "openrouter":
|
|
1427
|
+
return {
|
|
1428
|
+
...aiSdkProvider.createOpenRouter(config),
|
|
1429
|
+
textEmbeddingModel: () => {
|
|
1430
|
+
throw new Error("OpenRouter does not support text embeddings");
|
|
1431
|
+
},
|
|
1432
|
+
imageModel: () => {
|
|
1433
|
+
throw new Error("OpenRouter does not support image generation");
|
|
1434
|
+
}
|
|
1435
|
+
};
|
|
1436
|
+
case "gateway":
|
|
1437
|
+
return gateway.createGateway(config);
|
|
1414
1438
|
default:
|
|
1415
1439
|
throw new Error(`Unsupported provider: ${provider}`);
|
|
1416
1440
|
}
|
|
@@ -1470,26 +1494,29 @@ var _ModelFactory = class _ModelFactory {
|
|
|
1470
1494
|
return openai.openai(modelName);
|
|
1471
1495
|
case "google":
|
|
1472
1496
|
return google.google(modelName);
|
|
1497
|
+
case "openrouter":
|
|
1498
|
+
return aiSdkProvider.openrouter(modelName);
|
|
1499
|
+
case "gateway":
|
|
1500
|
+
return gateway.gateway(modelName);
|
|
1473
1501
|
default:
|
|
1474
|
-
throw new Error(
|
|
1502
|
+
throw new Error(
|
|
1503
|
+
`Unsupported provider: ${provider}. Supported providers are: ${_ModelFactory.BUILT_IN_PROVIDERS.join(", ")}. To access other models, use OpenRouter (openrouter/model-id) or Vercel AI Gateway (gateway/model-id).`
|
|
1504
|
+
);
|
|
1475
1505
|
}
|
|
1476
1506
|
}
|
|
1477
1507
|
/**
|
|
1478
1508
|
* Parse model string to extract provider and model name
|
|
1479
1509
|
* Examples: "anthropic/claude-sonnet-4" -> { provider: "anthropic", modelName: "claude-sonnet-4" }
|
|
1510
|
+
* "openrouter/anthropic/claude-sonnet-4" -> { provider: "openrouter", modelName: "anthropic/claude-sonnet-4" }
|
|
1480
1511
|
* "claude-sonnet-4" -> { provider: "anthropic", modelName: "claude-sonnet-4" } (default to anthropic)
|
|
1481
1512
|
*/
|
|
1482
1513
|
static parseModelString(modelString) {
|
|
1483
1514
|
if (modelString.includes("/")) {
|
|
1484
1515
|
const [provider, ...modelParts] = modelString.split("/");
|
|
1485
1516
|
const normalizedProvider = provider.toLowerCase();
|
|
1486
|
-
if (!_ModelFactory.
|
|
1487
|
-
logger5.error(
|
|
1488
|
-
{ provider: normalizedProvider, modelName: modelParts.join("/") },
|
|
1489
|
-
"Unsupported provider detected, falling back to anthropic"
|
|
1490
|
-
);
|
|
1517
|
+
if (!_ModelFactory.BUILT_IN_PROVIDERS.includes(normalizedProvider)) {
|
|
1491
1518
|
throw new Error(
|
|
1492
|
-
`Unsupported provider: ${normalizedProvider}.
|
|
1519
|
+
`Unsupported provider: ${normalizedProvider}. Supported providers are: ${_ModelFactory.BUILT_IN_PROVIDERS.join(", ")}. To access other models, use OpenRouter (openrouter/model-id) or Vercel AI Gateway (gateway/model-id).`
|
|
1493
1520
|
);
|
|
1494
1521
|
}
|
|
1495
1522
|
return {
|
|
@@ -1498,9 +1525,7 @@ var _ModelFactory = class _ModelFactory {
|
|
|
1498
1525
|
// In case model name has slashes
|
|
1499
1526
|
};
|
|
1500
1527
|
}
|
|
1501
|
-
throw new Error(
|
|
1502
|
-
`Invalid model provided: ${modelString}. Please provide a model in the format of provider/model-name.`
|
|
1503
|
-
);
|
|
1528
|
+
throw new Error(`No provider specified in model string: ${modelString}`);
|
|
1504
1529
|
}
|
|
1505
1530
|
/**
|
|
1506
1531
|
* Get generation parameters from provider options
|
|
@@ -1564,9 +1589,15 @@ var _ModelFactory = class _ModelFactory {
|
|
|
1564
1589
|
}
|
|
1565
1590
|
};
|
|
1566
1591
|
/**
|
|
1567
|
-
*
|
|
1592
|
+
* Built-in providers that have special handling
|
|
1568
1593
|
*/
|
|
1569
|
-
__publicField(_ModelFactory, "
|
|
1594
|
+
__publicField(_ModelFactory, "BUILT_IN_PROVIDERS", [
|
|
1595
|
+
"anthropic",
|
|
1596
|
+
"openai",
|
|
1597
|
+
"google",
|
|
1598
|
+
"openrouter",
|
|
1599
|
+
"gateway"
|
|
1600
|
+
]);
|
|
1570
1601
|
var ModelFactory = _ModelFactory;
|
|
1571
1602
|
|
|
1572
1603
|
// src/utils/graph-session.ts
|
|
@@ -1908,68 +1939,52 @@ var GraphSession = class {
|
|
|
1908
1939
|
}
|
|
1909
1940
|
const now = Date.now();
|
|
1910
1941
|
const elapsedTime = now - statusUpdateState.startTime;
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
continue;
|
|
1931
|
-
}
|
|
1932
|
-
const summaryToSend2 = {
|
|
1933
|
-
type: summary.data.type || summary.type,
|
|
1934
|
-
// Preserve the actual custom type from LLM
|
|
1935
|
-
label: summary.data.label,
|
|
1936
|
-
details: Object.fromEntries(
|
|
1937
|
-
Object.entries(summary.data).filter(([key]) => !["label", "type"].includes(key))
|
|
1938
|
-
)
|
|
1939
|
-
};
|
|
1940
|
-
await streamHelper.writeSummary(summaryToSend2);
|
|
1941
|
-
}
|
|
1942
|
-
const summaryTexts = result.summaries.map(
|
|
1943
|
-
(summary) => JSON.stringify({ type: summary.type, data: summary.data })
|
|
1944
|
-
);
|
|
1945
|
-
this.previousSummaries.push(...summaryTexts);
|
|
1946
|
-
if (this.statusUpdateState) {
|
|
1947
|
-
this.statusUpdateState.lastUpdateTime = now;
|
|
1948
|
-
this.statusUpdateState.lastEventCount = this.events.length;
|
|
1942
|
+
const statusComponents = statusUpdateState.config.statusComponents && statusUpdateState.config.statusComponents.length > 0 ? statusUpdateState.config.statusComponents : defaultStatusSchemas;
|
|
1943
|
+
const result = await this.generateStructuredStatusUpdate(
|
|
1944
|
+
this.events.slice(statusUpdateState.lastEventCount),
|
|
1945
|
+
elapsedTime,
|
|
1946
|
+
statusComponents,
|
|
1947
|
+
statusUpdateState.summarizerModel,
|
|
1948
|
+
this.previousSummaries
|
|
1949
|
+
);
|
|
1950
|
+
if (result.summaries && result.summaries.length > 0) {
|
|
1951
|
+
for (const summary of result.summaries) {
|
|
1952
|
+
if (!summary || !summary.type || !summary.data || !summary.data.label || Object.keys(summary.data).length === 0) {
|
|
1953
|
+
logger6.warn(
|
|
1954
|
+
{
|
|
1955
|
+
sessionId: this.sessionId,
|
|
1956
|
+
summary
|
|
1957
|
+
},
|
|
1958
|
+
"Skipping empty or invalid structured operation"
|
|
1959
|
+
);
|
|
1960
|
+
continue;
|
|
1949
1961
|
}
|
|
1950
|
-
|
|
1962
|
+
const summaryToSend = {
|
|
1963
|
+
type: summary.data.type || summary.type,
|
|
1964
|
+
// Preserve the actual custom type from LLM
|
|
1965
|
+
label: summary.data.label,
|
|
1966
|
+
details: Object.fromEntries(
|
|
1967
|
+
Object.entries(summary.data).filter(([key]) => !["label", "type"].includes(key))
|
|
1968
|
+
)
|
|
1969
|
+
};
|
|
1970
|
+
await streamHelper.writeSummary(summaryToSend);
|
|
1951
1971
|
}
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
this.events.slice(statusUpdateState.lastEventCount),
|
|
1955
|
-
elapsedTime,
|
|
1956
|
-
statusUpdateState.summarizerModel,
|
|
1957
|
-
this.previousSummaries
|
|
1972
|
+
const summaryTexts = result.summaries.map(
|
|
1973
|
+
(summary) => JSON.stringify({ type: summary.type, data: summary.data })
|
|
1958
1974
|
);
|
|
1959
|
-
this.previousSummaries.push(
|
|
1975
|
+
this.previousSummaries.push(...summaryTexts);
|
|
1976
|
+
if (this.statusUpdateState) {
|
|
1977
|
+
this.statusUpdateState.lastUpdateTime = now;
|
|
1978
|
+
this.statusUpdateState.lastEventCount = this.events.length;
|
|
1979
|
+
}
|
|
1980
|
+
return;
|
|
1960
1981
|
}
|
|
1961
1982
|
if (this.previousSummaries.length > 3) {
|
|
1962
1983
|
this.previousSummaries.shift();
|
|
1963
1984
|
}
|
|
1964
|
-
{
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
sessionId: this.sessionId,
|
|
1968
|
-
summaryToSend
|
|
1969
|
-
},
|
|
1970
|
-
"Skipping empty or invalid status update operation"
|
|
1971
|
-
);
|
|
1972
|
-
return;
|
|
1985
|
+
if (this.statusUpdateState) {
|
|
1986
|
+
this.statusUpdateState.lastUpdateTime = now;
|
|
1987
|
+
this.statusUpdateState.lastEventCount = this.events.length;
|
|
1973
1988
|
}
|
|
1974
1989
|
} catch (error) {
|
|
1975
1990
|
logger6.error(
|
|
@@ -2050,106 +2065,6 @@ var GraphSession = class {
|
|
|
2050
2065
|
this.statusUpdateState.updateLock = false;
|
|
2051
2066
|
}
|
|
2052
2067
|
}
|
|
2053
|
-
/**
|
|
2054
|
-
* Generate user-focused progress summary hiding internal operations
|
|
2055
|
-
*/
|
|
2056
|
-
async generateProgressSummary(newEvents, elapsedTime, summarizerModel, previousSummaries = []) {
|
|
2057
|
-
return tracer.startActiveSpan(
|
|
2058
|
-
"graph_session.generate_progress_summary",
|
|
2059
|
-
{
|
|
2060
|
-
attributes: {
|
|
2061
|
-
"graph_session.id": this.sessionId,
|
|
2062
|
-
"events.count": newEvents.length,
|
|
2063
|
-
"elapsed_time.seconds": Math.round(elapsedTime / 1e3),
|
|
2064
|
-
"llm.model": summarizerModel?.model,
|
|
2065
|
-
"previous_summaries.count": previousSummaries.length
|
|
2066
|
-
}
|
|
2067
|
-
},
|
|
2068
|
-
async (span) => {
|
|
2069
|
-
try {
|
|
2070
|
-
const userVisibleActivities = this.extractUserVisibleActivities(newEvents);
|
|
2071
|
-
let conversationContext = "";
|
|
2072
|
-
if (this.tenantId && this.projectId) {
|
|
2073
|
-
try {
|
|
2074
|
-
const conversationHistory = await getFormattedConversationHistory({
|
|
2075
|
-
tenantId: this.tenantId,
|
|
2076
|
-
projectId: this.projectId,
|
|
2077
|
-
conversationId: this.sessionId,
|
|
2078
|
-
options: {
|
|
2079
|
-
limit: 10,
|
|
2080
|
-
// Get recent conversation context
|
|
2081
|
-
maxOutputTokens: 2e3
|
|
2082
|
-
},
|
|
2083
|
-
filters: {}
|
|
2084
|
-
});
|
|
2085
|
-
conversationContext = conversationHistory.trim() ? `
|
|
2086
|
-
User's Question/Context:
|
|
2087
|
-
${conversationHistory}
|
|
2088
|
-
` : "";
|
|
2089
|
-
} catch (error) {
|
|
2090
|
-
logger6.warn(
|
|
2091
|
-
{ sessionId: this.sessionId, error },
|
|
2092
|
-
"Failed to fetch conversation history for status update"
|
|
2093
|
-
);
|
|
2094
|
-
}
|
|
2095
|
-
}
|
|
2096
|
-
const previousSummaryContext = previousSummaries.length > 0 ? `
|
|
2097
|
-
Previous updates provided to user:
|
|
2098
|
-
${previousSummaries.map((s, i) => `${i + 1}. ${s}`).join("\n")}
|
|
2099
|
-
` : "";
|
|
2100
|
-
const basePrompt = `Generate a meaningful status update that tells the user what specific information or result was just found/achieved.${conversationContext}${previousSummaries.length > 0 ? `
|
|
2101
|
-
${previousSummaryContext}` : ""}
|
|
2102
|
-
|
|
2103
|
-
Activities:
|
|
2104
|
-
${userVisibleActivities.join("\n") || "No New Activities"}
|
|
2105
|
-
|
|
2106
|
-
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".
|
|
2107
|
-
|
|
2108
|
-
${this.statusUpdateState?.config.prompt?.trim() || ""}`;
|
|
2109
|
-
const prompt = basePrompt;
|
|
2110
|
-
let modelToUse = summarizerModel;
|
|
2111
|
-
if (!summarizerModel?.model?.trim()) {
|
|
2112
|
-
if (!this.statusUpdateState?.baseModel?.model?.trim()) {
|
|
2113
|
-
throw new Error(
|
|
2114
|
-
"Either summarizer or base model is required for progress summary generation. Please configure models at the project level."
|
|
2115
|
-
);
|
|
2116
|
-
}
|
|
2117
|
-
modelToUse = this.statusUpdateState.baseModel;
|
|
2118
|
-
}
|
|
2119
|
-
if (!modelToUse) {
|
|
2120
|
-
throw new Error("No model configuration available");
|
|
2121
|
-
}
|
|
2122
|
-
const model = ModelFactory.createModel(modelToUse);
|
|
2123
|
-
const { text } = await ai.generateText({
|
|
2124
|
-
model,
|
|
2125
|
-
prompt,
|
|
2126
|
-
experimental_telemetry: {
|
|
2127
|
-
isEnabled: true,
|
|
2128
|
-
functionId: `status_update_${this.sessionId}`,
|
|
2129
|
-
recordInputs: true,
|
|
2130
|
-
recordOutputs: true,
|
|
2131
|
-
metadata: {
|
|
2132
|
-
operation: "progress_summary_generation",
|
|
2133
|
-
sessionId: this.sessionId
|
|
2134
|
-
}
|
|
2135
|
-
}
|
|
2136
|
-
});
|
|
2137
|
-
span.setAttributes({
|
|
2138
|
-
"summary.length": text.trim().length,
|
|
2139
|
-
"user_activities.count": userVisibleActivities.length
|
|
2140
|
-
});
|
|
2141
|
-
span.setStatus({ code: api.SpanStatusCode.OK });
|
|
2142
|
-
return text.trim();
|
|
2143
|
-
} catch (error) {
|
|
2144
|
-
agentsCore.setSpanWithError(span, error);
|
|
2145
|
-
logger6.error({ error }, "Failed to generate summary, using fallback");
|
|
2146
|
-
return this.generateFallbackSummary(newEvents, elapsedTime);
|
|
2147
|
-
} finally {
|
|
2148
|
-
span.end();
|
|
2149
|
-
}
|
|
2150
|
-
}
|
|
2151
|
-
);
|
|
2152
|
-
}
|
|
2153
2068
|
/**
|
|
2154
2069
|
* Generate structured status update using configured data components
|
|
2155
2070
|
*/
|
|
@@ -2228,17 +2143,45 @@ Rules:
|
|
|
2228
2143
|
- Fill in data for relevant components only
|
|
2229
2144
|
- Use 'no_relevant_updates' if nothing substantially new to report. DO NOT WRITE LABELS OR USE OTHER COMPONENTS IF YOU USE THIS COMPONENT.
|
|
2230
2145
|
- Never repeat previous values, make every update EXTREMELY unique. If you cannot do that the update is not worth mentioning.
|
|
2231
|
-
- Labels MUST be short 3-
|
|
2146
|
+
- Labels MUST be short 3-7 word phrases with ACTUAL information discovered. NEVER MAKE UP SOMETHING WITHOUT BACKING IT UP WITH ACTUAL INFORMATION.
|
|
2232
2147
|
- 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.
|
|
2233
2148
|
- DO NOT use action words like "Searching", "Processing", "Analyzing" - state what was FOUND
|
|
2234
2149
|
- Include specific details, numbers, requirements, or insights discovered
|
|
2235
2150
|
- Examples: "Admin permissions required", "Three OAuth steps found", "Token expires daily"
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
-
|
|
2239
|
-
-
|
|
2240
|
-
-
|
|
2241
|
-
-
|
|
2151
|
+
|
|
2152
|
+
CRITICAL - HIDE ALL INTERNAL SYSTEM OPERATIONS:
|
|
2153
|
+
- You are ONE unified AI system presenting results to the user
|
|
2154
|
+
- 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"
|
|
2155
|
+
- NEVER reveal internal architecture: No mentions of different agents, components, systems, or modules working together
|
|
2156
|
+
- NEVER mention artifact operations: Users don't need to know about data being saved, stored, or organized internally
|
|
2157
|
+
- NEVER describe handoffs or transitions: Present everything as one seamless operation
|
|
2158
|
+
- If you see "transfer", "delegation_sent", "delegation_returned", or "artifact_saved" events - IGNORE THEM or translate to user-facing information only
|
|
2159
|
+
- Focus ONLY on actual discoveries, findings, and results that matter to the user
|
|
2160
|
+
|
|
2161
|
+
- Bad examples:
|
|
2162
|
+
* "Transferring to search agent"
|
|
2163
|
+
* "Delegating research task"
|
|
2164
|
+
* "Routing to QA specialist"
|
|
2165
|
+
* "Artifact saved successfully"
|
|
2166
|
+
* "Storing results for later"
|
|
2167
|
+
* "Passing request to tool handler"
|
|
2168
|
+
* "Continuing with analysis"
|
|
2169
|
+
* "Handing off to processor"
|
|
2170
|
+
- Good examples:
|
|
2171
|
+
* "Slack bot needs admin privileges"
|
|
2172
|
+
* "Found 3-step OAuth flow required"
|
|
2173
|
+
* "Channel limit is 500 per workspace"
|
|
2174
|
+
* Use no_relevant_updates if nothing new to report
|
|
2175
|
+
|
|
2176
|
+
CRITICAL ANTI-HALLUCINATION RULES:
|
|
2177
|
+
- NEVER MAKE UP SOMETHING WITHOUT BACKING IT UP WITH ACTUAL INFORMATION. EVERY SINGLE UPDATE MUST BE BACKED UP WITH ACTUAL INFORMATION.
|
|
2178
|
+
- DO NOT MAKE UP PEOPLE, NAMES, PLACES, THINGS, ORGANIZATIONS, OR INFORMATION. IT IS OBVIOUS WHEN A PERSON/ENTITY DOES NOT EXIST.
|
|
2179
|
+
- Only report facts that are EXPLICITLY mentioned in the activities or tool results
|
|
2180
|
+
- If you don't have concrete information about something, DO NOT mention it
|
|
2181
|
+
- Never invent names like "John Doe", "Alice", "Bob", or any other placeholder names
|
|
2182
|
+
- Never create fictional companies, products, or services
|
|
2183
|
+
- If a tool returned no results or an error, DO NOT pretend it found something
|
|
2184
|
+
- Every detail in your status update must be traceable back to the actual activities provided
|
|
2242
2185
|
|
|
2243
2186
|
REMEMBER YOU CAN ONLY USE 'no_relevant_updates' ALONE! IT CANNOT BE CONCATENATED WITH OTHER STATUS UPDATES!
|
|
2244
2187
|
|
|
@@ -2311,7 +2254,7 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
|
|
|
2311
2254
|
}
|
|
2312
2255
|
return z5.z.object({
|
|
2313
2256
|
label: z5.z.string().describe(
|
|
2314
|
-
'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.'
|
|
2257
|
+
'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.'
|
|
2315
2258
|
)
|
|
2316
2259
|
});
|
|
2317
2260
|
}
|
|
@@ -2321,7 +2264,7 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
|
|
|
2321
2264
|
buildZodSchemaFromJson(jsonSchema) {
|
|
2322
2265
|
const properties = {};
|
|
2323
2266
|
properties["label"] = z5.z.string().describe(
|
|
2324
|
-
'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?'
|
|
2267
|
+
'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.'
|
|
2325
2268
|
);
|
|
2326
2269
|
for (const [key, value] of Object.entries(jsonSchema.properties)) {
|
|
2327
2270
|
let zodType;
|
|
@@ -2398,41 +2341,12 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
|
|
|
2398
2341
|
);
|
|
2399
2342
|
break;
|
|
2400
2343
|
}
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
);
|
|
2407
|
-
break;
|
|
2408
|
-
}
|
|
2409
|
-
case "delegation_sent": {
|
|
2410
|
-
const data = event.data;
|
|
2411
|
-
activities.push(
|
|
2412
|
-
`\u{1F4E4} **Processing**: ${data.taskDescription}
|
|
2413
|
-
${data.context ? `Context: ${JSON.stringify(data.context, null, 2)}` : ""}`
|
|
2414
|
-
);
|
|
2415
|
-
break;
|
|
2416
|
-
}
|
|
2417
|
-
case "delegation_returned": {
|
|
2418
|
-
const data = event.data;
|
|
2419
|
-
activities.push(
|
|
2420
|
-
`\u{1F4E5} **Completed subtask**
|
|
2421
|
-
Result: ${JSON.stringify(data.result, null, 2)}`
|
|
2422
|
-
);
|
|
2423
|
-
break;
|
|
2424
|
-
}
|
|
2425
|
-
case "artifact_saved": {
|
|
2426
|
-
const data = event.data;
|
|
2427
|
-
activities.push(
|
|
2428
|
-
`\u{1F4BE} **Artifact Saved**: ${data.artifactType}
|
|
2429
|
-
ID: ${data.artifactId}
|
|
2430
|
-
Task: ${data.taskId}
|
|
2431
|
-
${data.summaryData ? `Summary: ${data.summaryData}` : ""}
|
|
2432
|
-
${data.fullData ? `Full Data: ${data.fullData}` : ""}`
|
|
2433
|
-
);
|
|
2344
|
+
// INTERNAL OPERATIONS - DO NOT EXPOSE TO STATUS UPDATES
|
|
2345
|
+
case "transfer":
|
|
2346
|
+
case "delegation_sent":
|
|
2347
|
+
case "delegation_returned":
|
|
2348
|
+
case "artifact_saved":
|
|
2434
2349
|
break;
|
|
2435
|
-
}
|
|
2436
2350
|
case "agent_reasoning": {
|
|
2437
2351
|
const data = event.data;
|
|
2438
2352
|
activities.push(
|
|
@@ -2457,21 +2371,6 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
|
|
|
2457
2371
|
}
|
|
2458
2372
|
return activities;
|
|
2459
2373
|
}
|
|
2460
|
-
/**
|
|
2461
|
-
* Generate fallback summary when LLM fails
|
|
2462
|
-
*/
|
|
2463
|
-
generateFallbackSummary(events, elapsedTime) {
|
|
2464
|
-
const timeStr = Math.round(elapsedTime / 1e3);
|
|
2465
|
-
const toolCalls = events.filter((e) => e.eventType === "tool_execution").length;
|
|
2466
|
-
const artifacts = events.filter((e) => e.eventType === "artifact_saved").length;
|
|
2467
|
-
if (artifacts > 0) {
|
|
2468
|
-
return `Generated ${artifacts} result${artifacts > 1 ? "s" : ""} so far (${timeStr}s elapsed)`;
|
|
2469
|
-
} else if (toolCalls > 0) {
|
|
2470
|
-
return `Used ${toolCalls} tool${toolCalls > 1 ? "s" : ""} to gather information (${timeStr}s elapsed)`;
|
|
2471
|
-
} else {
|
|
2472
|
-
return `Processing your request... (${timeStr}s elapsed)`;
|
|
2473
|
-
}
|
|
2474
|
-
}
|
|
2475
2374
|
/**
|
|
2476
2375
|
* Process a single artifact to generate name and description using conversation context
|
|
2477
2376
|
*/
|
|
@@ -3225,7 +3124,7 @@ var _IncrementalStreamParser = class _IncrementalStreamParser {
|
|
|
3225
3124
|
await this.streamPart(part);
|
|
3226
3125
|
}
|
|
3227
3126
|
if (this.pendingTextBuffer) {
|
|
3228
|
-
const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
|
|
3127
|
+
const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/artifact:ref>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
|
|
3229
3128
|
if (cleanedText) {
|
|
3230
3129
|
this.collectedParts.push({
|
|
3231
3130
|
kind: "text",
|
|
@@ -3303,7 +3202,7 @@ var _IncrementalStreamParser = class _IncrementalStreamParser {
|
|
|
3303
3202
|
if (part.kind === "text" && part.text) {
|
|
3304
3203
|
this.pendingTextBuffer += part.text;
|
|
3305
3204
|
if (!this.artifactParser.hasIncompleteArtifact(this.pendingTextBuffer)) {
|
|
3306
|
-
const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
|
|
3205
|
+
const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/artifact:ref>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
|
|
3307
3206
|
if (cleanedText) {
|
|
3308
3207
|
await this.streamHelper.streamText(cleanedText, 50);
|
|
3309
3208
|
}
|
|
@@ -3311,7 +3210,7 @@ var _IncrementalStreamParser = class _IncrementalStreamParser {
|
|
|
3311
3210
|
}
|
|
3312
3211
|
} else if (part.kind === "data" && part.data) {
|
|
3313
3212
|
if (this.pendingTextBuffer) {
|
|
3314
|
-
const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
|
|
3213
|
+
const cleanedText = this.pendingTextBuffer.replace(/<\/?artifact:ref(?:\s[^>]*)?>\/?>/g, "").replace(/<\/?artifact(?:\s[^>]*)?>\/?>/g, "").replace(/<\/artifact:ref>/g, "").replace(/<\/(?:\w+:)?artifact>/g, "");
|
|
3315
3214
|
if (cleanedText) {
|
|
3316
3215
|
await this.streamHelper.streamText(cleanedText, 50);
|
|
3317
3216
|
}
|
|
@@ -7298,7 +7197,7 @@ var _VercelDataStreamHelper = class _VercelDataStreamHelper {
|
|
|
7298
7197
|
__publicField(this, "queuedEvents", []);
|
|
7299
7198
|
// Timing tracking for text sequences (text-end to text-start gap)
|
|
7300
7199
|
__publicField(this, "lastTextEndTimestamp", 0);
|
|
7301
|
-
__publicField(this, "TEXT_GAP_THRESHOLD",
|
|
7200
|
+
__publicField(this, "TEXT_GAP_THRESHOLD", 2e3);
|
|
7302
7201
|
// milliseconds - if gap between text sequences is less than this, queue operations
|
|
7303
7202
|
// Connection management and forced cleanup
|
|
7304
7203
|
__publicField(this, "connectionDropTimer");
|
|
@@ -9314,21 +9213,21 @@ function createExecutionHono(serverConfig, credentialStores) {
|
|
|
9314
9213
|
app6.route("/v1/mcp", mcp_default);
|
|
9315
9214
|
app6.route("/agents", agents_default);
|
|
9316
9215
|
setupOpenAPIRoutes(app6);
|
|
9317
|
-
app6.use("/tenants/*", async (
|
|
9216
|
+
app6.use("/tenants/*", async (_c, next) => {
|
|
9318
9217
|
await next();
|
|
9319
|
-
await
|
|
9218
|
+
await defaultBatchProcessor.forceFlush();
|
|
9320
9219
|
});
|
|
9321
|
-
app6.use("/agents/*", async (
|
|
9220
|
+
app6.use("/agents/*", async (_c, next) => {
|
|
9322
9221
|
await next();
|
|
9323
|
-
await
|
|
9222
|
+
await defaultBatchProcessor.forceFlush();
|
|
9324
9223
|
});
|
|
9325
|
-
app6.use("/v1/*", async (
|
|
9224
|
+
app6.use("/v1/*", async (_c, next) => {
|
|
9326
9225
|
await next();
|
|
9327
|
-
await
|
|
9226
|
+
await defaultBatchProcessor.forceFlush();
|
|
9328
9227
|
});
|
|
9329
|
-
app6.use("/api/*", async (
|
|
9228
|
+
app6.use("/api/*", async (_c, next) => {
|
|
9330
9229
|
await next();
|
|
9331
|
-
await
|
|
9230
|
+
await defaultBatchProcessor.forceFlush();
|
|
9332
9231
|
});
|
|
9333
9232
|
const baseApp = new hono.Hono();
|
|
9334
9233
|
baseApp.route("/", app6);
|