@cef-ai/cli 0.2.7 → 0.4.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 (153) 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-program.d.ts +14 -0
  27. package/dist/cli-program.d.ts.map +1 -0
  28. package/dist/cli-program.js +171 -0
  29. package/dist/cli-program.js.map +1 -0
  30. package/dist/cli.d.ts +2 -2
  31. package/dist/cli.d.ts.map +1 -0
  32. package/dist/cli.js +25 -65
  33. package/dist/cli.js.map +1 -0
  34. package/dist/commands/build.d.ts +41 -0
  35. package/dist/commands/build.d.ts.map +1 -0
  36. package/dist/commands/build.js +252 -0
  37. package/dist/commands/build.js.map +1 -0
  38. package/dist/commands/inspect.d.ts +49 -0
  39. package/dist/commands/inspect.d.ts.map +1 -0
  40. package/dist/commands/inspect.js +135 -0
  41. package/dist/commands/inspect.js.map +1 -0
  42. package/dist/commands/keypair.d.ts +21 -0
  43. package/dist/commands/keypair.d.ts.map +1 -0
  44. package/dist/commands/keypair.js +91 -0
  45. package/dist/commands/keypair.js.map +1 -0
  46. package/dist/commands/publish.d.ts +40 -0
  47. package/dist/commands/publish.d.ts.map +1 -0
  48. package/dist/commands/publish.js +187 -0
  49. package/dist/commands/publish.js.map +1 -0
  50. package/dist/commands/typegen.d.ts +36 -0
  51. package/dist/commands/typegen.d.ts.map +1 -0
  52. package/dist/commands/typegen.js +210 -0
  53. package/dist/commands/typegen.js.map +1 -0
  54. package/dist/index.d.ts +6 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +6 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/lib/cid.d.ts +3 -0
  59. package/dist/lib/cid.d.ts.map +1 -0
  60. package/dist/lib/cid.js +43 -0
  61. package/dist/lib/cid.js.map +1 -0
  62. package/dist/lib/credentials.d.ts +40 -16
  63. package/dist/lib/credentials.d.ts.map +1 -0
  64. package/dist/lib/credentials.js +222 -49
  65. package/dist/lib/credentials.js.map +1 -0
  66. package/dist/lib/jcs.d.ts +3 -0
  67. package/dist/lib/jcs.d.ts.map +1 -0
  68. package/dist/lib/jcs.js +48 -0
  69. package/dist/lib/jcs.js.map +1 -0
  70. package/dist/lib/signing.d.ts +13 -0
  71. package/dist/lib/signing.d.ts.map +1 -0
  72. package/dist/lib/signing.js +34 -0
  73. package/dist/lib/signing.js.map +1 -0
  74. package/dist/lib.d.ts +18 -0
  75. package/dist/lib.d.ts.map +1 -0
  76. package/dist/lib.js +12 -0
  77. package/dist/lib.js.map +1 -0
  78. package/dist/typegen/augment.d.ts +57 -0
  79. package/dist/typegen/augment.d.ts.map +1 -0
  80. package/dist/typegen/augment.js +87 -0
  81. package/dist/typegen/augment.js.map +1 -0
  82. package/dist/typegen/fetch.d.ts +30 -0
  83. package/dist/typegen/fetch.d.ts.map +1 -0
  84. package/dist/typegen/fetch.js +38 -0
  85. package/dist/typegen/fetch.js.map +1 -0
  86. package/dist/typegen/lockfile.d.ts +42 -0
  87. package/dist/typegen/lockfile.d.ts.map +1 -0
  88. package/dist/typegen/lockfile.js +58 -0
  89. package/dist/typegen/lockfile.js.map +1 -0
  90. package/dist/typegen/schema-to-ts.d.ts +21 -0
  91. package/dist/typegen/schema-to-ts.d.ts.map +1 -0
  92. package/dist/typegen/schema-to-ts.js +29 -0
  93. package/dist/typegen/schema-to-ts.js.map +1 -0
  94. package/package.json +23 -58
  95. package/dist/commands/auth/index.d.ts +0 -2
  96. package/dist/commands/auth/index.js +0 -162
  97. package/dist/commands/deploy/clone.d.ts +0 -13
  98. package/dist/commands/deploy/clone.js +0 -143
  99. package/dist/commands/deploy/delete.d.ts +0 -14
  100. package/dist/commands/deploy/delete.js +0 -134
  101. package/dist/commands/deploy/deploy.d.ts +0 -24
  102. package/dist/commands/deploy/deploy.js +0 -654
  103. package/dist/commands/deploy/index.d.ts +0 -2
  104. package/dist/commands/deploy/index.js +0 -216
  105. package/dist/commands/deploy/status.d.ts +0 -14
  106. package/dist/commands/deploy/status.js +0 -61
  107. package/dist/commands/dev/index.d.ts +0 -2
  108. package/dist/commands/dev/index.js +0 -134
  109. package/dist/commands/dev/server.d.ts +0 -14
  110. package/dist/commands/dev/server.js +0 -195
  111. package/dist/commands/dev/static/app.js +0 -633
  112. package/dist/commands/dev/static/index.html +0 -205
  113. package/dist/commands/dev/static/static/app.js +0 -633
  114. package/dist/commands/dev/static/static/index.html +0 -205
  115. package/dist/commands/dev/static/static/style.css +0 -184
  116. package/dist/commands/dev/static/style.css +0 -184
  117. package/dist/commands/playground/index.d.ts +0 -2
  118. package/dist/commands/playground/index.js +0 -75
  119. package/dist/commands/playground/test.d.ts +0 -15
  120. package/dist/commands/playground/test.js +0 -166
  121. package/dist/commands/service/index.d.ts +0 -2
  122. package/dist/commands/service/index.js +0 -89
  123. package/dist/lib/api.d.ts +0 -146
  124. package/dist/lib/api.js +0 -330
  125. package/dist/lib/config.d.ts +0 -12
  126. package/dist/lib/config.js +0 -145
  127. package/dist/lib/runtime/agent-router.d.ts +0 -12
  128. package/dist/lib/runtime/agent-router.js +0 -67
  129. package/dist/lib/runtime/context-builder.d.ts +0 -27
  130. package/dist/lib/runtime/context-builder.js +0 -166
  131. package/dist/lib/runtime/cubby-manager.d.ts +0 -20
  132. package/dist/lib/runtime/cubby-manager.js +0 -162
  133. package/dist/lib/runtime/index.d.ts +0 -51
  134. package/dist/lib/runtime/index.js +0 -181
  135. package/dist/lib/runtime/log-collector.d.ts +0 -17
  136. package/dist/lib/runtime/log-collector.js +0 -61
  137. package/dist/lib/runtime/stream-manager.d.ts +0 -10
  138. package/dist/lib/runtime/stream-manager.js +0 -77
  139. package/dist/lib/runtime/types.d.ts +0 -76
  140. package/dist/lib/runtime/types.js +0 -2
  141. package/dist/lib/transpile.d.ts +0 -1
  142. package/dist/lib/transpile.js +0 -9
  143. package/dist/lib/typecheck.d.ts +0 -31
  144. package/dist/lib/typecheck.js +0 -175
  145. package/dist/lib/types.d.ts +0 -246
  146. package/dist/lib/types.js +0 -2
  147. package/dist/lib/utils.d.ts +0 -4
  148. package/dist/lib/utils.js +0 -33
  149. package/example/.env.example +0 -6
  150. package/example/agents/object-detection/tasks/yolo.ts +0 -28
  151. package/example/agents/parking-violation-detector/tasks/detect.ts +0 -326
  152. package/example/cef.config.yaml +0 -91
  153. package/example/engagements/engagement.ts +0 -902
package/package.json CHANGED
@@ -1,70 +1,35 @@
1
1
  {
2
2
  "name": "@cef-ai/cli",
3
- "version": "0.2.7",
4
- "description": "CEF AI command-line interface",
3
+ "version": "0.4.0",
5
4
  "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
6
7
  "bin": {
7
- "cef": "dist/cli.js",
8
- "cef-deploy": "dist/cli.js"
8
+ "cef": "./dist/cli.js"
9
9
  },
10
10
  "files": [
11
- "dist/",
12
- "README.md",
13
- "example/agents",
14
- "example/engagements",
15
- "example/queries",
16
- "example/.env.example",
17
- "example/cef.config.yaml"
11
+ "dist"
18
12
  ],
19
- "repository": {
20
- "type": "git",
21
- "url": "https://github.com/CEF-AI/deploy-sdk"
22
- },
23
- "homepage": "https://github.com/CEF-AI/deploy-sdk#readme",
24
- "keywords": [
25
- "cef",
26
- "cef-ai",
27
- "deploy",
28
- "cli",
29
- "cere"
30
- ],
31
- "scripts": {
32
- "build": "tsc && cp -r src/commands/dev/static dist/commands/dev/static",
33
- "prepublishOnly": "npm run build",
34
- "test": "vitest run",
35
- "test:watch": "vitest",
36
- "test:coverage": "vitest run --coverage",
37
- "test:integration": "vitest run --config vitest.integration.config.ts",
38
- "test:e2e": "vitest run --config vitest.e2e.config.ts",
39
- "typecheck": "tsc --noEmit",
40
- "lint": "eslint src tests",
41
- "dev": "tsx src/cli.ts"
13
+ "publishConfig": {
14
+ "access": "public"
42
15
  },
43
16
  "dependencies": {
44
- "better-sqlite3": "^12.8.0",
45
- "esbuild": "^0.25.0",
46
- "chalk": "^5.6.2",
47
- "commander": "^14.0.3",
48
- "dotenv": "^16.4.5",
49
- "ora": "^9.3.0",
50
- "sqlite-vec": "^0.1.9",
51
- "typescript": "^5.4.5",
52
- "ws": "^8.20.0",
53
- "yaml": "^2.8.3"
17
+ "@noble/ed25519": "^2.1.0",
18
+ "@noble/hashes": "^2.2.0",
19
+ "canonicalize": "^3.0.0",
20
+ "commander": "^12.0.0",
21
+ "esbuild": "^0.21.0",
22
+ "json-schema-to-typescript": "^14.0.0",
23
+ "typescript": "^5.4.0",
24
+ "@cef-ai/agent-sdk": "0.1.0"
54
25
  },
55
26
  "devDependencies": {
56
- "@eslint/js": "^9.15.0",
57
- "@types/better-sqlite3": "^7.6.13",
58
- "@types/node": "^20.14.0",
59
- "@types/ws": "^8.18.1",
60
- "@vitest/coverage-v8": "^4.1.0",
61
- "eslint": "^9.15.0",
62
- "tsx": "^4.15.7",
63
- "typescript-eslint": "^8.15.0",
64
- "vitest": "^4.1.0"
27
+ "@types/node": "^20.11.0",
28
+ "vitest": "^1.5.0"
65
29
  },
66
- "engines": {
67
- "node": ">=18.0.0"
68
- },
69
- "license": "Apache-2.0"
70
- }
30
+ "scripts": {
31
+ "build": "tsc -b && chmod +x dist/cli.js",
32
+ "test": "vitest run",
33
+ "lint": "eslint src"
34
+ }
35
+ }
@@ -1,2 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function registerAuthCommands(program: Command): void;
@@ -1,162 +0,0 @@
1
- import http from 'http';
2
- import { exec } from 'child_process';
3
- import { saveCredentials, loadCredentials, clearCredentials, parseToken, getCredentialsPath, } from '../../lib/credentials.js';
4
- const DEFAULT_ROB_URL = 'https://rob.compute.test.ddcdragon.com';
5
- const LOGIN_TIMEOUT_MS = 300_000;
6
- function openBrowser(url) {
7
- const cmd = process.platform === 'darwin'
8
- ? `open "${url}"`
9
- : process.platform === 'win32'
10
- ? `start "" "${url}"`
11
- : `xdg-open "${url}"`;
12
- exec(cmd, (err) => {
13
- if (err) {
14
- console.log(` Could not open browser automatically.`);
15
- console.log(` Open this URL manually:\n ${url}\n`);
16
- }
17
- });
18
- }
19
- function saveAndPrint(token) {
20
- const parsed = parseToken(token);
21
- if (!parsed) {
22
- console.error(' Error: Invalid token format. Expected: base64.base64.signature');
23
- process.exit(1);
24
- }
25
- const expiresAt = new Date(parsed.expiresAt).getTime();
26
- if (expiresAt <= Date.now()) {
27
- console.error(' Error: Token is already expired.');
28
- process.exit(1);
29
- }
30
- saveCredentials({
31
- email: parsed.email,
32
- publicKey: parsed.publicKey,
33
- token,
34
- expiresAt: parsed.expiresAt,
35
- });
36
- const expiresIn = Math.round((expiresAt - Date.now()) / 3600000);
37
- console.log(`\n Logged in as ${parsed.email}`);
38
- console.log(` Token expires in ~${expiresIn}h`);
39
- console.log(` Credentials saved to ${getCredentialsPath()}\n`);
40
- }
41
- function loginWithCallback(robUrl) {
42
- return new Promise((resolve, reject) => {
43
- let port = 0;
44
- const server = http.createServer((req, res) => {
45
- // CORS preflight
46
- if (req.method === 'OPTIONS') {
47
- res.writeHead(204, {
48
- 'Access-Control-Allow-Origin': '*',
49
- 'Access-Control-Allow-Methods': 'POST',
50
- 'Access-Control-Allow-Headers': 'Content-Type',
51
- });
52
- res.end();
53
- return;
54
- }
55
- if (req.method === 'POST' && req.url === '/callback') {
56
- let body = '';
57
- req.on('data', (chunk) => { body += chunk; });
58
- req.on('end', () => {
59
- try {
60
- const { token } = JSON.parse(body);
61
- if (!token)
62
- throw new Error('Missing token');
63
- res.writeHead(200, {
64
- 'Content-Type': 'application/json',
65
- 'Access-Control-Allow-Origin': '*',
66
- });
67
- res.end(JSON.stringify({ ok: true }));
68
- saveAndPrint(token);
69
- server.close();
70
- resolve();
71
- }
72
- catch {
73
- res.writeHead(400, {
74
- 'Content-Type': 'application/json',
75
- 'Access-Control-Allow-Origin': '*',
76
- });
77
- res.end(JSON.stringify({ error: 'Invalid request' }));
78
- }
79
- });
80
- return;
81
- }
82
- res.writeHead(404);
83
- res.end();
84
- });
85
- server.on('error', (err) => {
86
- reject(err);
87
- });
88
- server.listen(0, '127.0.0.1', () => {
89
- const addr = server.address();
90
- port = typeof addr === 'object' ? addr.port : 0;
91
- const authUrl = `${robUrl}/#/cli-auth?port=${port}`;
92
- console.log(`\n Opening browser for authentication...`);
93
- console.log(` If the browser doesn't open, visit:\n ${authUrl}\n`);
94
- console.log(` Waiting for login...`);
95
- openBrowser(authUrl);
96
- });
97
- const timeout = setTimeout(() => {
98
- server.close();
99
- reject(new Error('Login timed out. Try again with: cef login'));
100
- }, LOGIN_TIMEOUT_MS);
101
- server.on('close', () => clearTimeout(timeout));
102
- });
103
- }
104
- async function handleLogin(opts) {
105
- if (opts.token) {
106
- saveAndPrint(opts.token);
107
- return;
108
- }
109
- await loginWithCallback(DEFAULT_ROB_URL);
110
- }
111
- function handleLogout() {
112
- const cleared = clearCredentials();
113
- if (cleared) {
114
- console.log('\n Logged out. Credentials cleared.\n');
115
- }
116
- else {
117
- console.log('\n Not logged in (no credentials found).\n');
118
- }
119
- }
120
- function handleWhoami() {
121
- const creds = loadCredentials();
122
- if (!creds) {
123
- console.log('\n Not logged in. Run `cef login` to authenticate.\n');
124
- return;
125
- }
126
- const expiresAt = new Date(creds.expiresAt);
127
- const msLeft = expiresAt.getTime() - Date.now();
128
- const hoursLeft = Math.max(0, Math.round(msLeft / 3600000));
129
- const minutesLeft = Math.max(0, Math.round(msLeft / 60000));
130
- console.log(`\n Email: ${creds.email}`);
131
- console.log(` Public Key: ${creds.publicKey}`);
132
- if (minutesLeft < 60) {
133
- console.log(` Expires in: ${minutesLeft} minutes`);
134
- }
135
- else {
136
- console.log(` Expires in: ~${hoursLeft} hours`);
137
- }
138
- console.log(` Stored at: ${getCredentialsPath()}\n`);
139
- }
140
- export function registerAuthCommands(program) {
141
- program
142
- .command('login')
143
- .description('Authenticate with CEF platform')
144
- .option('--token <token>', 'Manually provide a bearer token')
145
- .action(async (opts) => {
146
- try {
147
- await handleLogin(opts);
148
- }
149
- catch (err) {
150
- console.error(`\n Login failed: ${err.message}\n`);
151
- process.exit(1);
152
- }
153
- });
154
- program
155
- .command('logout')
156
- .description('Clear stored credentials')
157
- .action(() => handleLogout());
158
- program
159
- .command('whoami')
160
- .description('Show current authentication status')
161
- .action(() => handleWhoami());
162
- }
@@ -1,13 +0,0 @@
1
- import type { EnvConfig } from '../../lib/types.js';
2
- export interface CloneOptions {
3
- pubkey: string;
4
- outputDir: string;
5
- force: boolean;
6
- }
7
- export interface CloneResult {
8
- entity: string;
9
- name: string;
10
- action: 'written' | 'skipped' | 'fetched';
11
- file?: string;
12
- }
13
- export declare function runClone(env: EnvConfig, options: CloneOptions): Promise<CloneResult[]>;
@@ -1,143 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { stringify } from 'yaml';
4
- import { createApiClient } from '../../lib/api.js';
5
- import { toFileName, errorMessage } from '../../lib/utils.js';
6
- function writeFileIfAllowed(filePath, content, force, allowedBase) {
7
- if (allowedBase) {
8
- const resolved = path.resolve(filePath);
9
- const base = path.resolve(allowedBase);
10
- if (!resolved.startsWith(base + path.sep) && resolved !== base) {
11
- throw new Error(`Path traversal detected: ${filePath} escapes ${allowedBase}`);
12
- }
13
- }
14
- if (fs.existsSync(filePath) && !force)
15
- return 'skipped';
16
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
17
- fs.writeFileSync(filePath, content, 'utf8');
18
- return 'written';
19
- }
20
- async function safeFetch(label, fn) {
21
- try {
22
- return await fn();
23
- }
24
- catch (err) {
25
- console.warn(`Warning: Could not fetch ${label}: ${errorMessage(err)}`);
26
- return null;
27
- }
28
- }
29
- export async function runClone(env, options) {
30
- const { pubkey, outputDir, force } = options;
31
- const api = createApiClient(env, pubkey);
32
- const results = [];
33
- // Fetch in parallel
34
- const [engagementsRes, agentsRes, ontologyRes, cubbiesRes] = await Promise.all([
35
- safeFetch('engagements', () => api.getEngagements()),
36
- safeFetch('agents', () => api.getAgents()),
37
- safeFetch('ontology', () => api.getOntology()),
38
- safeFetch('cubbies', () => api.getCubbies()),
39
- ]);
40
- const allAgents = agentsRes?.data ?? [];
41
- const engagements = engagementsRes?.data ?? [];
42
- // Separate concierge agents from user agents
43
- const conciergeMap = new Map(allAgents.filter(a => a.isConcierge).map(a => [a.agentId, a]));
44
- const userAgents = allAgents.filter(a => !a.isConcierge);
45
- // ─── Write engagement files ────────────────────────────────────────────
46
- const engagementConfigs = engagements.map(eng => {
47
- const concierge = conciergeMap.get(eng.conciergeAgentId);
48
- const tsCode = concierge?.tasks[0]?.tsCode ?? '';
49
- let fileName = `${toFileName(eng.name)}.ts`;
50
- if (fileName === 'unknown.ts')
51
- fileName = `unknown-${eng.engagementId}.ts`;
52
- const relPath = `./engagements/${fileName}`;
53
- const absPath = path.join(outputDir, 'engagements', fileName);
54
- if (tsCode) {
55
- const action = writeFileIfAllowed(absPath, tsCode, force, outputDir);
56
- results.push({ entity: 'engagement', name: eng.name, action, file: relPath });
57
- }
58
- return {
59
- name: eng.name,
60
- description: eng.description || undefined,
61
- engagementId: eng.engagementId,
62
- file: relPath,
63
- version: eng.version || '1.0.0',
64
- };
65
- });
66
- // ─── Write agent task files ────────────────────────────────────────────
67
- const agentConfigs = userAgents.map(agent => {
68
- const tasks = agent.tasks.map(task => {
69
- let taskFileName = `${toFileName(task.alias)}.ts`;
70
- if (taskFileName === 'unknown.ts')
71
- taskFileName = `unknown-${task.id}.ts`;
72
- const relPath = `./agents/${agent.alias}/tasks/${taskFileName}`;
73
- const absPath = path.join(outputDir, 'agents', agent.alias, 'tasks', taskFileName);
74
- if (task.tsCode) {
75
- const action = writeFileIfAllowed(absPath, task.tsCode, force, outputDir);
76
- results.push({ entity: 'agent-task', name: `${agent.name}/${task.name}`, action, file: relPath });
77
- }
78
- return {
79
- name: task.name,
80
- alias: task.alias,
81
- file: relPath,
82
- parameters: task.parameters,
83
- returns: task.returns,
84
- };
85
- });
86
- return {
87
- name: agent.name,
88
- alias: agent.alias,
89
- description: agent.description || undefined,
90
- agentId: agent.agentId,
91
- version: agent.version || '1.0.0',
92
- tasks,
93
- };
94
- });
95
- // ─── Map ontology to workspace config ──────────────────────────────────
96
- const workspaceConfigs = ontologyRes?.workspaces?.map(ws => ({
97
- name: ws.name,
98
- description: ws.description || undefined,
99
- workspaceId: ws.workspaceId,
100
- streams: ws.streams?.map(s => ({
101
- name: s.name,
102
- description: s.description || undefined,
103
- streamId: s.streamId,
104
- selectors: s.selectors?.length ? s.selectors : undefined,
105
- deployments: s.deployments?.map(d => ({
106
- name: d.name,
107
- description: d.description || undefined,
108
- deploymentId: d.deploymentId,
109
- engagement: d.engagements?.[0]?.name ?? '',
110
- isActive: d.isActive,
111
- triggers: d.triggers?.length ? d.triggers : undefined,
112
- })),
113
- })),
114
- }));
115
- // ─── Map remote cubbies to config ───────────────────────────────────────
116
- const remoteCubbies = cubbiesRes ?? [];
117
- const cubbyConfigs = remoteCubbies.map(cubby => ({
118
- alias: cubby.alias,
119
- name: cubby.name,
120
- description: cubby.description || undefined,
121
- cubbyId: cubby.cubbyId,
122
- migrations: cubby.migrations,
123
- maxSizeBytes: cubby.maxSizeBytes,
124
- idleTimeout: cubby.idleTimeout,
125
- }));
126
- // ─── Build config ──────────────────────────────────────────────────────
127
- const config = {
128
- agentServicePubKey: pubkey,
129
- };
130
- if (engagementConfigs.length)
131
- config.engagements = engagementConfigs;
132
- if (agentConfigs.length)
133
- config.agents = agentConfigs;
134
- if (cubbyConfigs.length)
135
- config.cubbies = cubbyConfigs;
136
- if (workspaceConfigs && workspaceConfigs.length)
137
- config.workspaces = workspaceConfigs;
138
- // Write config file (respects --force)
139
- const configPath = path.join(outputDir, 'cef.config.yaml');
140
- const configAction = writeFileIfAllowed(configPath, stringify(config), force);
141
- results.push({ entity: 'config', name: 'cef.config.yaml', action: configAction, file: configPath });
142
- return results;
143
- }
@@ -1,14 +0,0 @@
1
- import type { ResolvedConfig } from '../../lib/types.js';
2
- export interface DeleteResult {
3
- entity: string;
4
- name: string;
5
- id: string;
6
- action: 'deleted' | 'skipped' | 'failed';
7
- error?: string;
8
- }
9
- interface DeleteOptions {
10
- only?: string;
11
- force?: boolean;
12
- }
13
- export declare function runDelete(resolved: ResolvedConfig, options: DeleteOptions): Promise<DeleteResult[]>;
14
- export {};
@@ -1,134 +0,0 @@
1
- import readline from 'readline/promises';
2
- import { createApiClient } from '../../lib/api.js';
3
- import { writeIdsBack } from './deploy.js';
4
- import { errorMessage } from '../../lib/utils.js';
5
- function collectEntitiesToDelete(config, api) {
6
- const entities = [];
7
- // Reverse dependency order: deployments -> rafts -> streams -> workspaces -> agents -> engagements
8
- for (const ws of config.workspaces ?? []) {
9
- for (const stream of ws.streams ?? []) {
10
- for (const dep of stream.deployments ?? []) {
11
- if (dep.deploymentId) {
12
- entities.push({
13
- entity: 'deployment',
14
- name: dep.name,
15
- id: dep.deploymentId,
16
- deleteFn: () => api.deleteDeployment(dep.deploymentId),
17
- clearId: () => { dep.deploymentId = undefined; },
18
- });
19
- }
20
- }
21
- for (const raft of stream.rafts ?? []) {
22
- if (raft.raftId) {
23
- entities.push({
24
- entity: 'raft',
25
- name: raft.name,
26
- id: raft.raftId,
27
- deleteFn: () => api.deleteRaft(raft.raftId),
28
- clearId: () => { raft.raftId = undefined; },
29
- });
30
- }
31
- }
32
- if (stream.streamId) {
33
- entities.push({
34
- entity: 'stream',
35
- name: stream.name,
36
- id: stream.streamId,
37
- deleteFn: () => api.deleteStream(stream.streamId),
38
- clearId: () => { stream.streamId = undefined; },
39
- });
40
- }
41
- }
42
- if (ws.workspaceId) {
43
- entities.push({
44
- entity: 'workspace',
45
- name: ws.name,
46
- id: ws.workspaceId,
47
- deleteFn: () => api.deleteWorkspace(ws.workspaceId),
48
- clearId: () => { ws.workspaceId = undefined; },
49
- });
50
- }
51
- }
52
- for (const agent of config.agents ?? []) {
53
- if (agent.agentId) {
54
- entities.push({
55
- entity: 'agent',
56
- name: agent.name,
57
- id: agent.agentId,
58
- deleteFn: () => api.deleteAgent(agent.agentId),
59
- clearId: () => { agent.agentId = undefined; },
60
- });
61
- }
62
- }
63
- for (const eng of config.engagements ?? []) {
64
- if (eng.engagementId) {
65
- entities.push({
66
- entity: 'engagement',
67
- name: eng.name,
68
- id: eng.engagementId,
69
- deleteFn: () => api.deleteEngagement(eng.engagementId),
70
- clearId: () => { eng.engagementId = undefined; },
71
- });
72
- }
73
- }
74
- return entities;
75
- }
76
- async function confirmDelete(count, pubkey) {
77
- if (!process.stdin.isTTY || !process.stdout.isTTY) {
78
- throw new Error(`Cannot confirm deletion of ${count} entities in non-interactive mode. Use --force to skip confirmation.`);
79
- }
80
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
81
- try {
82
- const answer = await rl.question(`Delete ${count} entity/entities from agent service ${pubkey}? This cannot be undone. (y/n) `);
83
- return /^y(es)?$/i.test((answer ?? '').trim());
84
- }
85
- finally {
86
- rl.close();
87
- }
88
- }
89
- export async function runDelete(resolved, options) {
90
- const { config, env, configPath } = resolved;
91
- const api = createApiClient(env, config.agentServicePubKey, config.agentServiceId);
92
- let entities = collectEntitiesToDelete(config, api);
93
- if (options.only) {
94
- entities = entities.filter(e => e.entity === options.only);
95
- }
96
- // Warn about cubbies that cannot be deleted via CLI
97
- for (const cubby of config.cubbies ?? []) {
98
- if (cubby.cubbyId && (!options.only || options.only === 'cubby')) {
99
- console.warn(`Warning: cubby "${cubby.name}" cannot be deleted via CLI. Remove manually if needed.`);
100
- }
101
- }
102
- if (entities.length === 0) {
103
- console.log('No entities with IDs to delete.');
104
- return [];
105
- }
106
- console.log(`\nEntities to delete (${entities.length}):`);
107
- for (const e of entities) {
108
- console.log(` ${e.entity}: ${e.name} (${e.id})`);
109
- }
110
- if (!options.force) {
111
- const confirmed = await confirmDelete(entities.length, config.agentServicePubKey);
112
- if (!confirmed) {
113
- console.log('Cancelled.');
114
- return entities.map(e => ({ entity: e.entity, name: e.name, id: e.id, action: 'skipped' }));
115
- }
116
- }
117
- const results = [];
118
- for (const e of entities) {
119
- try {
120
- console.log(`Deleting ${e.entity}: ${e.name} (${e.id})`);
121
- await e.deleteFn();
122
- e.clearId();
123
- results.push({ entity: e.entity, name: e.name, id: e.id, action: 'deleted' });
124
- }
125
- catch (err) {
126
- const msg = errorMessage(err);
127
- console.error(` Failed to delete ${e.entity} "${e.name}": ${msg}`);
128
- results.push({ entity: e.entity, name: e.name, id: e.id, action: 'failed', error: msg });
129
- }
130
- }
131
- // Write cleaned config (IDs removed for successfully deleted entities)
132
- writeIdsBack(configPath, config);
133
- return results;
134
- }
@@ -1,24 +0,0 @@
1
- import type { ResolvedConfig, DeployResult, CefConfig } from '../../lib/types.js';
2
- export type PromptForCopyEntity = 'engagement' | 'agent' | 'workspace' | 'stream' | 'deployment' | 'raft';
3
- export type PromptForCopy = (entity: PromptForCopyEntity, name: string) => Promise<boolean>;
4
- /** Return workspace ID for this agent service, or undefined to create new. */
5
- export type PromptForWorkspaceId = (workspaceName: string) => Promise<string | undefined>;
6
- /** Called when config.agentServiceId doesn't match the resolved ID from ROB, indicating the config was likely copied from another service. Return true to clear all entity IDs and deploy fresh. */
7
- export type PromptForClearIds = (oldServiceId: string, newServiceId: string) => Promise<boolean>;
8
- interface DeployOptions {
9
- dryRun?: boolean;
10
- only?: string;
11
- /** When update returns 404 (e.g. ID from another agent service), call this to ask if we should create a copy. Default: interactive y/n when TTY, else throw. */
12
- promptForCopy?: PromptForCopy;
13
- /** When workspace has no workspaceId and we can't resolve it from the orchestrator, call this. Return ID or undefined to create new. Default: interactive prompt when TTY. */
14
- promptForWorkspaceId?: PromptForWorkspaceId;
15
- /** When agentServiceId mismatch is detected (config copied from another service), call this to ask if all entity IDs should be cleared. Default: interactive y/n when TTY, else throw. */
16
- promptForClearIds?: PromptForClearIds;
17
- }
18
- /** Strip all entity IDs from config so everything deploys as new. */
19
- export declare function clearAllEntityIds(config: CefConfig): void;
20
- /** Detect if config was copied from a different agent service and offer to clear all entity IDs. */
21
- export declare function detectAndClearStaleIds(config: CefConfig, oldServiceId: string | undefined, newServiceId: string, promptFn: PromptForClearIds): Promise<boolean>;
22
- export declare function writeIdsBack(configPath: string, config: CefConfig): void;
23
- export declare function runDeploy(resolved: ResolvedConfig, options: DeployOptions): Promise<DeployResult[]>;
24
- export {};