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.
Files changed (197) hide show
  1. package/LICENSE +93 -0
  2. package/README.md +248 -0
  3. package/bin/oma.mjs +499 -0
  4. package/dist/scripts/alpha-openai-compatible-fixture.mjs +134 -0
  5. package/dist/scripts/alpha-smoke-models.mjs +92 -0
  6. package/dist/scripts/alpha-smoke.mjs +581 -0
  7. package/dist/scripts/oma-doctor.js +230 -0
  8. package/dist/scripts/oma-models.js +299 -0
  9. package/dist/scripts/oma-workspaces.js +133 -0
  10. package/dist/src/control-plane/admin/auth.js +43 -0
  11. package/dist/src/control-plane/admin/routes.js +76 -0
  12. package/dist/src/control-plane/admin/service.js +102 -0
  13. package/dist/src/control-plane/admission.js +90 -0
  14. package/dist/src/control-plane/agents/routes.js +63 -0
  15. package/dist/src/control-plane/agents/service.js +687 -0
  16. package/dist/src/control-plane/agents/store.js +391 -0
  17. package/dist/src/control-plane/agents/types.js +1 -0
  18. package/dist/src/control-plane/api-constants.js +3 -0
  19. package/dist/src/control-plane/app.js +907 -0
  20. package/dist/src/control-plane/console/auth.js +68 -0
  21. package/dist/src/control-plane/console/static.js +112 -0
  22. package/dist/src/control-plane/deployment-runtime-config.js +328 -0
  23. package/dist/src/control-plane/deployment-runtime-event-coordinator.js +25 -0
  24. package/dist/src/control-plane/deployment-runtime-turn-guard.js +14 -0
  25. package/dist/src/control-plane/deployment-session-coordinator.js +25 -0
  26. package/dist/src/control-plane/deployment-session-output-coordinator.js +27 -0
  27. package/dist/src/control-plane/deployment-storage.js +354 -0
  28. package/dist/src/control-plane/egress/image.js +48 -0
  29. package/dist/src/control-plane/egress/policy.js +571 -0
  30. package/dist/src/control-plane/egress/presets.js +77 -0
  31. package/dist/src/control-plane/egress/proxy.js +72 -0
  32. package/dist/src/control-plane/egress/ssrf.js +106 -0
  33. package/dist/src/control-plane/egress/utils/debug.js +14 -0
  34. package/dist/src/control-plane/egress/vendor/http-proxy.js +335 -0
  35. package/dist/src/control-plane/egress/vendor/mitm-ca.js +226 -0
  36. package/dist/src/control-plane/egress/vendor/mitm-leaf.js +124 -0
  37. package/dist/src/control-plane/egress/vendor/parent-proxy.js +438 -0
  38. package/dist/src/control-plane/egress/vendor/request-filter.js +105 -0
  39. package/dist/src/control-plane/egress/vendor/sandbox-config.js +1 -0
  40. package/dist/src/control-plane/egress/vendor/tls-terminate-proxy.js +269 -0
  41. package/dist/src/control-plane/environments/routes.js +54 -0
  42. package/dist/src/control-plane/environments/service.js +112 -0
  43. package/dist/src/control-plane/environments/store.js +132 -0
  44. package/dist/src/control-plane/environments/types.js +1 -0
  45. package/dist/src/control-plane/errors.js +81 -0
  46. package/dist/src/control-plane/events/broadcaster.js +217 -0
  47. package/dist/src/control-plane/events/constants.js +2 -0
  48. package/dist/src/control-plane/events/persist.js +39 -0
  49. package/dist/src/control-plane/events/request.js +190 -0
  50. package/dist/src/control-plane/events/routes.js +159 -0
  51. package/dist/src/control-plane/events/runtime-helpers.js +134 -0
  52. package/dist/src/control-plane/events/service.js +1985 -0
  53. package/dist/src/control-plane/events/session-guards.js +29 -0
  54. package/dist/src/control-plane/events/sse.js +6 -0
  55. package/dist/src/control-plane/events/store.js +772 -0
  56. package/dist/src/control-plane/events/tool-persistence.js +102 -0
  57. package/dist/src/control-plane/events/types.js +21 -0
  58. package/dist/src/control-plane/files/routes.js +121 -0
  59. package/dist/src/control-plane/files/service.js +65 -0
  60. package/dist/src/control-plane/files/store-common.js +87 -0
  61. package/dist/src/control-plane/files/store-local.js +488 -0
  62. package/dist/src/control-plane/files/store-memory.js +270 -0
  63. package/dist/src/control-plane/files/store.js +2 -0
  64. package/dist/src/control-plane/files/types.js +7 -0
  65. package/dist/src/control-plane/http.js +25 -0
  66. package/dist/src/control-plane/ids.js +43 -0
  67. package/dist/src/control-plane/logging.js +263 -0
  68. package/dist/src/control-plane/models/auth-storage-backend.js +238 -0
  69. package/dist/src/control-plane/models/catalog.js +78 -0
  70. package/dist/src/control-plane/models/config-security.js +376 -0
  71. package/dist/src/control-plane/models/deployment-config.js +93 -0
  72. package/dist/src/control-plane/models/routes.js +32 -0
  73. package/dist/src/control-plane/models/service.js +138 -0
  74. package/dist/src/control-plane/observability/instruments.js +65 -0
  75. package/dist/src/control-plane/observability/metrics.js +125 -0
  76. package/dist/src/control-plane/observability/routes.js +95 -0
  77. package/dist/src/control-plane/openapi/document.js +282 -0
  78. package/dist/src/control-plane/openapi/routes.js +78 -0
  79. package/dist/src/control-plane/request-idempotency.js +85 -0
  80. package/dist/src/control-plane/secrets/envelope.js +132 -0
  81. package/dist/src/control-plane/secrets/master-key.js +44 -0
  82. package/dist/src/control-plane/secrets/routes.js +20 -0
  83. package/dist/src/control-plane/secrets/service.js +71 -0
  84. package/dist/src/control-plane/secrets/store.js +212 -0
  85. package/dist/src/control-plane/secrets/types.js +3 -0
  86. package/dist/src/control-plane/sessions/pi/custom-tools.js +146 -0
  87. package/dist/src/control-plane/sessions/pi/mcp/bridge.js +527 -0
  88. package/dist/src/control-plane/sessions/pi/mcp/client.js +157 -0
  89. package/dist/src/control-plane/sessions/pi/mcp/credential.js +28 -0
  90. package/dist/src/control-plane/sessions/pi/mcp/fetch.js +69 -0
  91. package/dist/src/control-plane/sessions/pi/mcp/probe.js +202 -0
  92. package/dist/src/control-plane/sessions/pi/mcp/runtime.js +13 -0
  93. package/dist/src/control-plane/sessions/pi/runner.js +1104 -0
  94. package/dist/src/control-plane/sessions/pi/sandbox/cma-glob.js +388 -0
  95. package/dist/src/control-plane/sessions/pi/sandbox/cma-grep.js +124 -0
  96. package/dist/src/control-plane/sessions/pi/sandbox/docker-egress.js +347 -0
  97. package/dist/src/control-plane/sessions/pi/sandbox/docker.js +1589 -0
  98. package/dist/src/control-plane/sessions/pi/sandbox/glob.js +48 -0
  99. package/dist/src/control-plane/sessions/pi/sandbox/image.js +7 -0
  100. package/dist/src/control-plane/sessions/pi/sandbox/microsandbox.js +1677 -0
  101. package/dist/src/control-plane/sessions/pi/sandbox/provider.js +561 -0
  102. package/dist/src/control-plane/sessions/pi/sandbox/selection.js +168 -0
  103. package/dist/src/control-plane/sessions/pi/span-normalizer.js +82 -0
  104. package/dist/src/control-plane/sessions/pi/tool-permissions.js +392 -0
  105. package/dist/src/control-plane/sessions/pi/translator.js +100 -0
  106. package/dist/src/control-plane/sessions/request.js +164 -0
  107. package/dist/src/control-plane/sessions/resources.js +63 -0
  108. package/dist/src/control-plane/sessions/routes.js +88 -0
  109. package/dist/src/control-plane/sessions/serialize.js +24 -0
  110. package/dist/src/control-plane/sessions/service.js +733 -0
  111. package/dist/src/control-plane/sessions/store.js +538 -0
  112. package/dist/src/control-plane/sessions/types.js +1 -0
  113. package/dist/src/control-plane/skills/archive.js +169 -0
  114. package/dist/src/control-plane/skills/routes.js +41 -0
  115. package/dist/src/control-plane/skills/service.js +29 -0
  116. package/dist/src/control-plane/skills/store.js +233 -0
  117. package/dist/src/control-plane/skills/types.js +5 -0
  118. package/dist/src/control-plane/sqlite-transaction.js +15 -0
  119. package/dist/src/control-plane/vaults/mcp-oauth-validate.js +165 -0
  120. package/dist/src/control-plane/vaults/oauth-refresh-ticker.js +43 -0
  121. package/dist/src/control-plane/vaults/oauth-refresh.js +448 -0
  122. package/dist/src/control-plane/vaults/routes.js +66 -0
  123. package/dist/src/control-plane/vaults/service.js +553 -0
  124. package/dist/src/control-plane/vaults/store.js +691 -0
  125. package/dist/src/control-plane/vaults/types.js +1 -0
  126. package/dist/src/control-plane/wake-loop.js +65 -0
  127. package/dist/src/control-plane/wiring.js +92 -0
  128. package/dist/src/control-plane/workspace.js +4 -0
  129. package/dist/src/control-plane/workspaces/store.js +158 -0
  130. package/dist/src/egress-proxy-main.js +103 -0
  131. package/dist/src/main.js +124 -0
  132. package/dist/src/types/agents.js +1 -0
  133. package/dist/src/types/common.js +1 -0
  134. package/dist/src/types/environments.js +1 -0
  135. package/dist/src/types/events.js +121 -0
  136. package/dist/src/types/files.js +1 -0
  137. package/dist/src/types/json.js +19 -0
  138. package/dist/src/types/sessions.js +1 -0
  139. package/dist/ui/managed-agents-console/README.md +52 -0
  140. package/dist/ui/managed-agents-console/docs/agents.md +23 -0
  141. package/dist/ui/managed-agents-console/docs/console.md +23 -0
  142. package/dist/ui/managed-agents-console/docs/dreams.md +5 -0
  143. package/dist/ui/managed-agents-console/docs/environments.md +27 -0
  144. package/dist/ui/managed-agents-console/docs/events.md +19 -0
  145. package/dist/ui/managed-agents-console/docs/files.md +17 -0
  146. package/dist/ui/managed-agents-console/docs/github.md +11 -0
  147. package/dist/ui/managed-agents-console/docs/integrations.md +19 -0
  148. package/dist/ui/managed-agents-console/docs/memory.md +11 -0
  149. package/dist/ui/managed-agents-console/docs/migration.md +17 -0
  150. package/dist/ui/managed-agents-console/docs/multiagent.md +11 -0
  151. package/dist/ui/managed-agents-console/docs/outcomes.md +11 -0
  152. package/dist/ui/managed-agents-console/docs/overview.md +41 -0
  153. package/dist/ui/managed-agents-console/docs/permissions.md +24 -0
  154. package/dist/ui/managed-agents-console/docs/quickstart.md +51 -0
  155. package/dist/ui/managed-agents-console/docs/reference.md +27 -0
  156. package/dist/ui/managed-agents-console/docs/sandbox-reference.md +19 -0
  157. package/dist/ui/managed-agents-console/docs/sandbox-security.md +15 -0
  158. package/dist/ui/managed-agents-console/docs/scheduled-deployments.md +5 -0
  159. package/dist/ui/managed-agents-console/docs/self-hosted-sandboxes.md +15 -0
  160. package/dist/ui/managed-agents-console/docs/session-operations.md +21 -0
  161. package/dist/ui/managed-agents-console/docs/sessions.md +21 -0
  162. package/dist/ui/managed-agents-console/docs/skills.md +15 -0
  163. package/dist/ui/managed-agents-console/docs/tools.md +23 -0
  164. package/dist/ui/managed-agents-console/docs/vaults.md +19 -0
  165. package/dist/ui/managed-agents-console/docs/webhooks.md +11 -0
  166. package/dist/ui/managed-agents-console/index.html +47 -0
  167. package/dist/ui/managed-agents-console/serve.mjs +116 -0
  168. package/dist/ui/managed-agents-console/src/agents-files.jsx +273 -0
  169. package/dist/ui/managed-agents-console/src/api.js +1043 -0
  170. package/dist/ui/managed-agents-console/src/app.jsx +633 -0
  171. package/dist/ui/managed-agents-console/src/auth.jsx +215 -0
  172. package/dist/ui/managed-agents-console/src/console.css +733 -0
  173. package/dist/ui/managed-agents-console/src/data.js +188 -0
  174. package/dist/ui/managed-agents-console/src/detail.jsx +719 -0
  175. package/dist/ui/managed-agents-console/src/docs.jsx +200 -0
  176. package/dist/ui/managed-agents-console/src/environments.jsx +365 -0
  177. package/dist/ui/managed-agents-console/src/forms.jsx +494 -0
  178. package/dist/ui/managed-agents-console/src/icons.jsx +48 -0
  179. package/dist/ui/managed-agents-console/src/skills.jsx +21 -0
  180. package/dist/ui/managed-agents-console/src/sse.js +185 -0
  181. package/dist/ui/managed-agents-console/src/states.jsx +90 -0
  182. package/dist/ui/managed-agents-console/src/tweaks-panel.jsx +541 -0
  183. package/dist/ui/managed-agents-console/src/ui.jsx +190 -0
  184. package/dist/ui/managed-agents-console/src/vaults-data.js +89 -0
  185. package/dist/ui/managed-agents-console/src/vaults.jsx +171 -0
  186. package/dist/ui/managed-agents-console/vendor/babel.min.js +4 -0
  187. package/dist/ui/managed-agents-console/vendor/react-dom.production.min.js +267 -0
  188. package/dist/ui/managed-agents-console/vendor/react.production.min.js +31 -0
  189. package/dist/ui/openapi-docs/VENDOR.md +27 -0
  190. package/dist/ui/openapi-docs/index.html +16 -0
  191. package/dist/ui/openapi-docs/swagger-initializer.js +14 -0
  192. package/dist/ui/openapi-docs/vendor/LICENSE +202 -0
  193. package/dist/ui/openapi-docs/vendor/NOTICE +2 -0
  194. package/dist/ui/openapi-docs/vendor/swagger-ui-bundle.js +2 -0
  195. package/dist/ui/openapi-docs/vendor/swagger-ui-standalone-preset.js +2 -0
  196. package/dist/ui/openapi-docs/vendor/swagger-ui.css +3 -0
  197. package/package.json +53 -0
@@ -0,0 +1,391 @@
1
+ import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
2
+ import { DatabaseSync } from "node:sqlite";
3
+ import { withSqliteTransaction } from "../sqlite-transaction.js";
4
+ const SCHEMA = `
5
+ CREATE TABLE IF NOT EXISTS agents (
6
+ id TEXT PRIMARY KEY,
7
+ workspace_id TEXT NOT NULL,
8
+ type TEXT NOT NULL,
9
+ name TEXT NOT NULL,
10
+ model TEXT NOT NULL,
11
+ system TEXT,
12
+ description TEXT,
13
+ tools TEXT NOT NULL,
14
+ skills TEXT NOT NULL,
15
+ mcp_servers TEXT NOT NULL,
16
+ metadata TEXT NOT NULL,
17
+ multiagent TEXT,
18
+ version INTEGER NOT NULL,
19
+ created_at TEXT NOT NULL,
20
+ updated_at TEXT NOT NULL,
21
+ archived_at TEXT
22
+ );
23
+ CREATE INDEX IF NOT EXISTS agents_by_workspace ON agents (workspace_id, id);
24
+ CREATE TABLE IF NOT EXISTS agent_versions (
25
+ workspace_id TEXT NOT NULL,
26
+ agent_id TEXT NOT NULL,
27
+ version INTEGER NOT NULL,
28
+ name TEXT NOT NULL,
29
+ model TEXT NOT NULL,
30
+ system TEXT,
31
+ description TEXT,
32
+ tools TEXT NOT NULL,
33
+ skills TEXT NOT NULL,
34
+ mcp_servers TEXT NOT NULL,
35
+ metadata TEXT NOT NULL,
36
+ multiagent TEXT,
37
+ created_at TEXT NOT NULL,
38
+ updated_at TEXT NOT NULL,
39
+ PRIMARY KEY (workspace_id, agent_id, version)
40
+ );
41
+ CREATE INDEX IF NOT EXISTS agent_versions_newest
42
+ ON agent_versions (workspace_id, agent_id, version DESC);
43
+ `;
44
+ export class SqliteAgentStore {
45
+ db;
46
+ cursorSigningKey = randomBytes(32);
47
+ insertStmt;
48
+ insertVersionStmt;
49
+ updateHeadStmt;
50
+ retrieveVersionStmt;
51
+ listVersionsFirstStmt;
52
+ listVersionsAfterStmt;
53
+ retrieveActiveStmt;
54
+ retrieveAnyStmt;
55
+ archiveStmt;
56
+ listActiveStmt;
57
+ listAllStmt;
58
+ listActiveSinceStmt;
59
+ listAllSinceStmt;
60
+ constructor(db) {
61
+ this.db = db;
62
+ this.db.exec(SCHEMA);
63
+ withSqliteTransaction(this.db, () => {
64
+ migratePersistedModels(this.db);
65
+ this.db.exec(`INSERT OR IGNORE INTO agent_versions (
66
+ workspace_id, agent_id, version, name, model, system, description,
67
+ tools, skills, mcp_servers, metadata, multiagent, created_at, updated_at
68
+ ) SELECT workspace_id, id, version, name, model, system, description,
69
+ tools, skills, mcp_servers, metadata, multiagent, created_at, updated_at
70
+ FROM agents`);
71
+ assertAllPersistedModelsNormalized(this.db);
72
+ });
73
+ this.insertStmt = this.db.prepare(`INSERT INTO agents (
74
+ id, workspace_id, type, name, model, system, description, tools, skills,
75
+ mcp_servers, metadata, multiagent, version, created_at, updated_at,
76
+ archived_at
77
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
78
+ this.insertVersionStmt = this.db.prepare(`INSERT INTO agent_versions (
79
+ workspace_id, agent_id, version, name, model, system, description,
80
+ tools, skills, mcp_servers, metadata, multiagent, created_at, updated_at
81
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
82
+ this.updateHeadStmt = this.db.prepare(`UPDATE agents SET
83
+ name = ?, model = ?, system = ?, description = ?, tools = ?, skills = ?,
84
+ mcp_servers = ?, metadata = ?, multiagent = ?, version = ?, updated_at = ?
85
+ WHERE workspace_id = ? AND id = ? AND version = ? AND archived_at IS NULL`);
86
+ this.retrieveVersionStmt = this.db.prepare(`SELECT * FROM agent_versions
87
+ WHERE workspace_id = ? AND agent_id = ? AND version = ?`);
88
+ this.listVersionsFirstStmt = this.db.prepare(`SELECT * FROM agent_versions
89
+ WHERE workspace_id = ? AND agent_id = ?
90
+ ORDER BY version DESC LIMIT ?`);
91
+ this.listVersionsAfterStmt = this.db.prepare(`SELECT * FROM agent_versions
92
+ WHERE workspace_id = ? AND agent_id = ? AND version < ?
93
+ ORDER BY version DESC LIMIT ?`);
94
+ this.retrieveActiveStmt = this.db.prepare(`SELECT * FROM agents
95
+ WHERE workspace_id = ? AND id = ? AND archived_at IS NULL`);
96
+ this.retrieveAnyStmt = this.db.prepare(`SELECT * FROM agents
97
+ WHERE workspace_id = ? AND id = ?`);
98
+ this.archiveStmt = this.db.prepare(`UPDATE agents
99
+ SET archived_at = COALESCE(archived_at, ?),
100
+ updated_at = CASE WHEN archived_at IS NULL THEN ? ELSE updated_at END
101
+ WHERE workspace_id = ? AND id = ?`);
102
+ this.listActiveStmt = this.db.prepare(`SELECT * FROM agents
103
+ WHERE workspace_id = ? AND archived_at IS NULL
104
+ ORDER BY id ASC
105
+ LIMIT ?`);
106
+ this.listAllStmt = this.db.prepare(`SELECT * FROM agents
107
+ WHERE workspace_id = ?
108
+ ORDER BY id ASC
109
+ LIMIT ?`);
110
+ this.listActiveSinceStmt = this.db.prepare(`SELECT * FROM agents
111
+ WHERE workspace_id = ? AND id > ? AND archived_at IS NULL
112
+ ORDER BY id ASC
113
+ LIMIT ?`);
114
+ this.listAllSinceStmt = this.db.prepare(`SELECT * FROM agents
115
+ WHERE workspace_id = ? AND id > ?
116
+ ORDER BY id ASC
117
+ LIMIT ?`);
118
+ }
119
+ static open(path = ":memory:") {
120
+ return new SqliteAgentStore(new DatabaseSync(path));
121
+ }
122
+ create(record) {
123
+ const a = record.row;
124
+ return withSqliteTransaction(this.db, () => {
125
+ this.insertStmt.run(a.id, a.workspace_id, a.type, a.name, JSON.stringify(a.model), a.system, a.description, JSON.stringify(a.tools), JSON.stringify(a.skills), JSON.stringify(a.mcp_servers), JSON.stringify(a.metadata), a.multiagent === null ? null : JSON.stringify(a.multiagent), a.version, a.created_at, a.updated_at, a.archived_at);
126
+ this.insertVersion(a);
127
+ return a;
128
+ });
129
+ }
130
+ update(record) {
131
+ const next = record.row;
132
+ return withSqliteTransaction(this.db, () => {
133
+ const current = this.retrieveAny(next.workspace_id, next.id);
134
+ if (!current)
135
+ throw new AgentUpdateMissingError();
136
+ if (current.archived_at !== null)
137
+ throw new AgentUpdateArchivedError();
138
+ if (current.version !== record.expectedVersion) {
139
+ throw new AgentUpdateConflictError();
140
+ }
141
+ if (next.version !== current.version + 1) {
142
+ throw new Error("Agent update must allocate exactly one version");
143
+ }
144
+ this.insertVersion(next);
145
+ const result = this.updateHeadStmt.run(next.name, JSON.stringify(next.model), next.system, next.description, JSON.stringify(next.tools), JSON.stringify(next.skills), JSON.stringify(next.mcp_servers), JSON.stringify(next.metadata), next.multiagent === null ? null : JSON.stringify(next.multiagent), next.version, next.updated_at, next.workspace_id, next.id, record.expectedVersion);
146
+ if (result.changes !== 1)
147
+ throw new AgentUpdateConflictError();
148
+ return next;
149
+ });
150
+ }
151
+ retrieve(workspaceId, agentId) {
152
+ const row = this.retrieveActiveStmt.get(workspaceId, agentId);
153
+ return row ? deserialize(row) : undefined;
154
+ }
155
+ retrieveAny(workspaceId, agentId) {
156
+ const row = this.retrieveAnyStmt.get(workspaceId, agentId);
157
+ return row ? deserialize(row) : undefined;
158
+ }
159
+ retrieveVersion(workspaceId, agentId, version) {
160
+ const owner = this.retrieveAny(workspaceId, agentId);
161
+ if (!owner)
162
+ return undefined;
163
+ const row = this.retrieveVersionStmt.get(workspaceId, agentId, version);
164
+ return row ? deserializeVersion(row, owner.archived_at) : undefined;
165
+ }
166
+ listVersions(workspaceId, agentId, opts = {}) {
167
+ const owner = this.retrieveAny(workspaceId, agentId);
168
+ if (!owner)
169
+ throw new AgentUpdateMissingError();
170
+ const limit = normalizeLimit(opts.limit);
171
+ const anchor = opts.page === undefined
172
+ ? undefined
173
+ : decodeVersionCursor(opts.page, workspaceId, agentId, this.cursorSigningKey);
174
+ const rows = (anchor === undefined
175
+ ? this.listVersionsFirstStmt.all(workspaceId, agentId, limit + 1)
176
+ : this.listVersionsAfterStmt.all(workspaceId, agentId, anchor, limit + 1));
177
+ const selected = rows.slice(0, limit);
178
+ const data = selected.map((row) => deserializeVersion(row, owner.archived_at));
179
+ return {
180
+ data,
181
+ next_page: rows.length > limit && data.length > 0
182
+ ? encodeVersionCursor(data[data.length - 1].version, workspaceId, agentId, this.cursorSigningKey)
183
+ : null,
184
+ };
185
+ }
186
+ archive(workspaceId, agentId, archivedAt) {
187
+ this.archiveStmt.run(archivedAt, archivedAt, workspaceId, agentId);
188
+ return this.retrieveAny(workspaceId, agentId);
189
+ }
190
+ list(workspaceId, opts = {}) {
191
+ if (opts.page === "") {
192
+ return { data: [], has_more: false, next_page: null };
193
+ }
194
+ const limit = normalizeLimit(opts.limit);
195
+ const queryLimit = limit + 1;
196
+ const includeArchived = opts.includeArchived ?? false;
197
+ const rows = this.listStmt(includeArchived, opts.page !== undefined).all(...selectListArgs(workspaceId, queryLimit, opts.page));
198
+ const pageRows = rows.slice(0, limit);
199
+ const data = pageRows.map(deserialize);
200
+ return {
201
+ data,
202
+ has_more: rows.length > limit,
203
+ next_page: rows.length > limit ? data[data.length - 1]?.id ?? null : null,
204
+ };
205
+ }
206
+ close() {
207
+ this.db.close();
208
+ }
209
+ insertVersion(row) {
210
+ this.insertVersionStmt.run(row.workspace_id, row.id, row.version, row.name, JSON.stringify(row.model), row.system, row.description, JSON.stringify(row.tools), JSON.stringify(row.skills), JSON.stringify(row.mcp_servers), JSON.stringify(row.metadata), row.multiagent === null ? null : JSON.stringify(row.multiagent), row.created_at, row.updated_at);
211
+ }
212
+ listStmt(includeArchived, hasPage) {
213
+ if (includeArchived) {
214
+ return hasPage ? this.listAllSinceStmt : this.listAllStmt;
215
+ }
216
+ return hasPage ? this.listActiveSinceStmt : this.listActiveStmt;
217
+ }
218
+ }
219
+ export class AgentUpdateMissingError extends Error {
220
+ }
221
+ export class AgentUpdateArchivedError extends Error {
222
+ }
223
+ export class AgentUpdateConflictError extends Error {
224
+ }
225
+ function encodeVersionCursor(anchor, workspaceId, agentId, signingKey) {
226
+ const payload = Buffer.from(JSON.stringify({ v: 1, anchor, agentId }), "utf8")
227
+ .toString("base64url");
228
+ const signature = signVersionCursor(payload, workspaceId, signingKey);
229
+ return `${payload}.${signature.toString("base64url")}`;
230
+ }
231
+ function decodeVersionCursor(cursor, workspaceId, agentId, signingKey) {
232
+ try {
233
+ const parts = cursor.split(".");
234
+ if (parts.length !== 2)
235
+ throw new Error("invalid cursor");
236
+ const payloadBytes = decodeCanonicalBase64url(parts[0]);
237
+ const signature = decodeCanonicalBase64url(parts[1]);
238
+ const expected = signVersionCursor(parts[0], workspaceId, signingKey);
239
+ if (signature.length !== expected.length || !timingSafeEqual(signature, expected)) {
240
+ throw new Error("invalid signature");
241
+ }
242
+ const parsed = JSON.parse(payloadBytes.toString("utf8"));
243
+ if (parsed.v !== 1 ||
244
+ !Number.isSafeInteger(parsed.anchor) ||
245
+ (parsed.anchor ?? 0) <= 0 ||
246
+ parsed.agentId !== agentId)
247
+ throw new Error("invalid payload");
248
+ return parsed.anchor;
249
+ }
250
+ catch {
251
+ throw new Error("invalid page cursor");
252
+ }
253
+ }
254
+ function signVersionCursor(payload, workspaceId, key) {
255
+ return createHmac("sha256", key)
256
+ .update("oma-agent-versions-page-v1\0", "utf8")
257
+ .update(workspaceId, "utf8")
258
+ .update("\0", "utf8")
259
+ .update(payload, "utf8")
260
+ .digest();
261
+ }
262
+ function decodeCanonicalBase64url(value) {
263
+ if (!/^[A-Za-z0-9_-]+$/.test(value))
264
+ throw new Error("invalid base64url");
265
+ const decoded = Buffer.from(value, "base64url");
266
+ if (decoded.toString("base64url") !== value)
267
+ throw new Error("invalid base64url");
268
+ return decoded;
269
+ }
270
+ function selectListArgs(workspaceId, limit, page) {
271
+ return page === undefined ? [workspaceId, limit] : [workspaceId, page, limit];
272
+ }
273
+ function normalizeLimit(limit) {
274
+ if (limit === undefined)
275
+ return 20;
276
+ if (!Number.isSafeInteger(limit) || limit <= 0)
277
+ return 20;
278
+ return Math.min(limit, 100);
279
+ }
280
+ function migratePersistedModels(db) {
281
+ const updateHead = db.prepare("UPDATE agents SET model = ? WHERE workspace_id = ? AND id = ?");
282
+ const updateVersion = db.prepare(`UPDATE agent_versions SET model = ?
283
+ WHERE workspace_id = ? AND agent_id = ? AND version = ?`);
284
+ const heads = db.prepare("SELECT workspace_id, id, version, model FROM agents").all();
285
+ for (const row of heads) {
286
+ const parsed = parsePersistedModel(row.model, `agent ${row.id}`);
287
+ if (parsed.legacy) {
288
+ updateHead.run(JSON.stringify(parsed.model), row.workspace_id, row.id);
289
+ }
290
+ }
291
+ const versions = db.prepare(`SELECT workspace_id, agent_id AS id, version, model
292
+ FROM agent_versions`).all();
293
+ for (const row of versions) {
294
+ const parsed = parsePersistedModel(row.model, `agent version ${row.id}@${row.version}`);
295
+ if (parsed.legacy) {
296
+ updateVersion.run(JSON.stringify(parsed.model), row.workspace_id, row.id, row.version);
297
+ }
298
+ }
299
+ }
300
+ function assertAllPersistedModelsNormalized(db) {
301
+ const heads = db.prepare("SELECT workspace_id, id, version, model FROM agents").all();
302
+ const versions = db.prepare(`SELECT workspace_id, agent_id AS id, version, model FROM agent_versions`).all();
303
+ const rows = [...heads, ...versions];
304
+ for (const row of rows) {
305
+ const parsed = parsePersistedModel(row.model, `agent revision ${row.id}@${row.version}`);
306
+ if (parsed.legacy) {
307
+ throw new Error(`Agent model migration left a legacy row: ${row.id}@${row.version}`);
308
+ }
309
+ }
310
+ }
311
+ function parsePersistedModel(raw, location) {
312
+ let value;
313
+ try {
314
+ value = JSON.parse(raw);
315
+ }
316
+ catch {
317
+ throw new Error(`Invalid persisted model JSON for ${location}`);
318
+ }
319
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
320
+ throw new Error(`Invalid persisted model for ${location}`);
321
+ }
322
+ const model = value;
323
+ const legacy = model.provider === undefined;
324
+ const allowedKeys = legacy
325
+ ? new Set(["id", "speed"])
326
+ : new Set(["provider", "id", "speed"]);
327
+ if (Object.keys(model).some((key) => !allowedKeys.has(key))) {
328
+ throw new Error(`Invalid persisted model fields for ${location}`);
329
+ }
330
+ if (typeof model.id !== "string" || model.id.length === 0) {
331
+ throw new Error(`Invalid persisted model id for ${location}`);
332
+ }
333
+ if (model.speed !== "standard" && model.speed !== "fast") {
334
+ throw new Error(`Invalid persisted model speed for ${location}`);
335
+ }
336
+ if (!legacy && (typeof model.provider !== "string" || model.provider.length === 0)) {
337
+ throw new Error(`Invalid persisted model provider for ${location}`);
338
+ }
339
+ return {
340
+ model: {
341
+ provider: legacy ? "anthropic" : model.provider,
342
+ id: model.id,
343
+ speed: model.speed,
344
+ },
345
+ legacy,
346
+ };
347
+ }
348
+ function deserialize(row) {
349
+ return {
350
+ id: row.id,
351
+ workspace_id: row.workspace_id,
352
+ type: "agent",
353
+ name: row.name,
354
+ model: JSON.parse(row.model),
355
+ system: row.system,
356
+ description: row.description,
357
+ tools: JSON.parse(row.tools),
358
+ skills: JSON.parse(row.skills),
359
+ mcp_servers: JSON.parse(row.mcp_servers),
360
+ metadata: JSON.parse(row.metadata),
361
+ multiagent: row.multiagent === null
362
+ ? null
363
+ : JSON.parse(row.multiagent),
364
+ version: row.version,
365
+ created_at: row.created_at,
366
+ updated_at: row.updated_at,
367
+ archived_at: row.archived_at,
368
+ };
369
+ }
370
+ function deserializeVersion(row, archivedAt) {
371
+ return {
372
+ id: row.agent_id,
373
+ workspace_id: row.workspace_id,
374
+ type: "agent",
375
+ name: row.name,
376
+ model: JSON.parse(row.model),
377
+ system: row.system,
378
+ description: row.description,
379
+ tools: JSON.parse(row.tools),
380
+ skills: JSON.parse(row.skills),
381
+ mcp_servers: JSON.parse(row.mcp_servers),
382
+ metadata: JSON.parse(row.metadata),
383
+ multiagent: row.multiagent === null
384
+ ? null
385
+ : JSON.parse(row.multiagent),
386
+ version: row.version,
387
+ created_at: row.created_at,
388
+ updated_at: row.updated_at,
389
+ archived_at: archivedAt,
390
+ };
391
+ }
@@ -0,0 +1 @@
1
+ export { DEFAULT_WORKSPACE_ID } from "../workspace.js";
@@ -0,0 +1,3 @@
1
+ export const MANAGED_AGENTS_BETA = "managed-agents-2026-04-01";
2
+ export const FILES_API_BETA = "files-api-2025-04-14";
3
+ export const SKILLS_API_BETA = "skills-2025-10-02";