@inkeep/agents-run-api 0.1.6 → 0.1.7

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Inkeep Execution API
1
+ # Inkeep Agents Run API
2
2
 
3
- The Execution API is responsible for runtime agent operations, including Agent-to-Agent (A2A) communication, chat completions, and MCP (Model Context Protocol) tool integrations.
3
+ The Agents Run API is responsible for runtime agent operations, including Agent-to-Agent (A2A) communication, chat completions, and MCP (Model Context Protocol) tool integrations.
4
4
 
5
5
  ## Overview
6
6
 
@@ -82,8 +82,8 @@ The API uses environment-based configuration with defaults for local development
82
82
 
83
83
  ## Integration
84
84
 
85
- ### With Management API
86
- The Execution API reads agent configurations and relationships created by the Management API but doesn't modify them during runtime.
85
+ ### With Agents Manage API
86
+ The Agents Run API reads agent configurations and relationships created by the Agents Manage API but doesn't modify them during runtime.
87
87
 
88
88
  ### With MCP Tools
89
89
  Supports multiple MCP transport types:
@@ -114,4 +114,4 @@ The API implements comprehensive error handling:
114
114
  - **API Key Authentication**: Configurable authentication methods
115
115
  - **Input Validation**: Request sanitization and type checking
116
116
  - **CORS**: Configurable cross-origin policies
117
- - **Rate Limiting**: Configurable request throttling
117
+ - **Rate Limiting**: Configurable request throttling
@@ -30,22 +30,17 @@ var envSchema = z.object({
30
30
  NODE_ENV: z.enum(["development", "production", "test"]).optional(),
31
31
  ENVIRONMENT: z.enum(["development", "production", "pentest", "test"]).optional().default("development"),
32
32
  DB_FILE_NAME: z.string().default("file:../local.db"),
33
- PORT: z.coerce.number().optional().default(3003),
34
- AGENT_BASE_URL: z.string().optional(),
33
+ AGENTS_RUN_API_URL: z.string().optional().default("http://localhost:3003"),
35
34
  LOG_LEVEL: z.enum(["trace", "debug", "info", "warn", "error"]).optional().default("debug"),
36
35
  NANGO_SECRET_KEY: z.string().optional(),
37
36
  OPENAI_API_KEY: z.string().optional(),
38
37
  ANTHROPIC_API_KEY: z.string(),
39
38
  INKEEP_AGENTS_RUN_API_BYPASS_SECRET: z.string().optional(),
40
- OTEL_MAX_EXPORT_BATCH_SIZE: z.coerce.number().optional(),
41
- OTEL_EXPORTER_OTLP_ENDPOINT: z.string().optional().default("http://localhost:14318/v1/traces")
39
+ OTEL_MAX_EXPORT_BATCH_SIZE: z.coerce.number().optional()
42
40
  });
43
41
  var parseEnv = () => {
44
42
  try {
45
43
  const parsedEnv = envSchema.parse(process.env);
46
- if (!parsedEnv.AGENT_BASE_URL) {
47
- parsedEnv.AGENT_BASE_URL = `http://localhost:${parsedEnv.PORT}`;
48
- }
49
44
  return parsedEnv;
50
45
  } catch (error) {
51
46
  if (error instanceof z.ZodError) {
@@ -1 +1 @@
1
- export { createDefaultConversationHistoryConfig, getFormattedConversationHistory, getFullConversationContext, getScopedHistory, getUserFacingHistory, saveA2AMessageResponse } from './chunk-P6IQZWFC.js';
1
+ export { createDefaultConversationHistoryConfig, getFormattedConversationHistory, getFullConversationContext, getScopedHistory, getUserFacingHistory, saveA2AMessageResponse } from './chunk-HO5J26MO.js';
package/dist/index.cjs CHANGED
@@ -103,22 +103,17 @@ var init_env = __esm({
103
103
  NODE_ENV: z5.z.enum(["development", "production", "test"]).optional(),
104
104
  ENVIRONMENT: z5.z.enum(["development", "production", "pentest", "test"]).optional().default("development"),
105
105
  DB_FILE_NAME: z5.z.string().default("file:../local.db"),
106
- PORT: z5.z.coerce.number().optional().default(3003),
107
- AGENT_BASE_URL: z5.z.string().optional(),
106
+ AGENTS_RUN_API_URL: z5.z.string().optional().default("http://localhost:3003"),
108
107
  LOG_LEVEL: z5.z.enum(["trace", "debug", "info", "warn", "error"]).optional().default("debug"),
109
108
  NANGO_SECRET_KEY: z5.z.string().optional(),
110
109
  OPENAI_API_KEY: z5.z.string().optional(),
111
110
  ANTHROPIC_API_KEY: z5.z.string(),
112
111
  INKEEP_AGENTS_RUN_API_BYPASS_SECRET: z5.z.string().optional(),
113
- OTEL_MAX_EXPORT_BATCH_SIZE: z5.z.coerce.number().optional(),
114
- OTEL_EXPORTER_OTLP_ENDPOINT: z5.z.string().optional().default("http://localhost:14318/v1/traces")
112
+ OTEL_MAX_EXPORT_BATCH_SIZE: z5.z.coerce.number().optional()
115
113
  });
116
114
  parseEnv = () => {
117
115
  try {
118
116
  const parsedEnv = envSchema.parse(process.env);
119
- if (!parsedEnv.AGENT_BASE_URL) {
120
- parsedEnv.AGENT_BASE_URL = `http://localhost:${parsedEnv.PORT}`;
121
- }
122
117
  return parsedEnv;
123
118
  } catch (error) {
124
119
  if (error instanceof z5.z.ZodError) {
@@ -331,8 +326,7 @@ var init_conversations = __esm({
331
326
 
332
327
  // src/instrumentation.ts
333
328
  init_env();
334
- var otlpUrl = env.OTEL_EXPORTER_OTLP_ENDPOINT;
335
- var otlpExporter = new exporterTraceOtlpProto.OTLPTraceExporter({ url: otlpUrl });
329
+ var otlpExporter = new exporterTraceOtlpProto.OTLPTraceExporter();
336
330
  var FanOutSpanProcessor = class {
337
331
  constructor(inner) {
338
332
  this.inner = inner;
@@ -441,6 +435,10 @@ function createExecutionContext(params) {
441
435
  // src/middleware/api-key-auth.ts
442
436
  var logger2 = agentsCore.getLogger("env-key-auth");
443
437
  var apiKeyAuth = () => factory.createMiddleware(async (c, next) => {
438
+ if (c.req.method === "OPTIONS") {
439
+ await next();
440
+ return;
441
+ }
444
442
  const authHeader = c.req.header("Authorization");
445
443
  const tenantId = c.req.header("x-inkeep-tenant-id");
446
444
  const projectId = c.req.header("x-inkeep-project-id");
@@ -576,13 +574,13 @@ function setupOpenAPIRoutes(app6) {
576
574
  const document = app6.getOpenAPIDocument({
577
575
  openapi: "3.0.0",
578
576
  info: {
579
- title: "Inkeep Execution API",
577
+ title: "Inkeep Agents Run API",
580
578
  version: "1.0.0",
581
- description: "Complete REST API for Inkeep Execution application including chat completions, A2A agent communication, and comprehensive CRUD operations for all entities"
579
+ description: "Chat completions, MCP, and A2A run endpoints in the Inkeep Agent Framework."
582
580
  },
583
581
  servers: [
584
582
  {
585
- url: env.AGENT_BASE_URL || `http://localhost:3003`,
583
+ url: env.AGENTS_RUN_API_URL,
586
584
  description: "Development server"
587
585
  }
588
586
  ]
@@ -598,7 +596,7 @@ function setupOpenAPIRoutes(app6) {
598
596
  "/docs",
599
597
  swaggerUi.swaggerUI({
600
598
  url: "/openapi.json",
601
- title: "Inkeep Execution API Documentation"
599
+ title: "Inkeep Agents Run API Documentation"
602
600
  })
603
601
  );
604
602
  }
@@ -1217,11 +1215,6 @@ init_dbClient();
1217
1215
  // src/agents/Agent.ts
1218
1216
  init_conversations();
1219
1217
  init_dbClient();
1220
-
1221
- // package.json
1222
- var package_default = {
1223
- version: "0.1.6"};
1224
- var tracer = agentsCore.getTracer("agents-run-api", package_default.version);
1225
1218
  function agentInitializingOp(sessionId, graphId) {
1226
1219
  return {
1227
1220
  type: "agent_initializing",
@@ -1350,7 +1343,9 @@ var _ModelFactory = class _ModelFactory {
1350
1343
  */
1351
1344
  static createModel(config2) {
1352
1345
  if (!config2?.model?.trim()) {
1353
- throw new Error("Model configuration is required. Please configure models at the project level.");
1346
+ throw new Error(
1347
+ "Model configuration is required. Please configure models at the project level."
1348
+ );
1354
1349
  }
1355
1350
  const modelSettings = config2;
1356
1351
  const modelString = modelSettings.model.trim();
@@ -1371,7 +1366,9 @@ var _ModelFactory = class _ModelFactory {
1371
1366
  case "openai":
1372
1367
  return _ModelFactory.createOpenAIModel(modelName, modelSettings.providerOptions);
1373
1368
  default:
1374
- throw new Error(`Unsupported provider: ${provider}. Supported providers are: ${_ModelFactory.SUPPORTED_PROVIDERS.join(", ")}`);
1369
+ throw new Error(
1370
+ `Unsupported provider: ${provider}. Supported providers are: ${_ModelFactory.SUPPORTED_PROVIDERS.join(", ")}`
1371
+ );
1375
1372
  }
1376
1373
  } catch (error) {
1377
1374
  logger5.error(
@@ -1382,7 +1379,9 @@ var _ModelFactory = class _ModelFactory {
1382
1379
  },
1383
1380
  "Failed to create model"
1384
1381
  );
1385
- throw new Error(`Failed to create model ${modelString}: ${error instanceof Error ? error.message : "Unknown error"}`);
1382
+ throw new Error(
1383
+ `Failed to create model ${modelString}: ${error instanceof Error ? error.message : "Unknown error"}`
1384
+ );
1386
1385
  }
1387
1386
  }
1388
1387
  /**
@@ -1526,6 +1525,7 @@ var ModelFactory = _ModelFactory;
1526
1525
  // src/utils/graph-session.ts
1527
1526
  init_conversations();
1528
1527
  init_dbClient();
1528
+ var tracer = agentsCore.getTracer("agents-run-api");
1529
1529
 
1530
1530
  // src/utils/stream-registry.ts
1531
1531
  var streamHelperRegistry = /* @__PURE__ */ new Map();
@@ -1635,12 +1635,15 @@ var GraphSession = class {
1635
1635
  if (eventType === "artifact_saved" && data.pendingGeneration) {
1636
1636
  const artifactId = data.artifactId;
1637
1637
  if (this.pendingArtifacts.size >= this.MAX_PENDING_ARTIFACTS) {
1638
- logger6.warn({
1639
- sessionId: this.sessionId,
1640
- artifactId,
1641
- pendingCount: this.pendingArtifacts.size,
1642
- maxAllowed: this.MAX_PENDING_ARTIFACTS
1643
- }, "Too many pending artifacts, skipping processing");
1638
+ logger6.warn(
1639
+ {
1640
+ sessionId: this.sessionId,
1641
+ artifactId,
1642
+ pendingCount: this.pendingArtifacts.size,
1643
+ maxAllowed: this.MAX_PENDING_ARTIFACTS
1644
+ },
1645
+ "Too many pending artifacts, skipping processing"
1646
+ );
1644
1647
  return;
1645
1648
  }
1646
1649
  this.pendingArtifacts.add(artifactId);
@@ -1653,21 +1656,27 @@ var GraphSession = class {
1653
1656
  this.artifactProcessingErrors.set(artifactId, errorCount);
1654
1657
  if (errorCount >= this.MAX_ARTIFACT_RETRIES) {
1655
1658
  this.pendingArtifacts.delete(artifactId);
1656
- logger6.error({
1657
- sessionId: this.sessionId,
1658
- artifactId,
1659
- errorCount,
1660
- maxRetries: this.MAX_ARTIFACT_RETRIES,
1661
- error: error instanceof Error ? error.message : "Unknown error",
1662
- stack: error instanceof Error ? error.stack : void 0
1663
- }, "Artifact processing failed after max retries, giving up");
1659
+ logger6.error(
1660
+ {
1661
+ sessionId: this.sessionId,
1662
+ artifactId,
1663
+ errorCount,
1664
+ maxRetries: this.MAX_ARTIFACT_RETRIES,
1665
+ error: error instanceof Error ? error.message : "Unknown error",
1666
+ stack: error instanceof Error ? error.stack : void 0
1667
+ },
1668
+ "Artifact processing failed after max retries, giving up"
1669
+ );
1664
1670
  } else {
1665
- logger6.warn({
1666
- sessionId: this.sessionId,
1667
- artifactId,
1668
- errorCount,
1669
- error: error instanceof Error ? error.message : "Unknown error"
1670
- }, "Artifact processing failed, may retry");
1671
+ logger6.warn(
1672
+ {
1673
+ sessionId: this.sessionId,
1674
+ artifactId,
1675
+ errorCount,
1676
+ error: error instanceof Error ? error.message : "Unknown error"
1677
+ },
1678
+ "Artifact processing failed, may retry"
1679
+ );
1671
1680
  }
1672
1681
  });
1673
1682
  });
@@ -2071,7 +2080,9 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
2071
2080
  let modelToUse = summarizerModel;
2072
2081
  if (!summarizerModel?.model?.trim()) {
2073
2082
  if (!this.statusUpdateState?.baseModel?.model?.trim()) {
2074
- throw new Error("Either summarizer or base model is required for progress summary generation. Please configure models at the project level.");
2083
+ throw new Error(
2084
+ "Either summarizer or base model is required for progress summary generation. Please configure models at the project level."
2085
+ );
2075
2086
  }
2076
2087
  modelToUse = this.statusUpdateState.baseModel;
2077
2088
  }
@@ -2199,7 +2210,9 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
2199
2210
  let modelToUse = summarizerModel;
2200
2211
  if (!summarizerModel?.model?.trim()) {
2201
2212
  if (!this.statusUpdateState?.baseModel?.model?.trim()) {
2202
- throw new Error("Either summarizer or base model is required for status update generation. Please configure models at the project level.");
2213
+ throw new Error(
2214
+ "Either summarizer or base model is required for status update generation. Please configure models at the project level."
2215
+ );
2203
2216
  }
2204
2217
  modelToUse = this.statusUpdateState.baseModel;
2205
2218
  }
@@ -2489,7 +2502,9 @@ Make it specific and relevant.`;
2489
2502
  let modelToUse = this.statusUpdateState?.summarizerModel;
2490
2503
  if (!modelToUse?.model?.trim()) {
2491
2504
  if (!this.statusUpdateState?.baseModel?.model?.trim()) {
2492
- throw new Error("Either summarizer or base model is required for artifact name generation. Please configure models at the project level.");
2505
+ throw new Error(
2506
+ "Either summarizer or base model is required for artifact name generation. Please configure models at the project level."
2507
+ );
2493
2508
  }
2494
2509
  modelToUse = this.statusUpdateState.baseModel;
2495
2510
  }
@@ -2748,7 +2763,9 @@ var _ArtifactParser = class _ArtifactParser {
2748
2763
  * More robust detection that handles streaming fragments
2749
2764
  */
2750
2765
  hasIncompleteArtifact(text) {
2751
- return /^.*<(?:artifact(?::ref)?|a(?:r(?:t(?:i(?:f(?:a(?:c(?:t(?::(?:r(?:e(?:f)?)?)?)?)?)?)?)?)?)?)?)?$/.test(text) || /^.*<artifact:ref(?:[^>]*)$/.test(text) || // Incomplete artifact:ref at end
2766
+ return /^.*<(?:artifact(?::ref)?|a(?:r(?:t(?:i(?:f(?:a(?:c(?:t(?::(?:r(?:e(?:f)?)?)?)?)?)?)?)?)?)?)?)?$/.test(
2767
+ text
2768
+ ) || /^.*<artifact:ref(?:[^>]*)$/.test(text) || // Incomplete artifact:ref at end
2752
2769
  this.findSafeTextBoundary(text) < text.length;
2753
2770
  }
2754
2771
  /**
@@ -6219,6 +6236,40 @@ ${output}`;
6219
6236
  }
6220
6237
  };
6221
6238
 
6239
+ // src/utils/model-resolver.ts
6240
+ init_dbClient();
6241
+ async function resolveModelConfig(graphId, agent) {
6242
+ if (agent.models?.base?.model) {
6243
+ return {
6244
+ base: agent.models.base,
6245
+ structuredOutput: agent.models.structuredOutput || agent.models.base,
6246
+ summarizer: agent.models.summarizer || agent.models.base
6247
+ };
6248
+ }
6249
+ const graph = await agentsCore.getAgentGraph(dbClient_default)({
6250
+ scopes: { tenantId: agent.tenantId, projectId: agent.projectId },
6251
+ graphId
6252
+ });
6253
+ if (graph?.models?.base?.model) {
6254
+ return {
6255
+ base: graph.models.base,
6256
+ structuredOutput: agent.models?.structuredOutput || graph.models.structuredOutput || graph.models.base,
6257
+ summarizer: agent.models?.summarizer || graph.models.summarizer || graph.models.base
6258
+ };
6259
+ }
6260
+ const project = await agentsCore.getProject(dbClient_default)({
6261
+ scopes: { tenantId: agent.tenantId, projectId: agent.projectId }
6262
+ });
6263
+ if (project?.models?.base?.model) {
6264
+ return {
6265
+ base: project.models.base,
6266
+ structuredOutput: agent.models?.structuredOutput || project.models.structuredOutput || project.models.base,
6267
+ summarizer: agent.models?.summarizer || project.models.summarizer || project.models.base
6268
+ };
6269
+ }
6270
+ throw new Error("Base model configuration is required. Please configure models at the project level.");
6271
+ }
6272
+
6222
6273
  // src/agents/generateTaskHandler.ts
6223
6274
  function parseEmbeddedJson(data) {
6224
6275
  return traverse__default.default(data).map(function(x) {
@@ -6501,7 +6552,7 @@ var createTaskHandlerConfig = async (params) => {
6501
6552
  if (!agent) {
6502
6553
  throw new Error(`Agent not found: ${params.agentId}`);
6503
6554
  }
6504
- const effectiveModels = agent.models || agentGraph?.models || void 0;
6555
+ const effectiveModels = await resolveModelConfig(params.graphId, agent);
6505
6556
  const effectiveConversationHistoryConfig = agent.conversationHistoryConfig || { mode: "full" };
6506
6557
  return {
6507
6558
  tenantId: params.tenantId,
@@ -6513,7 +6564,7 @@ var createTaskHandlerConfig = async (params) => {
6513
6564
  name: agent.name,
6514
6565
  description: agent.description,
6515
6566
  prompt: agent.prompt,
6516
- models: effectiveModels || null,
6567
+ models: effectiveModels,
6517
6568
  conversationHistoryConfig: effectiveConversationHistoryConfig || null,
6518
6569
  stopWhen: agent.stopWhen || null,
6519
6570
  createdAt: agent.createdAt,
@@ -7076,7 +7127,9 @@ var _VercelDataStreamHelper = class _VercelDataStreamHelper {
7076
7127
  if (this.jsonBuffer.length + content.length > _VercelDataStreamHelper.MAX_BUFFER_SIZE) {
7077
7128
  const newBuffer = this.truncateJsonBufferSafely(this.jsonBuffer);
7078
7129
  if (newBuffer.length === this.jsonBuffer.length) {
7079
- console.warn("VercelDataStreamHelper: Could not find safe JSON truncation point, clearing buffer");
7130
+ console.warn(
7131
+ "VercelDataStreamHelper: Could not find safe JSON truncation point, clearing buffer"
7132
+ );
7080
7133
  this.jsonBuffer = "";
7081
7134
  this.sentItems.clear();
7082
7135
  } else {
@@ -7484,11 +7537,17 @@ var ExecutionHandler = class {
7484
7537
  );
7485
7538
  } catch (error) {
7486
7539
  if (error?.message?.includes("UNIQUE constraint failed") || error?.message?.includes("PRIMARY KEY constraint failed") || error?.code === "SQLITE_CONSTRAINT_PRIMARYKEY") {
7487
- logger19.info({ taskId, error: error.message }, "Task already exists, fetching existing task");
7540
+ logger19.info(
7541
+ { taskId, error: error.message },
7542
+ "Task already exists, fetching existing task"
7543
+ );
7488
7544
  const existingTask = await agentsCore.getTask(dbClient_default)({ id: taskId });
7489
7545
  if (existingTask) {
7490
7546
  task = existingTask;
7491
- logger19.info({ taskId, existingTask }, "Successfully reused existing task from race condition");
7547
+ logger19.info(
7548
+ { taskId, existingTask },
7549
+ "Successfully reused existing task from race condition"
7550
+ );
7492
7551
  } else {
7493
7552
  logger19.error({ taskId, error }, "Task constraint failed but task not found");
7494
7553
  throw error;
@@ -8889,15 +8948,12 @@ function createExecutionHono(serverConfig, credentialStores) {
8889
8948
  app6.use(
8890
8949
  "*",
8891
8950
  cors.cors({
8892
- origin: (origin) => {
8893
- if (!origin) return origin;
8894
- return origin.startsWith("http://localhost:") || origin.startsWith("https://localhost:") ? origin : null;
8895
- },
8951
+ origin: "*",
8952
+ // public API
8896
8953
  allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
8897
8954
  allowHeaders: ["*"],
8898
8955
  exposeHeaders: ["Content-Length"],
8899
- maxAge: 86400,
8900
- credentials: true
8956
+ maxAge: 86400
8901
8957
  })
8902
8958
  );
8903
8959
  app6.use("/tenants/*", apiKeyAuth());
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import { env, __publicField, dbClient_default, getFormattedConversationHistory, createDefaultConversationHistoryConfig, saveA2AMessageResponse } from './chunk-P6IQZWFC.js';
1
+ import { env, __publicField, dbClient_default, getFormattedConversationHistory, createDefaultConversationHistoryConfig, saveA2AMessageResponse } from './chunk-HO5J26MO.js';
2
2
  import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
3
3
  import { BaggageSpanProcessor, ALLOW_ALL_BAGGAGE_KEYS } from '@opentelemetry/baggage-span-processor';
4
4
  import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
5
5
  import { NodeSDK } from '@opentelemetry/sdk-node';
6
6
  import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-node';
7
- import { getLogger as getLogger$1, getTracer, HeadersScopeSchema, getRequestExecutionContext, getAgentGraphWithDefaultAgent, contextValidationMiddleware, getFullGraph, createOrGetConversation, getActiveAgentForConversation, setActiveAgentForConversation, getAgentById, handleContextResolution, createMessage, commonGetErrorResponses, createDefaultCredentialStores, CredentialStoreRegistry, listTaskIdsByContextId, getTask, getLedgerArtifacts, getAgentGraph, createTask, updateTask, updateConversation, handleApiError, setSpanWithError, TaskState, setActiveAgentForThread, getConversation, getRelatedAgentsForGraph, getToolsForAgent, getDataComponentsForAgent, getArtifactComponentsForAgent, validateAndGetApiKey, ContextResolver, CredentialStuffer, MCPServerType, getCredentialReference, McpClient, getContextConfigById, getFullGraphDefinition, TemplateEngine, graphHasArtifactComponents, MCPTransportType, getExternalAgent } from '@inkeep/agents-core';
7
+ import { getLogger as getLogger$1, getTracer, HeadersScopeSchema, getRequestExecutionContext, getAgentGraphWithDefaultAgent, contextValidationMiddleware, getFullGraph, createOrGetConversation, getActiveAgentForConversation, setActiveAgentForConversation, getAgentById, handleContextResolution, createMessage, commonGetErrorResponses, createDefaultCredentialStores, CredentialStoreRegistry, listTaskIdsByContextId, getTask, getLedgerArtifacts, getAgentGraph, createTask, updateTask, updateConversation, handleApiError, setSpanWithError, TaskState, setActiveAgentForThread, getConversation, getRelatedAgentsForGraph, getToolsForAgent, getDataComponentsForAgent, getArtifactComponentsForAgent, validateAndGetApiKey, getProject, ContextResolver, CredentialStuffer, MCPServerType, getCredentialReference, McpClient, getContextConfigById, getFullGraphDefinition, TemplateEngine, graphHasArtifactComponents, MCPTransportType, getExternalAgent } from '@inkeep/agents-core';
8
8
  import { Hono } from 'hono';
9
9
  import { OpenAPIHono, createRoute, z as z$1 } from '@hono/zod-openapi';
10
10
  import { trace, propagation, context, SpanStatusCode } from '@opentelemetry/api';
@@ -33,8 +33,7 @@ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/
33
33
  import { z as z$2 } from 'zod/v3';
34
34
  import { toReqRes, toFetchResponse } from 'fetch-to-node';
35
35
 
36
- var otlpUrl = env.OTEL_EXPORTER_OTLP_ENDPOINT;
37
- var otlpExporter = new OTLPTraceExporter({ url: otlpUrl });
36
+ var otlpExporter = new OTLPTraceExporter();
38
37
  var FanOutSpanProcessor = class {
39
38
  constructor(inner) {
40
39
  this.inner = inner;
@@ -136,6 +135,10 @@ function createExecutionContext(params) {
136
135
  // src/middleware/api-key-auth.ts
137
136
  var logger2 = getLogger$1("env-key-auth");
138
137
  var apiKeyAuth = () => createMiddleware(async (c, next) => {
138
+ if (c.req.method === "OPTIONS") {
139
+ await next();
140
+ return;
141
+ }
139
142
  const authHeader = c.req.header("Authorization");
140
143
  const tenantId = c.req.header("x-inkeep-tenant-id");
141
144
  const projectId = c.req.header("x-inkeep-project-id");
@@ -268,13 +271,13 @@ function setupOpenAPIRoutes(app6) {
268
271
  const document = app6.getOpenAPIDocument({
269
272
  openapi: "3.0.0",
270
273
  info: {
271
- title: "Inkeep Execution API",
274
+ title: "Inkeep Agents Run API",
272
275
  version: "1.0.0",
273
- description: "Complete REST API for Inkeep Execution application including chat completions, A2A agent communication, and comprehensive CRUD operations for all entities"
276
+ description: "Chat completions, MCP, and A2A run endpoints in the Inkeep Agent Framework."
274
277
  },
275
278
  servers: [
276
279
  {
277
- url: env.AGENT_BASE_URL || `http://localhost:3003`,
280
+ url: env.AGENTS_RUN_API_URL,
278
281
  description: "Development server"
279
282
  }
280
283
  ]
@@ -290,7 +293,7 @@ function setupOpenAPIRoutes(app6) {
290
293
  "/docs",
291
294
  swaggerUI({
292
295
  url: "/openapi.json",
293
- title: "Inkeep Execution API Documentation"
296
+ title: "Inkeep Agents Run API Documentation"
294
297
  })
295
298
  );
296
299
  }
@@ -899,11 +902,6 @@ async function handleTasksResubscribe(c, agent, request) {
899
902
  });
900
903
  }
901
904
  }
902
-
903
- // package.json
904
- var package_default = {
905
- version: "0.1.6"};
906
- var tracer = getTracer("agents-run-api", package_default.version);
907
905
  function agentInitializingOp(sessionId, graphId) {
908
906
  return {
909
907
  type: "agent_initializing",
@@ -1032,7 +1030,9 @@ var _ModelFactory = class _ModelFactory {
1032
1030
  */
1033
1031
  static createModel(config) {
1034
1032
  if (!config?.model?.trim()) {
1035
- throw new Error("Model configuration is required. Please configure models at the project level.");
1033
+ throw new Error(
1034
+ "Model configuration is required. Please configure models at the project level."
1035
+ );
1036
1036
  }
1037
1037
  const modelSettings = config;
1038
1038
  const modelString = modelSettings.model.trim();
@@ -1053,7 +1053,9 @@ var _ModelFactory = class _ModelFactory {
1053
1053
  case "openai":
1054
1054
  return _ModelFactory.createOpenAIModel(modelName, modelSettings.providerOptions);
1055
1055
  default:
1056
- throw new Error(`Unsupported provider: ${provider}. Supported providers are: ${_ModelFactory.SUPPORTED_PROVIDERS.join(", ")}`);
1056
+ throw new Error(
1057
+ `Unsupported provider: ${provider}. Supported providers are: ${_ModelFactory.SUPPORTED_PROVIDERS.join(", ")}`
1058
+ );
1057
1059
  }
1058
1060
  } catch (error) {
1059
1061
  logger5.error(
@@ -1064,7 +1066,9 @@ var _ModelFactory = class _ModelFactory {
1064
1066
  },
1065
1067
  "Failed to create model"
1066
1068
  );
1067
- throw new Error(`Failed to create model ${modelString}: ${error instanceof Error ? error.message : "Unknown error"}`);
1069
+ throw new Error(
1070
+ `Failed to create model ${modelString}: ${error instanceof Error ? error.message : "Unknown error"}`
1071
+ );
1068
1072
  }
1069
1073
  }
1070
1074
  /**
@@ -1204,6 +1208,7 @@ var _ModelFactory = class _ModelFactory {
1204
1208
  */
1205
1209
  __publicField(_ModelFactory, "SUPPORTED_PROVIDERS", ["anthropic", "openai"]);
1206
1210
  var ModelFactory = _ModelFactory;
1211
+ var tracer = getTracer("agents-run-api");
1207
1212
 
1208
1213
  // src/utils/stream-registry.ts
1209
1214
  var streamHelperRegistry = /* @__PURE__ */ new Map();
@@ -1313,12 +1318,15 @@ var GraphSession = class {
1313
1318
  if (eventType === "artifact_saved" && data.pendingGeneration) {
1314
1319
  const artifactId = data.artifactId;
1315
1320
  if (this.pendingArtifacts.size >= this.MAX_PENDING_ARTIFACTS) {
1316
- logger6.warn({
1317
- sessionId: this.sessionId,
1318
- artifactId,
1319
- pendingCount: this.pendingArtifacts.size,
1320
- maxAllowed: this.MAX_PENDING_ARTIFACTS
1321
- }, "Too many pending artifacts, skipping processing");
1321
+ logger6.warn(
1322
+ {
1323
+ sessionId: this.sessionId,
1324
+ artifactId,
1325
+ pendingCount: this.pendingArtifacts.size,
1326
+ maxAllowed: this.MAX_PENDING_ARTIFACTS
1327
+ },
1328
+ "Too many pending artifacts, skipping processing"
1329
+ );
1322
1330
  return;
1323
1331
  }
1324
1332
  this.pendingArtifacts.add(artifactId);
@@ -1331,21 +1339,27 @@ var GraphSession = class {
1331
1339
  this.artifactProcessingErrors.set(artifactId, errorCount);
1332
1340
  if (errorCount >= this.MAX_ARTIFACT_RETRIES) {
1333
1341
  this.pendingArtifacts.delete(artifactId);
1334
- logger6.error({
1335
- sessionId: this.sessionId,
1336
- artifactId,
1337
- errorCount,
1338
- maxRetries: this.MAX_ARTIFACT_RETRIES,
1339
- error: error instanceof Error ? error.message : "Unknown error",
1340
- stack: error instanceof Error ? error.stack : void 0
1341
- }, "Artifact processing failed after max retries, giving up");
1342
+ logger6.error(
1343
+ {
1344
+ sessionId: this.sessionId,
1345
+ artifactId,
1346
+ errorCount,
1347
+ maxRetries: this.MAX_ARTIFACT_RETRIES,
1348
+ error: error instanceof Error ? error.message : "Unknown error",
1349
+ stack: error instanceof Error ? error.stack : void 0
1350
+ },
1351
+ "Artifact processing failed after max retries, giving up"
1352
+ );
1342
1353
  } else {
1343
- logger6.warn({
1344
- sessionId: this.sessionId,
1345
- artifactId,
1346
- errorCount,
1347
- error: error instanceof Error ? error.message : "Unknown error"
1348
- }, "Artifact processing failed, may retry");
1354
+ logger6.warn(
1355
+ {
1356
+ sessionId: this.sessionId,
1357
+ artifactId,
1358
+ errorCount,
1359
+ error: error instanceof Error ? error.message : "Unknown error"
1360
+ },
1361
+ "Artifact processing failed, may retry"
1362
+ );
1349
1363
  }
1350
1364
  });
1351
1365
  });
@@ -1749,7 +1763,9 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
1749
1763
  let modelToUse = summarizerModel;
1750
1764
  if (!summarizerModel?.model?.trim()) {
1751
1765
  if (!this.statusUpdateState?.baseModel?.model?.trim()) {
1752
- throw new Error("Either summarizer or base model is required for progress summary generation. Please configure models at the project level.");
1766
+ throw new Error(
1767
+ "Either summarizer or base model is required for progress summary generation. Please configure models at the project level."
1768
+ );
1753
1769
  }
1754
1770
  modelToUse = this.statusUpdateState.baseModel;
1755
1771
  }
@@ -1877,7 +1893,9 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
1877
1893
  let modelToUse = summarizerModel;
1878
1894
  if (!summarizerModel?.model?.trim()) {
1879
1895
  if (!this.statusUpdateState?.baseModel?.model?.trim()) {
1880
- throw new Error("Either summarizer or base model is required for status update generation. Please configure models at the project level.");
1896
+ throw new Error(
1897
+ "Either summarizer or base model is required for status update generation. Please configure models at the project level."
1898
+ );
1881
1899
  }
1882
1900
  modelToUse = this.statusUpdateState.baseModel;
1883
1901
  }
@@ -2135,7 +2153,7 @@ ${this.statusUpdateState?.config.prompt?.trim() || ""}`;
2135
2153
  );
2136
2154
  }
2137
2155
  span.setAttributes({ "validation.passed": true });
2138
- const { getFormattedConversationHistory: getFormattedConversationHistory2 } = await import('./conversations-EUPRCMQZ.js');
2156
+ const { getFormattedConversationHistory: getFormattedConversationHistory2 } = await import('./conversations-ZQXUNCNE.js');
2139
2157
  const conversationHistory = await getFormattedConversationHistory2({
2140
2158
  tenantId: artifactData.tenantId,
2141
2159
  projectId: artifactData.projectId,
@@ -2167,7 +2185,9 @@ Make it specific and relevant.`;
2167
2185
  let modelToUse = this.statusUpdateState?.summarizerModel;
2168
2186
  if (!modelToUse?.model?.trim()) {
2169
2187
  if (!this.statusUpdateState?.baseModel?.model?.trim()) {
2170
- throw new Error("Either summarizer or base model is required for artifact name generation. Please configure models at the project level.");
2188
+ throw new Error(
2189
+ "Either summarizer or base model is required for artifact name generation. Please configure models at the project level."
2190
+ );
2171
2191
  }
2172
2192
  modelToUse = this.statusUpdateState.baseModel;
2173
2193
  }
@@ -2423,7 +2443,9 @@ var _ArtifactParser = class _ArtifactParser {
2423
2443
  * More robust detection that handles streaming fragments
2424
2444
  */
2425
2445
  hasIncompleteArtifact(text) {
2426
- return /^.*<(?:artifact(?::ref)?|a(?:r(?:t(?:i(?:f(?:a(?:c(?:t(?::(?:r(?:e(?:f)?)?)?)?)?)?)?)?)?)?)?)?$/.test(text) || /^.*<artifact:ref(?:[^>]*)$/.test(text) || // Incomplete artifact:ref at end
2446
+ return /^.*<(?:artifact(?::ref)?|a(?:r(?:t(?:i(?:f(?:a(?:c(?:t(?::(?:r(?:e(?:f)?)?)?)?)?)?)?)?)?)?)?)?$/.test(
2447
+ text
2448
+ ) || /^.*<artifact:ref(?:[^>]*)$/.test(text) || // Incomplete artifact:ref at end
2427
2449
  this.findSafeTextBoundary(text) < text.length;
2428
2450
  }
2429
2451
  /**
@@ -5891,6 +5913,37 @@ ${output}`;
5891
5913
  });
5892
5914
  }
5893
5915
  };
5916
+ async function resolveModelConfig(graphId, agent) {
5917
+ if (agent.models?.base?.model) {
5918
+ return {
5919
+ base: agent.models.base,
5920
+ structuredOutput: agent.models.structuredOutput || agent.models.base,
5921
+ summarizer: agent.models.summarizer || agent.models.base
5922
+ };
5923
+ }
5924
+ const graph = await getAgentGraph(dbClient_default)({
5925
+ scopes: { tenantId: agent.tenantId, projectId: agent.projectId },
5926
+ graphId
5927
+ });
5928
+ if (graph?.models?.base?.model) {
5929
+ return {
5930
+ base: graph.models.base,
5931
+ structuredOutput: agent.models?.structuredOutput || graph.models.structuredOutput || graph.models.base,
5932
+ summarizer: agent.models?.summarizer || graph.models.summarizer || graph.models.base
5933
+ };
5934
+ }
5935
+ const project = await getProject(dbClient_default)({
5936
+ scopes: { tenantId: agent.tenantId, projectId: agent.projectId }
5937
+ });
5938
+ if (project?.models?.base?.model) {
5939
+ return {
5940
+ base: project.models.base,
5941
+ structuredOutput: agent.models?.structuredOutput || project.models.structuredOutput || project.models.base,
5942
+ summarizer: agent.models?.summarizer || project.models.summarizer || project.models.base
5943
+ };
5944
+ }
5945
+ throw new Error("Base model configuration is required. Please configure models at the project level.");
5946
+ }
5894
5947
 
5895
5948
  // src/agents/generateTaskHandler.ts
5896
5949
  function parseEmbeddedJson(data) {
@@ -6174,7 +6227,7 @@ var createTaskHandlerConfig = async (params) => {
6174
6227
  if (!agent) {
6175
6228
  throw new Error(`Agent not found: ${params.agentId}`);
6176
6229
  }
6177
- const effectiveModels = agent.models || agentGraph?.models || void 0;
6230
+ const effectiveModels = await resolveModelConfig(params.graphId, agent);
6178
6231
  const effectiveConversationHistoryConfig = agent.conversationHistoryConfig || { mode: "full" };
6179
6232
  return {
6180
6233
  tenantId: params.tenantId,
@@ -6186,7 +6239,7 @@ var createTaskHandlerConfig = async (params) => {
6186
6239
  name: agent.name,
6187
6240
  description: agent.description,
6188
6241
  prompt: agent.prompt,
6189
- models: effectiveModels || null,
6242
+ models: effectiveModels,
6190
6243
  conversationHistoryConfig: effectiveConversationHistoryConfig || null,
6191
6244
  stopWhen: agent.stopWhen || null,
6192
6245
  createdAt: agent.createdAt,
@@ -6740,7 +6793,9 @@ var _VercelDataStreamHelper = class _VercelDataStreamHelper {
6740
6793
  if (this.jsonBuffer.length + content.length > _VercelDataStreamHelper.MAX_BUFFER_SIZE) {
6741
6794
  const newBuffer = this.truncateJsonBufferSafely(this.jsonBuffer);
6742
6795
  if (newBuffer.length === this.jsonBuffer.length) {
6743
- console.warn("VercelDataStreamHelper: Could not find safe JSON truncation point, clearing buffer");
6796
+ console.warn(
6797
+ "VercelDataStreamHelper: Could not find safe JSON truncation point, clearing buffer"
6798
+ );
6744
6799
  this.jsonBuffer = "";
6745
6800
  this.sentItems.clear();
6746
6801
  } else {
@@ -7145,11 +7200,17 @@ var ExecutionHandler = class {
7145
7200
  );
7146
7201
  } catch (error) {
7147
7202
  if (error?.message?.includes("UNIQUE constraint failed") || error?.message?.includes("PRIMARY KEY constraint failed") || error?.code === "SQLITE_CONSTRAINT_PRIMARYKEY") {
7148
- logger19.info({ taskId, error: error.message }, "Task already exists, fetching existing task");
7203
+ logger19.info(
7204
+ { taskId, error: error.message },
7205
+ "Task already exists, fetching existing task"
7206
+ );
7149
7207
  const existingTask = await getTask(dbClient_default)({ id: taskId });
7150
7208
  if (existingTask) {
7151
7209
  task = existingTask;
7152
- logger19.info({ taskId, existingTask }, "Successfully reused existing task from race condition");
7210
+ logger19.info(
7211
+ { taskId, existingTask },
7212
+ "Successfully reused existing task from race condition"
7213
+ );
7153
7214
  } else {
7154
7215
  logger19.error({ taskId, error }, "Task constraint failed but task not found");
7155
7216
  throw error;
@@ -8544,15 +8605,12 @@ function createExecutionHono(serverConfig, credentialStores) {
8544
8605
  app6.use(
8545
8606
  "*",
8546
8607
  cors({
8547
- origin: (origin) => {
8548
- if (!origin) return origin;
8549
- return origin.startsWith("http://localhost:") || origin.startsWith("https://localhost:") ? origin : null;
8550
- },
8608
+ origin: "*",
8609
+ // public API
8551
8610
  allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
8552
8611
  allowHeaders: ["*"],
8553
8612
  exposeHeaders: ["Content-Length"],
8554
- maxAge: 86400,
8555
- credentials: true
8613
+ maxAge: 86400
8556
8614
  })
8557
8615
  );
8558
8616
  app6.use("/tenants/*", apiKeyAuth());
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@inkeep/agents-run-api",
3
- "version": "0.1.6",
4
- "description": "Execution API for Inkeep Agent Framework - handles chat, agent execution, and streaming",
3
+ "version": "0.1.7",
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",
7
7
  "exports": {
@@ -44,7 +44,7 @@
44
44
  "traverse": "^0.6.11",
45
45
  "ts-pattern": "^5.7.1",
46
46
  "zod": "^4.1.5",
47
- "@inkeep/agents-core": "^0.1.6"
47
+ "@inkeep/agents-core": "^0.1.7"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@hono/vite-dev-server": "^0.20.1",