@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
package/dist/lib/api.js DELETED
@@ -1,330 +0,0 @@
1
- import crypto from 'crypto';
2
- // ROB error message fragments (for consistent handling and easier maintenance)
3
- const ROB_HTTP_FORBIDDEN = '403';
4
- const ROB_MSG_FORBIDDEN = 'Forbidden';
5
- const ROB_HTTP_CONFLICT = '409';
6
- const ROB_MSG_ALREADY_EXISTS = 'already exists';
7
- async function fetchJson(url, init) {
8
- let res;
9
- try {
10
- res = await fetch(url, {
11
- ...init,
12
- signal: AbortSignal.timeout(30_000),
13
- });
14
- }
15
- catch (err) {
16
- const cause = err?.cause?.message ?? err?.cause ?? err?.message ?? String(err);
17
- throw new Error(`Network error calling ${url}: ${cause}`);
18
- }
19
- if (!res.ok) {
20
- const body = await res.text();
21
- throw new Error(`HTTP ${res.status} ${res.statusText} (${url}): ${body}`);
22
- }
23
- const text = await res.text();
24
- if (!text)
25
- return {};
26
- try {
27
- return JSON.parse(text);
28
- }
29
- catch (err) {
30
- const msg = err instanceof Error ? err.message : String(err);
31
- throw new Error(`Invalid JSON from ${url}: ${msg}`);
32
- }
33
- }
34
- async function request(url, init) {
35
- return fetchJson(url, init);
36
- }
37
- async function requestAs(url, init) {
38
- return fetchJson(url, init);
39
- }
40
- export function createApiClient(env, asPubKey, agentServiceId) {
41
- const base = `${env.orchestratorUrl}/api/v1/agent-services/${asPubKey}`;
42
- const headers = {
43
- 'Content-Type': 'application/json',
44
- Authorization: `Bearer ${env.authToken}`,
45
- };
46
- function post(url, body) {
47
- return request(url, { method: 'POST', headers, body: JSON.stringify(body) });
48
- }
49
- function put(url, body) {
50
- return request(url, { method: 'PUT', headers, body: JSON.stringify(body) });
51
- }
52
- function get(url) {
53
- return requestAs(url, { method: 'GET', headers });
54
- }
55
- function del(url) {
56
- return request(url, { method: 'DELETE', headers });
57
- }
58
- let cachedServiceId = undefined;
59
- const fallbackServiceId = agentServiceId;
60
- function getRobHeaders() {
61
- let robOrigin = env.robOrigin;
62
- if (!robOrigin) {
63
- const match = env.robApiUrl.match(/api\.rob\.(\w+)\.cere\.io/);
64
- if (match)
65
- robOrigin = `https://rob.${match[1]}.cere.io`;
66
- }
67
- return { ...headers, ...(robOrigin && { Origin: robOrigin, Referer: `${robOrigin}/` }) };
68
- }
69
- async function requireServiceId() {
70
- if (cachedServiceId)
71
- return cachedServiceId;
72
- if (!env.robApiUrl)
73
- throw new Error('CEF_ROB_API_URL is required for this operation');
74
- try {
75
- const services = await listAgentServices(env.robApiUrl, env.authToken);
76
- const match = services.find(s => s.publicKey === asPubKey);
77
- if (!match) {
78
- throw new Error(`No agent service found with publicKey ${asPubKey}. ` +
79
- `Run \`npx tsx src/cli.ts services\` to see available services.`);
80
- }
81
- cachedServiceId = match.id;
82
- return cachedServiceId;
83
- }
84
- catch (err) {
85
- if (fallbackServiceId) {
86
- const msg = err instanceof Error ? err.message : String(err);
87
- console.warn(`[ROB] Could not list data services (${msg}). Using agentServiceId from config: ${fallbackServiceId}`);
88
- cachedServiceId = fallbackServiceId;
89
- return fallbackServiceId;
90
- }
91
- throw err;
92
- }
93
- }
94
- return {
95
- getResolvedAgentServiceId() {
96
- return cachedServiceId;
97
- },
98
- // ─── Engagement ───────────────────────────────────────────────────────
99
- createEngagement(payload) {
100
- return post(`${base}/engagements`, payload);
101
- },
102
- updateEngagement(engagementId, payload) {
103
- return put(`${base}/engagements/${engagementId}`, payload);
104
- },
105
- // ─── Agent ───────────────────────────────────────────────────────────
106
- createAgent(payload) {
107
- return post(`${base}/agents`, payload);
108
- },
109
- updateAgent(agentId, payload) {
110
- return put(`${base}/agents/${agentId}`, payload);
111
- },
112
- // ─── Workspace ────────────────────────────────────────────────────────
113
- async createWorkspaceOnRob(name) {
114
- const svcId = await requireServiceId();
115
- const url = `${env.robApiUrl.replace(/\/$/, '')}/data-services/${svcId}/organizations`;
116
- const res = await request(url, {
117
- method: 'POST',
118
- headers: getRobHeaders(),
119
- body: JSON.stringify({ name }),
120
- });
121
- const data = (res.data ?? res);
122
- const id = String(data.id ?? '');
123
- if (!id)
124
- throw new Error(`ROB workspace created but no ID in response: ${JSON.stringify(res)}`);
125
- return id;
126
- },
127
- createWorkspace(payload) {
128
- return post(`${base}/workspaces`, payload);
129
- },
130
- updateWorkspace(workspaceId, payload) {
131
- return put(`${base}/workspaces/${workspaceId}`, payload);
132
- },
133
- getWorkspaces() {
134
- return get(`${base}/workspaces`);
135
- },
136
- // ─── Stream ───────────────────────────────────────────────────────────
137
- createStream(workspaceId, payload) {
138
- return post(`${base}/workspaces/${workspaceId}/streams`, payload);
139
- },
140
- updateStream(streamId, payload) {
141
- return put(`${base}/streams/${streamId}`, payload);
142
- },
143
- // ─── Deployment ───────────────────────────────────────────────────────
144
- createDeployment(streamId, payload) {
145
- return post(`${base}/streams/${streamId}/deployments`, payload);
146
- },
147
- updateDeployment(deploymentId, payload) {
148
- return put(`${base}/deployments/${deploymentId}`, payload);
149
- },
150
- // ─── Cubby ────────────────────────────────────────────────────────────
151
- async createCubby(payload) {
152
- return post(`${base}/cubbies`, payload);
153
- },
154
- async updateCubby(cubbyId, payload) {
155
- return put(`${base}/cubbies/${cubbyId}`, payload);
156
- },
157
- // ─── Status (read) ────────────────────────────────────────────────────
158
- getAgents() {
159
- return get(`${base}/agents`);
160
- },
161
- getEngagements() {
162
- return get(`${base}/engagements`);
163
- },
164
- // ─── Ontology (full workspace/stream/deployment tree) ──────────────────
165
- getOntology() {
166
- return requestAs(`${base}/ontology`, { method: 'GET', headers });
167
- },
168
- // ─── Cubbies (read) ─────────────────────────────────────────────────
169
- async getCubbies() {
170
- const res = await get(`${base}/cubbies`);
171
- return res.data;
172
- },
173
- async getCubbyInstances(cubbyId) {
174
- const res = await requestAs(`${base}/cubbies/${cubbyId}/instances`, { method: 'GET', headers });
175
- return Array.isArray(res) ? res : (res.data ?? []);
176
- },
177
- async getCubbyStats(cubbyId) {
178
- return requestAs(`${base}/cubbies/${cubbyId}/stats`, { method: 'GET', headers });
179
- },
180
- // ─── Delete ─────────────────────────────────────────────────────────
181
- deleteEngagement(engagementId) {
182
- return del(`${base}/engagements/${engagementId}`);
183
- },
184
- deleteAgent(agentId) {
185
- return del(`${base}/agents/${agentId}`);
186
- },
187
- deleteWorkspace(workspaceId) {
188
- return del(`${base}/workspaces/${workspaceId}`);
189
- },
190
- deleteStream(streamId) {
191
- return del(`${base}/streams/${streamId}`);
192
- },
193
- deleteDeployment(deploymentId) {
194
- return del(`${base}/deployments/${deploymentId}`);
195
- },
196
- // ─── Raft ─────────────────────────────────────────────────────────────
197
- createRaft(streamId, payload) {
198
- return post(`${base}/streams/${streamId}/rafts`, payload);
199
- },
200
- updateRaft(raftId, payload) {
201
- return put(`${base}/rafts/${raftId}`, payload);
202
- },
203
- deleteRaft(raftId) {
204
- return del(`${base}/rafts/${raftId}`);
205
- },
206
- // Shared ROB (RMS) sync: register or update raft. Best-effort: warns on failure.
207
- async syncRaftToRob(payload, method) {
208
- if (!env.robApiUrl)
209
- return;
210
- const action = method === 'POST' ? 'registration' : 'update';
211
- try {
212
- const svcId = await requireServiceId();
213
- const base = `${env.robApiUrl.replace(/\/$/, '')}/rms-node-backend/rafts`;
214
- const url = method === 'POST' ? base : `${base}/${payload.raftId}`;
215
- await request(url, {
216
- method,
217
- headers: getRobHeaders(),
218
- body: JSON.stringify({
219
- id: payload.raftId,
220
- name: payload.name,
221
- description: payload.description ?? '',
222
- dataServiceId: svcId,
223
- dataSourcesIds: payload.dataSourcesIds ?? [],
224
- indexingScript: {
225
- id: payload.streamId,
226
- name: payload.name,
227
- tsCode: payload.tsCode,
228
- },
229
- queryOperations: payload.queryOperations ?? [],
230
- }),
231
- });
232
- }
233
- catch (robErr) {
234
- const msg = robErr instanceof Error ? robErr.message : String(robErr);
235
- if (msg.includes(ROB_HTTP_FORBIDDEN) || msg.includes(ROB_MSG_FORBIDDEN)) {
236
- console.warn(`[raft] ROB ${action} failed for "${payload.name}" (403 Forbidden).` +
237
- (method === 'POST' ? ' Use the same JWT as the ROB UI (CEF_AUTH_TOKEN).' : ''));
238
- }
239
- else if (method === 'POST' &&
240
- (msg.includes(ROB_HTTP_CONFLICT) || msg.includes(ROB_MSG_ALREADY_EXISTS))) {
241
- // Already registered, ignore
242
- }
243
- else {
244
- console.warn(`[raft] ROB ${action} failed for "${payload.name}": ${msg}`);
245
- }
246
- }
247
- },
248
- // Registers a raft with ROB (RMS) so it appears in the ROB UI. Best-effort: warns on failure.
249
- registerRaftOnRob(payload) {
250
- return this.syncRaftToRob(payload, 'POST');
251
- },
252
- // Updates a raft on ROB (RMS). Best-effort: warns on failure.
253
- updateRaftOnRob(payload) {
254
- return this.syncRaftToRob(payload, 'PUT');
255
- },
256
- // ─── MCP / Playground ─────────────────────────────────────────────────
257
- callTool(agentId, toolName, args) {
258
- const mcpUrl = `${env.orchestratorUrl}/api/v1/mcp/agent-services/${asPubKey}/agents/${agentId}`;
259
- const body = {
260
- jsonrpc: '2.0',
261
- id: Date.now(),
262
- method: 'tools/call',
263
- params: { name: toolName, arguments: args },
264
- context: {
265
- jobId: `playground-${crypto.randomUUID()}`,
266
- workspaceId: 'playground',
267
- engagementId: '',
268
- deploymentId: '',
269
- executionId: crypto.randomUUID(),
270
- },
271
- };
272
- return requestAs(mcpUrl, {
273
- method: 'POST',
274
- headers,
275
- body: JSON.stringify(body),
276
- });
277
- },
278
- listTools(agentId) {
279
- const mcpUrl = `${env.orchestratorUrl}/api/v1/mcp/agent-services/${asPubKey}/agents/${agentId}`;
280
- return requestAs(mcpUrl, {
281
- method: 'POST',
282
- headers,
283
- body: JSON.stringify({
284
- jsonrpc: '2.0',
285
- id: Date.now(),
286
- method: 'tools/list',
287
- params: {},
288
- }),
289
- });
290
- },
291
- };
292
- }
293
- export async function listAgentServices(robApiUrl, authToken) {
294
- const res = await request(robApiUrl + '/data-services', {
295
- method: 'GET',
296
- headers: {
297
- 'Content-Type': 'application/json',
298
- Authorization: `Bearer ${authToken}`,
299
- },
300
- });
301
- return (res.data ?? []);
302
- }
303
- export async function createAgentServiceOnRob(robApiUrl, authToken, name) {
304
- const res = await request(robApiUrl + '/data-services', {
305
- method: 'POST',
306
- headers: {
307
- 'Content-Type': 'application/json',
308
- Authorization: `Bearer ${authToken}`,
309
- },
310
- body: JSON.stringify({ name }),
311
- });
312
- const data = (res.data ?? res);
313
- return {
314
- id: String(data.id ?? ''),
315
- name: String(data.name ?? ''),
316
- publicKey: String(data.publicKey ?? ''),
317
- archived: Boolean(data.archived),
318
- createdAt: String(data.createdAt ?? ''),
319
- };
320
- }
321
- export async function createAgentServiceOnOrchestrator(orchestratorUrl, authToken, agentServicePubKey, bucketId, name) {
322
- return request(`${orchestratorUrl}/api/v1/agent-services`, {
323
- method: 'POST',
324
- headers: {
325
- 'Content-Type': 'application/json',
326
- Authorization: `Bearer ${authToken}`,
327
- },
328
- body: JSON.stringify({ agentServicePubKey, bucketId, name }),
329
- });
330
- }
@@ -1,12 +0,0 @@
1
- import type { CefConfig, EnvConfig, ResolvedConfig } from './types.js';
2
- export declare function validateConfig(config: CefConfig): void;
3
- export declare function loadEnv(): EnvConfig;
4
- export declare function resolveFilePaths(config: CefConfig, baseDir: string): void;
5
- export interface DevConfig {
6
- config: CefConfig;
7
- configPath: string;
8
- configDir: string;
9
- }
10
- /** Load config for local dev mode. Skips env validation (no auth token required). */
11
- export declare function loadConfigForDev(configPath: string): DevConfig;
12
- export declare function loadConfig(configPath: string): ResolvedConfig;
@@ -1,145 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { parse } from 'yaml';
4
- import dotenv from 'dotenv';
5
- import { toCamelCase } from './utils.js';
6
- import { loadCredentials } from './credentials.js';
7
- const VALID_ALIAS_RE = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
8
- export function validateConfig(config) {
9
- if (!config || typeof config !== 'object') {
10
- throw new Error('Config file must contain a YAML object');
11
- }
12
- if (!config.agentServicePubKey || typeof config.agentServicePubKey !== 'string') {
13
- throw new Error('Config missing required field: agentServicePubKey (string)');
14
- }
15
- if (!/^0x[0-9a-fA-F]{64}$/.test(config.agentServicePubKey)) {
16
- throw new Error('Config field agentServicePubKey must be a 64-character hex string prefixed with 0x');
17
- }
18
- for (const section of ['engagements', 'agents', 'cubbies', 'workspaces']) {
19
- const value = config[section];
20
- if (value !== undefined && !Array.isArray(value)) {
21
- throw new Error(`Config field "${section}" must be an array`);
22
- }
23
- }
24
- for (const agent of config.agents ?? []) {
25
- if (!Array.isArray(agent.tasks)) {
26
- throw new Error(`Agent "${agent.name ?? '?'}" is missing required "tasks" array`);
27
- }
28
- if (agent.alias && !VALID_ALIAS_RE.test(agent.alias)) {
29
- throw new Error(`Agent "${agent.name ?? '?'}" alias "${agent.alias}" is not a valid JavaScript identifier. Use camelCase (e.g. "myAgent").`);
30
- }
31
- for (const task of agent.tasks) {
32
- if (task.alias && !VALID_ALIAS_RE.test(task.alias)) {
33
- throw new Error(`Task "${task.name ?? '?'}" alias "${task.alias}" is not a valid JavaScript identifier. Use camelCase (e.g. "myTask").`);
34
- }
35
- }
36
- }
37
- for (const cubby of config.cubbies ?? []) {
38
- if (!cubby.alias || typeof cubby.alias !== 'string') {
39
- throw new Error(`Cubby "${cubby.name ?? '?'}" is missing required "alias" field`);
40
- }
41
- if (!VALID_ALIAS_RE.test(cubby.alias)) {
42
- throw new Error(`Cubby "${cubby.name ?? '?'}" alias "${cubby.alias}" is not a valid JavaScript identifier. Use camelCase (e.g. "myCubby").`);
43
- }
44
- }
45
- }
46
- export function loadEnv() {
47
- let authToken = (process.env['CEF_AUTH_TOKEN'] ?? '').trim();
48
- if (authToken.toLowerCase().startsWith('bearer ')) {
49
- authToken = authToken.slice(7).trim();
50
- }
51
- // Fallback to stored credentials from `cef login`
52
- if (!authToken) {
53
- const creds = loadCredentials();
54
- if (creds) {
55
- authToken = creds.token;
56
- const msLeft = new Date(creds.expiresAt).getTime() - Date.now();
57
- if (msLeft < 3600000) {
58
- console.warn('Warning: Token expires in less than 1 hour. Run `cef login` to refresh.');
59
- }
60
- }
61
- }
62
- if (!authToken)
63
- throw new Error('Not authenticated. Run `cef login` to authenticate.');
64
- let orchestratorUrl = (process.env['CEF_ORCHESTRATOR_URL'] ?? '').trim();
65
- if (!orchestratorUrl)
66
- orchestratorUrl = 'https://orchestrator.compute.test.ddcdragon.com';
67
- orchestratorUrl = orchestratorUrl.replace(/\/orchestrator\/?$/, '');
68
- const robApiUrl = (process.env['CEF_ROB_API_URL'] ?? '').trim() || 'https://rob-api.compute.test.ddcdragon.com/rms-node-backend';
69
- const robOrigin = (process.env['CEF_ROB_ORIGIN'] ?? '').trim() || undefined;
70
- return { authToken, orchestratorUrl, robApiUrl, robOrigin };
71
- }
72
- function resolveAndValidatePath(baseDir, file, label) {
73
- const filePath = path.resolve(baseDir, file);
74
- const resolvedBase = path.resolve(baseDir);
75
- if (!filePath.startsWith(resolvedBase + path.sep) && filePath !== resolvedBase) {
76
- throw new Error(`${label} file path escapes config directory: ${file}`);
77
- }
78
- if (!fs.existsSync(filePath)) {
79
- throw new Error(`${label} file not found: ${filePath}`);
80
- }
81
- return filePath;
82
- }
83
- export function resolveFilePaths(config, baseDir) {
84
- for (const engagement of config.engagements ?? []) {
85
- const filePath = resolveAndValidatePath(baseDir, engagement.file, 'Engagement');
86
- engagement.tsCode = fs.readFileSync(filePath, 'utf8');
87
- engagement._resolvedFilePath = filePath;
88
- }
89
- for (const agent of config.agents ?? []) {
90
- if (!agent.alias)
91
- agent.alias = toCamelCase(agent.name);
92
- for (const task of agent.tasks) {
93
- if (!task.alias)
94
- task.alias = toCamelCase(task.name);
95
- const filePath = resolveAndValidatePath(baseDir, task.file, 'Agent task');
96
- task.tsCode = fs.readFileSync(filePath, 'utf8');
97
- task._resolvedFilePath = filePath;
98
- if (task.batch_file) {
99
- const batchPath = resolveAndValidatePath(baseDir, task.batch_file, 'Agent task batch');
100
- task.batchSql = fs.readFileSync(batchPath, 'utf8');
101
- }
102
- }
103
- }
104
- // Cubbies have no file references to resolve (migrations are inline)
105
- for (const workspace of config.workspaces ?? []) {
106
- for (const stream of workspace.streams ?? []) {
107
- for (const raft of stream.rafts ?? []) {
108
- if (raft.file) {
109
- const filePath = resolveAndValidatePath(baseDir, raft.file, 'Raft');
110
- raft.tsCode = fs.readFileSync(filePath, 'utf8');
111
- raft._resolvedFilePath = filePath;
112
- }
113
- }
114
- }
115
- }
116
- }
117
- /** Load config for local dev mode. Skips env validation (no auth token required). */
118
- export function loadConfigForDev(configPath) {
119
- const absolutePath = path.resolve(configPath);
120
- if (!fs.existsSync(absolutePath)) {
121
- throw new Error(`Config file not found: ${absolutePath}`);
122
- }
123
- const configDir = path.dirname(absolutePath);
124
- // Load .env for optional vars but don't fail on missing required vars
125
- dotenv.config({ path: path.join(configDir, '.env') });
126
- const raw = fs.readFileSync(absolutePath, 'utf8');
127
- const config = parse(raw);
128
- validateConfig(config);
129
- resolveFilePaths(config, configDir);
130
- return { config, configPath: absolutePath, configDir };
131
- }
132
- export function loadConfig(configPath) {
133
- const absolutePath = path.resolve(configPath);
134
- if (!fs.existsSync(absolutePath)) {
135
- throw new Error(`Config file not found: ${absolutePath}`);
136
- }
137
- const configDir = path.dirname(absolutePath);
138
- dotenv.config({ path: path.join(configDir, '.env') });
139
- const raw = fs.readFileSync(absolutePath, 'utf8');
140
- const config = parse(raw);
141
- validateConfig(config);
142
- const env = loadEnv();
143
- resolveFilePaths(config, configDir);
144
- return { config, env, configPath: absolutePath };
145
- }
@@ -1,19 +0,0 @@
1
- export interface StoredCredentials {
2
- email: string;
3
- publicKey: string;
4
- token: string;
5
- expiresAt: string;
6
- }
7
- export declare function getCredentialsPath(): string;
8
- export declare function saveCredentials(creds: StoredCredentials): void;
9
- export declare function loadCredentials(): StoredCredentials | null;
10
- export declare function clearCredentials(): boolean;
11
- /**
12
- * Parse a wallet JWT token and extract payload fields.
13
- * Token format: base64(header).base64(payload).signature
14
- */
15
- export declare function parseToken(token: string): {
16
- email: string;
17
- publicKey: string;
18
- expiresAt: string;
19
- } | null;
@@ -1,68 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import os from 'os';
4
- function getCefDir() {
5
- return path.join(os.homedir(), '.cef');
6
- }
7
- export function getCredentialsPath() {
8
- return path.join(getCefDir(), 'credentials.json');
9
- }
10
- export function saveCredentials(creds) {
11
- const dir = getCefDir();
12
- if (!fs.existsSync(dir)) {
13
- fs.mkdirSync(dir, { recursive: true });
14
- }
15
- fs.writeFileSync(path.join(dir, 'credentials.json'), JSON.stringify(creds, null, 2), 'utf8');
16
- }
17
- export function loadCredentials() {
18
- const credFile = getCredentialsPath();
19
- if (!fs.existsSync(credFile)) {
20
- return null;
21
- }
22
- try {
23
- const raw = fs.readFileSync(credFile, 'utf8');
24
- const creds = JSON.parse(raw);
25
- if (!creds.token || !creds.expiresAt) {
26
- return null;
27
- }
28
- // Check expiry
29
- const expiresAt = new Date(creds.expiresAt).getTime();
30
- if (isNaN(expiresAt) || expiresAt <= Date.now()) {
31
- return null;
32
- }
33
- return creds;
34
- }
35
- catch {
36
- return null;
37
- }
38
- }
39
- export function clearCredentials() {
40
- const credFile = getCredentialsPath();
41
- if (fs.existsSync(credFile)) {
42
- fs.unlinkSync(credFile);
43
- return true;
44
- }
45
- return false;
46
- }
47
- /**
48
- * Parse a wallet JWT token and extract payload fields.
49
- * Token format: base64(header).base64(payload).signature
50
- */
51
- export function parseToken(token) {
52
- try {
53
- const parts = token.split('.');
54
- if (parts.length !== 3 || !parts[1])
55
- return null;
56
- const payload = JSON.parse(Buffer.from(parts[1], 'base64').toString('utf8'));
57
- if (!payload.email || !payload.publicKey || !payload.exp)
58
- return null;
59
- return {
60
- email: payload.email,
61
- publicKey: payload.publicKey,
62
- expiresAt: new Date(payload.exp).toISOString(),
63
- };
64
- }
65
- catch {
66
- return null;
67
- }
68
- }
@@ -1,12 +0,0 @@
1
- import type { AgentConfig } from '../types.js';
2
- export declare class AgentRouter {
3
- private tasks;
4
- private agentTasks;
5
- loadAgents(agents: AgentConfig[]): void;
6
- call(agentAlias: string, taskAlias: string, payload: unknown, context: unknown): Promise<unknown>;
7
- reloadTask(agentAlias: string, taskAlias: string, tsCode: string): void;
8
- getLoadedAgents(): string[];
9
- getTasksForAgent(agentAlias: string): string[];
10
- private compileAndStore;
11
- private transpile;
12
- }
@@ -1,67 +0,0 @@
1
- import vm from 'vm';
2
- import { transpileTypeScript } from '../transpile.js';
3
- export class AgentRouter {
4
- tasks = new Map(); // key: agentAlias/taskAlias
5
- agentTasks = new Map(); // agentAlias -> [taskAlias, ...]
6
- loadAgents(agents) {
7
- for (const agent of agents) {
8
- const taskAliases = [];
9
- for (const task of agent.tasks) {
10
- const code = task.tsCode ?? '';
11
- this.compileAndStore(agent.alias, task.alias, code);
12
- taskAliases.push(task.alias);
13
- }
14
- this.agentTasks.set(agent.alias, taskAliases);
15
- }
16
- }
17
- async call(agentAlias, taskAlias, payload, context) {
18
- const key = `${agentAlias}/${taskAlias}`;
19
- const compiled = this.tasks.get(key);
20
- if (!compiled) {
21
- if (!this.agentTasks.has(agentAlias)) {
22
- throw new Error(`Agent "${agentAlias}" not found`);
23
- }
24
- throw new Error(`Task "${taskAlias}" not found on agent "${agentAlias}"`);
25
- }
26
- const event = { payload, event_type: 'agent_call' };
27
- // Build restricted sandbox
28
- const sandbox = {
29
- event,
30
- context,
31
- console: {
32
- log: context?.log ?? (() => { }),
33
- warn: context?.warn ?? (() => { }),
34
- error: context?.error ?? (() => { }),
35
- },
36
- Promise,
37
- // Math, JSON, etc. are available in vm by default
38
- };
39
- // Wrap code to capture the handle function and call it
40
- const wrappedCode = `
41
- ${compiled.compiledJs}
42
- __result__ = handle(event, context);
43
- `;
44
- const vmContext = vm.createContext(sandbox);
45
- vm.runInContext(wrappedCode, vmContext);
46
- // handle returns a Promise
47
- const result = await sandbox.__result__;
48
- return result;
49
- }
50
- reloadTask(agentAlias, taskAlias, tsCode) {
51
- this.compileAndStore(agentAlias, taskAlias, tsCode);
52
- }
53
- getLoadedAgents() {
54
- return [...this.agentTasks.keys()];
55
- }
56
- getTasksForAgent(agentAlias) {
57
- return this.agentTasks.get(agentAlias) ?? [];
58
- }
59
- compileAndStore(agentAlias, taskAlias, tsCode) {
60
- const key = `${agentAlias}/${taskAlias}`;
61
- const compiledJs = this.transpile(tsCode);
62
- this.tasks.set(key, { agentAlias, taskAlias, compiledJs });
63
- }
64
- transpile(tsCode) {
65
- return transpileTypeScript(tsCode);
66
- }
67
- }
@@ -1,27 +0,0 @@
1
- import type { LogCollector } from './log-collector.js';
2
- import type { AgentRouter } from './agent-router.js';
3
- import type { CubbyManager } from './cubby-manager.js';
4
- import type { StreamManager } from './stream-manager.js';
5
- export interface BuildContextOptions {
6
- executionId: string;
7
- logCollector: LogCollector;
8
- agentRouter: AgentRouter;
9
- cubbyManager: CubbyManager;
10
- streamManager: StreamManager;
11
- workspaceId: string;
12
- agentServiceId: string;
13
- agentAlias?: string;
14
- taskAlias?: string;
15
- callerLabel?: string;
16
- }
17
- /**
18
- * Builds the context object injected into agent/engagement V8 sandboxes.
19
- *
20
- * This is THE single source of truth for the Context API shape.
21
- * When the platform API changes, update this file.
22
- *
23
- * Properties are grouped into:
24
- * 1. Typed properties (from typecheck.ts Context interface)
25
- * 2. Non-typed extensions (in platform docs but not in typecheck.ts)
26
- */
27
- export declare function buildContext(opts: BuildContextOptions): any;