@heddleagent/execution-host-client 6.7.0 → 7.0.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.
Files changed (52) hide show
  1. package/README.md +6 -1
  2. package/dist/agentcore/agentcore-execution-host.d.ts +1 -1
  3. package/dist/agentcore/agentcore-execution-host.d.ts.map +1 -1
  4. package/dist/agentcore/agentcore-execution-host.js +6 -3
  5. package/dist/agentcore/agentcore-execution-host.js.map +1 -1
  6. package/dist/contracts/index.d.ts +16 -1
  7. package/dist/contracts/index.d.ts.map +1 -1
  8. package/dist/contracts/index.js +19 -1
  9. package/dist/contracts/index.js.map +1 -1
  10. package/dist/conversation/hosted-conversation-turn-service.js +2 -2
  11. package/dist/conversation/hosted-conversation-turn-service.js.map +1 -1
  12. package/dist/conversation/types.d.ts +2 -2
  13. package/dist/conversation/types.d.ts.map +1 -1
  14. package/dist/conversation/types.js.map +1 -1
  15. package/dist/heartbeat/hosted-heartbeat-task-service.js +2 -2
  16. package/dist/heartbeat/hosted-heartbeat-task-service.js.map +1 -1
  17. package/dist/host/jwt-execution-host-mcp-capability-verifier.d.ts.map +1 -1
  18. package/dist/host/jwt-execution-host-mcp-capability-verifier.js +4 -2
  19. package/dist/host/jwt-execution-host-mcp-capability-verifier.js.map +1 -1
  20. package/dist/host/jwt-execution-identity-verifier.d.ts.map +1 -1
  21. package/dist/host/jwt-execution-identity-verifier.js +4 -2
  22. package/dist/host/jwt-execution-identity-verifier.js.map +1 -1
  23. package/dist/host/runtime-session/service.d.ts +2 -2
  24. package/dist/host/runtime-session/service.d.ts.map +1 -1
  25. package/dist/host/runtime-session/service.js +1 -1
  26. package/dist/host/runtime-session/service.js.map +1 -1
  27. package/dist/host/runtime-session/types.d.ts +2 -2
  28. package/dist/host/runtime-session/types.d.ts.map +1 -1
  29. package/dist/host/runtime-session/types.js.map +1 -1
  30. package/dist/host/schemas.d.ts +6 -0
  31. package/dist/host/schemas.d.ts.map +1 -1
  32. package/dist/host/schemas.js +22 -0
  33. package/dist/host/schemas.js.map +1 -1
  34. package/dist/host/types.d.ts +2 -0
  35. package/dist/host/types.d.ts.map +1 -1
  36. package/dist/host/types.js.map +1 -1
  37. package/dist/http-sse/direct-http-execution-host.d.ts.map +1 -1
  38. package/dist/http-sse/direct-http-execution-host.js +3 -3
  39. package/dist/http-sse/direct-http-execution-host.js.map +1 -1
  40. package/dist/http-sse/types.d.ts +3 -3
  41. package/dist/http-sse/types.d.ts.map +1 -1
  42. package/dist/http-sse/types.js.map +1 -1
  43. package/dist/node/direct-credentials.d.ts +3 -7
  44. package/dist/node/direct-credentials.d.ts.map +1 -1
  45. package/dist/node/direct-credentials.js +3 -15
  46. package/dist/node/direct-credentials.js.map +1 -1
  47. package/dist/testing/request.d.ts.map +1 -1
  48. package/dist/testing/request.js +14 -4
  49. package/dist/testing/request.js.map +1 -1
  50. package/package.json +1 -1
  51. package/spec/v1/openapi.json +62 -4
  52. package/spec/v1/schema-bundle.json +58 -0
@@ -1,9 +1,8 @@
1
1
  import { createHash, timingSafeEqual, } from 'node:crypto';
2
2
  import { z } from 'zod';
3
- import { AGENTCORE_RUNTIME_SESSION_HEADER, EXECUTION_ASSERTION_HEADER, EXECUTION_HOST_LOCAL_TOKEN_HEADER, ExecutionHostConversationTurnRequestSchema, MCP_CAPABILITY_HEADER, MODEL_API_KEY_HEADER, RuntimeSessionIdSchema, } from '../contracts/index.js';
3
+ import { AGENTCORE_RUNTIME_SESSION_HEADER, EXECUTION_ASSERTION_HEADER, EXECUTION_HOST_LOCAL_TOKEN_HEADER, ExecutionHostConversationTurnRequestSchema, ExecutionHostModelCredentialSchema, MCP_CAPABILITY_HEADER, MODEL_CREDENTIAL_HEADER, RuntimeSessionIdSchema, } from '../contracts/index.js';
4
4
  const MAX_REQUEST_BODY_BYTES = 262_144;
5
5
  const REDACTED_HEADER_VALUE = '[REDACTED]';
6
- const SecretSchema = z.string().min(8).max(4_096);
7
6
  const AssertionSchema = z.string().min(32).max(4_096);
8
7
  const ErrorCodeSchema = z.string().min(1).max(128).regex(/^[a-z0-9_]+$/);
9
8
  export async function parseLocalExecutionHostRequest(request, expectedLocalToken, signal) {
@@ -12,7 +11,7 @@ export async function parseLocalExecutionHostRequest(request, expectedLocalToken
12
11
  assertLocalToken(headers.localToken, expectedLocalToken);
13
12
  const runtimeSessionId = parseRequestValue(RuntimeSessionIdSchema, headers.runtimeSessionId, 400, 'invalid_runtime_session');
14
13
  parseRequestValue(AssertionSchema, headers.executionAssertion, 401, 'invalid_execution_identity');
15
- parseRequestValue(SecretSchema, headers.modelApiKey, 401, 'invalid_model_credential');
14
+ parseRequestValue(ExecutionHostModelCredentialSchema, parseSensitiveJson(headers.modelCredential), 401, 'invalid_model_credential');
16
15
  const mcpCapability = headers.mcpCapability === undefined
17
16
  ? undefined
18
17
  : parseRequestValue(AssertionSchema, headers.mcpCapability, 401, 'invalid_mcp_capability');
@@ -57,13 +56,24 @@ function takeInvocationHeaders(request) {
57
56
  runtimeSessionId: extractSensitiveHeader(request, AGENTCORE_RUNTIME_SESSION_HEADER),
58
57
  executionAssertion: extractSensitiveHeader(request, EXECUTION_ASSERTION_HEADER),
59
58
  mcpCapability: extractSensitiveHeader(request, MCP_CAPABILITY_HEADER),
60
- modelApiKey: extractSensitiveHeader(request, MODEL_API_KEY_HEADER),
59
+ modelCredential: extractSensitiveHeader(request, MODEL_CREDENTIAL_HEADER),
61
60
  };
62
61
  if (Object.values(extracted).some((header) => header.duplicate)) {
63
62
  throw new LocalExecutionHostRequestError(400, 'duplicate_sensitive_header');
64
63
  }
65
64
  return Object.fromEntries(Object.entries(extracted).map(([name, header]) => [name, header.value]));
66
65
  }
66
+ function parseSensitiveJson(value) {
67
+ if (!value) {
68
+ return undefined;
69
+ }
70
+ try {
71
+ return JSON.parse(value);
72
+ }
73
+ catch {
74
+ return undefined;
75
+ }
76
+ }
67
77
  function extractSensitiveHeader(request, name) {
68
78
  const occurrences = request.rawHeaders.reduce((count, headerName, index) => count
69
79
  + (index % 2 === 0 && headerName.toLowerCase() === name ? 1 : 0), 0);
@@ -1 +1 @@
1
- {"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/testing/request.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createHash,\n timingSafeEqual,\n} from 'node:crypto';\nimport type {\n IncomingMessage,\n ServerResponse,\n} from 'node:http';\nimport { z } from 'zod';\nimport {\n AGENTCORE_RUNTIME_SESSION_HEADER,\n EXECUTION_ASSERTION_HEADER,\n EXECUTION_HOST_LOCAL_TOKEN_HEADER,\n ExecutionHostConversationTurnRequestSchema,\n MCP_CAPABILITY_HEADER,\n MODEL_API_KEY_HEADER,\n RuntimeSessionIdSchema,\n type ExecutionHostConversationTurnRequest,\n} from '../contracts/index.js';\n\nconst MAX_REQUEST_BODY_BYTES = 262_144;\nconst REDACTED_HEADER_VALUE = '[REDACTED]';\nconst SecretSchema = z.string().min(8).max(4_096);\nconst AssertionSchema = z.string().min(32).max(4_096);\nconst ErrorCodeSchema = z.string().min(1).max(128).regex(/^[a-z0-9_]+$/);\n\nexport type ParsedLocalExecutionHostRequest = {\n request: ExecutionHostConversationTurnRequest;\n runtimeSessionId: string;\n mcpCapability?: string;\n};\n\nexport async function parseLocalExecutionHostRequest(\n request: IncomingMessage,\n expectedLocalToken: string,\n signal: AbortSignal,\n): Promise<ParsedLocalExecutionHostRequest> {\n const headers = takeInvocationHeaders(request);\n assertInvocationRoute(request);\n assertLocalToken(headers.localToken, expectedLocalToken);\n const runtimeSessionId = parseRequestValue(\n RuntimeSessionIdSchema,\n headers.runtimeSessionId,\n 400,\n 'invalid_runtime_session',\n );\n parseRequestValue(\n AssertionSchema,\n headers.executionAssertion,\n 401,\n 'invalid_execution_identity',\n );\n parseRequestValue(\n SecretSchema,\n headers.modelApiKey,\n 401,\n 'invalid_model_credential',\n );\n const mcpCapability = headers.mcpCapability === undefined\n ? undefined\n : parseRequestValue(\n AssertionSchema,\n headers.mcpCapability,\n 401,\n 'invalid_mcp_capability',\n );\n const parsedRequest = parseRequestValue(\n ExecutionHostConversationTurnRequestSchema,\n await readJsonBody(request, signal),\n 400,\n 'invalid_request',\n );\n return {\n request: parsedRequest,\n runtimeSessionId,\n mcpCapability,\n };\n}\n\nexport function writeLocalExecutionHostRejection(\n response: ServerResponse,\n error: unknown,\n): void {\n const rejection = error instanceof LocalExecutionHostRequestError\n ? { status: error.status, code: error.code }\n : { status: 500, code: 'fixture_internal_error' };\n const safeCode = ErrorCodeSchema.parse(rejection.code);\n const body = JSON.stringify({\n error: {\n code: safeCode,\n message: 'Local Execution Host fixture rejected the request.',\n },\n });\n response.writeHead(rejection.status, {\n 'Cache-Control': 'no-store',\n 'Content-Length': Buffer.byteLength(body),\n 'Content-Type': 'application/json; charset=utf-8',\n 'X-Content-Type-Options': 'nosniff',\n });\n response.end(body);\n}\n\ntype InvocationHeaders = {\n localToken: string | undefined;\n runtimeSessionId: string | undefined;\n executionAssertion: string | undefined;\n mcpCapability: string | undefined;\n modelApiKey: string | undefined;\n};\n\nclass LocalExecutionHostRequestError extends Error {\n constructor(\n readonly status: number,\n readonly code: string,\n ) {\n super(code);\n }\n}\n\nfunction takeInvocationHeaders(request: IncomingMessage): InvocationHeaders {\n const extracted = {\n localToken: extractSensitiveHeader(\n request,\n EXECUTION_HOST_LOCAL_TOKEN_HEADER,\n ),\n runtimeSessionId: extractSensitiveHeader(\n request,\n AGENTCORE_RUNTIME_SESSION_HEADER,\n ),\n executionAssertion: extractSensitiveHeader(\n request,\n EXECUTION_ASSERTION_HEADER,\n ),\n mcpCapability: extractSensitiveHeader(request, MCP_CAPABILITY_HEADER),\n modelApiKey: extractSensitiveHeader(request, MODEL_API_KEY_HEADER),\n };\n if (Object.values(extracted).some((header) => header.duplicate)) {\n throw new LocalExecutionHostRequestError(\n 400,\n 'duplicate_sensitive_header',\n );\n }\n return Object.fromEntries(\n Object.entries(extracted).map(([name, header]) => [name, header.value]),\n ) as InvocationHeaders;\n}\n\nfunction extractSensitiveHeader(\n request: IncomingMessage,\n name: string,\n): { value: string | undefined; duplicate: boolean } {\n const occurrences = request.rawHeaders.reduce(\n (count, headerName, index) => count\n + (index % 2 === 0 && headerName.toLowerCase() === name ? 1 : 0),\n 0,\n );\n const value = request.headers[name];\n request.headers[name] = value === undefined\n ? undefined\n : REDACTED_HEADER_VALUE;\n for (let index = 0; index < request.rawHeaders.length; index += 2) {\n if (request.rawHeaders[index]?.toLowerCase() === name) {\n request.rawHeaders[index + 1] = REDACTED_HEADER_VALUE;\n }\n }\n return {\n value: Array.isArray(value) ? undefined : value,\n duplicate: occurrences > 1 || Array.isArray(value),\n };\n}\n\nfunction assertInvocationRoute(request: IncomingMessage): void {\n if (request.method !== 'POST') {\n throw new LocalExecutionHostRequestError(405, 'method_not_allowed');\n }\n if (request.url !== '/invocations') {\n throw new LocalExecutionHostRequestError(404, 'not_found');\n }\n const contentType = request.headers['content-type']\n ?.split(';', 1)[0]\n ?.trim()\n .toLowerCase();\n if (contentType !== 'application/json') {\n throw new LocalExecutionHostRequestError(\n 415,\n 'unsupported_media_type',\n );\n }\n}\n\nfunction assertLocalToken(actual: string | undefined, expected: string): void {\n if (!actual || !constantTimeEqual(actual, expected)) {\n throw new LocalExecutionHostRequestError(401, 'invalid_local_token');\n }\n}\n\nfunction constantTimeEqual(left: string, right: string): boolean {\n const leftHash = createHash('sha256').update(left).digest();\n const rightHash = createHash('sha256').update(right).digest();\n return timingSafeEqual(leftHash, rightHash);\n}\n\nasync function readJsonBody(\n request: IncomingMessage,\n signal: AbortSignal,\n): Promise<unknown> {\n const chunks: Buffer[] = [];\n let totalBytes = 0;\n for await (const rawChunk of request) {\n signal.throwIfAborted();\n const chunk = Buffer.isBuffer(rawChunk)\n ? rawChunk\n : Buffer.from(rawChunk as Uint8Array);\n totalBytes += chunk.byteLength;\n if (totalBytes > MAX_REQUEST_BODY_BYTES) {\n throw new LocalExecutionHostRequestError(413, 'request_too_large');\n }\n chunks.push(chunk);\n }\n if (totalBytes === 0) {\n throw new LocalExecutionHostRequestError(400, 'invalid_request');\n }\n try {\n return JSON.parse(Buffer.concat(chunks, totalBytes).toString('utf8'));\n } catch {\n throw new LocalExecutionHostRequestError(400, 'invalid_request');\n }\n}\n\nfunction parseRequestValue<T>(\n schema: z.ZodType<T>,\n value: unknown,\n status: number,\n code: string,\n): T {\n const parsed = schema.safeParse(value);\n if (!parsed.success) {\n throw new LocalExecutionHostRequestError(status, code);\n }\n return parsed.data;\n}\n"]}
1
+ {"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/testing/request.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createHash,\n timingSafeEqual,\n} from 'node:crypto';\nimport type {\n IncomingMessage,\n ServerResponse,\n} from 'node:http';\nimport { z } from 'zod';\nimport {\n AGENTCORE_RUNTIME_SESSION_HEADER,\n EXECUTION_ASSERTION_HEADER,\n EXECUTION_HOST_LOCAL_TOKEN_HEADER,\n ExecutionHostConversationTurnRequestSchema,\n ExecutionHostModelCredentialSchema,\n MCP_CAPABILITY_HEADER,\n MODEL_CREDENTIAL_HEADER,\n RuntimeSessionIdSchema,\n type ExecutionHostConversationTurnRequest,\n} from '../contracts/index.js';\n\nconst MAX_REQUEST_BODY_BYTES = 262_144;\nconst REDACTED_HEADER_VALUE = '[REDACTED]';\nconst AssertionSchema = z.string().min(32).max(4_096);\nconst ErrorCodeSchema = z.string().min(1).max(128).regex(/^[a-z0-9_]+$/);\n\nexport type ParsedLocalExecutionHostRequest = {\n request: ExecutionHostConversationTurnRequest;\n runtimeSessionId: string;\n mcpCapability?: string;\n};\n\nexport async function parseLocalExecutionHostRequest(\n request: IncomingMessage,\n expectedLocalToken: string,\n signal: AbortSignal,\n): Promise<ParsedLocalExecutionHostRequest> {\n const headers = takeInvocationHeaders(request);\n assertInvocationRoute(request);\n assertLocalToken(headers.localToken, expectedLocalToken);\n const runtimeSessionId = parseRequestValue(\n RuntimeSessionIdSchema,\n headers.runtimeSessionId,\n 400,\n 'invalid_runtime_session',\n );\n parseRequestValue(\n AssertionSchema,\n headers.executionAssertion,\n 401,\n 'invalid_execution_identity',\n );\n parseRequestValue(\n ExecutionHostModelCredentialSchema,\n parseSensitiveJson(headers.modelCredential),\n 401,\n 'invalid_model_credential',\n );\n const mcpCapability = headers.mcpCapability === undefined\n ? undefined\n : parseRequestValue(\n AssertionSchema,\n headers.mcpCapability,\n 401,\n 'invalid_mcp_capability',\n );\n const parsedRequest = parseRequestValue(\n ExecutionHostConversationTurnRequestSchema,\n await readJsonBody(request, signal),\n 400,\n 'invalid_request',\n );\n return {\n request: parsedRequest,\n runtimeSessionId,\n mcpCapability,\n };\n}\n\nexport function writeLocalExecutionHostRejection(\n response: ServerResponse,\n error: unknown,\n): void {\n const rejection = error instanceof LocalExecutionHostRequestError\n ? { status: error.status, code: error.code }\n : { status: 500, code: 'fixture_internal_error' };\n const safeCode = ErrorCodeSchema.parse(rejection.code);\n const body = JSON.stringify({\n error: {\n code: safeCode,\n message: 'Local Execution Host fixture rejected the request.',\n },\n });\n response.writeHead(rejection.status, {\n 'Cache-Control': 'no-store',\n 'Content-Length': Buffer.byteLength(body),\n 'Content-Type': 'application/json; charset=utf-8',\n 'X-Content-Type-Options': 'nosniff',\n });\n response.end(body);\n}\n\ntype InvocationHeaders = {\n localToken: string | undefined;\n runtimeSessionId: string | undefined;\n executionAssertion: string | undefined;\n mcpCapability: string | undefined;\n modelCredential: string | undefined;\n};\n\nclass LocalExecutionHostRequestError extends Error {\n constructor(\n readonly status: number,\n readonly code: string,\n ) {\n super(code);\n }\n}\n\nfunction takeInvocationHeaders(request: IncomingMessage): InvocationHeaders {\n const extracted = {\n localToken: extractSensitiveHeader(\n request,\n EXECUTION_HOST_LOCAL_TOKEN_HEADER,\n ),\n runtimeSessionId: extractSensitiveHeader(\n request,\n AGENTCORE_RUNTIME_SESSION_HEADER,\n ),\n executionAssertion: extractSensitiveHeader(\n request,\n EXECUTION_ASSERTION_HEADER,\n ),\n mcpCapability: extractSensitiveHeader(request, MCP_CAPABILITY_HEADER),\n modelCredential: extractSensitiveHeader(request, MODEL_CREDENTIAL_HEADER),\n };\n if (Object.values(extracted).some((header) => header.duplicate)) {\n throw new LocalExecutionHostRequestError(\n 400,\n 'duplicate_sensitive_header',\n );\n }\n return Object.fromEntries(\n Object.entries(extracted).map(([name, header]) => [name, header.value]),\n ) as InvocationHeaders;\n}\n\nfunction parseSensitiveJson(value: string | undefined): unknown {\n if (!value) {\n return undefined;\n }\n try {\n return JSON.parse(value) as unknown;\n } catch {\n return undefined;\n }\n}\n\nfunction extractSensitiveHeader(\n request: IncomingMessage,\n name: string,\n): { value: string | undefined; duplicate: boolean } {\n const occurrences = request.rawHeaders.reduce(\n (count, headerName, index) => count\n + (index % 2 === 0 && headerName.toLowerCase() === name ? 1 : 0),\n 0,\n );\n const value = request.headers[name];\n request.headers[name] = value === undefined\n ? undefined\n : REDACTED_HEADER_VALUE;\n for (let index = 0; index < request.rawHeaders.length; index += 2) {\n if (request.rawHeaders[index]?.toLowerCase() === name) {\n request.rawHeaders[index + 1] = REDACTED_HEADER_VALUE;\n }\n }\n return {\n value: Array.isArray(value) ? undefined : value,\n duplicate: occurrences > 1 || Array.isArray(value),\n };\n}\n\nfunction assertInvocationRoute(request: IncomingMessage): void {\n if (request.method !== 'POST') {\n throw new LocalExecutionHostRequestError(405, 'method_not_allowed');\n }\n if (request.url !== '/invocations') {\n throw new LocalExecutionHostRequestError(404, 'not_found');\n }\n const contentType = request.headers['content-type']\n ?.split(';', 1)[0]\n ?.trim()\n .toLowerCase();\n if (contentType !== 'application/json') {\n throw new LocalExecutionHostRequestError(\n 415,\n 'unsupported_media_type',\n );\n }\n}\n\nfunction assertLocalToken(actual: string | undefined, expected: string): void {\n if (!actual || !constantTimeEqual(actual, expected)) {\n throw new LocalExecutionHostRequestError(401, 'invalid_local_token');\n }\n}\n\nfunction constantTimeEqual(left: string, right: string): boolean {\n const leftHash = createHash('sha256').update(left).digest();\n const rightHash = createHash('sha256').update(right).digest();\n return timingSafeEqual(leftHash, rightHash);\n}\n\nasync function readJsonBody(\n request: IncomingMessage,\n signal: AbortSignal,\n): Promise<unknown> {\n const chunks: Buffer[] = [];\n let totalBytes = 0;\n for await (const rawChunk of request) {\n signal.throwIfAborted();\n const chunk = Buffer.isBuffer(rawChunk)\n ? rawChunk\n : Buffer.from(rawChunk as Uint8Array);\n totalBytes += chunk.byteLength;\n if (totalBytes > MAX_REQUEST_BODY_BYTES) {\n throw new LocalExecutionHostRequestError(413, 'request_too_large');\n }\n chunks.push(chunk);\n }\n if (totalBytes === 0) {\n throw new LocalExecutionHostRequestError(400, 'invalid_request');\n }\n try {\n return JSON.parse(Buffer.concat(chunks, totalBytes).toString('utf8'));\n } catch {\n throw new LocalExecutionHostRequestError(400, 'invalid_request');\n }\n}\n\nfunction parseRequestValue<T>(\n schema: z.ZodType<T>,\n value: unknown,\n status: number,\n code: string,\n): T {\n const parsed = schema.safeParse(value);\n if (!parsed.success) {\n throw new LocalExecutionHostRequestError(status, code);\n }\n return parsed.data;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heddleagent/execution-host-client",
3
- "version": "6.7.0",
3
+ "version": "7.0.0",
4
4
  "description": "Contracts, execution authority, lifecycle services, and adopter clients for compatible Heddle Execution Hosts",
5
5
  "author": "Jay / Fienna Liang <roackb2@gmail.com>",
6
6
  "license": "MIT",
@@ -49,14 +49,14 @@
49
49
  }
50
50
  },
51
51
  {
52
- "name": "x-heddle-execution-host-model-api-key",
52
+ "name": "x-heddle-execution-host-model-credential",
53
53
  "in": "header",
54
54
  "required": true,
55
- "description": "Invocation-scoped model credential. It must be scrubbed before parsing or logging.",
55
+ "description": "JSON-encoded invocation-scoped model credential. OAuth refresh material is forbidden. The header must be scrubbed before parsing or logging.",
56
56
  "schema": {
57
57
  "type": "string",
58
- "minLength": 8,
59
- "maxLength": 4096
58
+ "minLength": 16,
59
+ "maxLength": 8192
60
60
  }
61
61
  },
62
62
  {
@@ -441,6 +441,64 @@
441
441
  }
442
442
  }
443
443
  },
444
+ "ModelCredential": {
445
+ "oneOf": [
446
+ {
447
+ "type": "object",
448
+ "properties": {
449
+ "type": {
450
+ "type": "string",
451
+ "const": "api-key"
452
+ },
453
+ "apiKey": {
454
+ "type": "string",
455
+ "minLength": 8,
456
+ "maxLength": 4096
457
+ }
458
+ },
459
+ "required": [
460
+ "type",
461
+ "apiKey"
462
+ ],
463
+ "additionalProperties": false
464
+ },
465
+ {
466
+ "type": "object",
467
+ "properties": {
468
+ "type": {
469
+ "type": "string",
470
+ "const": "oauth-access-token"
471
+ },
472
+ "provider": {
473
+ "type": "string",
474
+ "const": "openai"
475
+ },
476
+ "accessToken": {
477
+ "type": "string",
478
+ "minLength": 8,
479
+ "maxLength": 4096
480
+ },
481
+ "expiresAt": {
482
+ "type": "integer",
483
+ "exclusiveMinimum": 0,
484
+ "maximum": 9007199254740991
485
+ },
486
+ "accountId": {
487
+ "type": "string",
488
+ "minLength": 1,
489
+ "maxLength": 512
490
+ }
491
+ },
492
+ "required": [
493
+ "type",
494
+ "provider",
495
+ "accessToken",
496
+ "expiresAt"
497
+ ],
498
+ "additionalProperties": false
499
+ }
500
+ ]
501
+ },
444
502
  "RuntimePublicResult": {
445
503
  "type": "object",
446
504
  "properties": {
@@ -242,6 +242,64 @@
242
242
  }
243
243
  }
244
244
  },
245
+ "ModelCredential": {
246
+ "oneOf": [
247
+ {
248
+ "type": "object",
249
+ "properties": {
250
+ "type": {
251
+ "type": "string",
252
+ "const": "api-key"
253
+ },
254
+ "apiKey": {
255
+ "type": "string",
256
+ "minLength": 8,
257
+ "maxLength": 4096
258
+ }
259
+ },
260
+ "required": [
261
+ "type",
262
+ "apiKey"
263
+ ],
264
+ "additionalProperties": false
265
+ },
266
+ {
267
+ "type": "object",
268
+ "properties": {
269
+ "type": {
270
+ "type": "string",
271
+ "const": "oauth-access-token"
272
+ },
273
+ "provider": {
274
+ "type": "string",
275
+ "const": "openai"
276
+ },
277
+ "accessToken": {
278
+ "type": "string",
279
+ "minLength": 8,
280
+ "maxLength": 4096
281
+ },
282
+ "expiresAt": {
283
+ "type": "integer",
284
+ "exclusiveMinimum": 0,
285
+ "maximum": 9007199254740991
286
+ },
287
+ "accountId": {
288
+ "type": "string",
289
+ "minLength": 1,
290
+ "maxLength": 512
291
+ }
292
+ },
293
+ "required": [
294
+ "type",
295
+ "provider",
296
+ "accessToken",
297
+ "expiresAt"
298
+ ],
299
+ "additionalProperties": false
300
+ }
301
+ ]
302
+ },
245
303
  "RuntimePublicResult": {
246
304
  "type": "object",
247
305
  "properties": {