@inkeep/agents-manage-api 0.0.0-dev-20250912174511 → 0.0.0-dev-20250912184011

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 +327 -40
  2. package/dist/index.js +328 -41
  3. package/package.json +2 -2
package/dist/index.cjs CHANGED
@@ -3,8 +3,8 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var agentsCore = require('@inkeep/agents-core');
6
- var hono = require('hono');
7
6
  var zodOpenapi = require('@hono/zod-openapi');
7
+ var hono = require('hono');
8
8
  var cors = require('hono/cors');
9
9
  var httpException = require('hono/http-exception');
10
10
  var requestId = require('hono/request-id');
@@ -145,10 +145,10 @@ var apiKeyAuth = () => factory.createMiddleware(async (c, next) => {
145
145
  await next();
146
146
  return;
147
147
  });
148
- function setupOpenAPIRoutes(app19) {
149
- app19.get("/openapi.json", (c) => {
148
+ function setupOpenAPIRoutes(app20) {
149
+ app20.get("/openapi.json", (c) => {
150
150
  try {
151
- const document = app19.getOpenAPIDocument({
151
+ const document = app20.getOpenAPIDocument({
152
152
  openapi: "3.0.0",
153
153
  info: {
154
154
  title: "Inkeep Agents Manage API",
@@ -169,7 +169,7 @@ function setupOpenAPIRoutes(app19) {
169
169
  return c.json({ error: "Failed to generate OpenAPI document", details: errorDetails }, 500);
170
170
  }
171
171
  });
172
- app19.get(
172
+ app20.get(
173
173
  "/docs",
174
174
  swaggerUi.swaggerUI({
175
175
  url: "/openapi.json",
@@ -1926,21 +1926,31 @@ app7.openapi(
1926
1926
  ...keyDataWithoutKey,
1927
1927
  expiresAt: body.expiresAt || void 0
1928
1928
  };
1929
- const result = await agentsCore.createApiKey(dbClient_default)(insertData);
1930
- const { keyHash: _, tenantId: __, projectId: ___, ...sanitizedApiKey } = result;
1931
- return c.json(
1932
- {
1933
- data: {
1934
- apiKey: {
1935
- ...sanitizedApiKey,
1936
- lastUsedAt: sanitizedApiKey.lastUsedAt ?? null,
1937
- expiresAt: sanitizedApiKey.expiresAt ?? null
1938
- },
1939
- key
1940
- }
1941
- },
1942
- 201
1943
- );
1929
+ try {
1930
+ const result = await agentsCore.createApiKey(dbClient_default)(insertData);
1931
+ const { keyHash: _, tenantId: __, projectId: ___, ...sanitizedApiKey } = result;
1932
+ return c.json(
1933
+ {
1934
+ data: {
1935
+ apiKey: {
1936
+ ...sanitizedApiKey,
1937
+ lastUsedAt: sanitizedApiKey.lastUsedAt ?? null,
1938
+ expiresAt: sanitizedApiKey.expiresAt ?? null
1939
+ },
1940
+ key
1941
+ }
1942
+ },
1943
+ 201
1944
+ );
1945
+ } catch (error) {
1946
+ if (error?.cause?.code === "SQLITE_CONSTRAINT_FOREIGNKEY" || error?.cause?.rawCode === 787) {
1947
+ throw agentsCore.createApiError({
1948
+ code: "bad_request",
1949
+ message: "Invalid graphId - graph does not exist"
1950
+ });
1951
+ }
1952
+ throw error;
1953
+ }
1944
1954
  }
1945
1955
  );
1946
1956
  app7.openapi(
@@ -2154,10 +2164,20 @@ app8.openapi(
2154
2164
  summaryProps: body.summaryProps || void 0,
2155
2165
  fullProps: body.fullProps || void 0
2156
2166
  };
2157
- const artifactComponent = await agentsCore.createArtifactComponent(dbClient_default)({
2158
- ...componentData
2159
- });
2160
- return c.json({ data: artifactComponent }, 201);
2167
+ try {
2168
+ const artifactComponent = await agentsCore.createArtifactComponent(dbClient_default)({
2169
+ ...componentData
2170
+ });
2171
+ return c.json({ data: artifactComponent }, 201);
2172
+ } catch (error) {
2173
+ if (error?.cause?.code === "SQLITE_CONSTRAINT_PRIMARYKEY" || error?.cause?.rawCode === 1555) {
2174
+ throw agentsCore.createApiError({
2175
+ code: "conflict",
2176
+ message: `Artifact component with ID '${finalId}' already exists`
2177
+ });
2178
+ }
2179
+ throw error;
2180
+ }
2161
2181
  }
2162
2182
  );
2163
2183
  app8.openapi(
@@ -4691,7 +4711,7 @@ app15.openapi(
4691
4711
  }),
4692
4712
  async (c) => {
4693
4713
  const { tenantId, projectId, id } = c.req.valid("param");
4694
- const logger8 = getLogger("oauth-login");
4714
+ const logger9 = getLogger("oauth-login");
4695
4715
  try {
4696
4716
  const tool = await agentsCore.getToolById(dbClient_default)({ scopes: { tenantId, projectId }, toolId: id });
4697
4717
  if (!tool) {
@@ -4709,7 +4729,7 @@ app15.openapi(
4709
4729
  });
4710
4730
  return c.redirect(redirectUrl, 302);
4711
4731
  } catch (error) {
4712
- logger8.error({ toolId: id, error }, "OAuth login failed");
4732
+ logger9.error({ toolId: id, error }, "OAuth login failed");
4713
4733
  if (error && typeof error === "object" && "code" in error) {
4714
4734
  const apiError = error;
4715
4735
  return c.json({ error: apiError.message }, apiError.code === "not_found" ? 404 : 400);
@@ -4914,17 +4934,283 @@ app17.openapi(
4914
4934
  }
4915
4935
  );
4916
4936
  var oauth_default = app17;
4937
+ var logger8 = getLogger("projectFull");
4938
+ var app18 = new zodOpenapi.OpenAPIHono();
4939
+ var ProjectIdParamsSchema = zod.z.object({
4940
+ tenantId: zod.z.string().openapi({
4941
+ description: "Tenant identifier",
4942
+ example: "tenant_123"
4943
+ }),
4944
+ projectId: zod.z.string().openapi({
4945
+ description: "Project identifier",
4946
+ example: "project_456"
4947
+ })
4948
+ }).openapi("ProjectIdParams");
4949
+ var TenantParamsSchema2 = zod.z.object({
4950
+ tenantId: zod.z.string().openapi({
4951
+ description: "Tenant identifier",
4952
+ example: "tenant_123"
4953
+ })
4954
+ }).openapi("TenantParams");
4955
+ app18.openapi(
4956
+ zodOpenapi.createRoute({
4957
+ method: "post",
4958
+ path: "/project-full",
4959
+ summary: "Create Full Project",
4960
+ operationId: "create-full-project",
4961
+ tags: ["CRUD Full Project"],
4962
+ description: "Create a complete project with all graphs, agents, tools, and relationships from JSON definition",
4963
+ request: {
4964
+ params: TenantParamsSchema2,
4965
+ body: {
4966
+ content: {
4967
+ "application/json": {
4968
+ schema: agentsCore.FullProjectDefinitionSchema
4969
+ }
4970
+ }
4971
+ }
4972
+ },
4973
+ responses: {
4974
+ 201: {
4975
+ description: "Full project created successfully",
4976
+ content: {
4977
+ "application/json": {
4978
+ schema: agentsCore.SingleResponseSchema(agentsCore.FullProjectDefinitionSchema)
4979
+ }
4980
+ }
4981
+ },
4982
+ 409: {
4983
+ description: "Project already exists",
4984
+ content: {
4985
+ "application/json": {
4986
+ schema: agentsCore.ErrorResponseSchema
4987
+ }
4988
+ }
4989
+ },
4990
+ ...agentsCore.commonGetErrorResponses
4991
+ }
4992
+ }),
4993
+ async (c) => {
4994
+ const { tenantId } = c.req.valid("param");
4995
+ const projectData = c.req.valid("json");
4996
+ const validatedProjectData = agentsCore.FullProjectDefinitionSchema.parse(projectData);
4997
+ try {
4998
+ const createdProject = await agentsCore.createFullProjectServerSide(dbClient_default, logger8)(
4999
+ { tenantId, projectId: validatedProjectData.id },
5000
+ validatedProjectData
5001
+ );
5002
+ return c.json({ data: createdProject }, 201);
5003
+ } catch (error) {
5004
+ if (error?.cause?.code === "SQLITE_CONSTRAINT_PRIMARYKEY" || error?.cause?.rawCode === 1555) {
5005
+ throw agentsCore.createApiError({
5006
+ code: "conflict",
5007
+ message: `Project with ID '${projectData.id}' already exists`
5008
+ });
5009
+ }
5010
+ throw error;
5011
+ }
5012
+ }
5013
+ );
5014
+ app18.openapi(
5015
+ zodOpenapi.createRoute({
5016
+ method: "get",
5017
+ path: "/project-full/{projectId}",
5018
+ summary: "Get Full Project",
5019
+ operationId: "get-full-project",
5020
+ tags: ["CRUD Full Project"],
5021
+ description: "Retrieve a complete project definition with all graphs, agents, tools, and relationships",
5022
+ request: {
5023
+ params: ProjectIdParamsSchema
5024
+ },
5025
+ responses: {
5026
+ 200: {
5027
+ description: "Full project found",
5028
+ content: {
5029
+ "application/json": {
5030
+ schema: agentsCore.SingleResponseSchema(agentsCore.FullProjectDefinitionSchema)
5031
+ }
5032
+ }
5033
+ },
5034
+ ...agentsCore.commonGetErrorResponses
5035
+ }
5036
+ }),
5037
+ async (c) => {
5038
+ const { tenantId, projectId } = c.req.valid("param");
5039
+ try {
5040
+ const project = await agentsCore.getFullProject(
5041
+ dbClient_default,
5042
+ logger8
5043
+ )({
5044
+ scopes: { tenantId, projectId },
5045
+ projectId
5046
+ });
5047
+ if (!project) {
5048
+ throw agentsCore.createApiError({
5049
+ code: "not_found",
5050
+ message: "Project not found"
5051
+ });
5052
+ }
5053
+ return c.json({ data: project });
5054
+ } catch (error) {
5055
+ if (error instanceof Error && error.message.includes("not found")) {
5056
+ throw agentsCore.createApiError({
5057
+ code: "not_found",
5058
+ message: "Project not found"
5059
+ });
5060
+ }
5061
+ throw agentsCore.createApiError({
5062
+ code: "internal_server_error",
5063
+ message: error instanceof Error ? error.message : "Failed to retrieve project"
5064
+ });
5065
+ }
5066
+ }
5067
+ );
5068
+ app18.openapi(
5069
+ zodOpenapi.createRoute({
5070
+ method: "put",
5071
+ path: "/project-full/{projectId}",
5072
+ summary: "Update Full Project",
5073
+ operationId: "update-full-project",
5074
+ tags: ["CRUD Full Project"],
5075
+ description: "Update or create a complete project with all graphs, agents, tools, and relationships from JSON definition",
5076
+ request: {
5077
+ params: ProjectIdParamsSchema,
5078
+ body: {
5079
+ content: {
5080
+ "application/json": {
5081
+ schema: agentsCore.FullProjectDefinitionSchema
5082
+ }
5083
+ }
5084
+ }
5085
+ },
5086
+ responses: {
5087
+ 200: {
5088
+ description: "Full project updated successfully",
5089
+ content: {
5090
+ "application/json": {
5091
+ schema: agentsCore.SingleResponseSchema(agentsCore.FullProjectDefinitionSchema)
5092
+ }
5093
+ }
5094
+ },
5095
+ 201: {
5096
+ description: "Full project created successfully",
5097
+ content: {
5098
+ "application/json": {
5099
+ schema: agentsCore.SingleResponseSchema(agentsCore.FullProjectDefinitionSchema)
5100
+ }
5101
+ }
5102
+ },
5103
+ ...agentsCore.commonGetErrorResponses
5104
+ }
5105
+ }),
5106
+ async (c) => {
5107
+ const { tenantId, projectId } = c.req.valid("param");
5108
+ const projectData = c.req.valid("json");
5109
+ try {
5110
+ const validatedProjectData = agentsCore.FullProjectDefinitionSchema.parse(projectData);
5111
+ if (projectId !== validatedProjectData.id) {
5112
+ throw agentsCore.createApiError({
5113
+ code: "bad_request",
5114
+ message: `Project ID mismatch: expected ${projectId}, got ${validatedProjectData.id}`
5115
+ });
5116
+ }
5117
+ const existingProject = await agentsCore.getFullProject(
5118
+ dbClient_default,
5119
+ logger8
5120
+ )({
5121
+ scopes: { tenantId, projectId },
5122
+ projectId
5123
+ });
5124
+ const isCreate = !existingProject;
5125
+ const updatedProject = isCreate ? await agentsCore.createFullProjectServerSide(dbClient_default, logger8)(
5126
+ { tenantId, projectId },
5127
+ validatedProjectData
5128
+ ) : await agentsCore.updateFullProjectServerSide(dbClient_default, logger8)(
5129
+ { tenantId, projectId },
5130
+ validatedProjectData
5131
+ );
5132
+ return c.json({ data: updatedProject }, isCreate ? 201 : 200);
5133
+ } catch (error) {
5134
+ if (error instanceof zod.z.ZodError) {
5135
+ throw agentsCore.createApiError({
5136
+ code: "bad_request",
5137
+ message: "Invalid project definition"
5138
+ });
5139
+ }
5140
+ if (error instanceof Error && error.message.includes("ID mismatch")) {
5141
+ throw agentsCore.createApiError({
5142
+ code: "bad_request",
5143
+ message: error.message
5144
+ });
5145
+ }
5146
+ throw agentsCore.createApiError({
5147
+ code: "internal_server_error",
5148
+ message: error instanceof Error ? error.message : "Failed to update project"
5149
+ });
5150
+ }
5151
+ }
5152
+ );
5153
+ app18.openapi(
5154
+ zodOpenapi.createRoute({
5155
+ method: "delete",
5156
+ path: "/project-full/{projectId}",
5157
+ summary: "Delete Full Project",
5158
+ operationId: "delete-full-project",
5159
+ tags: ["CRUD Full Project"],
5160
+ description: "Delete a complete project and cascade to all related entities (graphs, agents, tools, relationships)",
5161
+ request: {
5162
+ params: ProjectIdParamsSchema
5163
+ },
5164
+ responses: {
5165
+ 204: {
5166
+ description: "Project deleted successfully"
5167
+ },
5168
+ ...agentsCore.commonGetErrorResponses
5169
+ }
5170
+ }),
5171
+ async (c) => {
5172
+ const { tenantId, projectId } = c.req.valid("param");
5173
+ try {
5174
+ const deleted = await agentsCore.deleteFullProject(
5175
+ dbClient_default,
5176
+ logger8
5177
+ )({
5178
+ scopes: { tenantId, projectId },
5179
+ projectId
5180
+ });
5181
+ if (!deleted) {
5182
+ throw agentsCore.createApiError({
5183
+ code: "not_found",
5184
+ message: "Project not found"
5185
+ });
5186
+ }
5187
+ return c.body(null, 204);
5188
+ } catch (error) {
5189
+ if (error instanceof Error && error.message.includes("not found")) {
5190
+ throw agentsCore.createApiError({
5191
+ code: "not_found",
5192
+ message: "Project not found"
5193
+ });
5194
+ }
5195
+ throw agentsCore.createApiError({
5196
+ code: "internal_server_error",
5197
+ message: error instanceof Error ? error.message : "Failed to delete project"
5198
+ });
5199
+ }
5200
+ }
5201
+ );
5202
+ var projectFull_default = app18;
4917
5203
 
4918
5204
  // src/app.ts
4919
5205
  function createManagementHono(serverConfig, credentialStores) {
4920
- const app19 = new zodOpenapi.OpenAPIHono();
4921
- app19.use("*", requestId.requestId());
4922
- app19.use("*", async (c, next) => {
5206
+ const app20 = new zodOpenapi.OpenAPIHono();
5207
+ app20.use("*", requestId.requestId());
5208
+ app20.use("*", async (c, next) => {
4923
5209
  c.set("serverConfig", serverConfig);
4924
5210
  c.set("credentialStores", credentialStores);
4925
5211
  return next();
4926
5212
  });
4927
- app19.use(
5213
+ app20.use(
4928
5214
  honoPino.pinoLogger({
4929
5215
  pino: getLogger(),
4930
5216
  http: {
@@ -4937,7 +5223,7 @@ function createManagementHono(serverConfig, credentialStores) {
4937
5223
  }
4938
5224
  })
4939
5225
  );
4940
- app19.onError(async (err, c) => {
5226
+ app20.onError(async (err, c) => {
4941
5227
  const isExpectedError = err instanceof httpException.HTTPException;
4942
5228
  const status = isExpectedError ? err.status : 500;
4943
5229
  const requestId2 = c.get("requestId") || "unknown";
@@ -5012,7 +5298,7 @@ function createManagementHono(serverConfig, credentialStores) {
5012
5298
  ...instance && { instance }
5013
5299
  });
5014
5300
  });
5015
- app19.use(
5301
+ app20.use(
5016
5302
  "*",
5017
5303
  cors.cors({
5018
5304
  origin: (origin) => {
@@ -5026,7 +5312,7 @@ function createManagementHono(serverConfig, credentialStores) {
5026
5312
  credentials: true
5027
5313
  })
5028
5314
  );
5029
- app19.openapi(
5315
+ app20.openapi(
5030
5316
  zodOpenapi.createRoute({
5031
5317
  method: "get",
5032
5318
  path: "/health",
@@ -5043,12 +5329,13 @@ function createManagementHono(serverConfig, credentialStores) {
5043
5329
  return c.body(null, 204);
5044
5330
  }
5045
5331
  );
5046
- app19.use("/tenants/*", apiKeyAuth());
5047
- app19.route("/tenants/:tenantId/crud", routes_default);
5048
- app19.route("/oauth", oauth_default);
5049
- setupOpenAPIRoutes(app19);
5332
+ app20.use("/tenants/*", apiKeyAuth());
5333
+ app20.route("/tenants/:tenantId/crud", routes_default);
5334
+ app20.route("/tenants/:tenantId", projectFull_default);
5335
+ app20.route("/oauth", oauth_default);
5336
+ setupOpenAPIRoutes(app20);
5050
5337
  const baseApp = new hono.Hono();
5051
- baseApp.route("/", app19);
5338
+ baseApp.route("/", app20);
5052
5339
  return baseApp;
5053
5340
  }
5054
5341
 
@@ -5064,8 +5351,8 @@ var defaultConfig = {
5064
5351
  };
5065
5352
  var defaultStores = agentsCore.createDefaultCredentialStores();
5066
5353
  var defaultRegistry = new agentsCore.CredentialStoreRegistry(defaultStores);
5067
- var app18 = createManagementHono(defaultConfig, defaultRegistry);
5068
- var index_default = app18;
5354
+ var app19 = createManagementHono(defaultConfig, defaultRegistry);
5355
+ var index_default = app19;
5069
5356
  function createManagementApp(config2) {
5070
5357
  const serverConfig = config2?.serverConfig ?? defaultConfig;
5071
5358
  const stores = config2?.credentialStores ?? defaultStores;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { getLogger as getLogger$1, createDatabaseClient, commonGetErrorResponses, TenantProjectParamsSchema, ArtifactComponentApiSelectSchema, getArtifactComponentsForAgent, getAgentsUsingArtifactComponent, ErrorResponseSchema, SingleResponseSchema, AgentArtifactComponentApiInsertSchema, AgentArtifactComponentApiSelectSchema, getAgentById, getArtifactComponentById, createApiError, isArtifactComponentAssociatedWithAgent, associateArtifactComponentWithAgent, RemovedResponseSchema, removeArtifactComponentFromAgent, ExistsResponseSchema, DataComponentApiSelectSchema, getDataComponentsForAgent, getAgentsUsingDataComponent, AgentDataComponentApiInsertSchema, AgentDataComponentApiSelectSchema, getDataComponent, isDataComponentAssociatedWithAgent, associateDataComponentWithAgent, removeDataComponentFromAgent, ListResponseSchema, PaginationQueryParamsSchema, AgentGraphApiSelectSchema, listAgentGraphs, IdParamsSchema, getAgentGraph, getGraphAgentInfos, FullGraphDefinitionSchema, getFullGraphDefinition, AgentGraphApiInsertSchema, createAgentGraph, AgentGraphApiUpdateSchema, updateAgentGraph, deleteAgentGraph, AgentRelationApiSelectSchema, AgentRelationQuerySchema, getAgentRelationsBySource, getAgentRelationsByTarget, getExternalAgentRelations, listAgentRelations, getAgentRelationById, AgentRelationApiInsertSchema, validateExternalAgent, validateInternalAgent, createAgentRelation, AgentRelationApiUpdateSchema, updateAgentRelation, deleteAgentRelation, AgentApiSelectSchema, listAgentsPaginated, TenantProjectIdParamsSchema, AgentApiInsertSchema, createAgent, AgentApiUpdateSchema, updateAgent, deleteAgent, AgentToolRelationApiSelectSchema, getAgentToolRelationByAgent, getAgentToolRelationByTool, listAgentToolRelations, getAgentToolRelationById, getToolsForAgent, getAgentsForTool, AgentToolRelationApiInsertSchema, createAgentToolRelation, AgentToolRelationApiUpdateSchema, updateAgentToolRelation, deleteAgentToolRelation, ApiKeyApiSelectSchema, listApiKeysPaginated, getApiKeyById, ApiKeyApiCreationResponseSchema, ApiKeyApiInsertSchema, generateApiKey, createApiKey, ApiKeyApiUpdateSchema, updateApiKey, deleteApiKey, listArtifactComponentsPaginated, ArtifactComponentApiInsertSchema, createArtifactComponent, ArtifactComponentApiUpdateSchema, updateArtifactComponent, deleteArtifactComponent, ContextConfigApiSelectSchema, listContextConfigsPaginated, getContextConfigById, ContextConfigApiInsertSchema, createContextConfig, commonUpdateErrorResponses, ContextConfigApiUpdateSchema, updateContextConfig, commonDeleteErrorResponses, deleteContextConfig, CredentialReferenceApiSelectSchema, listCredentialReferencesPaginated, getCredentialReferenceById, CredentialReferenceApiInsertSchema, createCredentialReference, CredentialReferenceApiUpdateSchema, updateCredentialReference, getCredentialStoreLookupKeyFromRetrievalParams, deleteCredentialReference, listDataComponentsPaginated, DataComponentApiInsertSchema, createDataComponent, DataComponentApiUpdateSchema, updateDataComponent, deleteDataComponent, ExternalAgentApiSelectSchema, listExternalAgentsPaginated, getExternalAgent, ExternalAgentApiInsertSchema, createExternalAgent, ExternalAgentApiUpdateSchema, updateExternalAgent, deleteExternalAgent, createFullGraphServerSide, getFullGraph, updateFullGraphServerSide, deleteFullGraph, TenantParamsSchema, ProjectApiSelectSchema, listProjectsPaginated, TenantIdParamsSchema, getProject, ProjectApiInsertSchema, createProject, ProjectApiUpdateSchema, updateProject, deleteProject, McpToolSchema, ToolStatusSchema, listToolsByStatus, dbResultToMcpTool, listTools, getToolById, ToolApiInsertSchema, createTool, ToolApiUpdateSchema, updateTool, deleteTool, getCredentialReference, CredentialStoreType, createDefaultCredentialStores, CredentialStoreRegistry, ContextResolver, CredentialStuffer, McpClient, detectAuthenticationRequired, handleApiError, MCPServerType, MCPTransportType } from '@inkeep/agents-core';
2
- import { Hono } from 'hono';
1
+ import { getLogger as getLogger$1, createDatabaseClient, commonGetErrorResponses, TenantProjectParamsSchema, ArtifactComponentApiSelectSchema, getArtifactComponentsForAgent, getAgentsUsingArtifactComponent, ErrorResponseSchema, SingleResponseSchema, AgentArtifactComponentApiInsertSchema, AgentArtifactComponentApiSelectSchema, getAgentById, getArtifactComponentById, createApiError, isArtifactComponentAssociatedWithAgent, associateArtifactComponentWithAgent, RemovedResponseSchema, removeArtifactComponentFromAgent, ExistsResponseSchema, DataComponentApiSelectSchema, getDataComponentsForAgent, getAgentsUsingDataComponent, AgentDataComponentApiInsertSchema, AgentDataComponentApiSelectSchema, getDataComponent, isDataComponentAssociatedWithAgent, associateDataComponentWithAgent, removeDataComponentFromAgent, ListResponseSchema, PaginationQueryParamsSchema, AgentGraphApiSelectSchema, listAgentGraphs, IdParamsSchema, getAgentGraph, getGraphAgentInfos, FullGraphDefinitionSchema, getFullGraphDefinition, AgentGraphApiInsertSchema, createAgentGraph, AgentGraphApiUpdateSchema, updateAgentGraph, deleteAgentGraph, AgentRelationApiSelectSchema, AgentRelationQuerySchema, getAgentRelationsBySource, getAgentRelationsByTarget, getExternalAgentRelations, listAgentRelations, getAgentRelationById, AgentRelationApiInsertSchema, validateExternalAgent, validateInternalAgent, createAgentRelation, AgentRelationApiUpdateSchema, updateAgentRelation, deleteAgentRelation, AgentApiSelectSchema, listAgentsPaginated, TenantProjectIdParamsSchema, AgentApiInsertSchema, createAgent, AgentApiUpdateSchema, updateAgent, deleteAgent, AgentToolRelationApiSelectSchema, getAgentToolRelationByAgent, getAgentToolRelationByTool, listAgentToolRelations, getAgentToolRelationById, getToolsForAgent, getAgentsForTool, AgentToolRelationApiInsertSchema, createAgentToolRelation, AgentToolRelationApiUpdateSchema, updateAgentToolRelation, deleteAgentToolRelation, ApiKeyApiSelectSchema, listApiKeysPaginated, getApiKeyById, ApiKeyApiCreationResponseSchema, ApiKeyApiInsertSchema, generateApiKey, createApiKey, ApiKeyApiUpdateSchema, updateApiKey, deleteApiKey, listArtifactComponentsPaginated, ArtifactComponentApiInsertSchema, createArtifactComponent, ArtifactComponentApiUpdateSchema, updateArtifactComponent, deleteArtifactComponent, ContextConfigApiSelectSchema, listContextConfigsPaginated, getContextConfigById, ContextConfigApiInsertSchema, createContextConfig, commonUpdateErrorResponses, ContextConfigApiUpdateSchema, updateContextConfig, commonDeleteErrorResponses, deleteContextConfig, CredentialReferenceApiSelectSchema, listCredentialReferencesPaginated, getCredentialReferenceById, CredentialReferenceApiInsertSchema, createCredentialReference, CredentialReferenceApiUpdateSchema, updateCredentialReference, getCredentialStoreLookupKeyFromRetrievalParams, deleteCredentialReference, listDataComponentsPaginated, DataComponentApiInsertSchema, createDataComponent, DataComponentApiUpdateSchema, updateDataComponent, deleteDataComponent, ExternalAgentApiSelectSchema, listExternalAgentsPaginated, getExternalAgent, ExternalAgentApiInsertSchema, createExternalAgent, ExternalAgentApiUpdateSchema, updateExternalAgent, deleteExternalAgent, createFullGraphServerSide, getFullGraph, updateFullGraphServerSide, deleteFullGraph, TenantParamsSchema, ProjectApiSelectSchema, listProjectsPaginated, TenantIdParamsSchema, getProject, ProjectApiInsertSchema, createProject, ProjectApiUpdateSchema, updateProject, deleteProject, McpToolSchema, ToolStatusSchema, listToolsByStatus, dbResultToMcpTool, listTools, getToolById, ToolApiInsertSchema, createTool, ToolApiUpdateSchema, updateTool, deleteTool, getCredentialReference, CredentialStoreType, FullProjectDefinitionSchema, createFullProjectServerSide, getFullProject, updateFullProjectServerSide, deleteFullProject, createDefaultCredentialStores, CredentialStoreRegistry, ContextResolver, CredentialStuffer, McpClient, detectAuthenticationRequired, handleApiError, MCPServerType, MCPTransportType } from '@inkeep/agents-core';
3
2
  import { OpenAPIHono, createRoute, z as z$1 } from '@hono/zod-openapi';
3
+ import { Hono } from 'hono';
4
4
  import { cors } from 'hono/cors';
5
5
  import { HTTPException } from 'hono/http-exception';
6
6
  import { requestId } from 'hono/request-id';
@@ -117,10 +117,10 @@ var apiKeyAuth = () => createMiddleware(async (c, next) => {
117
117
  await next();
118
118
  return;
119
119
  });
120
- function setupOpenAPIRoutes(app19) {
121
- app19.get("/openapi.json", (c) => {
120
+ function setupOpenAPIRoutes(app20) {
121
+ app20.get("/openapi.json", (c) => {
122
122
  try {
123
- const document = app19.getOpenAPIDocument({
123
+ const document = app20.getOpenAPIDocument({
124
124
  openapi: "3.0.0",
125
125
  info: {
126
126
  title: "Inkeep Agents Manage API",
@@ -141,7 +141,7 @@ function setupOpenAPIRoutes(app19) {
141
141
  return c.json({ error: "Failed to generate OpenAPI document", details: errorDetails }, 500);
142
142
  }
143
143
  });
144
- app19.get(
144
+ app20.get(
145
145
  "/docs",
146
146
  swaggerUI({
147
147
  url: "/openapi.json",
@@ -1898,21 +1898,31 @@ app7.openapi(
1898
1898
  ...keyDataWithoutKey,
1899
1899
  expiresAt: body.expiresAt || void 0
1900
1900
  };
1901
- const result = await createApiKey(dbClient_default)(insertData);
1902
- const { keyHash: _, tenantId: __, projectId: ___, ...sanitizedApiKey } = result;
1903
- return c.json(
1904
- {
1905
- data: {
1906
- apiKey: {
1907
- ...sanitizedApiKey,
1908
- lastUsedAt: sanitizedApiKey.lastUsedAt ?? null,
1909
- expiresAt: sanitizedApiKey.expiresAt ?? null
1910
- },
1911
- key
1912
- }
1913
- },
1914
- 201
1915
- );
1901
+ try {
1902
+ const result = await createApiKey(dbClient_default)(insertData);
1903
+ const { keyHash: _, tenantId: __, projectId: ___, ...sanitizedApiKey } = result;
1904
+ return c.json(
1905
+ {
1906
+ data: {
1907
+ apiKey: {
1908
+ ...sanitizedApiKey,
1909
+ lastUsedAt: sanitizedApiKey.lastUsedAt ?? null,
1910
+ expiresAt: sanitizedApiKey.expiresAt ?? null
1911
+ },
1912
+ key
1913
+ }
1914
+ },
1915
+ 201
1916
+ );
1917
+ } catch (error) {
1918
+ if (error?.cause?.code === "SQLITE_CONSTRAINT_FOREIGNKEY" || error?.cause?.rawCode === 787) {
1919
+ throw createApiError({
1920
+ code: "bad_request",
1921
+ message: "Invalid graphId - graph does not exist"
1922
+ });
1923
+ }
1924
+ throw error;
1925
+ }
1916
1926
  }
1917
1927
  );
1918
1928
  app7.openapi(
@@ -2126,10 +2136,20 @@ app8.openapi(
2126
2136
  summaryProps: body.summaryProps || void 0,
2127
2137
  fullProps: body.fullProps || void 0
2128
2138
  };
2129
- const artifactComponent = await createArtifactComponent(dbClient_default)({
2130
- ...componentData
2131
- });
2132
- return c.json({ data: artifactComponent }, 201);
2139
+ try {
2140
+ const artifactComponent = await createArtifactComponent(dbClient_default)({
2141
+ ...componentData
2142
+ });
2143
+ return c.json({ data: artifactComponent }, 201);
2144
+ } catch (error) {
2145
+ if (error?.cause?.code === "SQLITE_CONSTRAINT_PRIMARYKEY" || error?.cause?.rawCode === 1555) {
2146
+ throw createApiError({
2147
+ code: "conflict",
2148
+ message: `Artifact component with ID '${finalId}' already exists`
2149
+ });
2150
+ }
2151
+ throw error;
2152
+ }
2133
2153
  }
2134
2154
  );
2135
2155
  app8.openapi(
@@ -4663,7 +4683,7 @@ app15.openapi(
4663
4683
  }),
4664
4684
  async (c) => {
4665
4685
  const { tenantId, projectId, id } = c.req.valid("param");
4666
- const logger8 = getLogger("oauth-login");
4686
+ const logger9 = getLogger("oauth-login");
4667
4687
  try {
4668
4688
  const tool = await getToolById(dbClient_default)({ scopes: { tenantId, projectId }, toolId: id });
4669
4689
  if (!tool) {
@@ -4681,7 +4701,7 @@ app15.openapi(
4681
4701
  });
4682
4702
  return c.redirect(redirectUrl, 302);
4683
4703
  } catch (error) {
4684
- logger8.error({ toolId: id, error }, "OAuth login failed");
4704
+ logger9.error({ toolId: id, error }, "OAuth login failed");
4685
4705
  if (error && typeof error === "object" && "code" in error) {
4686
4706
  const apiError = error;
4687
4707
  return c.json({ error: apiError.message }, apiError.code === "not_found" ? 404 : 400);
@@ -4886,17 +4906,283 @@ app17.openapi(
4886
4906
  }
4887
4907
  );
4888
4908
  var oauth_default = app17;
4909
+ var logger8 = getLogger("projectFull");
4910
+ var app18 = new OpenAPIHono();
4911
+ var ProjectIdParamsSchema = z.object({
4912
+ tenantId: z.string().openapi({
4913
+ description: "Tenant identifier",
4914
+ example: "tenant_123"
4915
+ }),
4916
+ projectId: z.string().openapi({
4917
+ description: "Project identifier",
4918
+ example: "project_456"
4919
+ })
4920
+ }).openapi("ProjectIdParams");
4921
+ var TenantParamsSchema2 = z.object({
4922
+ tenantId: z.string().openapi({
4923
+ description: "Tenant identifier",
4924
+ example: "tenant_123"
4925
+ })
4926
+ }).openapi("TenantParams");
4927
+ app18.openapi(
4928
+ createRoute({
4929
+ method: "post",
4930
+ path: "/project-full",
4931
+ summary: "Create Full Project",
4932
+ operationId: "create-full-project",
4933
+ tags: ["CRUD Full Project"],
4934
+ description: "Create a complete project with all graphs, agents, tools, and relationships from JSON definition",
4935
+ request: {
4936
+ params: TenantParamsSchema2,
4937
+ body: {
4938
+ content: {
4939
+ "application/json": {
4940
+ schema: FullProjectDefinitionSchema
4941
+ }
4942
+ }
4943
+ }
4944
+ },
4945
+ responses: {
4946
+ 201: {
4947
+ description: "Full project created successfully",
4948
+ content: {
4949
+ "application/json": {
4950
+ schema: SingleResponseSchema(FullProjectDefinitionSchema)
4951
+ }
4952
+ }
4953
+ },
4954
+ 409: {
4955
+ description: "Project already exists",
4956
+ content: {
4957
+ "application/json": {
4958
+ schema: ErrorResponseSchema
4959
+ }
4960
+ }
4961
+ },
4962
+ ...commonGetErrorResponses
4963
+ }
4964
+ }),
4965
+ async (c) => {
4966
+ const { tenantId } = c.req.valid("param");
4967
+ const projectData = c.req.valid("json");
4968
+ const validatedProjectData = FullProjectDefinitionSchema.parse(projectData);
4969
+ try {
4970
+ const createdProject = await createFullProjectServerSide(dbClient_default, logger8)(
4971
+ { tenantId, projectId: validatedProjectData.id },
4972
+ validatedProjectData
4973
+ );
4974
+ return c.json({ data: createdProject }, 201);
4975
+ } catch (error) {
4976
+ if (error?.cause?.code === "SQLITE_CONSTRAINT_PRIMARYKEY" || error?.cause?.rawCode === 1555) {
4977
+ throw createApiError({
4978
+ code: "conflict",
4979
+ message: `Project with ID '${projectData.id}' already exists`
4980
+ });
4981
+ }
4982
+ throw error;
4983
+ }
4984
+ }
4985
+ );
4986
+ app18.openapi(
4987
+ createRoute({
4988
+ method: "get",
4989
+ path: "/project-full/{projectId}",
4990
+ summary: "Get Full Project",
4991
+ operationId: "get-full-project",
4992
+ tags: ["CRUD Full Project"],
4993
+ description: "Retrieve a complete project definition with all graphs, agents, tools, and relationships",
4994
+ request: {
4995
+ params: ProjectIdParamsSchema
4996
+ },
4997
+ responses: {
4998
+ 200: {
4999
+ description: "Full project found",
5000
+ content: {
5001
+ "application/json": {
5002
+ schema: SingleResponseSchema(FullProjectDefinitionSchema)
5003
+ }
5004
+ }
5005
+ },
5006
+ ...commonGetErrorResponses
5007
+ }
5008
+ }),
5009
+ async (c) => {
5010
+ const { tenantId, projectId } = c.req.valid("param");
5011
+ try {
5012
+ const project = await getFullProject(
5013
+ dbClient_default,
5014
+ logger8
5015
+ )({
5016
+ scopes: { tenantId, projectId },
5017
+ projectId
5018
+ });
5019
+ if (!project) {
5020
+ throw createApiError({
5021
+ code: "not_found",
5022
+ message: "Project not found"
5023
+ });
5024
+ }
5025
+ return c.json({ data: project });
5026
+ } catch (error) {
5027
+ if (error instanceof Error && error.message.includes("not found")) {
5028
+ throw createApiError({
5029
+ code: "not_found",
5030
+ message: "Project not found"
5031
+ });
5032
+ }
5033
+ throw createApiError({
5034
+ code: "internal_server_error",
5035
+ message: error instanceof Error ? error.message : "Failed to retrieve project"
5036
+ });
5037
+ }
5038
+ }
5039
+ );
5040
+ app18.openapi(
5041
+ createRoute({
5042
+ method: "put",
5043
+ path: "/project-full/{projectId}",
5044
+ summary: "Update Full Project",
5045
+ operationId: "update-full-project",
5046
+ tags: ["CRUD Full Project"],
5047
+ description: "Update or create a complete project with all graphs, agents, tools, and relationships from JSON definition",
5048
+ request: {
5049
+ params: ProjectIdParamsSchema,
5050
+ body: {
5051
+ content: {
5052
+ "application/json": {
5053
+ schema: FullProjectDefinitionSchema
5054
+ }
5055
+ }
5056
+ }
5057
+ },
5058
+ responses: {
5059
+ 200: {
5060
+ description: "Full project updated successfully",
5061
+ content: {
5062
+ "application/json": {
5063
+ schema: SingleResponseSchema(FullProjectDefinitionSchema)
5064
+ }
5065
+ }
5066
+ },
5067
+ 201: {
5068
+ description: "Full project created successfully",
5069
+ content: {
5070
+ "application/json": {
5071
+ schema: SingleResponseSchema(FullProjectDefinitionSchema)
5072
+ }
5073
+ }
5074
+ },
5075
+ ...commonGetErrorResponses
5076
+ }
5077
+ }),
5078
+ async (c) => {
5079
+ const { tenantId, projectId } = c.req.valid("param");
5080
+ const projectData = c.req.valid("json");
5081
+ try {
5082
+ const validatedProjectData = FullProjectDefinitionSchema.parse(projectData);
5083
+ if (projectId !== validatedProjectData.id) {
5084
+ throw createApiError({
5085
+ code: "bad_request",
5086
+ message: `Project ID mismatch: expected ${projectId}, got ${validatedProjectData.id}`
5087
+ });
5088
+ }
5089
+ const existingProject = await getFullProject(
5090
+ dbClient_default,
5091
+ logger8
5092
+ )({
5093
+ scopes: { tenantId, projectId },
5094
+ projectId
5095
+ });
5096
+ const isCreate = !existingProject;
5097
+ const updatedProject = isCreate ? await createFullProjectServerSide(dbClient_default, logger8)(
5098
+ { tenantId, projectId },
5099
+ validatedProjectData
5100
+ ) : await updateFullProjectServerSide(dbClient_default, logger8)(
5101
+ { tenantId, projectId },
5102
+ validatedProjectData
5103
+ );
5104
+ return c.json({ data: updatedProject }, isCreate ? 201 : 200);
5105
+ } catch (error) {
5106
+ if (error instanceof z.ZodError) {
5107
+ throw createApiError({
5108
+ code: "bad_request",
5109
+ message: "Invalid project definition"
5110
+ });
5111
+ }
5112
+ if (error instanceof Error && error.message.includes("ID mismatch")) {
5113
+ throw createApiError({
5114
+ code: "bad_request",
5115
+ message: error.message
5116
+ });
5117
+ }
5118
+ throw createApiError({
5119
+ code: "internal_server_error",
5120
+ message: error instanceof Error ? error.message : "Failed to update project"
5121
+ });
5122
+ }
5123
+ }
5124
+ );
5125
+ app18.openapi(
5126
+ createRoute({
5127
+ method: "delete",
5128
+ path: "/project-full/{projectId}",
5129
+ summary: "Delete Full Project",
5130
+ operationId: "delete-full-project",
5131
+ tags: ["CRUD Full Project"],
5132
+ description: "Delete a complete project and cascade to all related entities (graphs, agents, tools, relationships)",
5133
+ request: {
5134
+ params: ProjectIdParamsSchema
5135
+ },
5136
+ responses: {
5137
+ 204: {
5138
+ description: "Project deleted successfully"
5139
+ },
5140
+ ...commonGetErrorResponses
5141
+ }
5142
+ }),
5143
+ async (c) => {
5144
+ const { tenantId, projectId } = c.req.valid("param");
5145
+ try {
5146
+ const deleted = await deleteFullProject(
5147
+ dbClient_default,
5148
+ logger8
5149
+ )({
5150
+ scopes: { tenantId, projectId },
5151
+ projectId
5152
+ });
5153
+ if (!deleted) {
5154
+ throw createApiError({
5155
+ code: "not_found",
5156
+ message: "Project not found"
5157
+ });
5158
+ }
5159
+ return c.body(null, 204);
5160
+ } catch (error) {
5161
+ if (error instanceof Error && error.message.includes("not found")) {
5162
+ throw createApiError({
5163
+ code: "not_found",
5164
+ message: "Project not found"
5165
+ });
5166
+ }
5167
+ throw createApiError({
5168
+ code: "internal_server_error",
5169
+ message: error instanceof Error ? error.message : "Failed to delete project"
5170
+ });
5171
+ }
5172
+ }
5173
+ );
5174
+ var projectFull_default = app18;
4889
5175
 
4890
5176
  // src/app.ts
4891
5177
  function createManagementHono(serverConfig, credentialStores) {
4892
- const app19 = new OpenAPIHono();
4893
- app19.use("*", requestId());
4894
- app19.use("*", async (c, next) => {
5178
+ const app20 = new OpenAPIHono();
5179
+ app20.use("*", requestId());
5180
+ app20.use("*", async (c, next) => {
4895
5181
  c.set("serverConfig", serverConfig);
4896
5182
  c.set("credentialStores", credentialStores);
4897
5183
  return next();
4898
5184
  });
4899
- app19.use(
5185
+ app20.use(
4900
5186
  pinoLogger({
4901
5187
  pino: getLogger(),
4902
5188
  http: {
@@ -4909,7 +5195,7 @@ function createManagementHono(serverConfig, credentialStores) {
4909
5195
  }
4910
5196
  })
4911
5197
  );
4912
- app19.onError(async (err, c) => {
5198
+ app20.onError(async (err, c) => {
4913
5199
  const isExpectedError = err instanceof HTTPException;
4914
5200
  const status = isExpectedError ? err.status : 500;
4915
5201
  const requestId2 = c.get("requestId") || "unknown";
@@ -4984,7 +5270,7 @@ function createManagementHono(serverConfig, credentialStores) {
4984
5270
  ...instance && { instance }
4985
5271
  });
4986
5272
  });
4987
- app19.use(
5273
+ app20.use(
4988
5274
  "*",
4989
5275
  cors({
4990
5276
  origin: (origin) => {
@@ -4998,7 +5284,7 @@ function createManagementHono(serverConfig, credentialStores) {
4998
5284
  credentials: true
4999
5285
  })
5000
5286
  );
5001
- app19.openapi(
5287
+ app20.openapi(
5002
5288
  createRoute({
5003
5289
  method: "get",
5004
5290
  path: "/health",
@@ -5015,12 +5301,13 @@ function createManagementHono(serverConfig, credentialStores) {
5015
5301
  return c.body(null, 204);
5016
5302
  }
5017
5303
  );
5018
- app19.use("/tenants/*", apiKeyAuth());
5019
- app19.route("/tenants/:tenantId/crud", routes_default);
5020
- app19.route("/oauth", oauth_default);
5021
- setupOpenAPIRoutes(app19);
5304
+ app20.use("/tenants/*", apiKeyAuth());
5305
+ app20.route("/tenants/:tenantId/crud", routes_default);
5306
+ app20.route("/tenants/:tenantId", projectFull_default);
5307
+ app20.route("/oauth", oauth_default);
5308
+ setupOpenAPIRoutes(app20);
5022
5309
  const baseApp = new Hono();
5023
- baseApp.route("/", app19);
5310
+ baseApp.route("/", app20);
5024
5311
  return baseApp;
5025
5312
  }
5026
5313
 
@@ -5036,8 +5323,8 @@ var defaultConfig = {
5036
5323
  };
5037
5324
  var defaultStores = createDefaultCredentialStores();
5038
5325
  var defaultRegistry = new CredentialStoreRegistry(defaultStores);
5039
- var app18 = createManagementHono(defaultConfig, defaultRegistry);
5040
- var index_default = app18;
5326
+ var app19 = createManagementHono(defaultConfig, defaultRegistry);
5327
+ var index_default = app19;
5041
5328
  function createManagementApp(config2) {
5042
5329
  const serverConfig = config2?.serverConfig ?? defaultConfig;
5043
5330
  const stores = config2?.credentialStores ?? defaultStores;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkeep/agents-manage-api",
3
- "version": "0.0.0-dev-20250912174511",
3
+ "version": "0.0.0-dev-20250912184011",
4
4
  "description": "Agents Manage API for Inkeep Agent Framework - handles CRUD operations and OAuth",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -24,7 +24,7 @@
24
24
  "openid-client": "^6.6.4",
25
25
  "pino": "^9.7.0",
26
26
  "zod": "^4.1.5",
27
- "@inkeep/agents-core": "^0.0.0-dev-20250912174511"
27
+ "@inkeep/agents-core": "^0.0.0-dev-20250912184011"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@hono/vite-dev-server": "^0.20.1",