open-managed-agents 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +93 -0
- package/README.md +248 -0
- package/bin/oma.mjs +499 -0
- package/dist/scripts/alpha-openai-compatible-fixture.mjs +134 -0
- package/dist/scripts/alpha-smoke-models.mjs +92 -0
- package/dist/scripts/alpha-smoke.mjs +581 -0
- package/dist/scripts/oma-doctor.js +230 -0
- package/dist/scripts/oma-models.js +299 -0
- package/dist/scripts/oma-workspaces.js +133 -0
- package/dist/src/control-plane/admin/auth.js +43 -0
- package/dist/src/control-plane/admin/routes.js +76 -0
- package/dist/src/control-plane/admin/service.js +102 -0
- package/dist/src/control-plane/admission.js +90 -0
- package/dist/src/control-plane/agents/routes.js +63 -0
- package/dist/src/control-plane/agents/service.js +687 -0
- package/dist/src/control-plane/agents/store.js +391 -0
- package/dist/src/control-plane/agents/types.js +1 -0
- package/dist/src/control-plane/api-constants.js +3 -0
- package/dist/src/control-plane/app.js +907 -0
- package/dist/src/control-plane/console/auth.js +68 -0
- package/dist/src/control-plane/console/static.js +112 -0
- package/dist/src/control-plane/deployment-runtime-config.js +328 -0
- package/dist/src/control-plane/deployment-runtime-event-coordinator.js +25 -0
- package/dist/src/control-plane/deployment-runtime-turn-guard.js +14 -0
- package/dist/src/control-plane/deployment-session-coordinator.js +25 -0
- package/dist/src/control-plane/deployment-session-output-coordinator.js +27 -0
- package/dist/src/control-plane/deployment-storage.js +354 -0
- package/dist/src/control-plane/egress/image.js +48 -0
- package/dist/src/control-plane/egress/policy.js +571 -0
- package/dist/src/control-plane/egress/presets.js +77 -0
- package/dist/src/control-plane/egress/proxy.js +72 -0
- package/dist/src/control-plane/egress/ssrf.js +106 -0
- package/dist/src/control-plane/egress/utils/debug.js +14 -0
- package/dist/src/control-plane/egress/vendor/http-proxy.js +335 -0
- package/dist/src/control-plane/egress/vendor/mitm-ca.js +226 -0
- package/dist/src/control-plane/egress/vendor/mitm-leaf.js +124 -0
- package/dist/src/control-plane/egress/vendor/parent-proxy.js +438 -0
- package/dist/src/control-plane/egress/vendor/request-filter.js +105 -0
- package/dist/src/control-plane/egress/vendor/sandbox-config.js +1 -0
- package/dist/src/control-plane/egress/vendor/tls-terminate-proxy.js +269 -0
- package/dist/src/control-plane/environments/routes.js +54 -0
- package/dist/src/control-plane/environments/service.js +112 -0
- package/dist/src/control-plane/environments/store.js +132 -0
- package/dist/src/control-plane/environments/types.js +1 -0
- package/dist/src/control-plane/errors.js +81 -0
- package/dist/src/control-plane/events/broadcaster.js +217 -0
- package/dist/src/control-plane/events/constants.js +2 -0
- package/dist/src/control-plane/events/persist.js +39 -0
- package/dist/src/control-plane/events/request.js +190 -0
- package/dist/src/control-plane/events/routes.js +159 -0
- package/dist/src/control-plane/events/runtime-helpers.js +134 -0
- package/dist/src/control-plane/events/service.js +1985 -0
- package/dist/src/control-plane/events/session-guards.js +29 -0
- package/dist/src/control-plane/events/sse.js +6 -0
- package/dist/src/control-plane/events/store.js +772 -0
- package/dist/src/control-plane/events/tool-persistence.js +102 -0
- package/dist/src/control-plane/events/types.js +21 -0
- package/dist/src/control-plane/files/routes.js +121 -0
- package/dist/src/control-plane/files/service.js +65 -0
- package/dist/src/control-plane/files/store-common.js +87 -0
- package/dist/src/control-plane/files/store-local.js +488 -0
- package/dist/src/control-plane/files/store-memory.js +270 -0
- package/dist/src/control-plane/files/store.js +2 -0
- package/dist/src/control-plane/files/types.js +7 -0
- package/dist/src/control-plane/http.js +25 -0
- package/dist/src/control-plane/ids.js +43 -0
- package/dist/src/control-plane/logging.js +263 -0
- package/dist/src/control-plane/models/auth-storage-backend.js +238 -0
- package/dist/src/control-plane/models/catalog.js +78 -0
- package/dist/src/control-plane/models/config-security.js +376 -0
- package/dist/src/control-plane/models/deployment-config.js +93 -0
- package/dist/src/control-plane/models/routes.js +32 -0
- package/dist/src/control-plane/models/service.js +138 -0
- package/dist/src/control-plane/observability/instruments.js +65 -0
- package/dist/src/control-plane/observability/metrics.js +125 -0
- package/dist/src/control-plane/observability/routes.js +95 -0
- package/dist/src/control-plane/openapi/document.js +282 -0
- package/dist/src/control-plane/openapi/routes.js +78 -0
- package/dist/src/control-plane/request-idempotency.js +85 -0
- package/dist/src/control-plane/secrets/envelope.js +132 -0
- package/dist/src/control-plane/secrets/master-key.js +44 -0
- package/dist/src/control-plane/secrets/routes.js +20 -0
- package/dist/src/control-plane/secrets/service.js +71 -0
- package/dist/src/control-plane/secrets/store.js +212 -0
- package/dist/src/control-plane/secrets/types.js +3 -0
- package/dist/src/control-plane/sessions/pi/custom-tools.js +146 -0
- package/dist/src/control-plane/sessions/pi/mcp/bridge.js +527 -0
- package/dist/src/control-plane/sessions/pi/mcp/client.js +157 -0
- package/dist/src/control-plane/sessions/pi/mcp/credential.js +28 -0
- package/dist/src/control-plane/sessions/pi/mcp/fetch.js +69 -0
- package/dist/src/control-plane/sessions/pi/mcp/probe.js +202 -0
- package/dist/src/control-plane/sessions/pi/mcp/runtime.js +13 -0
- package/dist/src/control-plane/sessions/pi/runner.js +1104 -0
- package/dist/src/control-plane/sessions/pi/sandbox/cma-glob.js +388 -0
- package/dist/src/control-plane/sessions/pi/sandbox/cma-grep.js +124 -0
- package/dist/src/control-plane/sessions/pi/sandbox/docker-egress.js +347 -0
- package/dist/src/control-plane/sessions/pi/sandbox/docker.js +1589 -0
- package/dist/src/control-plane/sessions/pi/sandbox/glob.js +48 -0
- package/dist/src/control-plane/sessions/pi/sandbox/image.js +7 -0
- package/dist/src/control-plane/sessions/pi/sandbox/microsandbox.js +1677 -0
- package/dist/src/control-plane/sessions/pi/sandbox/provider.js +561 -0
- package/dist/src/control-plane/sessions/pi/sandbox/selection.js +168 -0
- package/dist/src/control-plane/sessions/pi/span-normalizer.js +82 -0
- package/dist/src/control-plane/sessions/pi/tool-permissions.js +392 -0
- package/dist/src/control-plane/sessions/pi/translator.js +100 -0
- package/dist/src/control-plane/sessions/request.js +164 -0
- package/dist/src/control-plane/sessions/resources.js +63 -0
- package/dist/src/control-plane/sessions/routes.js +88 -0
- package/dist/src/control-plane/sessions/serialize.js +24 -0
- package/dist/src/control-plane/sessions/service.js +733 -0
- package/dist/src/control-plane/sessions/store.js +538 -0
- package/dist/src/control-plane/sessions/types.js +1 -0
- package/dist/src/control-plane/skills/archive.js +169 -0
- package/dist/src/control-plane/skills/routes.js +41 -0
- package/dist/src/control-plane/skills/service.js +29 -0
- package/dist/src/control-plane/skills/store.js +233 -0
- package/dist/src/control-plane/skills/types.js +5 -0
- package/dist/src/control-plane/sqlite-transaction.js +15 -0
- package/dist/src/control-plane/vaults/mcp-oauth-validate.js +165 -0
- package/dist/src/control-plane/vaults/oauth-refresh-ticker.js +43 -0
- package/dist/src/control-plane/vaults/oauth-refresh.js +448 -0
- package/dist/src/control-plane/vaults/routes.js +66 -0
- package/dist/src/control-plane/vaults/service.js +553 -0
- package/dist/src/control-plane/vaults/store.js +691 -0
- package/dist/src/control-plane/vaults/types.js +1 -0
- package/dist/src/control-plane/wake-loop.js +65 -0
- package/dist/src/control-plane/wiring.js +92 -0
- package/dist/src/control-plane/workspace.js +4 -0
- package/dist/src/control-plane/workspaces/store.js +158 -0
- package/dist/src/egress-proxy-main.js +103 -0
- package/dist/src/main.js +124 -0
- package/dist/src/types/agents.js +1 -0
- package/dist/src/types/common.js +1 -0
- package/dist/src/types/environments.js +1 -0
- package/dist/src/types/events.js +121 -0
- package/dist/src/types/files.js +1 -0
- package/dist/src/types/json.js +19 -0
- package/dist/src/types/sessions.js +1 -0
- package/dist/ui/managed-agents-console/README.md +52 -0
- package/dist/ui/managed-agents-console/docs/agents.md +23 -0
- package/dist/ui/managed-agents-console/docs/console.md +23 -0
- package/dist/ui/managed-agents-console/docs/dreams.md +5 -0
- package/dist/ui/managed-agents-console/docs/environments.md +27 -0
- package/dist/ui/managed-agents-console/docs/events.md +19 -0
- package/dist/ui/managed-agents-console/docs/files.md +17 -0
- package/dist/ui/managed-agents-console/docs/github.md +11 -0
- package/dist/ui/managed-agents-console/docs/integrations.md +19 -0
- package/dist/ui/managed-agents-console/docs/memory.md +11 -0
- package/dist/ui/managed-agents-console/docs/migration.md +17 -0
- package/dist/ui/managed-agents-console/docs/multiagent.md +11 -0
- package/dist/ui/managed-agents-console/docs/outcomes.md +11 -0
- package/dist/ui/managed-agents-console/docs/overview.md +41 -0
- package/dist/ui/managed-agents-console/docs/permissions.md +24 -0
- package/dist/ui/managed-agents-console/docs/quickstart.md +51 -0
- package/dist/ui/managed-agents-console/docs/reference.md +27 -0
- package/dist/ui/managed-agents-console/docs/sandbox-reference.md +19 -0
- package/dist/ui/managed-agents-console/docs/sandbox-security.md +15 -0
- package/dist/ui/managed-agents-console/docs/scheduled-deployments.md +5 -0
- package/dist/ui/managed-agents-console/docs/self-hosted-sandboxes.md +15 -0
- package/dist/ui/managed-agents-console/docs/session-operations.md +21 -0
- package/dist/ui/managed-agents-console/docs/sessions.md +21 -0
- package/dist/ui/managed-agents-console/docs/skills.md +15 -0
- package/dist/ui/managed-agents-console/docs/tools.md +23 -0
- package/dist/ui/managed-agents-console/docs/vaults.md +19 -0
- package/dist/ui/managed-agents-console/docs/webhooks.md +11 -0
- package/dist/ui/managed-agents-console/index.html +47 -0
- package/dist/ui/managed-agents-console/serve.mjs +116 -0
- package/dist/ui/managed-agents-console/src/agents-files.jsx +273 -0
- package/dist/ui/managed-agents-console/src/api.js +1043 -0
- package/dist/ui/managed-agents-console/src/app.jsx +633 -0
- package/dist/ui/managed-agents-console/src/auth.jsx +215 -0
- package/dist/ui/managed-agents-console/src/console.css +733 -0
- package/dist/ui/managed-agents-console/src/data.js +188 -0
- package/dist/ui/managed-agents-console/src/detail.jsx +719 -0
- package/dist/ui/managed-agents-console/src/docs.jsx +200 -0
- package/dist/ui/managed-agents-console/src/environments.jsx +365 -0
- package/dist/ui/managed-agents-console/src/forms.jsx +494 -0
- package/dist/ui/managed-agents-console/src/icons.jsx +48 -0
- package/dist/ui/managed-agents-console/src/skills.jsx +21 -0
- package/dist/ui/managed-agents-console/src/sse.js +185 -0
- package/dist/ui/managed-agents-console/src/states.jsx +90 -0
- package/dist/ui/managed-agents-console/src/tweaks-panel.jsx +541 -0
- package/dist/ui/managed-agents-console/src/ui.jsx +190 -0
- package/dist/ui/managed-agents-console/src/vaults-data.js +89 -0
- package/dist/ui/managed-agents-console/src/vaults.jsx +171 -0
- package/dist/ui/managed-agents-console/vendor/babel.min.js +4 -0
- package/dist/ui/managed-agents-console/vendor/react-dom.production.min.js +267 -0
- package/dist/ui/managed-agents-console/vendor/react.production.min.js +31 -0
- package/dist/ui/openapi-docs/VENDOR.md +27 -0
- package/dist/ui/openapi-docs/index.html +16 -0
- package/dist/ui/openapi-docs/swagger-initializer.js +14 -0
- package/dist/ui/openapi-docs/vendor/LICENSE +202 -0
- package/dist/ui/openapi-docs/vendor/NOTICE +2 -0
- package/dist/ui/openapi-docs/vendor/swagger-ui-bundle.js +2 -0
- package/dist/ui/openapi-docs/vendor/swagger-ui-standalone-preset.js +2 -0
- package/dist/ui/openapi-docs/vendor/swagger-ui.css +3 -0
- package/package.json +53 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { FILES_API_BETA, MANAGED_AGENTS_BETA, SKILLS_API_BETA, } from "../api-constants.js";
|
|
2
|
+
import { EVENT_TYPES } from "../../types/events.js";
|
|
3
|
+
const DOCUMENTED_EVENT_TYPES = EVENT_TYPES;
|
|
4
|
+
const TAG_DESCRIPTIONS = {
|
|
5
|
+
Agents: "Versioned Managed Agents definitions.",
|
|
6
|
+
Environments: "Sandbox execution environment configuration.",
|
|
7
|
+
Files: "Workspace uploads, session outputs, and downloads.",
|
|
8
|
+
Skills: "Custom reusable skill bundles and immutable versions.",
|
|
9
|
+
"Secrets (OMA)": "OMA-specific write-only workspace secrets.",
|
|
10
|
+
Vaults: "Vault and MCP credential lifecycle.",
|
|
11
|
+
Sessions: "Managed Agent session lifecycle.",
|
|
12
|
+
"Session events": "User input, event history, and SSE streaming.",
|
|
13
|
+
"Models (OMA)": "OMA-specific provider/model readiness catalog.",
|
|
14
|
+
"Administration (OMA)": "OMA-specific local workspace and API-key administration.",
|
|
15
|
+
"Operations (OMA)": "OMA-specific health and metrics endpoints.",
|
|
16
|
+
};
|
|
17
|
+
const ref = (name) => ({ $ref: `#/components/schemas/${name}` });
|
|
18
|
+
const jsonContent = (schema, example) => ({
|
|
19
|
+
"application/json": { schema, ...(example === undefined ? {} : { example }) },
|
|
20
|
+
});
|
|
21
|
+
const jsonResponse = (description, schema, example) => ({
|
|
22
|
+
description,
|
|
23
|
+
content: jsonContent(schema, example),
|
|
24
|
+
});
|
|
25
|
+
const noContent = (description) => ({ description });
|
|
26
|
+
const jsonBody = (schema, required = true, example) => ({
|
|
27
|
+
required,
|
|
28
|
+
content: jsonContent(schema, example),
|
|
29
|
+
});
|
|
30
|
+
const multipartBody = (properties, required) => ({
|
|
31
|
+
required: true,
|
|
32
|
+
content: {
|
|
33
|
+
"multipart/form-data": {
|
|
34
|
+
schema: { type: "object", properties, required, additionalProperties: false },
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
const pathParam = (name, description) => ({
|
|
39
|
+
name,
|
|
40
|
+
in: "path",
|
|
41
|
+
required: true,
|
|
42
|
+
...(description === undefined ? {} : { description }),
|
|
43
|
+
schema: { type: "string", minLength: 1 },
|
|
44
|
+
});
|
|
45
|
+
const queryParam = (name, schema, description) => ({
|
|
46
|
+
name,
|
|
47
|
+
in: "query",
|
|
48
|
+
required: false,
|
|
49
|
+
...(description === undefined ? {} : { description }),
|
|
50
|
+
schema,
|
|
51
|
+
});
|
|
52
|
+
const headerParam = (name, schema, required, description) => ({
|
|
53
|
+
name,
|
|
54
|
+
in: "header",
|
|
55
|
+
required,
|
|
56
|
+
...(description === undefined ? {} : { description }),
|
|
57
|
+
schema,
|
|
58
|
+
});
|
|
59
|
+
const limit = queryParam("limit", { type: "integer", minimum: 1, maximum: 100 });
|
|
60
|
+
const page = queryParam("page", { type: "string", minLength: 1 }, "Opaque cursor; return it unchanged.");
|
|
61
|
+
const includeArchived = queryParam("include_archived", { type: "boolean", default: false });
|
|
62
|
+
const idempotencyKey = headerParam("idempotency-key", { type: "string", minLength: 1, maxLength: 255 }, false, "Optional idempotency key for safely retrying this write.");
|
|
63
|
+
const commonErrors = {
|
|
64
|
+
"400": jsonResponse("Invalid request", ref("Error")),
|
|
65
|
+
"401": jsonResponse("Authentication failed", ref("Error")),
|
|
66
|
+
"404": jsonResponse("Resource or route not found", ref("Error")),
|
|
67
|
+
"409": jsonResponse("Concurrent modification or idempotency conflict", ref("Error")),
|
|
68
|
+
"413": jsonResponse("Request too large", ref("Error")),
|
|
69
|
+
"429": jsonResponse("Workspace admission limit exceeded", ref("Error")),
|
|
70
|
+
"500": jsonResponse("Internal server error", ref("Error")),
|
|
71
|
+
};
|
|
72
|
+
function responses(status, schema, description = "Success") {
|
|
73
|
+
return {
|
|
74
|
+
[String(status)]: schema === undefined ? noContent(description) : jsonResponse(description, schema),
|
|
75
|
+
...commonErrors,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function route(contract) {
|
|
79
|
+
const { success, ...rest } = contract;
|
|
80
|
+
return {
|
|
81
|
+
...rest,
|
|
82
|
+
responses: success?.mediaType === undefined
|
|
83
|
+
? responses(success?.status ?? 200, success?.schema, success?.description ?? "Success")
|
|
84
|
+
: {
|
|
85
|
+
[String(success.status ?? 200)]: {
|
|
86
|
+
description: success.description ?? "Success",
|
|
87
|
+
content: {
|
|
88
|
+
[success.mediaType]: { schema: success.schema ?? { type: "string" } },
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
...commonErrors,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const agentId = pathParam("id", "Agent ID.");
|
|
96
|
+
const vaultId = pathParam("vaultId", "Vault ID.");
|
|
97
|
+
const credentialId = pathParam("credentialId", "Vault credential ID.");
|
|
98
|
+
const sessionId = pathParam("sessionId", "Session ID.");
|
|
99
|
+
export const OPENAPI_ROUTE_CONTRACTS = [
|
|
100
|
+
route({ method: "get", path: "/health", operationId: "getHealth", tag: "Operations (OMA)", summary: "Check appliance health", auth: "none", success: { schema: ref("Health") } }),
|
|
101
|
+
route({ method: "get", path: "/metrics", operationId: "getMetrics", tag: "Operations (OMA)", summary: "Read Prometheus metrics", description: "This route is registered only when metrics are enabled and the deployment exposure policy permits it. Otherwise it returns 404.", auth: "metrics", success: { schema: { type: "string" }, mediaType: "text/plain", description: "Prometheus exposition" } }),
|
|
102
|
+
route({ method: "post", path: "/v1/agents", operationId: "createAgent", tag: "Agents", summary: "Create an agent", auth: "workspace", beta: "managed", requestBody: jsonBody(ref("CreateAgentRequest"), true, { name: "Coding agent", model: "claude-sonnet-5" }), success: { schema: ref("Agent") } }),
|
|
103
|
+
route({ method: "get", path: "/v1/agents", operationId: "listAgents", tag: "Agents", summary: "List agents", auth: "workspace", beta: "managed", parameters: [limit, page, includeArchived], success: { schema: ref("ForwardAgentPage") } }),
|
|
104
|
+
route({ method: "get", path: "/v1/agents/{id}/versions", operationId: "listAgentVersions", tag: "Agents", summary: "List immutable agent versions", auth: "workspace", beta: "managed", parameters: [agentId, limit, page], success: { schema: ref("AgentVersionsPage") } }),
|
|
105
|
+
route({ method: "get", path: "/v1/agents/{id}", operationId: "getAgent", tag: "Agents", summary: "Retrieve an agent or historical version", auth: "workspace", beta: "managed", parameters: [agentId, queryParam("version", { type: "integer", minimum: 1 })], success: { schema: ref("Agent") } }),
|
|
106
|
+
route({ method: "post", path: "/v1/agents/{id}", operationId: "updateAgent", tag: "Agents", summary: "Create a new immutable agent version", auth: "workspace", beta: "managed", parameters: [agentId], requestBody: jsonBody(ref("UpdateAgentRequest")), success: { schema: ref("Agent") } }),
|
|
107
|
+
route({ method: "post", path: "/v1/agents/{id}/archive", operationId: "archiveAgent", tag: "Agents", summary: "Archive an agent", auth: "workspace", beta: "managed", parameters: [agentId], success: { schema: ref("Agent") } }),
|
|
108
|
+
route({ method: "post", path: "/v1/environments", operationId: "createEnvironment", tag: "Environments", summary: "Create an environment", auth: "workspace", beta: "managed", requestBody: jsonBody(ref("CreateEnvironmentRequest")), success: { schema: ref("Environment") } }),
|
|
109
|
+
route({ method: "get", path: "/v1/environments", operationId: "listEnvironments", tag: "Environments", summary: "List environments", auth: "workspace", beta: "managed", parameters: [limit, page, includeArchived], success: { schema: ref("ForwardEnvironmentPage") } }),
|
|
110
|
+
route({ method: "get", path: "/v1/environments/networking-presets", operationId: "listEnvironmentNetworkingPresets", tag: "Environments", summary: "List safe networking presets and deployment capability", auth: "workspace", beta: "managed", success: { schema: ref("EnvironmentNetworkingPresetCatalog") } }),
|
|
111
|
+
route({ method: "post", path: "/v1/environments/networking-presets/validate", operationId: "validateEnvironmentNetworkingHosts", tag: "Environments", summary: "Validate and normalize a custom hostname allowlist", auth: "workspace", beta: "managed", requestBody: jsonBody(ref("ValidateEnvironmentNetworkingHostsRequest")), success: { schema: ref("ValidateEnvironmentNetworkingHostsResponse") } }),
|
|
112
|
+
route({ method: "get", path: "/v1/environments/{id}", operationId: "getEnvironment", tag: "Environments", summary: "Retrieve an environment", auth: "workspace", beta: "managed", parameters: [pathParam("id", "Environment ID.")], success: { schema: ref("Environment") } }),
|
|
113
|
+
route({ method: "post", path: "/v1/environments/{id}/archive", operationId: "archiveEnvironment", tag: "Environments", summary: "Archive an environment", auth: "workspace", beta: "managed", parameters: [pathParam("id", "Environment ID.")], success: { schema: ref("Environment") } }),
|
|
114
|
+
route({ method: "delete", path: "/v1/environments/{id}", operationId: "deleteEnvironment", tag: "Environments", summary: "Delete an unreferenced environment", description: "OMA deliberately refuses deletion while any durable session references the environment.", auth: "workspace", beta: "managed", parameters: [pathParam("id", "Environment ID.")], success: { schema: ref("DeletedEnvironment") } }),
|
|
115
|
+
route({ method: "post", path: "/v1/files", operationId: "uploadFile", tag: "Files", summary: "Upload a file", auth: "workspace", beta: "files", requestBody: multipartBody({ file: { type: "string", format: "binary" } }, ["file"]), success: { schema: ref("File") } }),
|
|
116
|
+
route({ method: "get", path: "/v1/files", operationId: "listFiles", tag: "Files", summary: "List files", auth: "workspace", beta: "files", parameters: [limit, queryParam("after_id", { type: "string" }), queryParam("before_id", { type: "string" }), queryParam("scope_id", { type: "string" })], success: { schema: ref("FilePage") } }),
|
|
117
|
+
route({ method: "get", path: "/v1/files/{id}", operationId: "getFile", tag: "Files", summary: "Retrieve file metadata", auth: "workspace", beta: "files", parameters: [pathParam("id", "File ID.")], success: { schema: ref("File") } }),
|
|
118
|
+
route({ method: "get", path: "/v1/files/{id}/content", operationId: "downloadFile", tag: "Files", summary: "Download file content", auth: "workspace", beta: "files", parameters: [pathParam("id", "File ID.")], success: { schema: { type: "string", format: "binary" }, mediaType: "application/octet-stream", description: "Raw file bytes" } }),
|
|
119
|
+
route({ method: "delete", path: "/v1/files/{id}", operationId: "deleteFile", tag: "Files", summary: "Delete a file", auth: "workspace", beta: "files", parameters: [pathParam("id", "File ID.")], success: { schema: ref("DeletedFile") } }),
|
|
120
|
+
route({ method: "post", path: "/v1/skills", operationId: "createSkill", tag: "Skills", summary: "Create a custom skill", auth: "workspace", beta: "skills", requestBody: multipartBody({ display_title: { type: "string" }, "files[]": { type: "array", items: { type: "string", format: "binary" }, minItems: 1 } }, ["files[]"]), success: { schema: ref("Skill") } }),
|
|
121
|
+
route({ method: "get", path: "/v1/skills", operationId: "listSkills", tag: "Skills", summary: "List skills", auth: "workspace", beta: "skills", parameters: [limit, page], success: { schema: ref("SkillPage") } }),
|
|
122
|
+
route({ method: "get", path: "/v1/skills/{id}", operationId: "getSkill", tag: "Skills", summary: "Retrieve a skill", auth: "workspace", beta: "skills", parameters: [pathParam("id", "Skill ID.")], success: { schema: ref("Skill") } }),
|
|
123
|
+
route({ method: "delete", path: "/v1/skills/{id}", operationId: "deleteSkill", tag: "Skills", summary: "Delete a skill", auth: "workspace", beta: "skills", parameters: [pathParam("id", "Skill ID.")], success: { schema: ref("DeletedSkill") } }),
|
|
124
|
+
route({ method: "post", path: "/v1/skills/{id}/versions", operationId: "createSkillVersion", tag: "Skills", summary: "Create a skill version", auth: "workspace", beta: "skills", parameters: [pathParam("id", "Skill ID.")], requestBody: multipartBody({ "files[]": { type: "array", items: { type: "string", format: "binary" }, minItems: 1 } }, ["files[]"]), success: { schema: ref("SkillVersion") } }),
|
|
125
|
+
route({ method: "get", path: "/v1/skills/{id}/versions", operationId: "listSkillVersions", tag: "Skills", summary: "List skill versions", auth: "workspace", beta: "skills", parameters: [pathParam("id", "Skill ID."), limit, page], success: { schema: ref("SkillVersionPage") } }),
|
|
126
|
+
route({ method: "get", path: "/v1/skills/{id}/versions/{version}", operationId: "getSkillVersion", tag: "Skills", summary: "Retrieve a skill version", auth: "workspace", beta: "skills", parameters: [pathParam("id", "Skill ID."), pathParam("version", "Version or latest.")], success: { schema: ref("SkillVersion") } }),
|
|
127
|
+
route({ method: "delete", path: "/v1/skills/{id}/versions/{version}", operationId: "deleteSkillVersion", tag: "Skills", summary: "Delete a skill version", auth: "workspace", beta: "skills", parameters: [pathParam("id", "Skill ID."), pathParam("version", "Version or latest.")], success: { schema: ref("DeletedSkillVersion") } }),
|
|
128
|
+
route({ method: "post", path: "/v1/secrets", operationId: "upsertSecret", tag: "Secrets (OMA)", summary: "Create or replace a write-only secret", auth: "workspace", beta: "managed", requestBody: jsonBody(ref("CreateSecretRequest")), success: { status: 201, schema: ref("Secret") } }),
|
|
129
|
+
route({ method: "get", path: "/v1/secrets", operationId: "listSecrets", tag: "Secrets (OMA)", summary: "List secret metadata", auth: "workspace", beta: "managed", success: { schema: { type: "array", items: ref("Secret") } } }),
|
|
130
|
+
route({ method: "delete", path: "/v1/secrets/{name}", operationId: "deleteSecret", tag: "Secrets (OMA)", summary: "Delete a secret", auth: "workspace", beta: "managed", parameters: [pathParam("name", "Secret name.")], success: { status: 204, description: "Deleted" } }),
|
|
131
|
+
route({ method: "post", path: "/v1/vaults", operationId: "createVault", tag: "Vaults", summary: "Create a vault", auth: "workspace", beta: "managed", requestBody: jsonBody(ref("CreateVaultRequest")), success: { schema: ref("Vault") } }),
|
|
132
|
+
route({ method: "get", path: "/v1/vaults", operationId: "listVaults", tag: "Vaults", summary: "List vaults", auth: "workspace", beta: "managed", parameters: [limit, page, includeArchived], success: { schema: ref("ForwardVaultPage") } }),
|
|
133
|
+
route({ method: "get", path: "/v1/vaults/{vaultId}", operationId: "getVault", tag: "Vaults", summary: "Retrieve a vault", auth: "workspace", beta: "managed", parameters: [vaultId], success: { schema: ref("Vault") } }),
|
|
134
|
+
route({ method: "post", path: "/v1/vaults/{vaultId}/archive", operationId: "archiveVault", tag: "Vaults", summary: "Archive a vault", auth: "workspace", beta: "managed", parameters: [vaultId], success: { schema: ref("Vault") } }),
|
|
135
|
+
route({ method: "post", path: "/v1/vaults/{vaultId}", operationId: "updateVault", tag: "Vaults", summary: "Update a vault", auth: "workspace", beta: "managed", parameters: [vaultId], requestBody: jsonBody(ref("UpdateVaultRequest")), success: { schema: ref("Vault") } }),
|
|
136
|
+
route({ method: "delete", path: "/v1/vaults/{vaultId}", operationId: "deleteVault", tag: "Vaults", summary: "Delete a vault", auth: "workspace", beta: "managed", parameters: [vaultId], success: { schema: ref("DeletedVault") } }),
|
|
137
|
+
route({ method: "post", path: "/v1/vaults/{vaultId}/credentials", operationId: "createVaultCredential", tag: "Vaults", summary: "Create a vault credential", auth: "workspace", beta: "managed", parameters: [vaultId], requestBody: jsonBody(ref("CreateCredentialRequest")), success: { schema: ref("VaultCredential") } }),
|
|
138
|
+
route({ method: "get", path: "/v1/vaults/{vaultId}/credentials", operationId: "listVaultCredentials", tag: "Vaults", summary: "List vault credentials", auth: "workspace", beta: "managed", parameters: [vaultId, limit, page, includeArchived], success: { schema: ref("ForwardCredentialPage") } }),
|
|
139
|
+
route({ method: "post", path: "/v1/vaults/{vaultId}/credentials/{credentialId}/archive", operationId: "archiveVaultCredential", tag: "Vaults", summary: "Archive a vault credential", auth: "workspace", beta: "managed", parameters: [vaultId, credentialId], success: { schema: ref("VaultCredential") } }),
|
|
140
|
+
route({ method: "post", path: "/v1/vaults/{vaultId}/credentials/{credentialId}/mcp_oauth_validate", operationId: "validateVaultCredential", tag: "Vaults", summary: "Validate an MCP OAuth credential", auth: "workspace", beta: "managed", parameters: [vaultId, credentialId], success: { schema: { type: "object", additionalProperties: true } } }),
|
|
141
|
+
route({ method: "get", path: "/v1/vaults/{vaultId}/credentials/{credentialId}", operationId: "getVaultCredential", tag: "Vaults", summary: "Retrieve vault credential metadata", auth: "workspace", beta: "managed", parameters: [vaultId, credentialId], success: { schema: ref("VaultCredential") } }),
|
|
142
|
+
route({ method: "post", path: "/v1/vaults/{vaultId}/credentials/{credentialId}", operationId: "updateVaultCredential", tag: "Vaults", summary: "Update a vault credential", auth: "workspace", beta: "managed", parameters: [vaultId, credentialId], requestBody: jsonBody(ref("UpdateCredentialRequest")), success: { schema: ref("VaultCredential") } }),
|
|
143
|
+
route({ method: "delete", path: "/v1/vaults/{vaultId}/credentials/{credentialId}", operationId: "deleteVaultCredential", tag: "Vaults", summary: "Delete a vault credential", auth: "workspace", beta: "managed", parameters: [vaultId, credentialId], success: { status: 204, description: "Deleted" } }),
|
|
144
|
+
route({ method: "post", path: "/v1/sessions", operationId: "createSession", tag: "Sessions", summary: "Create a session", auth: "workspace", beta: "managed", parameters: [idempotencyKey], requestBody: jsonBody(ref("CreateSessionRequest")), success: { schema: ref("Session") } }),
|
|
145
|
+
route({ method: "get", path: "/v1/sessions", operationId: "listSessions", tag: "Sessions", summary: "List sessions with forward/backward cursors", auth: "workspace", beta: "managed", parameters: [limit, page, queryParam("order", { type: "string", enum: ["asc", "desc"], default: "desc" }), queryParam("agent_id", { type: "string" }), includeArchived], success: { schema: ref("SessionPage") } }),
|
|
146
|
+
route({ method: "get", path: "/v1/sessions/{id}", operationId: "getSession", tag: "Sessions", summary: "Retrieve a session", auth: "workspace", beta: "managed", parameters: [pathParam("id", "Session ID.")], success: { schema: ref("Session") } }),
|
|
147
|
+
route({ method: "post", path: "/v1/sessions/{id}/archive", operationId: "archiveSession", tag: "Sessions", summary: "Archive an idle session", auth: "workspace", beta: "managed", parameters: [pathParam("id", "Session ID.")], success: { schema: ref("Session") } }),
|
|
148
|
+
route({ method: "delete", path: "/v1/sessions/{id}", operationId: "deleteSession", tag: "Sessions", summary: "Delete an idle session", auth: "workspace", beta: "managed", parameters: [pathParam("id", "Session ID.")], success: { schema: ref("DeletedSession") } }),
|
|
149
|
+
route({ method: "post", path: "/v1/sessions/{sessionId}/events", operationId: "sendSessionEvents", tag: "Session events", summary: "Send user events to a session", auth: "workspace", beta: "managed", parameters: [sessionId, idempotencyKey], requestBody: jsonBody(ref("SendEventsRequest"), true, { events: [{ type: "user.message", content: [{ type: "text", text: "Hello" }] }] }), success: { schema: ref("EventPage") } }),
|
|
150
|
+
route({ method: "get", path: "/v1/sessions/{sessionId}/events", operationId: "listSessionEvents", tag: "Session events", summary: "List session events", auth: "workspace", beta: "managed", parameters: [sessionId, limit, page, queryParam("order", { type: "string", enum: ["asc", "desc"] }), queryParam("types[]", { type: "array", items: { type: "string", enum: DOCUMENTED_EVENT_TYPES } }, "Repeat to filter by an event type currently emitted by OMA.")], success: { schema: ref("EventPage") } }),
|
|
151
|
+
route({ method: "get", path: "/v1/sessions/{sessionId}/events/stream", operationId: "streamSessionEvents", tag: "Session events", summary: "Stream persisted session events over SSE", description: "OMA streams complete persisted events. Assistant text is emitted as a buffered `agent.message` after generation, not as token-preview deltas. The unsupported `event_deltas[]` query parameter is rejected with HTTP 400.", auth: "workspace", beta: "managed", parameters: [sessionId, headerParam("last-event-id", { type: "string" }, false, "Resume after this event ID.")], success: { schema: { type: "string", description: "SSE frames with id, event, and JSON data fields." }, mediaType: "text/event-stream", description: "SSE stream" } }),
|
|
152
|
+
route({ method: "get", path: "/v1/model-catalog", operationId: "listModelCatalog", tag: "Models (OMA)", summary: "List deployment-enabled model catalog entries", description: "OMA-specific discovery endpoint for provider/model readiness. It never returns base URLs, credential sources, header values, file paths, raw Pi config, or secrets.", auth: "workspace", beta: "managed", parameters: [queryParam("provider", { type: "string", minLength: 1 }, "Exact provider id."), queryParam("available", { type: "boolean", default: false }, "When true, include only models with configured local credentials."), limit, page], success: { schema: ref("ModelCatalogPage") } }),
|
|
153
|
+
route({ method: "post", path: "/admin/workspaces", operationId: "adminCreateWorkspace", tag: "Administration (OMA)", summary: "Create a workspace", auth: "admin", requestBody: jsonBody(ref("AdminCreateWorkspaceRequest")), success: { status: 201, schema: ref("AdminWorkspace") } }),
|
|
154
|
+
route({ method: "get", path: "/admin/workspaces", operationId: "adminListWorkspaces", tag: "Administration (OMA)", summary: "List workspaces", auth: "admin", success: { schema: { type: "array", items: ref("AdminWorkspace") } } }),
|
|
155
|
+
route({ method: "get", path: "/admin/workspaces/{id}", operationId: "adminGetWorkspace", tag: "Administration (OMA)", summary: "Retrieve a workspace", auth: "admin", parameters: [pathParam("id", "Workspace ID.")], success: { schema: ref("AdminWorkspace") } }),
|
|
156
|
+
route({ method: "post", path: "/admin/workspaces/{id}/keys", operationId: "adminMintWorkspaceKey", tag: "Administration (OMA)", summary: "Mint a workspace API key", auth: "admin", parameters: [pathParam("id", "Workspace ID.")], requestBody: jsonBody(ref("AdminMintKeyRequest"), false), success: { status: 201, schema: ref("AdminMintedKey") } }),
|
|
157
|
+
route({ method: "get", path: "/admin/workspaces/{id}/keys", operationId: "adminListWorkspaceKeys", tag: "Administration (OMA)", summary: "List workspace API key metadata", auth: "admin", parameters: [pathParam("id", "Workspace ID.")], success: { schema: { type: "array", items: ref("AdminKeyMetadata") } } }),
|
|
158
|
+
route({ method: "get", path: "/admin/workspaces/{id}/mcp-credentials", operationId: "adminListWorkspaceMcpCredentials", tag: "Administration (OMA)", summary: "List token-free MCP credential operational metadata", auth: "admin", parameters: [pathParam("id", "Workspace ID."), limit, page], success: { schema: ref("GenericForwardPage") } }),
|
|
159
|
+
route({ method: "delete", path: "/admin/keys/{sha256}", operationId: "adminRevokeWorkspaceKey", tag: "Administration (OMA)", summary: "Revoke a workspace API key", auth: "admin", parameters: [pathParam("sha256", "SHA-256 key fingerprint.")], success: { schema: ref("AdminKeyMetadata") } }),
|
|
160
|
+
];
|
|
161
|
+
const schemas = {
|
|
162
|
+
Error: { type: "object", required: ["type", "error", "request_id"], properties: { type: { const: "error" }, error: { type: "object", required: ["type", "message"], properties: { type: { type: "string" }, message: { type: "string" } }, additionalProperties: true }, request_id: { type: "string" } }, additionalProperties: false },
|
|
163
|
+
JsonObject: { type: "object", additionalProperties: true },
|
|
164
|
+
StringMap: { type: "object", additionalProperties: { type: "string" } },
|
|
165
|
+
NullableString: { type: ["string", "null"] },
|
|
166
|
+
ModelInput: { oneOf: [{ type: "string" }, { type: "object", required: ["id"], properties: { provider: { type: "string", minLength: 1 }, id: { type: "string", minLength: 1 }, speed: { type: "string", enum: ["standard", "fast"] } }, additionalProperties: false }] },
|
|
167
|
+
CreateAgentRequest: { type: "object", required: ["name", "model"], properties: { name: { type: "string", minLength: 1 }, model: ref("ModelInput"), system: ref("NullableString"), description: ref("NullableString"), tools: { type: "array", items: ref("JsonObject") }, skills: { type: "array", items: ref("JsonObject") }, mcp_servers: { type: "array", items: ref("JsonObject") }, metadata: ref("StringMap"), multiagent: { type: "null", description: "Full multi-agent runtime is not implemented. Omit this field or send null." } }, additionalProperties: false },
|
|
168
|
+
UpdateAgentRequest: { type: "object", required: ["version"], properties: { version: { type: "integer", minimum: 1 }, name: { type: "string", minLength: 1 }, model: ref("ModelInput"), system: ref("NullableString"), description: ref("NullableString"), tools: { type: ["array", "null"], items: ref("JsonObject") }, skills: { type: ["array", "null"], items: ref("JsonObject") }, mcp_servers: { type: ["array", "null"], items: ref("JsonObject") }, metadata: { type: "object", additionalProperties: { type: ["string", "null"] } }, multiagent: { type: "null", description: "Full multi-agent runtime is not implemented. Omit this field or send null." } }, additionalProperties: false },
|
|
169
|
+
Agent: { type: "object", required: ["id", "type", "name", "model", "version", "created_at", "updated_at", "archived_at"], properties: { id: { type: "string" }, type: { const: "agent" }, name: { type: "string" }, model: { type: "object", required: ["provider", "id", "speed"], properties: { provider: { type: "string" }, id: { type: "string" }, speed: { enum: ["standard", "fast"] } }, additionalProperties: false }, system: ref("NullableString"), description: ref("NullableString"), tools: { type: "array", items: ref("JsonObject") }, skills: { type: "array", items: ref("JsonObject") }, mcp_servers: { type: "array", items: ref("JsonObject") }, metadata: ref("StringMap"), multiagent: { type: ["object", "null"] }, version: { type: "integer", minimum: 1 }, created_at: { type: "string", format: "date-time" }, updated_at: { type: "string", format: "date-time" }, archived_at: { type: ["string", "null"], format: "date-time" } }, additionalProperties: false },
|
|
170
|
+
CreateEnvironmentRequest: { type: "object", required: ["name", "config"], properties: { name: { type: "string", minLength: 1 }, config: ref("JsonObject") }, additionalProperties: false },
|
|
171
|
+
Environment: { type: "object", required: ["id", "type", "name", "config", "created_at", "updated_at", "archived_at"], properties: { id: { type: "string" }, type: { const: "environment" }, name: { type: "string" }, config: ref("JsonObject"), created_at: { type: "string", format: "date-time" }, updated_at: { type: "string", format: "date-time" }, archived_at: { type: ["string", "null"], format: "date-time" } } },
|
|
172
|
+
DeletedEnvironment: { type: "object", required: ["type", "id"], properties: { type: { const: "environment_deleted" }, id: { type: "string" } }, additionalProperties: false },
|
|
173
|
+
EnvironmentNetworkingPresetCatalog: { type: "object", required: ["type", "deployment", "presets", "custom"], properties: { type: { const: "environment_networking_presets" }, deployment: { type: "object", required: ["provider", "egress_supported", "reason"], properties: { provider: { type: ["string", "null"] }, egress_supported: { type: "boolean" }, reason: { type: ["string", "null"] } }, additionalProperties: false }, presets: { type: "array", items: { type: "object", required: ["id", "version", "name", "description", "networking"], properties: { id: { type: "string" }, version: { type: "integer", minimum: 1 }, name: { type: "string" }, description: { type: "string" }, networking: { type: "object", required: ["type", "allowed_hosts"], properties: { type: { const: "limited" }, allowed_hosts: { type: "array", items: { type: "string" } } }, additionalProperties: false } }, additionalProperties: false } }, custom: { type: "object", required: ["https_only", "wildcard_matches_bare_domain"], properties: { https_only: { const: true }, wildcard_matches_bare_domain: { const: false } }, additionalProperties: false } }, additionalProperties: false },
|
|
174
|
+
ValidateEnvironmentNetworkingHostsRequest: { type: "object", required: ["allowed_hosts"], properties: { allowed_hosts: { type: "array", items: { type: "string" } } }, additionalProperties: false },
|
|
175
|
+
ValidateEnvironmentNetworkingHostsResponse: { type: "object", required: ["allowed_hosts"], properties: { allowed_hosts: { type: "array", items: { type: "string" } } }, additionalProperties: false },
|
|
176
|
+
File: { type: "object", required: ["id", "type", "filename", "mime_type", "size_bytes", "created_at", "downloadable", "scope"], properties: { id: { type: "string" }, type: { const: "file" }, filename: { type: "string" }, mime_type: { type: "string" }, size_bytes: { type: "integer", minimum: 0 }, downloadable: { type: "boolean" }, scope: { type: ["object", "null"] }, created_at: { type: "string", format: "date-time" } }, additionalProperties: false },
|
|
177
|
+
DeletedFile: { type: "object", required: ["id", "type"], properties: { id: { type: "string" }, type: { const: "file_deleted" } }, additionalProperties: false },
|
|
178
|
+
Skill: { type: "object", required: ["id", "type", "display_title", "source", "latest_version", "created_at", "updated_at"], properties: { id: { type: "string" }, type: { const: "skill" }, display_title: { type: "string" }, source: { const: "custom" }, latest_version: { type: ["string", "null"] }, created_at: { type: "string", format: "date-time" }, updated_at: { type: "string", format: "date-time" } }, additionalProperties: false },
|
|
179
|
+
SkillVersion: { type: "object", required: ["id", "type", "skill_id", "version", "name", "description", "directory", "created_at"], properties: { id: { type: "string" }, type: { const: "skill_version" }, skill_id: { type: "string" }, version: { type: "string" }, name: { type: "string" }, description: { type: "string" }, directory: { type: "string" }, created_at: { type: "string", format: "date-time" } }, additionalProperties: false },
|
|
180
|
+
DeletedSkill: { type: "object", required: ["id", "type"], properties: { id: { type: "string" }, type: { const: "skill_deleted" } }, additionalProperties: false },
|
|
181
|
+
DeletedSkillVersion: { type: "object", required: ["id", "type"], properties: { id: { type: "string" }, type: { const: "skill_version_deleted" } }, additionalProperties: false },
|
|
182
|
+
CreateSecretRequest: { type: "object", required: ["name", "value"], properties: { name: { type: "string", minLength: 1, maxLength: 256 }, value: { type: "string", minLength: 1, writeOnly: true } }, additionalProperties: false },
|
|
183
|
+
Secret: { type: "object", required: ["id", "type", "name", "created_at", "updated_at"], properties: { id: { type: "string" }, type: { const: "secret" }, name: { type: "string" }, created_at: { type: "string", format: "date-time" }, updated_at: { type: "string", format: "date-time" } }, additionalProperties: false },
|
|
184
|
+
CreateVaultRequest: { type: "object", required: ["display_name"], properties: { display_name: { type: "string", minLength: 1 }, metadata: ref("StringMap") }, additionalProperties: false },
|
|
185
|
+
UpdateVaultRequest: { type: "object", properties: { display_name: { type: "string", minLength: 1 }, metadata: ref("StringMap") }, additionalProperties: false },
|
|
186
|
+
Vault: { type: "object", required: ["id", "type", "display_name", "metadata", "created_at", "updated_at", "archived_at"], properties: { id: { type: "string" }, type: { const: "vault" }, display_name: { type: "string" }, metadata: ref("StringMap"), created_at: { type: "string", format: "date-time" }, updated_at: { type: "string", format: "date-time" }, archived_at: { type: ["string", "null"], format: "date-time" } } },
|
|
187
|
+
DeletedVault: { type: "object", required: ["id", "type"], properties: { id: { type: "string" }, type: { const: "vault_deleted" } } },
|
|
188
|
+
CreateCredentialRequest: { type: "object", required: ["auth"], properties: { display_name: ref("NullableString"), metadata: ref("StringMap"), auth: ref("JsonObject") }, additionalProperties: false },
|
|
189
|
+
UpdateCredentialRequest: { type: "object", properties: { display_name: ref("NullableString"), metadata: ref("StringMap"), auth: ref("JsonObject") }, additionalProperties: false },
|
|
190
|
+
VaultCredential: { type: "object", required: ["id", "type", "vault_id", "metadata", "auth", "created_at", "updated_at", "archived_at"], properties: { id: { type: "string" }, type: { const: "vault_credential" }, vault_id: { type: "string" }, display_name: ref("NullableString"), metadata: ref("StringMap"), auth: ref("JsonObject"), created_at: { type: "string", format: "date-time" }, updated_at: { type: "string", format: "date-time" }, archived_at: { type: ["string", "null"], format: "date-time" } }, additionalProperties: false },
|
|
191
|
+
CreateSessionRequest: { type: "object", required: ["agent", "environment_id"], properties: { agent: { oneOf: [{ type: "string" }, { type: "object", required: ["type", "id"], properties: { type: { const: "agent" }, id: { type: "string" }, version: { type: "integer", minimum: 1 } }, additionalProperties: false }] }, environment_id: { type: "string" }, vault_ids: { type: "array", items: { type: "string" } }, title: ref("NullableString"), metadata: ref("StringMap"), resources: { type: "array", items: ref("JsonObject") } }, additionalProperties: false },
|
|
192
|
+
Session: { type: "object", required: ["id", "type", "agent", "environment_id", "vault_ids", "status", "metadata", "created_at", "updated_at", "archived_at", "resources"], properties: { id: { type: "string" }, type: { const: "session" }, agent: { type: "object", required: ["type", "id", "version"], properties: { type: { const: "agent" }, id: { type: "string" }, version: { type: "integer" } } }, environment_id: { type: "string" }, vault_ids: { type: "array", items: { type: "string" } }, status: { enum: ["idle", "running", "rescheduling", "terminated"] }, title: ref("NullableString"), metadata: ref("StringMap"), created_at: { type: "string", format: "date-time" }, updated_at: { type: "string", format: "date-time" }, archived_at: { type: ["string", "null"], format: "date-time" }, usage: { type: "null" }, resources: { type: "array", items: ref("JsonObject") } }, additionalProperties: false },
|
|
193
|
+
DeletedSession: { type: "object", required: ["id", "type"], properties: { id: { type: "string" }, type: { const: "session_deleted" } }, additionalProperties: false },
|
|
194
|
+
Event: { type: "object", required: ["id", "type", "processed_at"], properties: { id: { type: "string" }, type: { type: "string", enum: DOCUMENTED_EVENT_TYPES }, processed_at: { type: ["string", "null"], format: "date-time" } }, additionalProperties: true },
|
|
195
|
+
SendEventsRequest: { type: "object", required: ["events"], properties: { events: { type: "array", minItems: 1, maxItems: 200, items: { oneOf: [{ type: "object", required: ["type", "content"], properties: { type: { const: "user.message" }, content: { type: "array", items: ref("JsonObject") } }, additionalProperties: false }, { type: "object", required: ["type"], properties: { type: { const: "user.interrupt" } }, additionalProperties: false }, { type: "object", required: ["type", "custom_tool_use_id"], properties: { type: { const: "user.custom_tool_result" }, custom_tool_use_id: { type: "string" }, content: { type: "array", items: ref("JsonObject") }, is_error: { type: "boolean" } }, additionalProperties: false }, { type: "object", required: ["type", "tool_use_id", "result"], properties: { type: { const: "user.tool_confirmation" }, tool_use_id: { type: "string" }, result: { enum: ["allow", "deny"] }, deny_message: ref("NullableString") }, additionalProperties: false }] } } }, additionalProperties: false },
|
|
196
|
+
ModelCatalogEntry: { type: "object", required: ["type", "provider", "id", "name", "provider_name", "reasoning", "input", "context_window", "max_output_tokens", "credentials_configured", "default"], properties: { type: { const: "model" }, provider: { type: "string" }, id: { type: "string" }, name: { type: "string" }, provider_name: { type: "string" }, reasoning: { type: "boolean" }, input: { type: "array", items: { type: "string" } }, context_window: { type: "integer", minimum: 0 }, max_output_tokens: { type: "integer", minimum: 0 }, credentials_configured: { type: "boolean" }, default: { type: "boolean" } }, additionalProperties: false },
|
|
197
|
+
AdminCreateWorkspaceRequest: { type: "object", required: ["name"], properties: { name: { type: "string", minLength: 1 } }, additionalProperties: false },
|
|
198
|
+
AdminMintKeyRequest: { type: "object", properties: { label: { type: "string", minLength: 1, default: "default" } }, additionalProperties: false },
|
|
199
|
+
AdminWorkspace: { type: "object", required: ["id", "name", "created_at"], properties: { id: { type: "string" }, name: { type: "string" }, created_at: { type: "string", format: "date-time" } }, additionalProperties: false },
|
|
200
|
+
AdminMintedKey: { type: "object", required: ["workspace_id", "label", "key_sha256", "api_key"], properties: { workspace_id: { type: "string" }, label: { type: "string" }, key_sha256: { type: "string" }, api_key: { type: "string", writeOnly: true } }, additionalProperties: false },
|
|
201
|
+
AdminKeyMetadata: { type: "object", required: ["key_sha256", "workspace_id", "label", "created_at", "revoked_at"], properties: { key_sha256: { type: "string" }, workspace_id: { type: "string" }, label: { type: "string" }, created_at: { type: "string", format: "date-time" }, revoked_at: { type: ["string", "null"], format: "date-time" } }, additionalProperties: false },
|
|
202
|
+
Health: { type: "object", required: ["status", "version", "uptime_seconds", "checks"], properties: { status: { enum: ["ok", "degraded"] }, version: { type: "string" }, uptime_seconds: { type: "integer", minimum: 0 }, checks: { type: "object", required: ["storage", "runtime"], properties: { storage: ref("HealthCheck"), runtime: ref("HealthCheck") }, additionalProperties: false } }, additionalProperties: false },
|
|
203
|
+
HealthCheck: { type: "object", required: ["status"], properties: { status: { enum: ["ok", "failed"] }, detail: { type: "string" } }, additionalProperties: false },
|
|
204
|
+
};
|
|
205
|
+
for (const [name, item] of [
|
|
206
|
+
["ForwardAgentPage", "Agent"],
|
|
207
|
+
["AgentVersionsPage", "Agent"],
|
|
208
|
+
["ForwardEnvironmentPage", "Environment"],
|
|
209
|
+
["SkillPage", "Skill"],
|
|
210
|
+
["SkillVersionPage", "SkillVersion"],
|
|
211
|
+
["ForwardVaultPage", "Vault"],
|
|
212
|
+
["ForwardCredentialPage", "VaultCredential"],
|
|
213
|
+
]) {
|
|
214
|
+
const hasMore = name !== "AgentVersionsPage";
|
|
215
|
+
schemas[name] = {
|
|
216
|
+
type: "object",
|
|
217
|
+
required: ["data", "next_page", ...(hasMore ? ["has_more"] : [])],
|
|
218
|
+
properties: {
|
|
219
|
+
data: { type: "array", items: ref(item) },
|
|
220
|
+
next_page: { type: ["string", "null"] },
|
|
221
|
+
...(hasMore ? { has_more: { type: "boolean" } } : {}),
|
|
222
|
+
},
|
|
223
|
+
additionalProperties: false,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
schemas.FilePage = { type: "object", required: ["data", "has_more", "first_id", "last_id"], properties: { data: { type: "array", items: ref("File") }, has_more: { type: "boolean" }, first_id: { type: ["string", "null"] }, last_id: { type: ["string", "null"] } }, additionalProperties: false };
|
|
227
|
+
schemas.SessionPage = { type: "object", required: ["data", "next_page", "prev_page"], properties: { data: { type: "array", items: ref("Session") }, next_page: { type: ["string", "null"] }, prev_page: { type: ["string", "null"] } }, additionalProperties: false };
|
|
228
|
+
schemas.EventPage = { type: "object", required: ["data"], properties: { data: { type: "array", items: ref("Event") }, next_page: { type: ["string", "null"] } }, additionalProperties: false };
|
|
229
|
+
schemas.GenericForwardPage = { type: "object", required: ["data", "has_more", "next_page"], properties: { data: { type: "array", items: ref("JsonObject") }, has_more: { type: "boolean" }, next_page: { type: ["string", "null"] } }, additionalProperties: false };
|
|
230
|
+
schemas.ModelCatalogPage = { type: "object", required: ["data", "next_page"], properties: { data: { type: "array", items: ref("ModelCatalogEntry") }, next_page: { type: ["string", "null"] } }, additionalProperties: false };
|
|
231
|
+
function betaParameter(kind) {
|
|
232
|
+
const feature = kind === "files" ? FILES_API_BETA : kind === "skills" ? SKILLS_API_BETA : MANAGED_AGENTS_BETA;
|
|
233
|
+
const alternative = kind === "managed" ? "" : ` The general ${MANAGED_AGENTS_BETA} beta is also accepted.`;
|
|
234
|
+
return headerParam("anthropic-beta", { type: "string", example: feature }, true, `Required beta feature header. Multiple features are comma-separated.${alternative}`);
|
|
235
|
+
}
|
|
236
|
+
export function createOpenApiDocument() {
|
|
237
|
+
const paths = {};
|
|
238
|
+
for (const contract of OPENAPI_ROUTE_CONTRACTS) {
|
|
239
|
+
const parameters = [
|
|
240
|
+
...(contract.beta === undefined ? [] : [betaParameter(contract.beta)]),
|
|
241
|
+
...(contract.parameters ?? []),
|
|
242
|
+
];
|
|
243
|
+
const operation = {
|
|
244
|
+
operationId: contract.operationId,
|
|
245
|
+
tags: [contract.tag],
|
|
246
|
+
summary: contract.summary,
|
|
247
|
+
...(contract.description === undefined ? {} : { description: contract.description }),
|
|
248
|
+
security: contract.auth === "none"
|
|
249
|
+
? []
|
|
250
|
+
: contract.auth === "metrics"
|
|
251
|
+
? [{}, { MetricsBearer: [] }]
|
|
252
|
+
: [{ [contract.auth === "workspace" ? "WorkspaceApiKey" : "AdminApiKey"]: [] }],
|
|
253
|
+
...(parameters.length === 0 ? {} : { parameters }),
|
|
254
|
+
...(contract.requestBody === undefined ? {} : { requestBody: contract.requestBody }),
|
|
255
|
+
responses: contract.responses,
|
|
256
|
+
};
|
|
257
|
+
(paths[contract.path] ??= {})[contract.method] = operation;
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
openapi: "3.1.0",
|
|
261
|
+
info: {
|
|
262
|
+
title: "Open Managed Agents API",
|
|
263
|
+
version: "0.0.1-alpha",
|
|
264
|
+
description: "The currently shipped OMA API surface. Unsupported Claude Managed Agents operations are intentionally omitted.",
|
|
265
|
+
},
|
|
266
|
+
servers: [{ url: "/", description: "This OMA appliance" }],
|
|
267
|
+
tags: [...new Set(OPENAPI_ROUTE_CONTRACTS.map((contract) => contract.tag))]
|
|
268
|
+
.map((name) => ({ name, description: TAG_DESCRIPTIONS[name] })),
|
|
269
|
+
paths,
|
|
270
|
+
components: {
|
|
271
|
+
securitySchemes: {
|
|
272
|
+
WorkspaceApiKey: { type: "apiKey", in: "header", name: "x-api-key", description: "Workspace-scoped API key." },
|
|
273
|
+
AdminApiKey: { type: "apiKey", in: "header", name: "x-admin-key", description: "Local appliance administrator key. Keep it out of URLs, cookies, and persistent browser storage." },
|
|
274
|
+
MetricsBearer: { type: "http", scheme: "bearer", description: "Optional deployment-configured metrics bearer token." },
|
|
275
|
+
},
|
|
276
|
+
schemas,
|
|
277
|
+
},
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
export function openApiContractRouteKeys() {
|
|
281
|
+
return OPENAPI_ROUTE_CONTRACTS.map((contract) => `${contract.method.toUpperCase()} ${contract.path}`).sort();
|
|
282
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { createReadStream, realpathSync, statSync } from "node:fs";
|
|
2
|
+
import { extname, resolve, sep } from "node:path";
|
|
3
|
+
import { Readable } from "node:stream";
|
|
4
|
+
import { createOpenApiDocument } from "./document.js";
|
|
5
|
+
export const OPENAPI_DOCUMENT_PATH = "/openapi.json";
|
|
6
|
+
export const OPENAPI_DOCS_MOUNT = "/docs";
|
|
7
|
+
const CONTENT_TYPES = new Map([
|
|
8
|
+
[".css", "text/css; charset=utf-8"],
|
|
9
|
+
[".html", "text/html; charset=utf-8"],
|
|
10
|
+
[".js", "text/javascript; charset=utf-8"],
|
|
11
|
+
]);
|
|
12
|
+
const DOCS_CSP = [
|
|
13
|
+
"default-src 'none'",
|
|
14
|
+
"script-src 'self'",
|
|
15
|
+
"style-src 'self' 'unsafe-inline'",
|
|
16
|
+
"img-src 'self' data:",
|
|
17
|
+
"connect-src 'self'",
|
|
18
|
+
"font-src 'self' data:",
|
|
19
|
+
"base-uri 'none'",
|
|
20
|
+
"form-action 'none'",
|
|
21
|
+
"frame-ancestors 'none'",
|
|
22
|
+
].join("; ");
|
|
23
|
+
export function registerOpenApiRoutes(app, config) {
|
|
24
|
+
const realRoot = realpathSync(resolve(config.root));
|
|
25
|
+
const serialized = JSON.stringify(createOpenApiDocument(), null, 2) + "\n";
|
|
26
|
+
app.get(OPENAPI_DOCUMENT_PATH, (c) => {
|
|
27
|
+
setDocsHeaders(c);
|
|
28
|
+
c.header("content-type", "application/json; charset=utf-8");
|
|
29
|
+
return c.body(serialized);
|
|
30
|
+
});
|
|
31
|
+
app.get(OPENAPI_DOCS_MOUNT, (c) => c.redirect(`${OPENAPI_DOCS_MOUNT}/`, 301));
|
|
32
|
+
app.get(`${OPENAPI_DOCS_MOUNT}/*`, (c) => {
|
|
33
|
+
const raw = c.req.path.slice(OPENAPI_DOCS_MOUNT.length + 1);
|
|
34
|
+
const relative = raw === "" ? "index.html" : decodeOrNull(raw);
|
|
35
|
+
if (relative === null || relative.includes("\0"))
|
|
36
|
+
return notFound(c);
|
|
37
|
+
const candidate = resolve(realRoot, relative);
|
|
38
|
+
if (!contains(realRoot, candidate))
|
|
39
|
+
return notFound(c);
|
|
40
|
+
let file;
|
|
41
|
+
try {
|
|
42
|
+
file = realpathSync(candidate);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return notFound(c);
|
|
46
|
+
}
|
|
47
|
+
if (!contains(realRoot, file) || !statSync(file).isFile())
|
|
48
|
+
return notFound(c);
|
|
49
|
+
const contentType = CONTENT_TYPES.get(extname(file));
|
|
50
|
+
if (contentType === undefined)
|
|
51
|
+
return notFound(c);
|
|
52
|
+
setDocsHeaders(c);
|
|
53
|
+
c.header("content-type", contentType);
|
|
54
|
+
return c.body(Readable.toWeb(createReadStream(file)));
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function contains(root, candidate) {
|
|
58
|
+
return candidate === root || candidate.startsWith(root + sep);
|
|
59
|
+
}
|
|
60
|
+
function decodeOrNull(value) {
|
|
61
|
+
try {
|
|
62
|
+
return decodeURIComponent(value);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function notFound(c) {
|
|
69
|
+
setDocsHeaders(c);
|
|
70
|
+
return c.text("Not found\n", 404);
|
|
71
|
+
}
|
|
72
|
+
function setDocsHeaders(c) {
|
|
73
|
+
c.header("cache-control", "no-store");
|
|
74
|
+
c.header("content-security-policy", DOCS_CSP);
|
|
75
|
+
c.header("referrer-policy", "no-referrer");
|
|
76
|
+
c.header("x-content-type-options", "nosniff");
|
|
77
|
+
c.header("x-frame-options", "DENY");
|
|
78
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { conflict, invalidRequest, toApiErrorBody } from "./errors.js";
|
|
3
|
+
export const IDEMPOTENCY_RESPONSE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
4
|
+
export const IDEMPOTENCY_ABANDONED_IN_PROGRESS_MS = 5 * 60 * 1000;
|
|
5
|
+
export const IDEMPOTENCY_RETRY_AFTER_SECONDS = 5;
|
|
6
|
+
export const IDEMPOTENCY_HEARTBEAT_INTERVAL_MS = 60 * 1000;
|
|
7
|
+
const MAX_IDEMPOTENCY_KEY_LENGTH = 255;
|
|
8
|
+
export function validateIdempotencyKey(value) {
|
|
9
|
+
if (value.length === 0) {
|
|
10
|
+
throw invalidRequest("`Idempotency-Key` must not be empty");
|
|
11
|
+
}
|
|
12
|
+
if (value.length > MAX_IDEMPOTENCY_KEY_LENGTH) {
|
|
13
|
+
throw invalidRequest(`\`Idempotency-Key\` must be at most ${MAX_IDEMPOTENCY_KEY_LENGTH} characters`);
|
|
14
|
+
}
|
|
15
|
+
if (!/^[\x21-\x7E]+$/.test(value)) {
|
|
16
|
+
throw invalidRequest("`Idempotency-Key` must contain only visible ASCII characters");
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
export function requestFingerprint(method, concretePath, rawBody) {
|
|
21
|
+
const hash = createHash("sha256");
|
|
22
|
+
hash.update(method);
|
|
23
|
+
hash.update("\n");
|
|
24
|
+
hash.update(concretePath);
|
|
25
|
+
hash.update("\n");
|
|
26
|
+
hash.update(rawBody);
|
|
27
|
+
return hash.digest("hex");
|
|
28
|
+
}
|
|
29
|
+
export function reserveWindow(now = new Date()) {
|
|
30
|
+
return {
|
|
31
|
+
now: now.toISOString(),
|
|
32
|
+
expiresAt: new Date(now.getTime() + IDEMPOTENCY_RESPONSE_TTL_MS).toISOString(),
|
|
33
|
+
abandonedBefore: new Date(now.getTime() - IDEMPOTENCY_ABANDONED_IN_PROGRESS_MS).toISOString(),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function completionWindow(now = new Date()) {
|
|
37
|
+
return {
|
|
38
|
+
now: now.toISOString(),
|
|
39
|
+
expiresAt: new Date(now.getTime() + IDEMPOTENCY_RESPONSE_TTL_MS).toISOString(),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export async function withIdempotencyReservationHeartbeat(ledger, input, operation) {
|
|
43
|
+
if (!ledger || !input)
|
|
44
|
+
return operation;
|
|
45
|
+
const refresh = () => {
|
|
46
|
+
ledger.refreshIdempotencyReservation({
|
|
47
|
+
...input,
|
|
48
|
+
...completionWindow(),
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
refresh();
|
|
52
|
+
const timer = setInterval(refresh, IDEMPOTENCY_HEARTBEAT_INTERVAL_MS);
|
|
53
|
+
timer.unref?.();
|
|
54
|
+
try {
|
|
55
|
+
return await operation;
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
clearInterval(timer);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export function idempotencyCompletion(workspaceId, idempotency, response, resource) {
|
|
62
|
+
return {
|
|
63
|
+
...idempotency,
|
|
64
|
+
workspaceId,
|
|
65
|
+
responseStatus: response.status,
|
|
66
|
+
responseBody: response.body,
|
|
67
|
+
...completionWindow(),
|
|
68
|
+
...(resource === undefined
|
|
69
|
+
? {}
|
|
70
|
+
: { resourceType: resource.type, resourceId: resource.id }),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
export function idempotencyConflictResponse(requestId) {
|
|
74
|
+
// This is client retry guidance in seconds. It is intentionally much shorter
|
|
75
|
+
// than the abandoned in-progress threshold used for crash recovery.
|
|
76
|
+
const error = conflict("A request with this `Idempotency-Key` is already in progress; retry later");
|
|
77
|
+
return {
|
|
78
|
+
status: error.status,
|
|
79
|
+
body: toApiErrorBody(error, requestId),
|
|
80
|
+
headers: { "retry-after": String(IDEMPOTENCY_RETRY_AFTER_SECONDS) },
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export function idempotencyMismatchError() {
|
|
84
|
+
return invalidRequest("`Idempotency-Key` was already used for a different request");
|
|
85
|
+
}
|