@cef-ai/cli 0.2.6 → 0.3.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 (127) hide show
  1. package/README.md +75 -1247
  2. package/dist/build/duration.d.ts +22 -0
  3. package/dist/build/duration.d.ts.map +1 -0
  4. package/dist/build/duration.js +44 -0
  5. package/dist/build/duration.js.map +1 -0
  6. package/dist/build/esbuild-plugin.d.ts +32 -0
  7. package/dist/build/esbuild-plugin.d.ts.map +1 -0
  8. package/dist/build/esbuild-plugin.js +53 -0
  9. package/dist/build/esbuild-plugin.js.map +1 -0
  10. package/dist/build/lints.d.ts +55 -0
  11. package/dist/build/lints.d.ts.map +1 -0
  12. package/dist/build/lints.js +214 -0
  13. package/dist/build/lints.js.map +1 -0
  14. package/dist/build/load-config.d.ts +114 -0
  15. package/dist/build/load-config.d.ts.map +1 -0
  16. package/dist/build/load-config.js +150 -0
  17. package/dist/build/load-config.js.map +1 -0
  18. package/dist/build/manifest.d.ts +156 -0
  19. package/dist/build/manifest.d.ts.map +1 -0
  20. package/dist/build/manifest.js +111 -0
  21. package/dist/build/manifest.js.map +1 -0
  22. package/dist/build/targeting.d.ts +15 -0
  23. package/dist/build/targeting.d.ts.map +1 -0
  24. package/dist/build/targeting.js +69 -0
  25. package/dist/build/targeting.js.map +1 -0
  26. package/dist/cli.d.ts +2 -2
  27. package/dist/cli.d.ts.map +1 -0
  28. package/dist/cli.js +107 -62
  29. package/dist/cli.js.map +1 -0
  30. package/dist/commands/build.d.ts +41 -0
  31. package/dist/commands/build.d.ts.map +1 -0
  32. package/dist/commands/build.js +252 -0
  33. package/dist/commands/build.js.map +1 -0
  34. package/dist/commands/inspect.d.ts +49 -0
  35. package/dist/commands/inspect.d.ts.map +1 -0
  36. package/dist/commands/inspect.js +135 -0
  37. package/dist/commands/inspect.js.map +1 -0
  38. package/dist/commands/typegen.d.ts +36 -0
  39. package/dist/commands/typegen.d.ts.map +1 -0
  40. package/dist/commands/typegen.js +210 -0
  41. package/dist/commands/typegen.js.map +1 -0
  42. package/dist/index.d.ts +6 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +6 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/lib.d.ts +12 -0
  47. package/dist/lib.d.ts.map +1 -0
  48. package/dist/lib.js +9 -0
  49. package/dist/lib.js.map +1 -0
  50. package/dist/typegen/augment.d.ts +57 -0
  51. package/dist/typegen/augment.d.ts.map +1 -0
  52. package/dist/typegen/augment.js +87 -0
  53. package/dist/typegen/augment.js.map +1 -0
  54. package/dist/typegen/fetch.d.ts +30 -0
  55. package/dist/typegen/fetch.d.ts.map +1 -0
  56. package/dist/typegen/fetch.js +38 -0
  57. package/dist/typegen/fetch.js.map +1 -0
  58. package/dist/typegen/lockfile.d.ts +42 -0
  59. package/dist/typegen/lockfile.d.ts.map +1 -0
  60. package/dist/typegen/lockfile.js +58 -0
  61. package/dist/typegen/lockfile.js.map +1 -0
  62. package/dist/typegen/schema-to-ts.d.ts +21 -0
  63. package/dist/typegen/schema-to-ts.d.ts.map +1 -0
  64. package/dist/typegen/schema-to-ts.js +29 -0
  65. package/dist/typegen/schema-to-ts.js.map +1 -0
  66. package/package.json +20 -58
  67. package/dist/commands/auth/index.d.ts +0 -2
  68. package/dist/commands/auth/index.js +0 -162
  69. package/dist/commands/deploy/clone.d.ts +0 -13
  70. package/dist/commands/deploy/clone.js +0 -143
  71. package/dist/commands/deploy/delete.d.ts +0 -14
  72. package/dist/commands/deploy/delete.js +0 -134
  73. package/dist/commands/deploy/deploy.d.ts +0 -24
  74. package/dist/commands/deploy/deploy.js +0 -654
  75. package/dist/commands/deploy/index.d.ts +0 -2
  76. package/dist/commands/deploy/index.js +0 -216
  77. package/dist/commands/deploy/status.d.ts +0 -14
  78. package/dist/commands/deploy/status.js +0 -61
  79. package/dist/commands/dev/index.d.ts +0 -2
  80. package/dist/commands/dev/index.js +0 -134
  81. package/dist/commands/dev/server.d.ts +0 -14
  82. package/dist/commands/dev/server.js +0 -195
  83. package/dist/commands/dev/static/app.js +0 -633
  84. package/dist/commands/dev/static/index.html +0 -205
  85. package/dist/commands/dev/static/static/app.js +0 -633
  86. package/dist/commands/dev/static/static/index.html +0 -205
  87. package/dist/commands/dev/static/static/style.css +0 -184
  88. package/dist/commands/dev/static/style.css +0 -184
  89. package/dist/commands/playground/index.d.ts +0 -2
  90. package/dist/commands/playground/index.js +0 -75
  91. package/dist/commands/playground/test.d.ts +0 -15
  92. package/dist/commands/playground/test.js +0 -166
  93. package/dist/commands/service/index.d.ts +0 -2
  94. package/dist/commands/service/index.js +0 -75
  95. package/dist/lib/api.d.ts +0 -146
  96. package/dist/lib/api.js +0 -330
  97. package/dist/lib/config.d.ts +0 -12
  98. package/dist/lib/config.js +0 -145
  99. package/dist/lib/credentials.d.ts +0 -19
  100. package/dist/lib/credentials.js +0 -68
  101. package/dist/lib/runtime/agent-router.d.ts +0 -12
  102. package/dist/lib/runtime/agent-router.js +0 -67
  103. package/dist/lib/runtime/context-builder.d.ts +0 -27
  104. package/dist/lib/runtime/context-builder.js +0 -166
  105. package/dist/lib/runtime/cubby-manager.d.ts +0 -20
  106. package/dist/lib/runtime/cubby-manager.js +0 -162
  107. package/dist/lib/runtime/index.d.ts +0 -51
  108. package/dist/lib/runtime/index.js +0 -181
  109. package/dist/lib/runtime/log-collector.d.ts +0 -17
  110. package/dist/lib/runtime/log-collector.js +0 -61
  111. package/dist/lib/runtime/stream-manager.d.ts +0 -10
  112. package/dist/lib/runtime/stream-manager.js +0 -77
  113. package/dist/lib/runtime/types.d.ts +0 -76
  114. package/dist/lib/runtime/types.js +0 -2
  115. package/dist/lib/transpile.d.ts +0 -1
  116. package/dist/lib/transpile.js +0 -9
  117. package/dist/lib/typecheck.d.ts +0 -31
  118. package/dist/lib/typecheck.js +0 -175
  119. package/dist/lib/types.d.ts +0 -246
  120. package/dist/lib/types.js +0 -2
  121. package/dist/lib/utils.d.ts +0 -4
  122. package/dist/lib/utils.js +0 -33
  123. package/example/.env.example +0 -6
  124. package/example/agents/object-detection/tasks/yolo.ts +0 -28
  125. package/example/agents/parking-violation-detector/tasks/detect.ts +0 -326
  126. package/example/cef.config.yaml +0 -91
  127. package/example/engagements/engagement.ts +0 -902
@@ -1,654 +0,0 @@
1
- import fs from 'fs';
2
- import readline from 'readline/promises';
3
- import { stringify } from 'yaml';
4
- import { createApiClient, listAgentServices } from '../../lib/api.js';
5
- import { typecheckAll } from '../../lib/typecheck.js';
6
- import { extractId } from '../../lib/utils.js';
7
- const NOT_FOUND_HTTP = '404';
8
- const NOT_FOUND_CODE = 'RESOURCE_NOT_FOUND';
9
- function isNotFoundError(err) {
10
- const msg = err instanceof Error ? err.message : String(err);
11
- return msg.includes(NOT_FOUND_HTTP) || msg.includes(NOT_FOUND_CODE);
12
- }
13
- // Required by the API; replaced server-side with a permanent value
14
- const PLACEHOLDER_CID_PREFIX = 'temp-cid-';
15
- function defaultPromptForCopy(entity, name) {
16
- if (!process.stdin.isTTY || !process.stdout.isTTY) {
17
- throw new Error(`${entity} "${name}" not found on this agent service (ID may be from another service). ` +
18
- 'Run deploy in an interactive terminal to create a copy here, or remove the id from cef.config.yaml.');
19
- }
20
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
21
- const question = `${entity} "${name}" not found on this agent service (ID may be from another service). Create a copy here? (y/n) `;
22
- return rl.question(question).then((answer) => {
23
- rl.close();
24
- return /^y(es)?$/i.test((answer ?? '').trim());
25
- }).catch((err) => {
26
- rl.close();
27
- throw err;
28
- });
29
- }
30
- function defaultPromptForWorkspaceId(workspaceName) {
31
- if (!process.stdin.isTTY || !process.stdout.isTTY) {
32
- return Promise.resolve(undefined);
33
- }
34
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
35
- const question = `Workspace "${workspaceName}" has no workspaceId. Enter workspace ID for this agent service (or press Enter to create new): `;
36
- return rl.question(question).then((answer) => {
37
- rl.close();
38
- const id = (answer ?? '').trim();
39
- return id === '' ? undefined : id;
40
- }).catch((err) => {
41
- rl.close();
42
- throw err;
43
- });
44
- }
45
- function defaultPromptForClearIds(oldServiceId, newServiceId) {
46
- if (!process.stdin.isTTY || !process.stdout.isTTY) {
47
- throw new Error(`Config appears to be from a different agent service (old: ${oldServiceId}, resolved: ${newServiceId}). ` +
48
- 'Run deploy in an interactive terminal to clear IDs and deploy fresh, or manually remove entity IDs from cef.config.yaml.');
49
- }
50
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
51
- const question = `Config appears to be from a different agent service (old: ${oldServiceId}, resolved: ${newServiceId}). ` +
52
- `Clear all entity IDs and deploy fresh? (y/n) `;
53
- return rl.question(question).then((answer) => {
54
- rl.close();
55
- return /^y(es)?$/i.test((answer ?? '').trim());
56
- }).catch((err) => {
57
- rl.close();
58
- throw err;
59
- });
60
- }
61
- /** Check if config has any entity IDs that might be stale from another service. */
62
- function configHasEntityIds(config) {
63
- for (const eng of config.engagements ?? []) {
64
- if (eng.engagementId)
65
- return true;
66
- }
67
- for (const agent of config.agents ?? []) {
68
- if (agent.agentId)
69
- return true;
70
- }
71
- for (const cubby of config.cubbies ?? []) {
72
- if (cubby.cubbyId)
73
- return true;
74
- }
75
- for (const ws of config.workspaces ?? []) {
76
- if (ws.workspaceId)
77
- return true;
78
- for (const stream of ws.streams ?? []) {
79
- if (stream.streamId)
80
- return true;
81
- for (const dep of stream.deployments ?? []) {
82
- if (dep.deploymentId)
83
- return true;
84
- }
85
- for (const raft of stream.rafts ?? []) {
86
- if (raft.raftId)
87
- return true;
88
- }
89
- }
90
- }
91
- return false;
92
- }
93
- /** Strip all entity IDs from config so everything deploys as new. */
94
- export function clearAllEntityIds(config) {
95
- for (const eng of config.engagements ?? []) {
96
- eng.engagementId = undefined;
97
- }
98
- for (const agent of config.agents ?? []) {
99
- agent.agentId = undefined;
100
- }
101
- for (const cubby of config.cubbies ?? []) {
102
- cubby.cubbyId = undefined;
103
- }
104
- for (const ws of config.workspaces ?? []) {
105
- ws.workspaceId = undefined;
106
- for (const stream of ws.streams ?? []) {
107
- stream.streamId = undefined;
108
- for (const dep of stream.deployments ?? []) {
109
- dep.deploymentId = undefined;
110
- }
111
- for (const raft of stream.rafts ?? []) {
112
- raft.raftId = undefined;
113
- }
114
- }
115
- }
116
- }
117
- /** Detect if config was copied from a different agent service and offer to clear all entity IDs. */
118
- export async function detectAndClearStaleIds(config, oldServiceId, newServiceId, promptFn) {
119
- if (!oldServiceId)
120
- return false;
121
- if (oldServiceId === newServiceId)
122
- return false;
123
- if (!configHasEntityIds(config))
124
- return false;
125
- const shouldClear = await promptFn(oldServiceId, newServiceId);
126
- if (shouldClear) {
127
- clearAllEntityIds(config);
128
- config.agentServiceId = newServiceId;
129
- log('Cleared all entity IDs. Deploying fresh.');
130
- return true;
131
- }
132
- return false;
133
- }
134
- function log(msg) {
135
- console.log(msg);
136
- }
137
- /** Resolve current agentServiceId (ROB data-service id) from ROB so config stays up to date. Run before creating API client. */
138
- async function resolveAgentServiceId(env, agentServicePubKey) {
139
- if (!env.robApiUrl?.trim())
140
- return undefined;
141
- try {
142
- const services = await listAgentServices(env.robApiUrl, env.authToken);
143
- const match = services.find((s) => s.publicKey === agentServicePubKey);
144
- return match?.id;
145
- }
146
- catch {
147
- return undefined;
148
- }
149
- }
150
- /** Fetch workspaces for this agent service, resolve workspaceId by name, and clear stale IDs. Run before any deploy commands. */
151
- async function resolveAndVerifyWorkspaces(ctx) {
152
- const workspaces = ctx.config.workspaces ?? [];
153
- if (workspaces.length === 0) {
154
- ctx.remoteWorkspaces = [];
155
- return;
156
- }
157
- if (ctx.dryRun) {
158
- ctx.remoteWorkspaces = [];
159
- return;
160
- }
161
- try {
162
- const res = await ctx.api.getWorkspaces();
163
- const list = (res.data ?? []).map((w) => ({
164
- workspaceId: w.workspaceId,
165
- name: w.name,
166
- }));
167
- ctx.remoteWorkspaces = list;
168
- if (list.length > 0) {
169
- log(`Verifying workspaces: found ${list.length} workspace(s) for this agent service.`);
170
- }
171
- const byId = new Map(list.map((w) => [w.workspaceId, w]));
172
- for (const workspace of workspaces) {
173
- const byName = list.filter((w) => w.name === workspace.name);
174
- if (byName.length === 1) {
175
- workspace.workspaceId = byName[0].workspaceId;
176
- log(` Resolved "${workspace.name}" → workspaceId: ${workspace.workspaceId}`);
177
- }
178
- else if (workspace.workspaceId && !byId.has(workspace.workspaceId)) {
179
- log(` Workspace "${workspace.name}" has workspaceId ${workspace.workspaceId} which is not in the orchestrator's workspace list for this agent service. Keeping existing ID (may have been created via ROB UI or another path).`);
180
- }
181
- if (!workspace.workspaceId) {
182
- const entered = await ctx.promptForWorkspaceId(workspace.name);
183
- if (entered) {
184
- workspace.workspaceId = entered;
185
- log(` Using workspaceId for "${workspace.name}": ${entered}`);
186
- }
187
- }
188
- }
189
- }
190
- catch (err) {
191
- const msg = err instanceof Error ? err.message : String(err);
192
- console.warn(`Warning: Could not fetch remote workspaces: ${msg}`);
193
- ctx.remoteWorkspaces = [];
194
- // Orchestrator may not support getWorkspaces; deployWorkspaceTree will handle prompt/create
195
- }
196
- }
197
- export function writeIdsBack(configPath, config) {
198
- const clean = JSON.parse(JSON.stringify(config));
199
- for (const eng of clean.engagements ?? []) {
200
- delete eng.tsCode;
201
- delete eng._resolvedFilePath;
202
- }
203
- for (const agent of clean.agents ?? []) {
204
- for (const task of agent.tasks ?? []) {
205
- delete task.tsCode;
206
- delete task._resolvedFilePath;
207
- }
208
- }
209
- // Cubbies have no transient fields to strip
210
- for (const ws of clean.workspaces ?? []) {
211
- for (const stream of ws.streams ?? []) {
212
- for (const raft of stream.rafts ?? []) {
213
- delete raft.tsCode;
214
- delete raft._resolvedFilePath;
215
- }
216
- }
217
- }
218
- const tmpPath = configPath + '.tmp';
219
- fs.writeFileSync(tmpPath, stringify(clean, { indent: 2 }));
220
- fs.renameSync(tmpPath, configPath);
221
- }
222
- async function deployEngagements(ctx, engagementIdMap) {
223
- for (const eng of ctx.config.engagements ?? []) {
224
- const payload = {
225
- agentServicePubKey: ctx.config.agentServicePubKey,
226
- name: eng.name,
227
- description: eng.description ?? '',
228
- version: eng.version ?? '1.0.0',
229
- conciergeAgent: {
230
- name: `Concierge for ${eng.name}`,
231
- description: `Orchestrates ${eng.name}`,
232
- tsCode: eng.tsCode ?? '',
233
- },
234
- };
235
- if (ctx.dryRun) {
236
- log(`[dry-run] Would ${eng.engagementId ? 'update' : 'create'} engagement: ${eng.name}`);
237
- ctx.results.push({ entity: 'engagement', name: eng.name, action: 'dry-run' });
238
- if (eng.engagementId)
239
- engagementIdMap.set(eng.name, eng.engagementId);
240
- continue;
241
- }
242
- if (eng.engagementId) {
243
- try {
244
- log(`Updating engagement: ${eng.name}`);
245
- await ctx.api.updateEngagement(eng.engagementId, payload);
246
- engagementIdMap.set(eng.name, eng.engagementId);
247
- ctx.results.push({ entity: 'engagement', name: eng.name, action: 'updated', id: eng.engagementId });
248
- }
249
- catch (err) {
250
- if (!isNotFoundError(err))
251
- throw err;
252
- const createCopy = await ctx.promptForCopy('engagement', eng.name);
253
- if (!createCopy) {
254
- throw new Error(`Engagement "${eng.name}" not found on this agent service. Remove engagementId from cef.config.yaml to create a new one, or use the correct agent service.`);
255
- }
256
- log(`Creating engagement: ${eng.name}`);
257
- const res = await ctx.api.createEngagement(payload);
258
- const id = extractId(res, 'engagementId', 'id', '_id');
259
- if (!id)
260
- log(`Warning: engagement created but no ID in response: ${JSON.stringify(res)}`);
261
- eng.engagementId = id;
262
- engagementIdMap.set(eng.name, id);
263
- ctx.results.push({ entity: 'engagement', name: eng.name, action: 'created', id });
264
- }
265
- }
266
- else {
267
- log(`Creating engagement: ${eng.name}`);
268
- const res = await ctx.api.createEngagement(payload);
269
- const id = extractId(res, 'engagementId', 'id', '_id');
270
- if (!id)
271
- log(`Warning: engagement created but no ID in response: ${JSON.stringify(res)}`);
272
- eng.engagementId = id;
273
- engagementIdMap.set(eng.name, id);
274
- ctx.results.push({ entity: 'engagement', name: eng.name, action: 'created', id });
275
- }
276
- }
277
- }
278
- async function deployAgents(ctx) {
279
- for (const agent of ctx.config.agents ?? []) {
280
- const tasks = agent.tasks.map(task => ({
281
- name: task.name,
282
- alias: task.alias,
283
- tsCode: task.tsCode ?? '',
284
- parameters: task.parameters ?? { properties: {}, type: 'object' },
285
- returns: task.returns ?? { properties: {}, type: 'object' },
286
- }));
287
- if (ctx.dryRun) {
288
- log(`[dry-run] Would ${agent.agentId ? 'update' : 'create'} agent: ${agent.name}`);
289
- ctx.results.push({ entity: 'agent', name: agent.name, action: 'dry-run' });
290
- continue;
291
- }
292
- if (agent.agentId) {
293
- try {
294
- log(`Updating agent: ${agent.name}`);
295
- await ctx.api.updateAgent(agent.agentId, { tasks });
296
- ctx.results.push({ entity: 'agent', name: agent.name, action: 'updated', id: agent.agentId });
297
- }
298
- catch (err) {
299
- if (!isNotFoundError(err))
300
- throw err;
301
- const createCopy = await ctx.promptForCopy('agent', agent.name);
302
- if (!createCopy) {
303
- throw new Error(`Agent "${agent.name}" not found on this agent service. Remove agentId from cef.config.yaml to create a new one, or use the correct agent service.`);
304
- }
305
- log(`Creating agent: ${agent.name}`);
306
- const res = await ctx.api.createAgent({
307
- agentServicePubKey: ctx.config.agentServicePubKey,
308
- name: agent.name,
309
- alias: agent.alias,
310
- description: agent.description ?? '',
311
- version: agent.version ?? '1.0.0',
312
- cid: `${PLACEHOLDER_CID_PREFIX}${Date.now()}`,
313
- tasks,
314
- });
315
- const id = extractId(res, 'agentId', 'id', '_id');
316
- agent.agentId = id;
317
- ctx.results.push({ entity: 'agent', name: agent.name, action: 'created', id });
318
- }
319
- }
320
- else {
321
- log(`Creating agent: ${agent.name}`);
322
- const res = await ctx.api.createAgent({
323
- agentServicePubKey: ctx.config.agentServicePubKey,
324
- name: agent.name,
325
- alias: agent.alias,
326
- description: agent.description ?? '',
327
- version: agent.version ?? '1.0.0',
328
- cid: `${PLACEHOLDER_CID_PREFIX}${Date.now()}`,
329
- tasks,
330
- });
331
- const id = extractId(res, 'agentId', 'id', '_id');
332
- agent.agentId = id;
333
- ctx.results.push({ entity: 'agent', name: agent.name, action: 'created', id });
334
- }
335
- }
336
- }
337
- async function deployCubbies(ctx) {
338
- for (const cubby of ctx.config.cubbies ?? []) {
339
- const isNew = !cubby.cubbyId;
340
- if (ctx.dryRun) {
341
- log(`[dry-run] Would ${isNew ? 'create' : 'update'} cubby: ${cubby.name}`);
342
- ctx.results.push({ entity: 'cubby', name: cubby.name, action: 'dry-run' });
343
- continue;
344
- }
345
- const payload = {
346
- alias: cubby.alias,
347
- name: cubby.name,
348
- description: cubby.description,
349
- migrations: cubby.migrations,
350
- maxSizeBytes: cubby.maxSizeBytes,
351
- idleTimeout: cubby.idleTimeout,
352
- };
353
- if (isNew) {
354
- log(`Creating cubby: ${cubby.name}`);
355
- const res = await ctx.api.createCubby(payload);
356
- const id = extractId(res, 'cubbyId', 'id');
357
- cubby.cubbyId = id;
358
- ctx.results.push({ entity: 'cubby', name: cubby.name, action: 'created', id });
359
- }
360
- else {
361
- log(`Updating cubby: ${cubby.name}`);
362
- await ctx.api.updateCubby(cubby.cubbyId, payload);
363
- ctx.results.push({ entity: 'cubby', name: cubby.name, action: 'updated', id: cubby.cubbyId });
364
- }
365
- }
366
- }
367
- async function deployWorkspaceTree(ctx, engagementIdMap, only) {
368
- const shouldRun = (entity) => !only || only === entity;
369
- for (const workspace of ctx.config.workspaces ?? []) {
370
- if (shouldRun('workspace')) {
371
- if (!workspace.workspaceId && !ctx.dryRun) {
372
- const entered = await ctx.promptForWorkspaceId(workspace.name);
373
- if (entered) {
374
- workspace.workspaceId = entered;
375
- log(`Using workspaceId for "${workspace.name}": ${entered}`);
376
- }
377
- }
378
- if (ctx.dryRun) {
379
- log(`[dry-run] Would ${workspace.workspaceId ? 'update' : 'create'} workspace: ${workspace.name}`);
380
- ctx.results.push({ entity: 'workspace', name: workspace.name, action: 'dry-run' });
381
- }
382
- else if (workspace.workspaceId) {
383
- try {
384
- log(`Updating workspace: ${workspace.name}`);
385
- await ctx.api.updateWorkspace(workspace.workspaceId, {
386
- agentServicePubKey: ctx.config.agentServicePubKey,
387
- name: workspace.name,
388
- description: workspace.description ?? '',
389
- workspaceId: workspace.workspaceId,
390
- });
391
- ctx.results.push({ entity: 'workspace', name: workspace.name, action: 'updated', id: workspace.workspaceId });
392
- }
393
- catch (err) {
394
- if (!isNotFoundError(err))
395
- throw err;
396
- const createCopy = await ctx.promptForCopy('workspace', workspace.name);
397
- if (!createCopy) {
398
- throw new Error(`Workspace "${workspace.name}" not found on this agent service. Remove workspaceId from cef.config.yaml to create a new one, or use the correct agent service.`);
399
- }
400
- log(`Creating workspace: ${workspace.name}`);
401
- const robId = await ctx.api.createWorkspaceOnRob(workspace.name);
402
- log(` ROB workspace registered (id: ${robId}), provisioning on orchestrator…`);
403
- await ctx.api.createWorkspace({
404
- agentServicePubKey: ctx.config.agentServicePubKey,
405
- name: workspace.name,
406
- description: workspace.description ?? '',
407
- workspaceId: robId,
408
- });
409
- workspace.workspaceId = robId;
410
- ctx.results.push({ entity: 'workspace', name: workspace.name, action: 'created', id: robId });
411
- }
412
- }
413
- else {
414
- log(`Creating workspace: ${workspace.name}`);
415
- const robId = await ctx.api.createWorkspaceOnRob(workspace.name);
416
- log(` ROB workspace registered (id: ${robId}), provisioning on orchestrator…`);
417
- await ctx.api.createWorkspace({
418
- agentServicePubKey: ctx.config.agentServicePubKey,
419
- name: workspace.name,
420
- description: workspace.description ?? '',
421
- workspaceId: robId,
422
- });
423
- workspace.workspaceId = robId;
424
- ctx.results.push({ entity: 'workspace', name: workspace.name, action: 'created', id: robId });
425
- }
426
- }
427
- const effectiveWorkspaceId = workspace.workspaceId;
428
- if (!effectiveWorkspaceId && !ctx.dryRun && (shouldRun('stream') || shouldRun('deployment'))) {
429
- throw new Error(`Workspace "${workspace.name}" has no workspaceId. ` +
430
- `Run a full deploy (or --only workspace) first to create it.`);
431
- }
432
- for (const stream of workspace.streams ?? []) {
433
- if (shouldRun('stream')) {
434
- const baseStreamPayload = {
435
- agentServicePubKey: ctx.config.agentServicePubKey,
436
- name: stream.name,
437
- description: stream.description ?? '',
438
- selectors: stream.selectors ?? [{ name: 'all', conditions: ['*'] }],
439
- };
440
- if (ctx.dryRun) {
441
- log(`[dry-run] Would ${stream.streamId ? 'update' : 'create'} stream: ${stream.name}`);
442
- ctx.results.push({ entity: 'stream', name: stream.name, action: 'dry-run' });
443
- }
444
- else if (stream.streamId) {
445
- try {
446
- log(`Updating stream: ${stream.name}`);
447
- await ctx.api.updateStream(stream.streamId, { ...baseStreamPayload, parentId: effectiveWorkspaceId });
448
- ctx.results.push({ entity: 'stream', name: stream.name, action: 'updated', id: stream.streamId });
449
- }
450
- catch (err) {
451
- if (!isNotFoundError(err))
452
- throw err;
453
- const createCopy = await ctx.promptForCopy('stream', stream.name);
454
- if (!createCopy) {
455
- throw new Error(`Stream "${stream.name}" not found on this agent service. Remove streamId from cef.config.yaml to create a new one, or use the correct agent service.`);
456
- }
457
- log(`Creating stream: ${stream.name}`);
458
- const res = await ctx.api.createStream(effectiveWorkspaceId, { ...baseStreamPayload, workspaceId: effectiveWorkspaceId });
459
- const id = extractId(res, 'streamId', 'id', '_id');
460
- stream.streamId = id;
461
- ctx.results.push({ entity: 'stream', name: stream.name, action: 'created', id });
462
- }
463
- }
464
- else {
465
- log(`Creating stream: ${stream.name}`);
466
- const res = await ctx.api.createStream(effectiveWorkspaceId, { ...baseStreamPayload, workspaceId: effectiveWorkspaceId });
467
- const id = extractId(res, 'streamId', 'id', '_id');
468
- stream.streamId = id;
469
- ctx.results.push({ entity: 'stream', name: stream.name, action: 'created', id });
470
- }
471
- }
472
- const effectiveStreamId = stream.streamId ?? '';
473
- // ─── Deploy rafts ───────────────────────────────────────────────────
474
- async function createRaftAndRegisterOnRob(raft, effectiveStreamId, raftPayload) {
475
- log(`Creating raft: ${raft.name}`);
476
- const res = await ctx.api.createRaft(effectiveStreamId, raftPayload);
477
- const id = extractId(res, 'raftId', 'id', '_id');
478
- raft.raftId = id;
479
- const robPayload = {
480
- raftId: id,
481
- streamId: effectiveStreamId,
482
- name: raft.name,
483
- description: raft.description,
484
- tsCode: raft.tsCode ?? '',
485
- dataSourcesIds: raft.dataSourcesIds,
486
- queryOperations: raft.queryOperations,
487
- };
488
- await ctx.api.registerRaftOnRob(robPayload);
489
- ctx.results.push({ entity: 'raft', name: raft.name, action: 'created', id });
490
- }
491
- for (const raft of stream.rafts ?? []) {
492
- if (!shouldRun('raft'))
493
- continue;
494
- const raftPayload = {
495
- alias: raft.name.replace(/[^a-zA-Z0-9_]/g, '_'),
496
- tsCode: raft.tsCode ?? '',
497
- };
498
- if (ctx.dryRun) {
499
- log(`[dry-run] Would ${raft.raftId ? 'update' : 'create'} raft: ${raft.name}`);
500
- ctx.results.push({ entity: 'raft', name: raft.name, action: 'dry-run' });
501
- }
502
- else if (raft.raftId) {
503
- try {
504
- log(`Updating raft: ${raft.name}`);
505
- await ctx.api.updateRaft(raft.raftId, raftPayload);
506
- await ctx.api.updateRaftOnRob({
507
- raftId: raft.raftId,
508
- streamId: effectiveStreamId,
509
- name: raft.name,
510
- description: raft.description,
511
- tsCode: raft.tsCode ?? '',
512
- dataSourcesIds: raft.dataSourcesIds,
513
- queryOperations: raft.queryOperations,
514
- });
515
- ctx.results.push({ entity: 'raft', name: raft.name, action: 'updated', id: raft.raftId });
516
- }
517
- catch (err) {
518
- if (!isNotFoundError(err))
519
- throw err;
520
- const createCopy = await ctx.promptForCopy('raft', raft.name);
521
- if (!createCopy) {
522
- throw new Error(`Raft "${raft.name}" not found on this agent service. Remove raftId from cef.config.yaml to create a new one, or use the correct agent service.`);
523
- }
524
- await createRaftAndRegisterOnRob(raft, effectiveStreamId, raftPayload);
525
- }
526
- }
527
- else {
528
- await createRaftAndRegisterOnRob(raft, effectiveStreamId, raftPayload);
529
- }
530
- }
531
- for (const deployment of stream.deployments ?? []) {
532
- if (!shouldRun('deployment'))
533
- continue;
534
- const resolvedEngagementId = engagementIdMap.get(deployment.engagement)
535
- ?? ctx.config.engagements?.find(e => e.name === deployment.engagement)?.engagementId
536
- ?? '';
537
- if (!resolvedEngagementId && !ctx.dryRun) {
538
- throw new Error(`Cannot resolve engagementId for deployment "${deployment.name}": ` +
539
- `engagement "${deployment.engagement}" not found or not yet deployed.`);
540
- }
541
- const deploymentPayload = {
542
- name: deployment.name,
543
- description: deployment.description ?? '',
544
- isActive: deployment.isActive ?? true,
545
- streamId: effectiveStreamId,
546
- engagements: [{ id: resolvedEngagementId, rules: deployment.engagementRules ?? [] }],
547
- triggers: deployment.triggers ?? [{ name: 'all-events', conditions: ['*'] }],
548
- };
549
- if (ctx.dryRun) {
550
- log(`[dry-run] Would ${deployment.deploymentId ? 'update' : 'create'} deployment: ${deployment.name}`);
551
- ctx.results.push({ entity: 'deployment', name: deployment.name, action: 'dry-run' });
552
- }
553
- else if (deployment.deploymentId) {
554
- try {
555
- log(`Updating deployment: ${deployment.name}`);
556
- await ctx.api.updateDeployment(deployment.deploymentId, {
557
- ...deploymentPayload,
558
- deploymentId: deployment.deploymentId,
559
- });
560
- ctx.results.push({ entity: 'deployment', name: deployment.name, action: 'updated', id: deployment.deploymentId });
561
- }
562
- catch (err) {
563
- if (!isNotFoundError(err))
564
- throw err;
565
- const createCopy = await ctx.promptForCopy('deployment', deployment.name);
566
- if (!createCopy) {
567
- throw new Error(`Deployment "${deployment.name}" not found on this agent service. Remove deploymentId from cef.config.yaml to create a new one, or use the correct agent service.`);
568
- }
569
- log(`Creating deployment: ${deployment.name}`);
570
- const res = await ctx.api.createDeployment(effectiveStreamId, deploymentPayload);
571
- const id = extractId(res, 'deploymentId', 'id', '_id');
572
- deployment.deploymentId = id;
573
- ctx.results.push({ entity: 'deployment', name: deployment.name, action: 'created', id });
574
- }
575
- }
576
- else {
577
- log(`Creating deployment: ${deployment.name}`);
578
- const res = await ctx.api.createDeployment(effectiveStreamId, deploymentPayload);
579
- const id = extractId(res, 'deploymentId', 'id', '_id');
580
- deployment.deploymentId = id;
581
- ctx.results.push({ entity: 'deployment', name: deployment.name, action: 'created', id });
582
- }
583
- }
584
- }
585
- }
586
- }
587
- export async function runDeploy(resolved, options) {
588
- const { config, env, configPath } = resolved;
589
- const { dryRun = false, only } = options;
590
- const typeErrors = typecheckAll(config);
591
- if (typeErrors.length > 0) {
592
- for (const e of typeErrors) {
593
- log(` TypeScript error ${e.file}:${e.line} — ${e.message}`);
594
- }
595
- throw new Error(`Type check failed with ${typeErrors.length} error(s). Fix before deploying.`);
596
- }
597
- const oldAgentServiceId = config.agentServiceId;
598
- const resolvedAgentServiceId = await resolveAgentServiceId(env, config.agentServicePubKey);
599
- if (resolvedAgentServiceId) {
600
- if (config.agentServiceId !== resolvedAgentServiceId) {
601
- log(`Resolved agentServiceId from ROB: ${resolvedAgentServiceId}`);
602
- }
603
- const promptForClearIds = options.promptForClearIds ?? defaultPromptForClearIds;
604
- await detectAndClearStaleIds(config, oldAgentServiceId, resolvedAgentServiceId, promptForClearIds);
605
- config.agentServiceId = resolvedAgentServiceId;
606
- }
607
- // Prefer fresh id from ROB; pass config.agentServiceId as fallback when listing data services fails (e.g. 403).
608
- const api = createApiClient(env, config.agentServicePubKey, config.agentServiceId);
609
- const results = [];
610
- const engagementIdMap = new Map();
611
- const shouldRun = (entity) => !only || only === entity;
612
- const promptForCopy = options.promptForCopy ?? defaultPromptForCopy;
613
- const promptForWorkspaceId = options.promptForWorkspaceId ?? defaultPromptForWorkspaceId;
614
- const ctx = {
615
- config,
616
- api,
617
- dryRun,
618
- results,
619
- promptForCopy,
620
- promptForWorkspaceId,
621
- configPath,
622
- remoteWorkspaces: [],
623
- };
624
- await resolveAndVerifyWorkspaces(ctx);
625
- // writeIdsBack is called after each entity type so that IDs are persisted
626
- // incrementally. If the process crashes mid-deploy, already-created IDs
627
- // are preserved in the config file for crash recovery.
628
- if (shouldRun('engagement')) {
629
- await deployEngagements(ctx, engagementIdMap);
630
- if (!dryRun)
631
- writeIdsBack(configPath, config);
632
- }
633
- if (shouldRun('agent')) {
634
- await deployAgents(ctx);
635
- if (!dryRun)
636
- writeIdsBack(configPath, config);
637
- }
638
- if (shouldRun('cubby')) {
639
- await deployCubbies(ctx);
640
- if (!dryRun)
641
- writeIdsBack(configPath, config);
642
- }
643
- await deployWorkspaceTree(ctx, engagementIdMap, only);
644
- if (!dryRun)
645
- writeIdsBack(configPath, config);
646
- if (!dryRun) {
647
- const resolvedSvcId = api.getResolvedAgentServiceId() ?? resolvedAgentServiceId;
648
- if (resolvedSvcId) {
649
- config.agentServiceId = resolvedSvcId;
650
- writeIdsBack(configPath, config);
651
- }
652
- }
653
- return results;
654
- }
@@ -1,2 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function registerDeployCommands(program: Command): void;