@syntropic137/cli 0.19.6 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/syn.js +159 -181
- package/package.json +4 -2
package/dist/syn.js
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
// src/config.ts
|
|
4
4
|
var CLI_NAME = "syn";
|
|
5
|
-
var CLI_VERSION = "0.18.0";
|
|
6
5
|
var CLI_DESCRIPTION = "Syntropic137 - Event-sourced workflow engine for AI agents";
|
|
6
|
+
var CLI_VERSION = true ? "0.20.0" : "0.0.0-dev";
|
|
7
7
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
8
8
|
var SSE_CONNECT_TIMEOUT_MS = 5e3;
|
|
9
9
|
function getApiUrl() {
|
|
10
|
-
|
|
10
|
+
const url = process.env["SYN_API_URL"] ?? "http://localhost:8137";
|
|
11
|
+
return url.replace(/\/api\/v1\/*$/, "");
|
|
11
12
|
}
|
|
12
13
|
function getAuthHeaders() {
|
|
13
14
|
const token = process.env["SYN_API_TOKEN"];
|
|
@@ -68,6 +69,7 @@ function print(message) {
|
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
// src/client/http.ts
|
|
72
|
+
var API_PREFIX = "/api/v1";
|
|
71
73
|
var SynClient = class {
|
|
72
74
|
baseUrl;
|
|
73
75
|
timeoutMs;
|
|
@@ -128,7 +130,8 @@ var SynClient = class {
|
|
|
128
130
|
const base = new URL(this.baseUrl);
|
|
129
131
|
const basePath = base.pathname.replace(/\/+$/, "");
|
|
130
132
|
const reqPath = path8.startsWith("/") ? path8 : `/${path8}`;
|
|
131
|
-
const
|
|
133
|
+
const prefix = basePath.endsWith(API_PREFIX) ? "" : API_PREFIX;
|
|
134
|
+
const url = new URL(`${basePath}${prefix}${reqPath}`, base);
|
|
132
135
|
if (params) {
|
|
133
136
|
for (const [key, value] of Object.entries(params)) {
|
|
134
137
|
if (value !== void 0) {
|
|
@@ -194,6 +197,21 @@ async function apiGetList(path8, options) {
|
|
|
194
197
|
checkResponse(status, data, options?.expected ?? [200]);
|
|
195
198
|
return data;
|
|
196
199
|
}
|
|
200
|
+
async function apiGetPaginated(path8, key, options) {
|
|
201
|
+
const client = new SynClient();
|
|
202
|
+
const { status, data } = await safeRequest(
|
|
203
|
+
() => client.get(path8, options?.params)
|
|
204
|
+
);
|
|
205
|
+
checkResponse(status, data, options?.expected ?? [200]);
|
|
206
|
+
if (typeof data !== "object" || data === null) {
|
|
207
|
+
throw new CLIError(`Unexpected API response for "${path8}": expected an object containing "${key}".`);
|
|
208
|
+
}
|
|
209
|
+
const items = data[key];
|
|
210
|
+
if (!Array.isArray(items)) {
|
|
211
|
+
throw new CLIError(`Unexpected API response for "${path8}": expected "${key}" to be an array.`);
|
|
212
|
+
}
|
|
213
|
+
return items;
|
|
214
|
+
}
|
|
197
215
|
async function apiPost(path8, options) {
|
|
198
216
|
const client = new SynClient(
|
|
199
217
|
options?.timeoutMs !== void 0 ? { timeoutMs: options.timeoutMs } : void 0
|
|
@@ -212,6 +230,14 @@ async function apiPut(path8, options) {
|
|
|
212
230
|
checkResponse(status, data, options?.expected ?? [200]);
|
|
213
231
|
return data;
|
|
214
232
|
}
|
|
233
|
+
async function apiPatch(path8, options) {
|
|
234
|
+
const client = new SynClient();
|
|
235
|
+
const { status, data } = await safeRequest(
|
|
236
|
+
() => client.patch(path8, options?.body)
|
|
237
|
+
);
|
|
238
|
+
checkResponse(status, data, options?.expected ?? [200]);
|
|
239
|
+
return data;
|
|
240
|
+
}
|
|
215
241
|
async function apiDelete(path8, options) {
|
|
216
242
|
const client = new SynClient();
|
|
217
243
|
const { status, data } = await safeRequest(() => client.delete(path8));
|
|
@@ -2370,56 +2396,8 @@ var marketplaceGroup = new CommandGroup(
|
|
|
2370
2396
|
);
|
|
2371
2397
|
marketplaceGroup.command(addCommand).command(listMarketplaceCommand).command(removeCommand).command(refreshCommand);
|
|
2372
2398
|
|
|
2373
|
-
// src/commands/agent.ts
|
|
2374
|
-
var listCommand2 = {
|
|
2375
|
-
name: "list",
|
|
2376
|
-
description: "List available agent providers",
|
|
2377
|
-
handler: async () => {
|
|
2378
|
-
const providers = await apiGetList("/agents/providers");
|
|
2379
|
-
const table = new Table({ title: "Agent Providers" });
|
|
2380
|
-
table.addColumn("Provider", { style: CYAN });
|
|
2381
|
-
table.addColumn("Display Name");
|
|
2382
|
-
table.addColumn("Available");
|
|
2383
|
-
table.addColumn("Default Model");
|
|
2384
|
-
for (const p of providers) {
|
|
2385
|
-
const available = p["available"] ? style("Yes", GREEN) : style("No", "\x1B[31m");
|
|
2386
|
-
table.addRow(
|
|
2387
|
-
String(p["provider"] ?? ""),
|
|
2388
|
-
String(p["display_name"] ?? ""),
|
|
2389
|
-
available,
|
|
2390
|
-
String(p["default_model"] ?? "")
|
|
2391
|
-
);
|
|
2392
|
-
}
|
|
2393
|
-
table.print();
|
|
2394
|
-
}
|
|
2395
|
-
};
|
|
2396
|
-
var testCommand = {
|
|
2397
|
-
name: "test",
|
|
2398
|
-
description: "Test an agent provider with a simple prompt",
|
|
2399
|
-
options: {
|
|
2400
|
-
provider: { type: "string", short: "p", description: "Agent provider (claude, mock)", default: "claude" },
|
|
2401
|
-
prompt: { type: "string", description: "Test prompt", default: "Say hello in one sentence." },
|
|
2402
|
-
model: { type: "string", short: "m", description: "Model override" }
|
|
2403
|
-
},
|
|
2404
|
-
handler: async (parsed) => {
|
|
2405
|
-
const provider = parsed.values["provider"] ?? "claude";
|
|
2406
|
-
const prompt = parsed.values["prompt"] ?? "Say hello in one sentence.";
|
|
2407
|
-
const model = parsed.values["model"] ?? null;
|
|
2408
|
-
const result = await apiPost("/agents/test", {
|
|
2409
|
-
body: { provider, prompt, model },
|
|
2410
|
-
timeoutMs: 6e4
|
|
2411
|
-
});
|
|
2412
|
-
print(`${style(`Response from ${String(result["provider"] ?? provider)}:`, GREEN)}`);
|
|
2413
|
-
print(` Model: ${String(result["model"] ?? "unknown")}`);
|
|
2414
|
-
print(` Response: ${String(result["response_text"] ?? "")}`);
|
|
2415
|
-
print(` Tokens: ${String(result["input_tokens"] ?? 0)} in / ${String(result["output_tokens"] ?? 0)} out`);
|
|
2416
|
-
}
|
|
2417
|
-
};
|
|
2418
|
-
var agentGroup = new CommandGroup("agent", "AI agent management and testing");
|
|
2419
|
-
agentGroup.command(listCommand2).command(testCommand);
|
|
2420
|
-
|
|
2421
2399
|
// src/commands/artifacts.ts
|
|
2422
|
-
var
|
|
2400
|
+
var listCommand2 = {
|
|
2423
2401
|
name: "list",
|
|
2424
2402
|
description: "List artifacts",
|
|
2425
2403
|
options: {
|
|
@@ -2534,63 +2512,55 @@ var createCommand2 = {
|
|
|
2534
2512
|
}
|
|
2535
2513
|
};
|
|
2536
2514
|
var artifactsGroup = new CommandGroup("artifacts", "Browse and retrieve workflow artifacts");
|
|
2537
|
-
artifactsGroup.command(
|
|
2515
|
+
artifactsGroup.command(listCommand2).command(showCommand2).command(contentCommand).command(createCommand2);
|
|
2538
2516
|
|
|
2539
2517
|
// src/commands/config.ts
|
|
2540
2518
|
var showCommand3 = {
|
|
2541
2519
|
name: "show",
|
|
2542
|
-
description: "Display current configuration",
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
const
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
});
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
${style(
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
}
|
|
2559
|
-
}
|
|
2520
|
+
description: "Display current CLI configuration",
|
|
2521
|
+
handler: async () => {
|
|
2522
|
+
const apiUrl = getApiUrl();
|
|
2523
|
+
const headers = getAuthHeaders();
|
|
2524
|
+
const hasAuth = Object.keys(headers).length > 0;
|
|
2525
|
+
const authType = headers["Authorization"]?.startsWith("Bearer") ? "token" : headers["Authorization"]?.startsWith("Basic") ? "basic" : "none";
|
|
2526
|
+
print(style("CLI Configuration", BOLD));
|
|
2527
|
+
print(` Version: ${CLI_VERSION}`);
|
|
2528
|
+
print(` API URL: ${apiUrl}`);
|
|
2529
|
+
print(` Auth: ${hasAuth ? style(authType, GREEN) : style("none", DIM)}`);
|
|
2530
|
+
print("");
|
|
2531
|
+
print(style("Environment Variables", BOLD));
|
|
2532
|
+
print(` SYN_API_URL: ${process.env["SYN_API_URL"] ?? style("(default: http://localhost:8137)", DIM)}`);
|
|
2533
|
+
print(` SYN_API_TOKEN: ${process.env["SYN_API_TOKEN"] ? style("set", GREEN) : style("not set", DIM)}`);
|
|
2534
|
+
print(` SYN_API_USER: ${process.env["SYN_API_USER"] ?? style("not set", DIM)}`);
|
|
2535
|
+
print(` SYN_API_PASSWORD: ${process.env["SYN_API_PASSWORD"] ? style("set", GREEN) : style("not set", DIM)}`);
|
|
2560
2536
|
}
|
|
2561
2537
|
};
|
|
2562
2538
|
var validateCommand2 = {
|
|
2563
2539
|
name: "validate",
|
|
2564
|
-
description: "Validate configuration
|
|
2540
|
+
description: "Validate CLI configuration",
|
|
2565
2541
|
handler: async () => {
|
|
2566
|
-
|
|
2567
|
-
const
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
print(style("No issues found.", GREEN));
|
|
2571
|
-
return;
|
|
2542
|
+
const issues = [];
|
|
2543
|
+
const apiUrl = getApiUrl();
|
|
2544
|
+
if (!apiUrl.startsWith("http://") && !apiUrl.startsWith("https://")) {
|
|
2545
|
+
issues.push("SYN_API_URL must start with http:// or https://");
|
|
2572
2546
|
}
|
|
2573
|
-
const
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
for (const issue of issues) {
|
|
2580
|
-
const level = issue["level"] ?? "info";
|
|
2581
|
-
const levelColor = levelStyles[level];
|
|
2582
|
-
table.addRow(
|
|
2583
|
-
levelColor ? style(level, levelColor) : level,
|
|
2584
|
-
issue["category"] ?? "",
|
|
2585
|
-
issue["message"] ?? ""
|
|
2586
|
-
);
|
|
2587
|
-
if (level === "error") hasErrors = true;
|
|
2547
|
+
const headers = getAuthHeaders();
|
|
2548
|
+
let isLocal = false;
|
|
2549
|
+
try {
|
|
2550
|
+
const parsed = new URL(apiUrl);
|
|
2551
|
+
isLocal = parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1";
|
|
2552
|
+
} catch {
|
|
2588
2553
|
}
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2554
|
+
if (Object.keys(headers).length === 0 && !isLocal) {
|
|
2555
|
+
issues.push("No authentication configured for non-localhost API URL");
|
|
2556
|
+
}
|
|
2557
|
+
if (issues.length === 0) {
|
|
2558
|
+
print(style("Configuration is valid.", GREEN));
|
|
2559
|
+
} else {
|
|
2560
|
+
for (const issue of issues) {
|
|
2561
|
+
print(`${style("!", RED)} ${issue}`);
|
|
2562
|
+
}
|
|
2563
|
+
throw new CLIError("Configuration has issues", 1);
|
|
2594
2564
|
}
|
|
2595
2565
|
}
|
|
2596
2566
|
};
|
|
@@ -2598,12 +2568,22 @@ var envCommand = {
|
|
|
2598
2568
|
name: "env",
|
|
2599
2569
|
description: "Show environment variable template",
|
|
2600
2570
|
handler: async () => {
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
print(
|
|
2571
|
+
print("# Syntropic137 CLI configuration");
|
|
2572
|
+
print("# Copy and adjust these variables in your shell profile");
|
|
2573
|
+
print("");
|
|
2574
|
+
print("# API server URL (default: http://localhost:8137)");
|
|
2575
|
+
print("export SYN_API_URL=http://localhost:8137");
|
|
2576
|
+
print("");
|
|
2577
|
+
print("# Authentication (choose one):");
|
|
2578
|
+
print("# Option 1: Bearer token");
|
|
2579
|
+
print("export SYN_API_TOKEN=your-token-here");
|
|
2580
|
+
print("");
|
|
2581
|
+
print("# Option 2: Basic auth");
|
|
2582
|
+
print("# export SYN_API_USER=admin");
|
|
2583
|
+
print("# export SYN_API_PASSWORD=your-password-here");
|
|
2604
2584
|
}
|
|
2605
2585
|
};
|
|
2606
|
-
var configGroup = new CommandGroup("config", "
|
|
2586
|
+
var configGroup = new CommandGroup("config", "CLI configuration");
|
|
2607
2587
|
configGroup.command(showCommand3).command(validateCommand2).command(envCommand);
|
|
2608
2588
|
|
|
2609
2589
|
// src/commands/control.ts
|
|
@@ -3105,7 +3085,7 @@ var eventsGroup = new CommandGroup("events", "Query domain events and session ob
|
|
|
3105
3085
|
eventsGroup.command(recentCommand).command(sessionEventsCommand).command(timelineCommand).command(costsCommand).command(toolsCommand);
|
|
3106
3086
|
|
|
3107
3087
|
// src/commands/execution.ts
|
|
3108
|
-
var
|
|
3088
|
+
var listCommand3 = {
|
|
3109
3089
|
name: "list",
|
|
3110
3090
|
description: "List all workflow executions",
|
|
3111
3091
|
options: {
|
|
@@ -3195,7 +3175,7 @@ var showCommand5 = {
|
|
|
3195
3175
|
}
|
|
3196
3176
|
};
|
|
3197
3177
|
var executionGroup = new CommandGroup("execution", "List and inspect workflow executions");
|
|
3198
|
-
executionGroup.command(
|
|
3178
|
+
executionGroup.command(listCommand3).command(showCommand5);
|
|
3199
3179
|
|
|
3200
3180
|
// src/commands/insights.ts
|
|
3201
3181
|
var SPARKLINE_CHARS = " \u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588";
|
|
@@ -3253,7 +3233,7 @@ var costCommand = {
|
|
|
3253
3233
|
},
|
|
3254
3234
|
handler: async (parsed) => {
|
|
3255
3235
|
const days = parsed.values["days"] ?? "30";
|
|
3256
|
-
const d = await apiGet("/insights/
|
|
3236
|
+
const d = await apiGet("/insights/cost", { params: { days } });
|
|
3257
3237
|
print(style(`Cost Overview (last ${days} days)`, CYAN));
|
|
3258
3238
|
print(` ${style("Total cost:", BOLD)} ${formatCost(String(d["total_cost_usd"] ?? "0"))}`);
|
|
3259
3239
|
print(` ${style("Total tokens:", BOLD)} ${formatTokens(Number(d["total_tokens"] ?? 0))}`);
|
|
@@ -3294,30 +3274,24 @@ var heatmapCommand = {
|
|
|
3294
3274
|
days: { type: "string", short: "d", description: "Number of days to show", default: "14" }
|
|
3295
3275
|
},
|
|
3296
3276
|
handler: async (parsed) => {
|
|
3297
|
-
const
|
|
3298
|
-
const
|
|
3299
|
-
const
|
|
3300
|
-
|
|
3277
|
+
const numDays = parseInt(parsed.values["days"] ?? "14", 10);
|
|
3278
|
+
const endDate = /* @__PURE__ */ new Date();
|
|
3279
|
+
const startDate = /* @__PURE__ */ new Date();
|
|
3280
|
+
startDate.setDate(endDate.getDate() - numDays);
|
|
3281
|
+
const fmt = (dt) => dt.toISOString().split("T")[0];
|
|
3282
|
+
const d = await apiGet("/insights/contribution-heatmap", {
|
|
3283
|
+
params: { start_date: fmt(startDate), end_date: fmt(endDate) }
|
|
3284
|
+
});
|
|
3285
|
+
const days = d["days"] ?? [];
|
|
3286
|
+
if (days.length === 0) {
|
|
3301
3287
|
printDim("No activity data.");
|
|
3302
3288
|
return;
|
|
3303
3289
|
}
|
|
3304
|
-
const values =
|
|
3305
|
-
print(style(`Activity Heatmap (last ${
|
|
3290
|
+
const values = days.map((b) => Number(b["count"] ?? 0));
|
|
3291
|
+
print(style(`Activity Heatmap (last ${numDays} days)`, CYAN));
|
|
3306
3292
|
print(` ${renderSparkline(values)}`);
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
if (topRepos.length > 0) {
|
|
3310
|
-
const table = new Table({ title: "Top Repositories" });
|
|
3311
|
-
table.addColumn("Repository", { style: CYAN });
|
|
3312
|
-
table.addColumn("Events", { align: "right" });
|
|
3313
|
-
for (const r of topRepos.slice(0, 5)) {
|
|
3314
|
-
table.addRow(
|
|
3315
|
-
String(r["repo_name"] ?? r["repo_id"] ?? ""),
|
|
3316
|
-
String(r["count"] ?? 0)
|
|
3317
|
-
);
|
|
3318
|
-
}
|
|
3319
|
-
table.print();
|
|
3320
|
-
}
|
|
3293
|
+
const total = Number(d["total"] ?? values.reduce((a, b) => a + b, 0));
|
|
3294
|
+
print(style(` ${total} total events`, DIM));
|
|
3321
3295
|
}
|
|
3322
3296
|
};
|
|
3323
3297
|
var insightsGroup = new CommandGroup("insights", "Global system insights and cost analysis");
|
|
@@ -3390,7 +3364,7 @@ var toolTimelineCommand = {
|
|
|
3390
3364
|
handler: async (parsed) => {
|
|
3391
3365
|
const sid = reqSessionId2(parsed);
|
|
3392
3366
|
const limit = parsed.values["limit"] ?? "100";
|
|
3393
|
-
const entries = await
|
|
3367
|
+
const entries = await apiGetPaginated(`/observability/sessions/${sid}/tools`, "executions", { params: { limit } });
|
|
3394
3368
|
if (entries.length === 0) {
|
|
3395
3369
|
printDim("No tool timeline entries.");
|
|
3396
3370
|
return;
|
|
@@ -3419,7 +3393,7 @@ var tokenMetricsCommand = {
|
|
|
3419
3393
|
args: [{ name: "session-id", description: "Session ID", required: true }],
|
|
3420
3394
|
handler: async (parsed) => {
|
|
3421
3395
|
const sid = reqSessionId2(parsed);
|
|
3422
|
-
const d = await apiGet(`/
|
|
3396
|
+
const d = await apiGet(`/observability/sessions/${sid}/tokens`);
|
|
3423
3397
|
print(`${style("Token Metrics:", BOLD)} ${d["session_id"] ?? sid}`);
|
|
3424
3398
|
print(` Input tokens: ${Number(d["input_tokens"] ?? 0).toLocaleString()}`);
|
|
3425
3399
|
print(` Output tokens: ${Number(d["output_tokens"] ?? 0).toLocaleString()}`);
|
|
@@ -3464,11 +3438,11 @@ var createCommand3 = {
|
|
|
3464
3438
|
if (d["slug"]) print(` Slug: ${String(d["slug"])}`);
|
|
3465
3439
|
}
|
|
3466
3440
|
};
|
|
3467
|
-
var
|
|
3441
|
+
var listCommand4 = {
|
|
3468
3442
|
name: "list",
|
|
3469
3443
|
description: "List all organizations",
|
|
3470
3444
|
handler: async () => {
|
|
3471
|
-
const items = await
|
|
3445
|
+
const items = await apiGetPaginated("/organizations", "organizations");
|
|
3472
3446
|
if (items.length === 0) {
|
|
3473
3447
|
printDim("No organizations found.");
|
|
3474
3448
|
return;
|
|
@@ -3546,7 +3520,7 @@ var deleteCommand2 = {
|
|
|
3546
3520
|
}
|
|
3547
3521
|
};
|
|
3548
3522
|
var orgGroup = new CommandGroup("org", "Manage organizations");
|
|
3549
|
-
orgGroup.command(createCommand3).command(
|
|
3523
|
+
orgGroup.command(createCommand3).command(listCommand4).command(showCommand7).command(updateCommand2).command(deleteCommand2);
|
|
3550
3524
|
|
|
3551
3525
|
// src/commands/repo.ts
|
|
3552
3526
|
function reqRepoId(parsed) {
|
|
@@ -3578,11 +3552,11 @@ var registerCommand = {
|
|
|
3578
3552
|
if (org) body["organization_id"] = org;
|
|
3579
3553
|
const d = await apiPost("/repos", { body, expected: [200, 201] });
|
|
3580
3554
|
printSuccess(`Repository registered: ${d["repo_id"] ?? ""}`);
|
|
3581
|
-
print(`
|
|
3555
|
+
print(` Name: ${d["full_name"] ?? url}`);
|
|
3582
3556
|
if (d["system_id"]) print(` System: ${String(d["system_id"])}`);
|
|
3583
3557
|
}
|
|
3584
3558
|
};
|
|
3585
|
-
var
|
|
3559
|
+
var listCommand5 = {
|
|
3586
3560
|
name: "list",
|
|
3587
3561
|
description: "List repositories",
|
|
3588
3562
|
options: {
|
|
@@ -3594,22 +3568,20 @@ var listCommand6 = {
|
|
|
3594
3568
|
organization_id: parsed.values["org"] ?? null,
|
|
3595
3569
|
system_id: parsed.values["system"] ?? null
|
|
3596
3570
|
});
|
|
3597
|
-
const items = await
|
|
3571
|
+
const items = await apiGetPaginated("/repos", "repos", { params });
|
|
3598
3572
|
if (items.length === 0) {
|
|
3599
3573
|
printDim("No repositories found.");
|
|
3600
3574
|
return;
|
|
3601
3575
|
}
|
|
3602
3576
|
const table = new Table({ title: "Repositories" });
|
|
3603
3577
|
table.addColumn("ID", { style: CYAN });
|
|
3604
|
-
table.addColumn("
|
|
3578
|
+
table.addColumn("Name");
|
|
3605
3579
|
table.addColumn("System", { style: DIM });
|
|
3606
|
-
table.addColumn("Status");
|
|
3607
3580
|
for (const r of items) {
|
|
3608
3581
|
table.addRow(
|
|
3609
3582
|
String(r["repo_id"] ?? ""),
|
|
3610
|
-
String(r["
|
|
3611
|
-
String(r["system_id"] ?? "\u2014")
|
|
3612
|
-
formatStatus(String(r["status"] ?? ""))
|
|
3583
|
+
String(r["full_name"] ?? ""),
|
|
3584
|
+
String(r["system_id"] ?? "\u2014")
|
|
3613
3585
|
);
|
|
3614
3586
|
}
|
|
3615
3587
|
table.print();
|
|
@@ -3622,11 +3594,10 @@ var showCommand8 = {
|
|
|
3622
3594
|
handler: async (parsed) => {
|
|
3623
3595
|
const id = reqRepoId(parsed);
|
|
3624
3596
|
const d = await apiGet(`/repos/${id}`);
|
|
3625
|
-
print(`${style("Repository:", BOLD)} ${d["
|
|
3597
|
+
print(`${style("Repository:", BOLD)} ${d["full_name"] ?? id}`);
|
|
3626
3598
|
print(` ID: ${d["repo_id"] ?? id}`);
|
|
3627
3599
|
if (d["system_id"]) print(` System: ${String(d["system_id"])}`);
|
|
3628
3600
|
if (d["organization_id"]) print(` Org: ${String(d["organization_id"])}`);
|
|
3629
|
-
print(` Status: ${formatStatus(String(d["status"] ?? ""))}`);
|
|
3630
3601
|
}
|
|
3631
3602
|
};
|
|
3632
3603
|
var assignCommand = {
|
|
@@ -3643,7 +3614,7 @@ var assignCommand = {
|
|
|
3643
3614
|
printError("Missing --system");
|
|
3644
3615
|
throw new CLIError("Missing option", 1);
|
|
3645
3616
|
}
|
|
3646
|
-
await
|
|
3617
|
+
await apiPost(`/repos/${id}/assign`, { body: { system_id: system } });
|
|
3647
3618
|
printSuccess(`Repository ${id} assigned to system ${system}.`);
|
|
3648
3619
|
}
|
|
3649
3620
|
};
|
|
@@ -3696,7 +3667,7 @@ var costCommand2 = {
|
|
|
3696
3667
|
args: [{ name: "repo-id", description: "Repository ID", required: true }],
|
|
3697
3668
|
handler: async (parsed) => {
|
|
3698
3669
|
const id = reqRepoId(parsed);
|
|
3699
|
-
const d = await apiGet(`/repos/${id}/
|
|
3670
|
+
const d = await apiGet(`/repos/${id}/cost`);
|
|
3700
3671
|
print(`${style("Repository Costs:", BOLD)} ${id}`);
|
|
3701
3672
|
print(` Total cost: ${formatCost(String(d["total_cost_usd"] ?? "0"))}`);
|
|
3702
3673
|
print(` Tokens: ${formatTokens(Number(d["total_tokens"] ?? 0))}`);
|
|
@@ -3727,7 +3698,7 @@ var activityCommand = {
|
|
|
3727
3698
|
handler: async (parsed) => {
|
|
3728
3699
|
const id = reqRepoId(parsed);
|
|
3729
3700
|
const limit = parsed.values["limit"] ?? "20";
|
|
3730
|
-
const items = await
|
|
3701
|
+
const items = await apiGetPaginated(`/repos/${id}/activity`, "entries", { params: { limit } });
|
|
3731
3702
|
if (items.length === 0) {
|
|
3732
3703
|
printDim("No recent activity.");
|
|
3733
3704
|
return;
|
|
@@ -3762,7 +3733,7 @@ var failuresCommand = {
|
|
|
3762
3733
|
handler: async (parsed) => {
|
|
3763
3734
|
const id = reqRepoId(parsed);
|
|
3764
3735
|
const limit = parsed.values["limit"] ?? "10";
|
|
3765
|
-
const items = await
|
|
3736
|
+
const items = await apiGetPaginated(`/repos/${id}/failures`, "failures", { params: { limit } });
|
|
3766
3737
|
if (items.length === 0) {
|
|
3767
3738
|
printDim("No recent failures.");
|
|
3768
3739
|
return;
|
|
@@ -3793,7 +3764,7 @@ var sessionsCommand2 = {
|
|
|
3793
3764
|
handler: async (parsed) => {
|
|
3794
3765
|
const id = reqRepoId(parsed);
|
|
3795
3766
|
const limit = parsed.values["limit"] ?? "20";
|
|
3796
|
-
const items = await
|
|
3767
|
+
const items = await apiGetPaginated(`/repos/${id}/sessions`, "sessions", { params: { limit } });
|
|
3797
3768
|
if (items.length === 0) {
|
|
3798
3769
|
printDim("No sessions found.");
|
|
3799
3770
|
return;
|
|
@@ -3817,10 +3788,10 @@ var sessionsCommand2 = {
|
|
|
3817
3788
|
}
|
|
3818
3789
|
};
|
|
3819
3790
|
var repoGroup = new CommandGroup("repo", "Manage repositories and view observability data");
|
|
3820
|
-
repoGroup.command(registerCommand).command(
|
|
3791
|
+
repoGroup.command(registerCommand).command(listCommand5).command(showCommand8).command(assignCommand).command(unassignCommand).command(healthCommand2).command(costCommand2).command(activityCommand).command(failuresCommand).command(sessionsCommand2);
|
|
3821
3792
|
|
|
3822
3793
|
// src/commands/sessions.ts
|
|
3823
|
-
var
|
|
3794
|
+
var listCommand6 = {
|
|
3824
3795
|
name: "list",
|
|
3825
3796
|
description: "List agent sessions",
|
|
3826
3797
|
options: {
|
|
@@ -3903,7 +3874,7 @@ var showCommand9 = {
|
|
|
3903
3874
|
}
|
|
3904
3875
|
};
|
|
3905
3876
|
var sessionsGroup = new CommandGroup("sessions", "List and inspect agent sessions");
|
|
3906
|
-
sessionsGroup.command(
|
|
3877
|
+
sessionsGroup.command(listCommand6).command(showCommand9);
|
|
3907
3878
|
|
|
3908
3879
|
// src/commands/system.ts
|
|
3909
3880
|
function reqId3(parsed) {
|
|
@@ -3938,7 +3909,7 @@ var createCommand4 = {
|
|
|
3938
3909
|
print(` Name: ${d["name"] ?? name}`);
|
|
3939
3910
|
}
|
|
3940
3911
|
};
|
|
3941
|
-
var
|
|
3912
|
+
var listCommand7 = {
|
|
3942
3913
|
name: "list",
|
|
3943
3914
|
description: "List all systems",
|
|
3944
3915
|
options: {
|
|
@@ -3948,7 +3919,7 @@ var listCommand8 = {
|
|
|
3948
3919
|
const params = buildParams({
|
|
3949
3920
|
organization_id: parsed.values["org"] ?? null
|
|
3950
3921
|
});
|
|
3951
|
-
const items = await
|
|
3922
|
+
const items = await apiGetPaginated("/systems", "systems", { params });
|
|
3952
3923
|
if (items.length === 0) {
|
|
3953
3924
|
printDim("No systems found.");
|
|
3954
3925
|
return;
|
|
@@ -3958,14 +3929,12 @@ var listCommand8 = {
|
|
|
3958
3929
|
table.addColumn("Name");
|
|
3959
3930
|
table.addColumn("Org", { style: DIM });
|
|
3960
3931
|
table.addColumn("Repos", { align: "right" });
|
|
3961
|
-
table.addColumn("Status");
|
|
3962
3932
|
for (const s of items) {
|
|
3963
3933
|
table.addRow(
|
|
3964
3934
|
String(s["system_id"] ?? ""),
|
|
3965
3935
|
String(s["name"] ?? ""),
|
|
3966
3936
|
String(s["organization_id"] ?? "\u2014"),
|
|
3967
|
-
String(s["repo_count"] ?? 0)
|
|
3968
|
-
formatStatus(String(s["status"] ?? ""))
|
|
3937
|
+
String(s["repo_count"] ?? 0)
|
|
3969
3938
|
);
|
|
3970
3939
|
}
|
|
3971
3940
|
table.print();
|
|
@@ -3983,7 +3952,6 @@ var showCommand10 = {
|
|
|
3983
3952
|
if (d["description"]) print(` Description: ${String(d["description"])}`);
|
|
3984
3953
|
if (d["organization_id"]) print(` Org: ${String(d["organization_id"])}`);
|
|
3985
3954
|
print(` Repos: ${d["repo_count"] ?? 0}`);
|
|
3986
|
-
print(` Status: ${formatStatus(String(d["status"] ?? ""))}`);
|
|
3987
3955
|
}
|
|
3988
3956
|
};
|
|
3989
3957
|
var updateCommand3 = {
|
|
@@ -4066,7 +4034,7 @@ var costCommand3 = {
|
|
|
4066
4034
|
args: [{ name: "system-id", description: "System ID", required: true }],
|
|
4067
4035
|
handler: async (parsed) => {
|
|
4068
4036
|
const id = reqId3(parsed);
|
|
4069
|
-
const d = await apiGet(`/systems/${id}/
|
|
4037
|
+
const d = await apiGet(`/systems/${id}/cost`);
|
|
4070
4038
|
print(`${style("System Costs:", BOLD)} ${id}`);
|
|
4071
4039
|
print(` Total cost: ${formatCost(String(d["total_cost_usd"] ?? "0"))}`);
|
|
4072
4040
|
print(` Tokens: ${formatTokens(Number(d["total_tokens"] ?? 0))}`);
|
|
@@ -4097,7 +4065,7 @@ var activityCommand2 = {
|
|
|
4097
4065
|
handler: async (parsed) => {
|
|
4098
4066
|
const id = reqId3(parsed);
|
|
4099
4067
|
const limit = parsed.values["limit"] ?? "20";
|
|
4100
|
-
const items = await
|
|
4068
|
+
const items = await apiGetPaginated(`/systems/${id}/activity`, "entries", { params: { limit } });
|
|
4101
4069
|
if (items.length === 0) {
|
|
4102
4070
|
printDim("No recent activity.");
|
|
4103
4071
|
return;
|
|
@@ -4179,7 +4147,7 @@ var historyCommand = {
|
|
|
4179
4147
|
limit: parsed.values["limit"] ?? "50",
|
|
4180
4148
|
status: parsed.values["status"] ?? null
|
|
4181
4149
|
});
|
|
4182
|
-
const items = await
|
|
4150
|
+
const items = await apiGetPaginated(`/systems/${id}/history`, "entries", { params });
|
|
4183
4151
|
if (items.length === 0) {
|
|
4184
4152
|
printDim("No execution history.");
|
|
4185
4153
|
return;
|
|
@@ -4205,7 +4173,7 @@ var historyCommand = {
|
|
|
4205
4173
|
}
|
|
4206
4174
|
};
|
|
4207
4175
|
var systemGroup = new CommandGroup("system", "Manage systems and view system observability");
|
|
4208
|
-
systemGroup.command(createCommand4).command(
|
|
4176
|
+
systemGroup.command(createCommand4).command(listCommand7).command(showCommand10).command(updateCommand3).command(deleteCommand3).command(statusCommand3).command(costCommand3).command(activityCommand2).command(patternsCommand).command(historyCommand);
|
|
4209
4177
|
|
|
4210
4178
|
// src/commands/triggers.ts
|
|
4211
4179
|
function reqId4(parsed) {
|
|
@@ -4254,9 +4222,10 @@ var registerCommand2 = {
|
|
|
4254
4222
|
const conditionStrs = parsed.values["condition"] ?? [];
|
|
4255
4223
|
const conditions = conditionStrs.length > 0 ? parseConditions(conditionStrs) : [];
|
|
4256
4224
|
const body = {
|
|
4257
|
-
|
|
4225
|
+
name: `${event} \u2192 ${workflow}`,
|
|
4226
|
+
repository: repo,
|
|
4258
4227
|
workflow_id: workflow,
|
|
4259
|
-
|
|
4228
|
+
event,
|
|
4260
4229
|
conditions,
|
|
4261
4230
|
max_fires_per_period: parseInt(parsed.values["max-fires"] ?? "5", 10),
|
|
4262
4231
|
cooldown_seconds: parseInt(parsed.values["cooldown"] ?? "300", 10)
|
|
@@ -4272,8 +4241,7 @@ var enablePresetCommand = {
|
|
|
4272
4241
|
description: "Enable a built-in trigger preset",
|
|
4273
4242
|
args: [{ name: "preset", description: "Preset name (self-healing, review-fix)", required: true }],
|
|
4274
4243
|
options: {
|
|
4275
|
-
repo: { type: "string", short: "r", description: "Repository ID" }
|
|
4276
|
-
workflow: { type: "string", short: "w", description: "Workflow ID" }
|
|
4244
|
+
repo: { type: "string", short: "r", description: "Repository ID" }
|
|
4277
4245
|
},
|
|
4278
4246
|
handler: async (parsed) => {
|
|
4279
4247
|
const preset = parsed.positionals[0];
|
|
@@ -4286,14 +4254,11 @@ var enablePresetCommand = {
|
|
|
4286
4254
|
printError("Missing --repo");
|
|
4287
4255
|
throw new CLIError("Missing option", 1);
|
|
4288
4256
|
}
|
|
4289
|
-
const
|
|
4290
|
-
const workflow = parsed.values["workflow"];
|
|
4291
|
-
if (workflow) body["workflow_id"] = workflow;
|
|
4292
|
-
const d = await apiPost("/triggers/presets", { body, expected: [200, 201] });
|
|
4257
|
+
const d = await apiPost(`/triggers/presets/${encodeURIComponent(preset)}`, { body: { repository: repo }, expected: [200, 201] });
|
|
4293
4258
|
printSuccess(`Preset "${preset}" enabled: ${d["trigger_id"] ?? ""}`);
|
|
4294
4259
|
}
|
|
4295
4260
|
};
|
|
4296
|
-
var
|
|
4261
|
+
var listCommand8 = {
|
|
4297
4262
|
name: "list",
|
|
4298
4263
|
description: "List trigger rules",
|
|
4299
4264
|
options: {
|
|
@@ -4302,10 +4267,10 @@ var listCommand9 = {
|
|
|
4302
4267
|
},
|
|
4303
4268
|
handler: async (parsed) => {
|
|
4304
4269
|
const params = buildParams({
|
|
4305
|
-
|
|
4270
|
+
repository: parsed.values["repo"] ?? null,
|
|
4306
4271
|
status: parsed.values["status"] ?? null
|
|
4307
4272
|
});
|
|
4308
|
-
const items = await
|
|
4273
|
+
const items = await apiGetPaginated("/triggers", "triggers", { params });
|
|
4309
4274
|
if (items.length === 0) {
|
|
4310
4275
|
printDim("No triggers found.");
|
|
4311
4276
|
return;
|
|
@@ -4320,8 +4285,8 @@ var listCommand9 = {
|
|
|
4320
4285
|
for (const t of items) {
|
|
4321
4286
|
table.addRow(
|
|
4322
4287
|
String(t["trigger_id"] ?? "").slice(0, 12),
|
|
4323
|
-
String(t["
|
|
4324
|
-
String(t["
|
|
4288
|
+
String(t["event"] ?? ""),
|
|
4289
|
+
String(t["repository"] ?? "").slice(0, 12),
|
|
4325
4290
|
String(t["workflow_id"] ?? "").slice(0, 12),
|
|
4326
4291
|
formatStatus(String(t["status"] ?? "")),
|
|
4327
4292
|
String(t["fire_count"] ?? 0)
|
|
@@ -4338,8 +4303,8 @@ var showCommand11 = {
|
|
|
4338
4303
|
const id = reqId4(parsed);
|
|
4339
4304
|
const d = await apiGet(`/triggers/${id}`);
|
|
4340
4305
|
print(`${style("Trigger:", BOLD)} ${d["trigger_id"] ?? id}`);
|
|
4341
|
-
print(` Event: ${d["
|
|
4342
|
-
print(` Repo: ${d["
|
|
4306
|
+
print(` Event: ${d["event"] ?? ""}`);
|
|
4307
|
+
print(` Repo: ${d["repository"] ?? ""}`);
|
|
4343
4308
|
print(` Workflow: ${d["workflow_id"] ?? ""}`);
|
|
4344
4309
|
print(` Status: ${formatStatus(String(d["status"] ?? ""))}`);
|
|
4345
4310
|
print(` Fires: ${d["fire_count"] ?? 0} / max ${d["max_fires_per_period"] ?? "\u2014"}`);
|
|
@@ -4365,7 +4330,7 @@ var historyCommand2 = {
|
|
|
4365
4330
|
handler: async (parsed) => {
|
|
4366
4331
|
const id = reqId4(parsed);
|
|
4367
4332
|
const limit = parsed.values["limit"] ?? "20";
|
|
4368
|
-
const items = await
|
|
4333
|
+
const items = await apiGetPaginated(`/triggers/${id}/history`, "entries", { params: { limit } });
|
|
4369
4334
|
if (items.length === 0) {
|
|
4370
4335
|
printDim("No trigger history.");
|
|
4371
4336
|
return;
|
|
@@ -4392,7 +4357,7 @@ var pauseCommand2 = {
|
|
|
4392
4357
|
args: [{ name: "trigger-id", description: "Trigger ID", required: true }],
|
|
4393
4358
|
handler: async (parsed) => {
|
|
4394
4359
|
const id = reqId4(parsed);
|
|
4395
|
-
await
|
|
4360
|
+
await apiPatch(`/triggers/${id}`, { body: { action: "pause" } });
|
|
4396
4361
|
printSuccess(`Trigger ${id} paused.`);
|
|
4397
4362
|
}
|
|
4398
4363
|
};
|
|
@@ -4402,7 +4367,7 @@ var resumeCommand2 = {
|
|
|
4402
4367
|
args: [{ name: "trigger-id", description: "Trigger ID", required: true }],
|
|
4403
4368
|
handler: async (parsed) => {
|
|
4404
4369
|
const id = reqId4(parsed);
|
|
4405
|
-
await
|
|
4370
|
+
await apiPatch(`/triggers/${id}`, { body: { action: "resume" } });
|
|
4406
4371
|
printSuccess(`Trigger ${id} resumed.`);
|
|
4407
4372
|
}
|
|
4408
4373
|
};
|
|
@@ -4440,12 +4405,26 @@ var disableAllCommand = {
|
|
|
4440
4405
|
printError(`Use --force to confirm disabling all triggers for repo ${repo}`);
|
|
4441
4406
|
throw new CLIError("Confirmation required", 1);
|
|
4442
4407
|
}
|
|
4443
|
-
await
|
|
4444
|
-
|
|
4408
|
+
const triggers = await apiGetPaginated("/triggers", "triggers", {
|
|
4409
|
+
params: { repository: repo, status: "active" }
|
|
4410
|
+
});
|
|
4411
|
+
if (triggers.length === 0) {
|
|
4412
|
+
printDim("No active triggers found.");
|
|
4413
|
+
return;
|
|
4414
|
+
}
|
|
4415
|
+
let count = 0;
|
|
4416
|
+
for (const t of triggers) {
|
|
4417
|
+
const tid = String(t["trigger_id"] ?? "");
|
|
4418
|
+
if (tid) {
|
|
4419
|
+
await apiPatch(`/triggers/${tid}`, { body: { action: "pause" } });
|
|
4420
|
+
count++;
|
|
4421
|
+
}
|
|
4422
|
+
}
|
|
4423
|
+
printSuccess(`Disabled ${count} trigger(s) for repository ${repo}.`);
|
|
4445
4424
|
}
|
|
4446
4425
|
};
|
|
4447
4426
|
var triggersGroup = new CommandGroup("triggers", "Manage self-healing trigger rules");
|
|
4448
|
-
triggersGroup.command(registerCommand2).command(enablePresetCommand).command(
|
|
4427
|
+
triggersGroup.command(registerCommand2).command(enablePresetCommand).command(listCommand8).command(showCommand11).command(historyCommand2).command(pauseCommand2).command(resumeCommand2).command(deleteCommand4).command(disableAllCommand);
|
|
4449
4428
|
|
|
4450
4429
|
// src/client/sse.ts
|
|
4451
4430
|
function parseSseLine(line) {
|
|
@@ -4534,7 +4513,7 @@ var executionCommand = {
|
|
|
4534
4513
|
print(style(`Watching execution ${id}...`, BOLD));
|
|
4535
4514
|
printDim("Press Ctrl+C to stop.\n");
|
|
4536
4515
|
try {
|
|
4537
|
-
for await (const event of streamSSE(`/
|
|
4516
|
+
for await (const event of streamSSE(`/sse/executions/${id}`)) {
|
|
4538
4517
|
renderEvent(event);
|
|
4539
4518
|
}
|
|
4540
4519
|
print(style("\nStream ended.", DIM));
|
|
@@ -4803,7 +4782,6 @@ cli.addCommand({
|
|
|
4803
4782
|
});
|
|
4804
4783
|
cli.addGroup(workflowGroup);
|
|
4805
4784
|
cli.addGroup(marketplaceGroup);
|
|
4806
|
-
cli.addGroup(agentGroup);
|
|
4807
4785
|
cli.addGroup(artifactsGroup);
|
|
4808
4786
|
cli.addGroup(configGroup);
|
|
4809
4787
|
cli.addGroup(controlGroup);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syntropic137/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Syntropic137 CLI - Event-sourced workflow engine for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -18,9 +18,11 @@
|
|
|
18
18
|
"test:watch": "vitest",
|
|
19
19
|
"typecheck": "tsc --noEmit",
|
|
20
20
|
"generate:types": "tsx scripts/generate-types.ts",
|
|
21
|
-
"check:api-drift": "tsx scripts/check-api-drift.ts"
|
|
21
|
+
"check:api-drift": "tsx scripts/check-api-drift.ts",
|
|
22
|
+
"generate:docs": "tsx scripts/generate-cli-docs.ts"
|
|
22
23
|
},
|
|
23
24
|
"dependencies": {
|
|
25
|
+
"openapi-fetch": "^0.17.0",
|
|
24
26
|
"zod": "^3.24.0"
|
|
25
27
|
},
|
|
26
28
|
"devDependencies": {
|