struere 0.13.1 → 0.14.1
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/bin/struere.js +274 -160
- package/dist/cli/commands/integration.d.ts.map +1 -1
- package/dist/cli/commands/sync.d.ts.map +1 -1
- package/dist/cli/commands/threads.d.ts.map +1 -1
- package/dist/cli/index.js +274 -160
- package/dist/cli/utils/extractor.d.ts +8 -0
- package/dist/cli/utils/extractor.d.ts.map +1 -1
- package/dist/cli/utils/integrations.d.ts +21 -0
- package/dist/cli/utils/integrations.d.ts.map +1 -1
- package/dist/cli/utils/runtime.d.ts +1 -0
- package/dist/cli/utils/runtime.d.ts.map +1 -1
- package/dist/cli/utils/validator.d.ts.map +1 -1
- package/dist/define/router.d.ts.map +1 -1
- package/dist/index.js +14 -0
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/bin/struere.js
CHANGED
|
@@ -2549,6 +2549,22 @@ import chalk3 from "chalk";
|
|
|
2549
2549
|
function isInteractive() {
|
|
2550
2550
|
return process.stdout.isTTY === true && !process.env.CI && !getApiKey();
|
|
2551
2551
|
}
|
|
2552
|
+
function createSilentOutput() {
|
|
2553
|
+
return {
|
|
2554
|
+
start() {},
|
|
2555
|
+
succeed() {},
|
|
2556
|
+
fail() {},
|
|
2557
|
+
stop() {},
|
|
2558
|
+
info() {},
|
|
2559
|
+
warn() {},
|
|
2560
|
+
error(msg) {
|
|
2561
|
+
console.error(msg);
|
|
2562
|
+
},
|
|
2563
|
+
json(data) {
|
|
2564
|
+
console.log(JSON.stringify(data, null, 2));
|
|
2565
|
+
}
|
|
2566
|
+
};
|
|
2567
|
+
}
|
|
2552
2568
|
function createOutput() {
|
|
2553
2569
|
if (isInteractive()) {
|
|
2554
2570
|
const spinner = ora3();
|
|
@@ -2658,15 +2674,15 @@ orgCommand.command("list").description("List your organizations").option("--json
|
|
|
2658
2674
|
await refreshToken();
|
|
2659
2675
|
const fresh = loadCredentials();
|
|
2660
2676
|
const token = fresh?.token || credentials.token;
|
|
2661
|
-
const spinner = ora4();
|
|
2662
|
-
spinner
|
|
2677
|
+
const spinner = options.json ? null : ora4();
|
|
2678
|
+
spinner?.start("Fetching organizations");
|
|
2663
2679
|
const { organizations, error } = await listMyOrganizations(token);
|
|
2664
2680
|
if (error) {
|
|
2665
|
-
spinner
|
|
2681
|
+
spinner?.fail("Failed to fetch organizations");
|
|
2666
2682
|
console.log(chalk4.red(error));
|
|
2667
2683
|
process.exit(1);
|
|
2668
2684
|
}
|
|
2669
|
-
spinner
|
|
2685
|
+
spinner?.stop();
|
|
2670
2686
|
if (options.json) {
|
|
2671
2687
|
console.log(JSON.stringify(organizations, null, 2));
|
|
2672
2688
|
return;
|
|
@@ -2706,15 +2722,15 @@ orgCommand.command("create").argument("[name]", "Organization name").description
|
|
|
2706
2722
|
}
|
|
2707
2723
|
name = name.trim();
|
|
2708
2724
|
const slug = options.slug || slugify(name);
|
|
2709
|
-
const spinner = ora4();
|
|
2710
|
-
spinner
|
|
2725
|
+
const spinner = options.json ? null : ora4();
|
|
2726
|
+
spinner?.start("Creating organization");
|
|
2711
2727
|
const { organization, error } = await createOrganization(token, name, slug);
|
|
2712
2728
|
if (error || !organization) {
|
|
2713
|
-
spinner
|
|
2729
|
+
spinner?.fail("Failed to create organization");
|
|
2714
2730
|
console.log(chalk4.red(error || "Unknown error"));
|
|
2715
2731
|
process.exit(1);
|
|
2716
2732
|
}
|
|
2717
|
-
spinner
|
|
2733
|
+
spinner?.stop();
|
|
2718
2734
|
if (options.json) {
|
|
2719
2735
|
console.log(JSON.stringify(organization, null, 2));
|
|
2720
2736
|
return;
|
|
@@ -2964,7 +2980,9 @@ var BUILTIN_TOOLS = [
|
|
|
2964
2980
|
"payment.create",
|
|
2965
2981
|
"payment.getStatus",
|
|
2966
2982
|
"web.search",
|
|
2967
|
-
"web.fetch"
|
|
2983
|
+
"web.fetch",
|
|
2984
|
+
"voice.call",
|
|
2985
|
+
"voice.inject"
|
|
2968
2986
|
];
|
|
2969
2987
|
function extractSyncPayload(resources) {
|
|
2970
2988
|
const customToolsMap = new Map;
|
|
@@ -3073,7 +3091,8 @@ function extractSyncPayload(resources) {
|
|
|
3073
3091
|
classifyModel: r.classifyModel,
|
|
3074
3092
|
contextMessages: r.contextMessages,
|
|
3075
3093
|
maxTransfers: r.maxTransfers,
|
|
3076
|
-
inactivityResetMs: r.inactivityResetMs
|
|
3094
|
+
inactivityResetMs: r.inactivityResetMs,
|
|
3095
|
+
voiceConfig: r.voiceConfig
|
|
3077
3096
|
})) : undefined;
|
|
3078
3097
|
const fixtures = resources.fixtures.length > 0 ? resources.fixtures.map((f) => ({
|
|
3079
3098
|
name: f.name,
|
|
@@ -3107,6 +3126,11 @@ function extractAgentPayload(agent, customToolsMap) {
|
|
|
3107
3126
|
const tools = (agent.tools || []).map((toolName) => {
|
|
3108
3127
|
const isBuiltin = BUILTIN_TOOLS.includes(toolName);
|
|
3109
3128
|
if (!isBuiltin && !customToolsMap.has(toolName)) {
|
|
3129
|
+
const builtinPrefixes = ["entity.", "calendar.", "whatsapp.", "agent.", "airtable.", "email.", "payment.", "web.", "voice.", "router."];
|
|
3130
|
+
const looksBuiltin = builtinPrefixes.some((prefix) => toolName.startsWith(prefix));
|
|
3131
|
+
if (looksBuiltin) {
|
|
3132
|
+
throw new Error(`Agent "${agent.name}" references tool "${toolName}" which looks like a built-in tool but is not recognized. Try updating the CLI: npm install -g struere@latest`);
|
|
3133
|
+
}
|
|
3110
3134
|
const available = customToolsMap.size > 0 ? `Available custom tools: ${Array.from(customToolsMap.keys()).join(", ")}` : "No custom tools were loaded from tools/index.ts";
|
|
3111
3135
|
throw new Error(`Agent "${agent.name}" references tool "${toolName}" but it was not found. ${available}`);
|
|
3112
3136
|
}
|
|
@@ -3152,7 +3176,8 @@ var INTEGRATION_PREFIXES = {
|
|
|
3152
3176
|
"calendar.": "Google Calendar",
|
|
3153
3177
|
"airtable.": "Airtable",
|
|
3154
3178
|
"email.": "Resend",
|
|
3155
|
-
"payment.": "Flow / Polar"
|
|
3179
|
+
"payment.": "Flow / Polar",
|
|
3180
|
+
"voice.": "Twilio Voice"
|
|
3156
3181
|
};
|
|
3157
3182
|
function validateResources(payload, resources) {
|
|
3158
3183
|
const warnings = [];
|
|
@@ -3477,8 +3502,42 @@ var syncCommand = new Command5("sync").description("Sync resources to Convex and
|
|
|
3477
3502
|
output.start("Syncing to Convex");
|
|
3478
3503
|
try {
|
|
3479
3504
|
const result = await syncToEnvironment(cwd, project.organization.id, environment);
|
|
3480
|
-
if (!jsonMode)
|
|
3505
|
+
if (!jsonMode) {
|
|
3481
3506
|
output.succeed(`Synced to ${environment}`);
|
|
3507
|
+
console.log();
|
|
3508
|
+
const types = [
|
|
3509
|
+
{ label: "agent", data: result.agents },
|
|
3510
|
+
{ label: "entity type", data: result.entityTypes },
|
|
3511
|
+
{ label: "role", data: result.roles },
|
|
3512
|
+
{ label: "trigger", data: result.triggers },
|
|
3513
|
+
{ label: "router", data: result.routers },
|
|
3514
|
+
{ label: "eval suite", data: result.evalSuites }
|
|
3515
|
+
];
|
|
3516
|
+
let hasChanges = false;
|
|
3517
|
+
for (const { label, data } of types) {
|
|
3518
|
+
if (!data)
|
|
3519
|
+
continue;
|
|
3520
|
+
for (const name of data.created) {
|
|
3521
|
+
console.log(chalk6.green(` + Created ${label}: ${name}`));
|
|
3522
|
+
hasChanges = true;
|
|
3523
|
+
}
|
|
3524
|
+
for (const name of data.updated) {
|
|
3525
|
+
console.log(chalk6.blue(` ~ Updated ${label}: ${name}`));
|
|
3526
|
+
hasChanges = true;
|
|
3527
|
+
}
|
|
3528
|
+
for (const name of data.deleted) {
|
|
3529
|
+
console.log(chalk6.red(` - Deleted ${label}: ${name}`));
|
|
3530
|
+
hasChanges = true;
|
|
3531
|
+
}
|
|
3532
|
+
}
|
|
3533
|
+
if (!hasChanges) {
|
|
3534
|
+
console.log(chalk6.gray(" No changes detected"));
|
|
3535
|
+
}
|
|
3536
|
+
if (result.evalSuites?.skipped && result.evalSuites.skipped.length > 0) {
|
|
3537
|
+
console.log(chalk6.yellow(` Skipped eval suites (agent not found): ${result.evalSuites.skipped.join(", ")}`));
|
|
3538
|
+
}
|
|
3539
|
+
console.log();
|
|
3540
|
+
}
|
|
3482
3541
|
if (jsonMode) {
|
|
3483
3542
|
console.log(JSON.stringify({
|
|
3484
3543
|
success: true,
|
|
@@ -5334,17 +5393,17 @@ function flattenEntityForTable(entity) {
|
|
|
5334
5393
|
var entitiesCommand = new Command13("data").description("Manage data records");
|
|
5335
5394
|
entitiesCommand.command("types").description("List available data types").option("--env <environment>", "Environment (development|production)", "development").option("--json", "Output raw JSON").action(async (opts) => {
|
|
5336
5395
|
await ensureAuth();
|
|
5337
|
-
const spinner = ora11();
|
|
5396
|
+
const spinner = opts.json ? null : ora11();
|
|
5338
5397
|
const env = opts.env;
|
|
5339
5398
|
const orgId = getOrgId();
|
|
5340
|
-
spinner
|
|
5399
|
+
spinner?.start("Fetching data types");
|
|
5341
5400
|
const { data, error } = await queryEntityTypes(env, orgId);
|
|
5342
5401
|
if (error || !data) {
|
|
5343
|
-
spinner
|
|
5402
|
+
spinner?.fail("Failed to fetch data types");
|
|
5344
5403
|
console.log(chalk15.red("Error:"), error);
|
|
5345
5404
|
process.exit(1);
|
|
5346
5405
|
}
|
|
5347
|
-
spinner
|
|
5406
|
+
spinner?.succeed("Data types loaded");
|
|
5348
5407
|
const types = data;
|
|
5349
5408
|
if (opts.json) {
|
|
5350
5409
|
console.log(JSON.stringify(types, null, 2));
|
|
@@ -5369,10 +5428,10 @@ entitiesCommand.command("types").description("List available data types").option
|
|
|
5369
5428
|
});
|
|
5370
5429
|
entitiesCommand.command("list <type>").description("List records of a type").option("--env <environment>", "Environment (development|production)", "development").option("--status <status>", "Filter by status").option("--limit <n>", "Maximum results", "50").option("--json", "Output raw JSON").action(async (type, opts) => {
|
|
5371
5430
|
await ensureAuth();
|
|
5372
|
-
const spinner = ora11();
|
|
5431
|
+
const spinner = opts.json ? null : ora11();
|
|
5373
5432
|
const env = opts.env;
|
|
5374
5433
|
const orgId = getOrgId();
|
|
5375
|
-
spinner
|
|
5434
|
+
spinner?.start(`Fetching ${type} records`);
|
|
5376
5435
|
const [entitiesResult, typeResult] = await Promise.all([
|
|
5377
5436
|
queryEntities(type, env, {
|
|
5378
5437
|
status: opts.status,
|
|
@@ -5381,12 +5440,12 @@ entitiesCommand.command("list <type>").description("List records of a type").opt
|
|
|
5381
5440
|
queryEntityTypeBySlug(type, env, orgId)
|
|
5382
5441
|
]);
|
|
5383
5442
|
if (entitiesResult.error || !entitiesResult.data) {
|
|
5384
|
-
spinner
|
|
5443
|
+
spinner?.fail(`Failed to fetch ${type} records`);
|
|
5385
5444
|
console.log(chalk15.red("Error:"), entitiesResult.error);
|
|
5386
5445
|
process.exit(1);
|
|
5387
5446
|
}
|
|
5388
5447
|
const entities = entitiesResult.data;
|
|
5389
|
-
spinner
|
|
5448
|
+
spinner?.succeed(`Found ${entities.length} ${type} records`);
|
|
5390
5449
|
if (opts.json) {
|
|
5391
5450
|
console.log(JSON.stringify(entities, null, 2));
|
|
5392
5451
|
return;
|
|
@@ -5401,25 +5460,26 @@ entitiesCommand.command("list <type>").description("List records of a type").opt
|
|
|
5401
5460
|
});
|
|
5402
5461
|
entitiesCommand.command("get <id>").description("Get record details").option("--env <environment>", "Environment (development|production)", "development").option("--json", "Output raw JSON").action(async (rawId, opts) => {
|
|
5403
5462
|
await ensureAuth();
|
|
5404
|
-
const spinner = ora11();
|
|
5463
|
+
const spinner = opts.json ? null : ora11();
|
|
5405
5464
|
const env = opts.env;
|
|
5406
5465
|
const orgId = getOrgId();
|
|
5407
|
-
spinner
|
|
5466
|
+
spinner?.start("Resolving record ID");
|
|
5408
5467
|
const resolved = await resolveEntityId(rawId, env, orgId);
|
|
5409
5468
|
if (resolved.error || !resolved.data) {
|
|
5410
|
-
spinner
|
|
5469
|
+
spinner?.fail("Record not found");
|
|
5411
5470
|
console.log(chalk15.red("Error:"), resolved.error || `No record matched "${rawId}"`);
|
|
5412
5471
|
process.exit(1);
|
|
5413
5472
|
}
|
|
5414
5473
|
const id = resolved.data;
|
|
5415
|
-
spinner
|
|
5474
|
+
if (spinner)
|
|
5475
|
+
spinner.text = "Fetching record";
|
|
5416
5476
|
const { data, error } = await queryEntity(id, env, orgId);
|
|
5417
5477
|
if (error || !data) {
|
|
5418
|
-
spinner
|
|
5478
|
+
spinner?.fail("Failed to fetch record");
|
|
5419
5479
|
console.log(chalk15.red("Error:"), error || "Record not found");
|
|
5420
5480
|
process.exit(1);
|
|
5421
5481
|
}
|
|
5422
|
-
spinner
|
|
5482
|
+
spinner?.succeed("Record loaded");
|
|
5423
5483
|
const result = data;
|
|
5424
5484
|
if (opts.json) {
|
|
5425
5485
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -5449,7 +5509,7 @@ entitiesCommand.command("get <id>").description("Get record details").option("--
|
|
|
5449
5509
|
});
|
|
5450
5510
|
entitiesCommand.command("create <type>").description("Create a new record").option("--env <environment>", "Environment (development|production)", "development").option("--data <json>", "Record data as JSON").option("--status <status>", "Initial status").option("--json", "Output raw JSON").action(async (type, opts) => {
|
|
5451
5511
|
await ensureAuth();
|
|
5452
|
-
const spinner = ora11();
|
|
5512
|
+
const spinner = opts.json ? null : ora11();
|
|
5453
5513
|
const env = opts.env;
|
|
5454
5514
|
const orgId = getOrgId();
|
|
5455
5515
|
let data;
|
|
@@ -5464,14 +5524,14 @@ entitiesCommand.command("create <type>").description("Create a new record").opti
|
|
|
5464
5524
|
console.log(chalk15.red("--data <json> is required in non-interactive mode"));
|
|
5465
5525
|
process.exit(1);
|
|
5466
5526
|
} else {
|
|
5467
|
-
spinner
|
|
5527
|
+
spinner?.start(`Fetching ${type} schema`);
|
|
5468
5528
|
const { data: typeData, error: error2 } = await queryEntityTypeBySlug(type, env, orgId);
|
|
5469
5529
|
if (error2 || !typeData) {
|
|
5470
|
-
spinner
|
|
5530
|
+
spinner?.fail(`Data type not found: ${type}`);
|
|
5471
5531
|
console.log(chalk15.red("Error:"), error2 || "Not found");
|
|
5472
5532
|
process.exit(1);
|
|
5473
5533
|
}
|
|
5474
|
-
spinner
|
|
5534
|
+
spinner?.succeed(`Schema loaded for ${type}`);
|
|
5475
5535
|
console.log();
|
|
5476
5536
|
const entityType = typeData;
|
|
5477
5537
|
const schema = entityType.schema;
|
|
@@ -5505,14 +5565,14 @@ entitiesCommand.command("create <type>").description("Create a new record").opti
|
|
|
5505
5565
|
}
|
|
5506
5566
|
console.log();
|
|
5507
5567
|
}
|
|
5508
|
-
spinner
|
|
5568
|
+
spinner?.start(`Creating ${type} record`);
|
|
5509
5569
|
const { data: result, error } = await createEntity(type, data, env, opts.status, orgId);
|
|
5510
5570
|
if (error) {
|
|
5511
|
-
spinner
|
|
5571
|
+
spinner?.fail("Failed to create record");
|
|
5512
5572
|
console.log(chalk15.red("Error:"), error);
|
|
5513
5573
|
process.exit(1);
|
|
5514
5574
|
}
|
|
5515
|
-
spinner
|
|
5575
|
+
spinner?.succeed(`Record created`);
|
|
5516
5576
|
if (opts.json) {
|
|
5517
5577
|
console.log(JSON.stringify({ id: result }, null, 2));
|
|
5518
5578
|
} else {
|
|
@@ -5523,7 +5583,7 @@ entitiesCommand.command("create <type>").description("Create a new record").opti
|
|
|
5523
5583
|
});
|
|
5524
5584
|
entitiesCommand.command("update <id>").description("Update a record").option("--env <environment>", "Environment (development|production)", "development").option("--data <json>", "Update data as JSON").option("--status <status>", "New status").option("--json", "Output raw JSON").action(async (rawId, opts) => {
|
|
5525
5585
|
await ensureAuth();
|
|
5526
|
-
const spinner = ora11();
|
|
5586
|
+
const spinner = opts.json ? null : ora11();
|
|
5527
5587
|
const env = opts.env;
|
|
5528
5588
|
const orgId = getOrgId();
|
|
5529
5589
|
if (!opts.data && !opts.status) {
|
|
@@ -5539,22 +5599,23 @@ entitiesCommand.command("update <id>").description("Update a record").option("--
|
|
|
5539
5599
|
process.exit(1);
|
|
5540
5600
|
}
|
|
5541
5601
|
}
|
|
5542
|
-
spinner
|
|
5602
|
+
spinner?.start("Resolving record ID");
|
|
5543
5603
|
const resolved = await resolveEntityId(rawId, env, orgId);
|
|
5544
5604
|
if (resolved.error || !resolved.data) {
|
|
5545
|
-
spinner
|
|
5605
|
+
spinner?.fail("Record not found");
|
|
5546
5606
|
console.log(chalk15.red("Error:"), resolved.error || `No record matched "${rawId}"`);
|
|
5547
5607
|
process.exit(1);
|
|
5548
5608
|
}
|
|
5549
5609
|
const id = resolved.data;
|
|
5550
|
-
spinner
|
|
5610
|
+
if (spinner)
|
|
5611
|
+
spinner.text = "Updating record";
|
|
5551
5612
|
const { data: result, error } = await updateEntity(id, data, env, opts.status, orgId);
|
|
5552
5613
|
if (error) {
|
|
5553
|
-
spinner
|
|
5614
|
+
spinner?.fail("Failed to update record");
|
|
5554
5615
|
console.log(chalk15.red("Error:"), error);
|
|
5555
5616
|
process.exit(1);
|
|
5556
5617
|
}
|
|
5557
|
-
spinner
|
|
5618
|
+
spinner?.succeed("Record updated");
|
|
5558
5619
|
if (opts.json) {
|
|
5559
5620
|
console.log(JSON.stringify(result, null, 2));
|
|
5560
5621
|
} else {
|
|
@@ -5642,21 +5703,21 @@ entitiesCommand.command("delete <id>").description("Delete a record").option("--
|
|
|
5642
5703
|
});
|
|
5643
5704
|
entitiesCommand.command("search <type> <query>").description("Search records").option("--env <environment>", "Environment (development|production)", "development").option("--limit <n>", "Maximum results", "25").option("--json", "Output raw JSON").action(async (type, query, opts) => {
|
|
5644
5705
|
await ensureAuth();
|
|
5645
|
-
const spinner = ora11();
|
|
5706
|
+
const spinner = opts.json ? null : ora11();
|
|
5646
5707
|
const env = opts.env;
|
|
5647
5708
|
const orgId = getOrgId();
|
|
5648
|
-
spinner
|
|
5709
|
+
spinner?.start(`Searching ${type} for "${query}"`);
|
|
5649
5710
|
const [searchResult, typeResult] = await Promise.all([
|
|
5650
5711
|
searchEntities(type, query, env, parseInt(opts.limit, 10), orgId),
|
|
5651
5712
|
queryEntityTypeBySlug(type, env, orgId)
|
|
5652
5713
|
]);
|
|
5653
5714
|
if (searchResult.error || !searchResult.data) {
|
|
5654
|
-
spinner
|
|
5715
|
+
spinner?.fail("Search failed");
|
|
5655
5716
|
console.log(chalk15.red("Error:"), searchResult.error);
|
|
5656
5717
|
process.exit(1);
|
|
5657
5718
|
}
|
|
5658
5719
|
const entities = searchResult.data;
|
|
5659
|
-
spinner
|
|
5720
|
+
spinner?.succeed(`Found ${entities.length} results`);
|
|
5660
5721
|
if (opts.json) {
|
|
5661
5722
|
console.log(JSON.stringify(entities, null, 2));
|
|
5662
5723
|
return;
|
|
@@ -5835,21 +5896,21 @@ function formatTimestamp(ts) {
|
|
|
5835
5896
|
var logsCommand = new Command14("logs").description("View and debug agent conversations");
|
|
5836
5897
|
logsCommand.command("list", { isDefault: true }).description("List recent conversations").option("--env <environment>", "Environment (development|production|eval)", "development").option("--agent <slug>", "Filter by agent slug").option("--channel <channel>", "Filter by channel (api|whatsapp|widget|dashboard)").option("--phone <number>", "Filter by phone number").option("--limit <n>", "Maximum results", "20").option("--json", "Output raw JSON").action(async (opts) => {
|
|
5837
5898
|
await ensureAuth2();
|
|
5838
|
-
const spinner = ora12();
|
|
5899
|
+
const spinner = opts.json ? null : ora12();
|
|
5839
5900
|
const orgId = getOrgId2();
|
|
5840
5901
|
let agentId;
|
|
5841
5902
|
if (opts.agent) {
|
|
5842
|
-
spinner
|
|
5903
|
+
spinner?.start(`Resolving agent "${opts.agent}"`);
|
|
5843
5904
|
const resolved = await resolveAgentSlug(opts.agent, orgId);
|
|
5844
5905
|
if (resolved.error || !resolved.data) {
|
|
5845
|
-
spinner
|
|
5906
|
+
spinner?.fail("Agent not found");
|
|
5846
5907
|
console.log(chalk16.red("Error:"), resolved.error || `No agent matched "${opts.agent}"`);
|
|
5847
5908
|
process.exit(1);
|
|
5848
5909
|
}
|
|
5849
5910
|
agentId = resolved.data;
|
|
5850
|
-
spinner
|
|
5911
|
+
spinner?.succeed(`Agent resolved: ${opts.agent}`);
|
|
5851
5912
|
}
|
|
5852
|
-
spinner
|
|
5913
|
+
spinner?.start("Fetching conversations");
|
|
5853
5914
|
const { data, error } = await queryThreads({
|
|
5854
5915
|
environment: opts.env,
|
|
5855
5916
|
agentId,
|
|
@@ -5858,17 +5919,16 @@ logsCommand.command("list", { isDefault: true }).description("List recent conver
|
|
|
5858
5919
|
limit: parseInt(opts.limit, 10)
|
|
5859
5920
|
});
|
|
5860
5921
|
if (error || !data) {
|
|
5861
|
-
spinner
|
|
5922
|
+
spinner?.fail("Failed to fetch conversations");
|
|
5862
5923
|
console.log(chalk16.red("Error:"), error);
|
|
5863
5924
|
process.exit(1);
|
|
5864
5925
|
}
|
|
5865
5926
|
const threads = data;
|
|
5866
5927
|
if (opts.json) {
|
|
5867
|
-
spinner.stop();
|
|
5868
5928
|
console.log(JSON.stringify(threads, null, 2));
|
|
5869
5929
|
return;
|
|
5870
5930
|
}
|
|
5871
|
-
spinner
|
|
5931
|
+
spinner?.succeed(`Found ${threads.length} conversations`);
|
|
5872
5932
|
console.log();
|
|
5873
5933
|
renderTable([
|
|
5874
5934
|
{ key: "id", label: "ID", width: 14 },
|
|
@@ -5892,25 +5952,25 @@ logsCommand.command("list", { isDefault: true }).description("List recent conver
|
|
|
5892
5952
|
});
|
|
5893
5953
|
logsCommand.command("view <thread-id>").description("View conversation messages").option("--env <environment>", "Environment hint for resolving short IDs").option("--exec", "Include execution details").option("--verbose", "Show full tool call arguments and results").option("--tail", "Show most recent messages (use with --limit)").option("--json", "Output raw JSON").option("--limit <n>", "Message limit", "100").action(async (rawThreadId, opts) => {
|
|
5894
5954
|
await ensureAuth2();
|
|
5895
|
-
const spinner = ora12();
|
|
5896
|
-
spinner
|
|
5955
|
+
const spinner = opts.json ? null : ora12();
|
|
5956
|
+
spinner?.start("Resolving thread");
|
|
5897
5957
|
const resolved = await resolveThreadId(rawThreadId, opts.env);
|
|
5898
5958
|
if (resolved.error || !resolved.data) {
|
|
5899
|
-
spinner
|
|
5959
|
+
spinner?.fail("Thread not found");
|
|
5900
5960
|
console.log(chalk16.red("Error:"), resolved.error || `No thread matched "${rawThreadId}"`);
|
|
5901
5961
|
process.exit(1);
|
|
5902
5962
|
}
|
|
5903
5963
|
const threadId = resolved.data;
|
|
5904
|
-
spinner
|
|
5905
|
-
spinner
|
|
5964
|
+
spinner?.stop();
|
|
5965
|
+
spinner?.start("Fetching conversation");
|
|
5906
5966
|
const fetchLimit = opts.tail ? 1000 : parseInt(opts.limit, 10);
|
|
5907
5967
|
const { data, error } = await queryThreadDetail(threadId, fetchLimit);
|
|
5908
5968
|
if (error || !data) {
|
|
5909
|
-
spinner
|
|
5969
|
+
spinner?.fail("Failed to fetch conversation");
|
|
5910
5970
|
console.log(chalk16.red("Error:"), error || "Thread not found");
|
|
5911
5971
|
process.exit(1);
|
|
5912
5972
|
}
|
|
5913
|
-
spinner
|
|
5973
|
+
spinner?.stop();
|
|
5914
5974
|
const result = data;
|
|
5915
5975
|
let executions = [];
|
|
5916
5976
|
if (opts.exec) {
|
|
@@ -6791,7 +6851,7 @@ var templatesCommand = new Command16("templates").description("Manage WhatsApp m
|
|
|
6791
6851
|
templatesCommand.command("list").description("List all message templates").option("--env <environment>", "Environment to find connection (development|production|eval)").option("--json", "Output raw JSON").action(async (opts) => {
|
|
6792
6852
|
await ensureAuth3();
|
|
6793
6853
|
const connectionId = await resolveConnectionId(opts.env ?? "production");
|
|
6794
|
-
const out = createOutput();
|
|
6854
|
+
const out = opts.json ? createSilentOutput() : createOutput();
|
|
6795
6855
|
out.start("Fetching templates");
|
|
6796
6856
|
const { data, error } = await listTemplates(connectionId);
|
|
6797
6857
|
if (error) {
|
|
@@ -6853,22 +6913,22 @@ templatesCommand.command("create <name>").description("Create a new message temp
|
|
|
6853
6913
|
console.log(chalk18.red("Components must be a JSON array"));
|
|
6854
6914
|
process.exit(1);
|
|
6855
6915
|
}
|
|
6856
|
-
const out = createOutput();
|
|
6916
|
+
const out = opts.json ? createSilentOutput() : createOutput();
|
|
6857
6917
|
out.start(`Creating template "${name}"`);
|
|
6858
6918
|
const { data, error } = await createTemplate(connectionId, name, opts.language, opts.category.toUpperCase(), components, opts.allowCategoryChange);
|
|
6859
|
-
|
|
6919
|
+
const result = data;
|
|
6920
|
+
if (error || result?.error) {
|
|
6860
6921
|
out.fail("Failed to create template");
|
|
6861
|
-
out.error(error);
|
|
6922
|
+
out.error(error ?? result?.error ?? "Unknown error");
|
|
6862
6923
|
process.exit(1);
|
|
6863
6924
|
}
|
|
6864
|
-
const result = data;
|
|
6865
6925
|
out.succeed(`Template "${name}" created`);
|
|
6866
6926
|
if (opts.json) {
|
|
6867
6927
|
console.log(JSON.stringify(result, null, 2));
|
|
6868
6928
|
} else {
|
|
6869
6929
|
console.log();
|
|
6870
6930
|
console.log(` ${chalk18.gray("ID:")} ${result.id}`);
|
|
6871
|
-
console.log(` ${chalk18.gray("Status:")} ${statusColor2(result.status)}`);
|
|
6931
|
+
console.log(` ${chalk18.gray("Status:")} ${statusColor2(result.status ?? "")}`);
|
|
6872
6932
|
console.log(` ${chalk18.gray("Category:")} ${result.category}`);
|
|
6873
6933
|
console.log();
|
|
6874
6934
|
}
|
|
@@ -6900,7 +6960,7 @@ templatesCommand.command("delete <name>").description("Delete a message template
|
|
|
6900
6960
|
templatesCommand.command("status <name>").description("Check template approval status").option("--env <environment>", "Environment to find connection").option("--connection <id>", "WhatsApp connection ID").option("--json", "Output raw JSON").action(async (name, opts) => {
|
|
6901
6961
|
await ensureAuth3();
|
|
6902
6962
|
const connectionId = await resolveConnectionId(opts.env ?? "production", opts.connection);
|
|
6903
|
-
const out = createOutput();
|
|
6963
|
+
const out = opts.json ? createSilentOutput() : createOutput();
|
|
6904
6964
|
out.start(`Checking status for "${name}"`);
|
|
6905
6965
|
const { data, error } = await getTemplateStatus(connectionId, name);
|
|
6906
6966
|
if (error) {
|
|
@@ -6938,7 +6998,7 @@ templatesCommand.command("status <name>").description("Check template approval s
|
|
|
6938
6998
|
templatesCommand.command("edit <name>").description("Edit a message template").option("--env <environment>", "Environment to find connection").option("--connection <id>", "WhatsApp connection ID").option("--components <json>", "New components as JSON string").option("--file <path>", "Read components from a JSON file").option("--category <cat>", "New category (UTILITY|MARKETING|AUTHENTICATION)").option("--language <code>", "Language code").option("--json", "Output raw JSON").action(async (name, opts) => {
|
|
6939
6999
|
await ensureAuth3();
|
|
6940
7000
|
const connectionId = await resolveConnectionId(opts.env ?? "production", opts.connection);
|
|
6941
|
-
const out = createOutput();
|
|
7001
|
+
const out = opts.json ? createSilentOutput() : createOutput();
|
|
6942
7002
|
out.start(`Fetching template "${name}"`);
|
|
6943
7003
|
const { data: statusData, error: statusError } = await getTemplateStatus(connectionId, name);
|
|
6944
7004
|
if (statusError) {
|
|
@@ -7137,9 +7197,15 @@ async function listIntegrationConfigs(env) {
|
|
|
7137
7197
|
async function setIntegrationStatus(provider, env, status) {
|
|
7138
7198
|
return convexMutation4("integrations:setConfigStatus", { provider, environment: env, status });
|
|
7139
7199
|
}
|
|
7200
|
+
async function createVoiceConnection(args) {
|
|
7201
|
+
return convexMutation4("voiceConnections:createConnection", args);
|
|
7202
|
+
}
|
|
7203
|
+
async function setVoicePhoneAgent(args) {
|
|
7204
|
+
return convexMutation4("voiceConnections:setPhoneAgentBySlug", args);
|
|
7205
|
+
}
|
|
7140
7206
|
|
|
7141
7207
|
// src/cli/commands/integration.ts
|
|
7142
|
-
var VALID_PROVIDERS = ["airtable", "resend", "flow"];
|
|
7208
|
+
var VALID_PROVIDERS = ["airtable", "resend", "flow", "twilio"];
|
|
7143
7209
|
async function ensureAuth4() {
|
|
7144
7210
|
const cwd = process.cwd();
|
|
7145
7211
|
const nonInteractive = !isInteractive();
|
|
@@ -7194,6 +7260,8 @@ function getProviderHelp(provider) {
|
|
|
7194
7260
|
return `Usage: struere integration resend --from-email <email> [--from-name <name>] [--reply-to <email>]`;
|
|
7195
7261
|
case "flow":
|
|
7196
7262
|
return `Usage: struere integration flow --api-url <url> --api-key <key> --secret-key <secret> [--return-url <url>]`;
|
|
7263
|
+
case "twilio":
|
|
7264
|
+
return `Usage: struere integration twilio --account-sid <sid> --auth-token <token> --phone-number <number> [--router <slug>] [--agent <slug>]`;
|
|
7197
7265
|
default:
|
|
7198
7266
|
return "";
|
|
7199
7267
|
}
|
|
@@ -7235,12 +7303,22 @@ function buildConfigFromOpts(provider, opts) {
|
|
|
7235
7303
|
return null;
|
|
7236
7304
|
return config;
|
|
7237
7305
|
}
|
|
7306
|
+
if (provider === "twilio") {
|
|
7307
|
+
const config = {};
|
|
7308
|
+
if (opts.accountSid)
|
|
7309
|
+
config.accountSid = opts.accountSid;
|
|
7310
|
+
if (opts.authToken)
|
|
7311
|
+
config.authToken = opts.authToken;
|
|
7312
|
+
if (Object.keys(config).length === 0)
|
|
7313
|
+
return null;
|
|
7314
|
+
return config;
|
|
7315
|
+
}
|
|
7238
7316
|
return null;
|
|
7239
7317
|
}
|
|
7240
|
-
var integrationCommand = new Command17("integration").description("Manage integrations").argument("[provider]", "Integration provider (airtable, resend, flow)").option("--env <environment>", "Environment (development|production)", "development").option("--token <pat>", "Personal access token (airtable)").option("--base-id <id>", "Default base ID (airtable)").option("--from-email <email>", "From email address (resend)").option("--from-name <name>", "From display name (resend)").option("--reply-to <email>", "Reply-to address (resend)").option("--api-url <url>", "API URL (flow)").option("--api-key <key>", "API key (flow)").option("--secret-key <secret>", "Secret key (flow)").option("--return-url <url>", "Return URL after payment (flow)").option("--test", "Test the connection after saving").option("--remove", "Remove integration config").option("--enable", "Enable integration").option("--disable", "Disable integration").option("--status", "Show current config status").option("--yes", "Skip confirmation prompts").option("--json", "Output raw JSON").action(async (provider, opts) => {
|
|
7318
|
+
var integrationCommand = new Command17("integration").description("Manage integrations").argument("[provider]", "Integration provider (airtable, resend, flow)").option("--env <environment>", "Environment (development|production)", "development").option("--token <pat>", "Personal access token (airtable)").option("--base-id <id>", "Default base ID (airtable)").option("--from-email <email>", "From email address (resend)").option("--from-name <name>", "From display name (resend)").option("--reply-to <email>", "Reply-to address (resend)").option("--api-url <url>", "API URL (flow)").option("--api-key <key>", "API key (flow)").option("--secret-key <secret>", "Secret key (flow)").option("--return-url <url>", "Return URL after payment (flow)").option("--account-sid <sid>", "Twilio Account SID (twilio)").option("--auth-token <token>", "Twilio Auth Token (twilio)").option("--phone-number <number>", "Twilio phone number in E.164 format (twilio)").option("--router <slug>", "Router slug to assign to phone number (twilio)").option("--agent <slug>", "Agent slug to assign to phone number (twilio)").option("--test", "Test the connection after saving").option("--remove", "Remove integration config").option("--enable", "Enable integration").option("--disable", "Disable integration").option("--status", "Show current config status").option("--yes", "Skip confirmation prompts").option("--json", "Output raw JSON").action(async (provider, opts) => {
|
|
7241
7319
|
await ensureAuth4();
|
|
7242
7320
|
const env = opts.env;
|
|
7243
|
-
const out = createOutput();
|
|
7321
|
+
const out = opts.json ? createSilentOutput() : createOutput();
|
|
7244
7322
|
if (!provider || provider === "list") {
|
|
7245
7323
|
out.start("Fetching integrations");
|
|
7246
7324
|
const { data, error } = await listIntegrationConfigs(env);
|
|
@@ -7336,6 +7414,39 @@ var integrationCommand = new Command17("integration").description("Manage integr
|
|
|
7336
7414
|
process.exit(1);
|
|
7337
7415
|
}
|
|
7338
7416
|
out.succeed(`${provider} config saved`);
|
|
7417
|
+
if (provider === "twilio" && opts.phoneNumber) {
|
|
7418
|
+
const phoneNumber = opts.phoneNumber.startsWith("+") ? opts.phoneNumber : `+${opts.phoneNumber}`;
|
|
7419
|
+
out.start(`Adding voice connection for ${phoneNumber}`);
|
|
7420
|
+
const { data: connData, error: connError } = await createVoiceConnection({
|
|
7421
|
+
twilioAccountSid: config.accountSid,
|
|
7422
|
+
twilioPhoneNumber: phoneNumber,
|
|
7423
|
+
label: `Twilio ${phoneNumber}`,
|
|
7424
|
+
environment: env
|
|
7425
|
+
});
|
|
7426
|
+
if (connError) {
|
|
7427
|
+
out.fail(`Failed to create voice connection`);
|
|
7428
|
+
out.error(connError);
|
|
7429
|
+
} else {
|
|
7430
|
+
out.succeed(`Voice connection created for ${phoneNumber}`);
|
|
7431
|
+
const conn = connData;
|
|
7432
|
+
if (connData && (opts.router || opts.agent)) {
|
|
7433
|
+
out.start(`Assigning ${opts.router ? "router" : "agent"}`);
|
|
7434
|
+
const connectionId = connData;
|
|
7435
|
+
const assignArgs = { connectionId };
|
|
7436
|
+
if (opts.router)
|
|
7437
|
+
assignArgs.routerSlug = opts.router;
|
|
7438
|
+
if (opts.agent)
|
|
7439
|
+
assignArgs.agentSlug = opts.agent;
|
|
7440
|
+
const { error: assignError } = await setVoicePhoneAgent(assignArgs);
|
|
7441
|
+
if (assignError) {
|
|
7442
|
+
out.fail(`Failed to assign`);
|
|
7443
|
+
out.error(assignError);
|
|
7444
|
+
} else {
|
|
7445
|
+
out.succeed(`Assigned to ${opts.router ? `router: ${opts.router}` : `agent: ${opts.agent}`}`);
|
|
7446
|
+
}
|
|
7447
|
+
}
|
|
7448
|
+
}
|
|
7449
|
+
}
|
|
7339
7450
|
if (opts.test) {
|
|
7340
7451
|
out.start(`Testing ${provider} connection`);
|
|
7341
7452
|
const { data: testData, error: testError } = await testIntegrationConnection(provider, env);
|
|
@@ -7723,9 +7834,9 @@ function renderExecutionLog(executionLog, verbose) {
|
|
|
7723
7834
|
var triggersCommand = new Command18("triggers").description("Manage triggers and automation runs");
|
|
7724
7835
|
triggersCommand.command("list", { isDefault: true }).description("List all triggers").option("--env <environment>", "Environment (development|production|eval)", "development").option("--json", "Output raw JSON").option("--failed", "Show only triggers with recent failures").action(async (opts) => {
|
|
7725
7836
|
await ensureAuth5();
|
|
7726
|
-
const spinner = ora14();
|
|
7837
|
+
const spinner = opts.json ? null : ora14();
|
|
7727
7838
|
try {
|
|
7728
|
-
spinner
|
|
7839
|
+
spinner?.start("Fetching triggers");
|
|
7729
7840
|
const [triggers, statuses] = await Promise.all([
|
|
7730
7841
|
listTriggers(opts.env),
|
|
7731
7842
|
getLastRunStatuses(opts.env)
|
|
@@ -7734,7 +7845,7 @@ triggersCommand.command("list", { isDefault: true }).description("List all trigg
|
|
|
7734
7845
|
if (opts.failed) {
|
|
7735
7846
|
filtered = triggers.filter((t) => statuses[t.slug]?.status === "failed");
|
|
7736
7847
|
}
|
|
7737
|
-
spinner
|
|
7848
|
+
spinner?.succeed(`Found ${filtered.length} triggers${opts.failed ? " (failed only)" : ""}`);
|
|
7738
7849
|
if (opts.json) {
|
|
7739
7850
|
console.log(JSON.stringify(filtered, null, 2));
|
|
7740
7851
|
return;
|
|
@@ -7760,7 +7871,7 @@ triggersCommand.command("list", { isDefault: true }).description("List all trigg
|
|
|
7760
7871
|
console.log();
|
|
7761
7872
|
} catch (err) {
|
|
7762
7873
|
const message = err instanceof Error ? err.message : String(err);
|
|
7763
|
-
spinner
|
|
7874
|
+
spinner?.fail("Failed to fetch triggers");
|
|
7764
7875
|
if (opts.json) {
|
|
7765
7876
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
7766
7877
|
} else {
|
|
@@ -7771,18 +7882,18 @@ triggersCommand.command("list", { isDefault: true }).description("List all trigg
|
|
|
7771
7882
|
});
|
|
7772
7883
|
triggersCommand.command("get <slug>").description("View trigger details").option("--env <environment>", "Environment", "development").option("--json", "Output raw JSON").action(async (slug, opts) => {
|
|
7773
7884
|
await ensureAuth5();
|
|
7774
|
-
const spinner = ora14();
|
|
7885
|
+
const spinner = opts.json ? null : ora14();
|
|
7775
7886
|
try {
|
|
7776
|
-
spinner
|
|
7887
|
+
spinner?.start("Fetching trigger");
|
|
7777
7888
|
const trigger = await getTrigger(slug, opts.env);
|
|
7778
7889
|
if (!trigger) {
|
|
7779
|
-
spinner
|
|
7890
|
+
spinner?.fail("Trigger not found");
|
|
7780
7891
|
if (opts.json) {
|
|
7781
7892
|
console.log(JSON.stringify({ success: false, error: "Trigger not found" }));
|
|
7782
7893
|
}
|
|
7783
7894
|
process.exit(1);
|
|
7784
7895
|
}
|
|
7785
|
-
spinner
|
|
7896
|
+
spinner?.succeed("Trigger loaded");
|
|
7786
7897
|
if (opts.json) {
|
|
7787
7898
|
console.log(JSON.stringify(trigger, null, 2));
|
|
7788
7899
|
return;
|
|
@@ -7839,7 +7950,7 @@ triggersCommand.command("get <slug>").description("View trigger details").option
|
|
|
7839
7950
|
console.log();
|
|
7840
7951
|
} catch (err) {
|
|
7841
7952
|
const message = err instanceof Error ? err.message : String(err);
|
|
7842
|
-
spinner
|
|
7953
|
+
spinner?.fail("Failed to fetch trigger");
|
|
7843
7954
|
if (opts.json) {
|
|
7844
7955
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
7845
7956
|
} else {
|
|
@@ -7850,16 +7961,16 @@ triggersCommand.command("get <slug>").description("View trigger details").option
|
|
|
7850
7961
|
});
|
|
7851
7962
|
triggersCommand.command("runs [slug]").description("List trigger runs").option("--env <environment>", "Environment", "development").option("--status <status>", "Filter by status (pending|running|completed|failed|dead)").option("--limit <n>", "Maximum results", "20").option("--json", "Output raw JSON").action(async (slug, opts) => {
|
|
7852
7963
|
await ensureAuth5();
|
|
7853
|
-
const spinner = ora14();
|
|
7964
|
+
const spinner = opts.json ? null : ora14();
|
|
7854
7965
|
try {
|
|
7855
|
-
spinner
|
|
7966
|
+
spinner?.start("Fetching runs");
|
|
7856
7967
|
const runs = await listTriggerRuns({
|
|
7857
7968
|
environment: opts.env,
|
|
7858
7969
|
status: opts.status,
|
|
7859
7970
|
triggerSlug: slug,
|
|
7860
7971
|
limit: parseInt(opts.limit, 10)
|
|
7861
7972
|
});
|
|
7862
|
-
spinner
|
|
7973
|
+
spinner?.succeed(`Found ${runs.length} runs`);
|
|
7863
7974
|
if (opts.json) {
|
|
7864
7975
|
console.log(JSON.stringify(runs, null, 2));
|
|
7865
7976
|
return;
|
|
@@ -7885,7 +7996,7 @@ triggersCommand.command("runs [slug]").description("List trigger runs").option("
|
|
|
7885
7996
|
console.log();
|
|
7886
7997
|
} catch (err) {
|
|
7887
7998
|
const message = err instanceof Error ? err.message : String(err);
|
|
7888
|
-
spinner
|
|
7999
|
+
spinner?.fail("Failed to fetch runs");
|
|
7889
8000
|
if (opts.json) {
|
|
7890
8001
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
7891
8002
|
} else {
|
|
@@ -7896,18 +8007,18 @@ triggersCommand.command("runs [slug]").description("List trigger runs").option("
|
|
|
7896
8007
|
});
|
|
7897
8008
|
triggersCommand.command("run <run-id>").description("View trigger run details").option("--env <environment>", "Environment", "development").option("--json", "Output raw JSON").option("-v, --verbose", "Show detailed agent tool calls").action(async (runId, opts) => {
|
|
7898
8009
|
await ensureAuth5();
|
|
7899
|
-
const spinner = ora14();
|
|
8010
|
+
const spinner = opts.json ? null : ora14();
|
|
7900
8011
|
try {
|
|
7901
|
-
spinner
|
|
8012
|
+
spinner?.start("Fetching run");
|
|
7902
8013
|
const run = await getTriggerRunDetail(runId, opts.env);
|
|
7903
8014
|
if (!run) {
|
|
7904
|
-
spinner
|
|
8015
|
+
spinner?.fail("Run not found");
|
|
7905
8016
|
if (opts.json) {
|
|
7906
8017
|
console.log(JSON.stringify({ success: false, error: "Run not found" }));
|
|
7907
8018
|
}
|
|
7908
8019
|
process.exit(1);
|
|
7909
8020
|
}
|
|
7910
|
-
spinner
|
|
8021
|
+
spinner?.succeed("Run loaded");
|
|
7911
8022
|
if (opts.json) {
|
|
7912
8023
|
console.log(JSON.stringify(run, null, 2));
|
|
7913
8024
|
return;
|
|
@@ -7930,7 +8041,7 @@ triggersCommand.command("run <run-id>").description("View trigger run details").
|
|
|
7930
8041
|
console.log();
|
|
7931
8042
|
} catch (err) {
|
|
7932
8043
|
const message = err instanceof Error ? err.message : String(err);
|
|
7933
|
-
spinner
|
|
8044
|
+
spinner?.fail("Failed to fetch run");
|
|
7934
8045
|
if (opts.json) {
|
|
7935
8046
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
7936
8047
|
} else {
|
|
@@ -7941,11 +8052,11 @@ triggersCommand.command("run <run-id>").description("View trigger run details").
|
|
|
7941
8052
|
});
|
|
7942
8053
|
triggersCommand.command("stats").description("Show trigger run statistics").option("--env <environment>", "Environment", "development").option("--json", "Output raw JSON").action(async (opts) => {
|
|
7943
8054
|
await ensureAuth5();
|
|
7944
|
-
const spinner = ora14();
|
|
8055
|
+
const spinner = opts.json ? null : ora14();
|
|
7945
8056
|
try {
|
|
7946
|
-
spinner
|
|
8057
|
+
spinner?.start("Fetching statistics");
|
|
7947
8058
|
const stats = await getTriggerRunStats(opts.env);
|
|
7948
|
-
spinner
|
|
8059
|
+
spinner?.succeed("Run statistics");
|
|
7949
8060
|
if (opts.json) {
|
|
7950
8061
|
console.log(JSON.stringify(stats, null, 2));
|
|
7951
8062
|
return;
|
|
@@ -7984,7 +8095,7 @@ triggersCommand.command("stats").description("Show trigger run statistics").opti
|
|
|
7984
8095
|
console.log();
|
|
7985
8096
|
} catch (err) {
|
|
7986
8097
|
const message = err instanceof Error ? err.message : String(err);
|
|
7987
|
-
spinner
|
|
8098
|
+
spinner?.fail("Failed to fetch statistics");
|
|
7988
8099
|
if (opts.json) {
|
|
7989
8100
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
7990
8101
|
} else {
|
|
@@ -7995,15 +8106,15 @@ triggersCommand.command("stats").description("Show trigger run statistics").opti
|
|
|
7995
8106
|
});
|
|
7996
8107
|
triggersCommand.command("logs [slug]").description("View trigger execution history").option("--env <environment>", "Environment", "development").option("--limit <n>", "Maximum results", "10").option("--json", "Output raw JSON").option("-v, --verbose", "Show full error messages").action(async (slug, opts) => {
|
|
7997
8108
|
await ensureAuth5();
|
|
7998
|
-
const spinner = ora14();
|
|
8109
|
+
const spinner = opts.json ? null : ora14();
|
|
7999
8110
|
try {
|
|
8000
|
-
spinner
|
|
8111
|
+
spinner?.start("Fetching execution logs");
|
|
8001
8112
|
const executions = await withTriggerAuthRetry(() => listTriggerExecutions({
|
|
8002
8113
|
environment: opts.env,
|
|
8003
8114
|
triggerSlug: slug,
|
|
8004
8115
|
limit: parseInt(opts.limit, 10)
|
|
8005
8116
|
}));
|
|
8006
|
-
spinner
|
|
8117
|
+
spinner?.succeed(`Found ${executions.length} executions`);
|
|
8007
8118
|
if (opts.json) {
|
|
8008
8119
|
console.log(JSON.stringify(executions, null, 2));
|
|
8009
8120
|
return;
|
|
@@ -8048,7 +8159,7 @@ triggersCommand.command("logs [slug]").description("View trigger execution histo
|
|
|
8048
8159
|
console.log();
|
|
8049
8160
|
} catch (err) {
|
|
8050
8161
|
const message = err instanceof Error ? err.message : String(err);
|
|
8051
|
-
spinner
|
|
8162
|
+
spinner?.fail("Failed to fetch execution logs");
|
|
8052
8163
|
if (opts.json) {
|
|
8053
8164
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
8054
8165
|
} else {
|
|
@@ -8059,7 +8170,7 @@ triggersCommand.command("logs [slug]").description("View trigger execution histo
|
|
|
8059
8170
|
});
|
|
8060
8171
|
triggersCommand.command("log <identifier>").description("View detailed trigger execution log (by event ID or trigger slug)").option("--env <environment>", "Environment", "development").option("--nth <n>", "Show nth most recent execution (when using slug)", "1").option("--json", "Output raw JSON").option("-v, --verbose", "Show detailed agent tool calls").action(async (identifier, opts) => {
|
|
8061
8172
|
await ensureAuth5();
|
|
8062
|
-
const spinner = ora14();
|
|
8173
|
+
const spinner = opts.json ? null : ora14();
|
|
8063
8174
|
try {
|
|
8064
8175
|
const nth = parseInt(opts.nth, 10);
|
|
8065
8176
|
if (isNaN(nth) || nth < 1) {
|
|
@@ -8069,14 +8180,14 @@ triggersCommand.command("log <identifier>").description("View detailed trigger e
|
|
|
8069
8180
|
let eventId = identifier;
|
|
8070
8181
|
const isConvexId = /^[0-9a-zA-Z]{20,}$/.test(identifier);
|
|
8071
8182
|
if (!isConvexId) {
|
|
8072
|
-
spinner
|
|
8183
|
+
spinner?.start("Resolving trigger slug to latest execution");
|
|
8073
8184
|
const executions = await withTriggerAuthRetry(() => listTriggerExecutions({
|
|
8074
8185
|
environment: opts.env,
|
|
8075
8186
|
triggerSlug: identifier,
|
|
8076
8187
|
limit: nth
|
|
8077
8188
|
}));
|
|
8078
8189
|
if (!executions.length) {
|
|
8079
|
-
spinner
|
|
8190
|
+
spinner?.fail(`No executions found for trigger "${identifier}" in ${opts.env}`);
|
|
8080
8191
|
if (opts.json) {
|
|
8081
8192
|
console.log(JSON.stringify({ success: false, error: `No executions found for trigger "${identifier}"` }));
|
|
8082
8193
|
}
|
|
@@ -8084,22 +8195,22 @@ triggersCommand.command("log <identifier>").description("View detailed trigger e
|
|
|
8084
8195
|
}
|
|
8085
8196
|
const idx = nth - 1;
|
|
8086
8197
|
if (idx >= executions.length) {
|
|
8087
|
-
spinner
|
|
8198
|
+
spinner?.fail(`Only ${executions.length} executions found, cannot get #${nth}`);
|
|
8088
8199
|
process.exit(1);
|
|
8089
8200
|
}
|
|
8090
8201
|
eventId = executions[idx]._id;
|
|
8091
|
-
spinner
|
|
8202
|
+
spinner?.succeed(`Found execution for "${identifier}"`);
|
|
8092
8203
|
}
|
|
8093
|
-
spinner
|
|
8204
|
+
spinner?.start("Fetching execution detail");
|
|
8094
8205
|
const event = await withTriggerAuthRetry(() => getTriggerExecutionDetail(eventId, opts.env));
|
|
8095
8206
|
if (!event) {
|
|
8096
|
-
spinner
|
|
8207
|
+
spinner?.fail("Execution not found");
|
|
8097
8208
|
if (opts.json) {
|
|
8098
8209
|
console.log(JSON.stringify({ success: false, error: "Execution not found" }));
|
|
8099
8210
|
}
|
|
8100
8211
|
process.exit(1);
|
|
8101
8212
|
}
|
|
8102
|
-
spinner
|
|
8213
|
+
spinner?.succeed("Execution loaded");
|
|
8103
8214
|
if (opts.json) {
|
|
8104
8215
|
console.log(JSON.stringify(event, null, 2));
|
|
8105
8216
|
return;
|
|
@@ -8129,7 +8240,7 @@ triggersCommand.command("log <identifier>").description("View detailed trigger e
|
|
|
8129
8240
|
}
|
|
8130
8241
|
} catch (err) {
|
|
8131
8242
|
const message = err instanceof Error ? err.message : String(err);
|
|
8132
|
-
spinner
|
|
8243
|
+
spinner?.fail("Failed to fetch execution detail");
|
|
8133
8244
|
if (opts.json) {
|
|
8134
8245
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
8135
8246
|
} else {
|
|
@@ -8140,7 +8251,7 @@ triggersCommand.command("log <identifier>").description("View detailed trigger e
|
|
|
8140
8251
|
});
|
|
8141
8252
|
triggersCommand.command("retry <run-id>").description("Retry a failed or dead run").option("--env <environment>", "Environment", "development").option("--json", "Output raw JSON").option("--confirm", "Skip production confirmation").action(async (runId, opts) => {
|
|
8142
8253
|
await ensureAuth5();
|
|
8143
|
-
const spinner = ora14();
|
|
8254
|
+
const spinner = opts.json ? null : ora14();
|
|
8144
8255
|
const environment = opts.env;
|
|
8145
8256
|
if (environment === "production" && !opts.confirm && isInteractive()) {
|
|
8146
8257
|
const readline = await import("readline");
|
|
@@ -8152,15 +8263,15 @@ triggersCommand.command("retry <run-id>").description("Retry a failed or dead ru
|
|
|
8152
8263
|
rl.close();
|
|
8153
8264
|
}
|
|
8154
8265
|
try {
|
|
8155
|
-
spinner
|
|
8266
|
+
spinner?.start("Retrying run...");
|
|
8156
8267
|
await retryTriggerRun(runId, environment);
|
|
8157
|
-
spinner
|
|
8268
|
+
spinner?.succeed(chalk20.green(`Run ${runId} queued for retry`));
|
|
8158
8269
|
if (opts.json) {
|
|
8159
8270
|
console.log(JSON.stringify({ success: true, runId }));
|
|
8160
8271
|
}
|
|
8161
8272
|
} catch (err) {
|
|
8162
8273
|
const message = err instanceof Error ? err.message : String(err);
|
|
8163
|
-
spinner
|
|
8274
|
+
spinner?.fail("Failed to retry run");
|
|
8164
8275
|
if (opts.json) {
|
|
8165
8276
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
8166
8277
|
} else {
|
|
@@ -8171,7 +8282,7 @@ triggersCommand.command("retry <run-id>").description("Retry a failed or dead ru
|
|
|
8171
8282
|
});
|
|
8172
8283
|
triggersCommand.command("cancel <run-id>").description("Cancel a pending run").option("--env <environment>", "Environment", "development").option("--json", "Output raw JSON").option("--confirm", "Skip production confirmation").action(async (runId, opts) => {
|
|
8173
8284
|
await ensureAuth5();
|
|
8174
|
-
const spinner = ora14();
|
|
8285
|
+
const spinner = opts.json ? null : ora14();
|
|
8175
8286
|
const environment = opts.env;
|
|
8176
8287
|
if (environment === "production" && !opts.confirm && isInteractive()) {
|
|
8177
8288
|
const readline = await import("readline");
|
|
@@ -8183,15 +8294,15 @@ triggersCommand.command("cancel <run-id>").description("Cancel a pending run").o
|
|
|
8183
8294
|
rl.close();
|
|
8184
8295
|
}
|
|
8185
8296
|
try {
|
|
8186
|
-
spinner
|
|
8297
|
+
spinner?.start("Cancelling run...");
|
|
8187
8298
|
await cancelTriggerRun(runId, environment);
|
|
8188
|
-
spinner
|
|
8299
|
+
spinner?.succeed(chalk20.green(`Run ${runId} cancelled`));
|
|
8189
8300
|
if (opts.json) {
|
|
8190
8301
|
console.log(JSON.stringify({ success: true, runId }));
|
|
8191
8302
|
}
|
|
8192
8303
|
} catch (err) {
|
|
8193
8304
|
const message = err instanceof Error ? err.message : String(err);
|
|
8194
|
-
spinner
|
|
8305
|
+
spinner?.fail("Failed to cancel run");
|
|
8195
8306
|
if (opts.json) {
|
|
8196
8307
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
8197
8308
|
} else {
|
|
@@ -8202,7 +8313,7 @@ triggersCommand.command("cancel <run-id>").description("Cancel a pending run").o
|
|
|
8202
8313
|
});
|
|
8203
8314
|
triggersCommand.command("enable <slug>").description("Enable a trigger").option("--env <environment>", "Environment", "development").option("--json", "Output raw JSON").option("--confirm", "Skip production confirmation").action(async (slug, opts) => {
|
|
8204
8315
|
await ensureAuth5();
|
|
8205
|
-
const spinner = ora14();
|
|
8316
|
+
const spinner = opts.json ? null : ora14();
|
|
8206
8317
|
const environment = opts.env;
|
|
8207
8318
|
if (environment === "production" && !opts.confirm && isInteractive()) {
|
|
8208
8319
|
const readline = await import("readline");
|
|
@@ -8214,15 +8325,15 @@ triggersCommand.command("enable <slug>").description("Enable a trigger").option(
|
|
|
8214
8325
|
rl.close();
|
|
8215
8326
|
}
|
|
8216
8327
|
try {
|
|
8217
|
-
spinner
|
|
8328
|
+
spinner?.start("Enabling trigger...");
|
|
8218
8329
|
await toggleTrigger(slug, true, environment);
|
|
8219
|
-
spinner
|
|
8330
|
+
spinner?.succeed(chalk20.green(`Trigger ${slug} enabled`));
|
|
8220
8331
|
if (opts.json) {
|
|
8221
8332
|
console.log(JSON.stringify({ success: true, slug }));
|
|
8222
8333
|
}
|
|
8223
8334
|
} catch (err) {
|
|
8224
8335
|
const message = err instanceof Error ? err.message : String(err);
|
|
8225
|
-
spinner
|
|
8336
|
+
spinner?.fail("Failed to enable trigger");
|
|
8226
8337
|
if (opts.json) {
|
|
8227
8338
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
8228
8339
|
} else {
|
|
@@ -8233,7 +8344,7 @@ triggersCommand.command("enable <slug>").description("Enable a trigger").option(
|
|
|
8233
8344
|
});
|
|
8234
8345
|
triggersCommand.command("disable <slug>").description("Disable a trigger").option("--env <environment>", "Environment", "development").option("--json", "Output raw JSON").option("--confirm", "Skip production confirmation").action(async (slug, opts) => {
|
|
8235
8346
|
await ensureAuth5();
|
|
8236
|
-
const spinner = ora14();
|
|
8347
|
+
const spinner = opts.json ? null : ora14();
|
|
8237
8348
|
const environment = opts.env;
|
|
8238
8349
|
if (environment === "production" && !opts.confirm && isInteractive()) {
|
|
8239
8350
|
const readline = await import("readline");
|
|
@@ -8245,15 +8356,15 @@ triggersCommand.command("disable <slug>").description("Disable a trigger").optio
|
|
|
8245
8356
|
rl.close();
|
|
8246
8357
|
}
|
|
8247
8358
|
try {
|
|
8248
|
-
spinner
|
|
8359
|
+
spinner?.start("Disabling trigger...");
|
|
8249
8360
|
await toggleTrigger(slug, false, environment);
|
|
8250
|
-
spinner
|
|
8361
|
+
spinner?.succeed(chalk20.green(`Trigger ${slug} disabled`));
|
|
8251
8362
|
if (opts.json) {
|
|
8252
8363
|
console.log(JSON.stringify({ success: true, slug }));
|
|
8253
8364
|
}
|
|
8254
8365
|
} catch (err) {
|
|
8255
8366
|
const message = err instanceof Error ? err.message : String(err);
|
|
8256
|
-
spinner
|
|
8367
|
+
spinner?.fail("Failed to disable trigger");
|
|
8257
8368
|
if (opts.json) {
|
|
8258
8369
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
8259
8370
|
} else {
|
|
@@ -8264,7 +8375,7 @@ triggersCommand.command("disable <slug>").description("Disable a trigger").optio
|
|
|
8264
8375
|
});
|
|
8265
8376
|
triggersCommand.command("retry-event <event-id>").description("Retry a failed immediate trigger execution").option("--env <environment>", "Environment (development|production|eval)", "development").option("--json", "Output raw JSON").option("--confirm", "Skip production confirmation").action(async (eventId, opts) => {
|
|
8266
8377
|
await ensureAuth5();
|
|
8267
|
-
const spinner = ora14();
|
|
8378
|
+
const spinner = opts.json ? null : ora14();
|
|
8268
8379
|
const environment = opts.env;
|
|
8269
8380
|
if (environment === "production" && !opts.confirm && isInteractive()) {
|
|
8270
8381
|
const readline = await import("readline");
|
|
@@ -8276,19 +8387,19 @@ triggersCommand.command("retry-event <event-id>").description("Retry a failed im
|
|
|
8276
8387
|
rl.close();
|
|
8277
8388
|
}
|
|
8278
8389
|
try {
|
|
8279
|
-
spinner
|
|
8390
|
+
spinner?.start("Retrying failed execution...");
|
|
8280
8391
|
const result = await retryImmediateExecution(eventId, environment);
|
|
8281
8392
|
if (result.success) {
|
|
8282
|
-
spinner
|
|
8393
|
+
spinner?.succeed(chalk20.green(`Execution retried successfully`));
|
|
8283
8394
|
} else {
|
|
8284
|
-
spinner
|
|
8395
|
+
spinner?.fail(chalk20.red(`Execution retry failed again`));
|
|
8285
8396
|
}
|
|
8286
8397
|
if (opts.json) {
|
|
8287
8398
|
console.log(JSON.stringify(result));
|
|
8288
8399
|
}
|
|
8289
8400
|
} catch (err) {
|
|
8290
8401
|
const message = err instanceof Error ? err.message : String(err);
|
|
8291
|
-
spinner
|
|
8402
|
+
spinner?.fail("Failed to retry execution");
|
|
8292
8403
|
if (opts.json) {
|
|
8293
8404
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
8294
8405
|
} else {
|
|
@@ -8299,7 +8410,7 @@ triggersCommand.command("retry-event <event-id>").description("Retry a failed im
|
|
|
8299
8410
|
});
|
|
8300
8411
|
triggersCommand.command("fire <slug>").description("Manually fire a trigger").option("--env <environment>", "Environment (development|production|eval)", "development").option("--entity <entityId>", "Entity ID to provide as context").option("--data <json>", "JSON data for template context").option("--json", "Output raw JSON").option("--confirm", "Skip production confirmation").option("-v, --verbose", "Show detailed agent tool calls").action(async (slug, opts) => {
|
|
8301
8412
|
await ensureAuth5();
|
|
8302
|
-
const spinner = ora14();
|
|
8413
|
+
const spinner = opts.json ? null : ora14();
|
|
8303
8414
|
const environment = opts.env;
|
|
8304
8415
|
if (environment === "production" && !opts.confirm && isInteractive()) {
|
|
8305
8416
|
const readline = await import("readline");
|
|
@@ -8320,7 +8431,7 @@ triggersCommand.command("fire <slug>").description("Manually fire a trigger").op
|
|
|
8320
8431
|
}
|
|
8321
8432
|
}
|
|
8322
8433
|
try {
|
|
8323
|
-
spinner
|
|
8434
|
+
spinner?.start(`Firing trigger ${chalk20.cyan(slug)}...`);
|
|
8324
8435
|
const { result, error } = await fireTrigger({
|
|
8325
8436
|
slug,
|
|
8326
8437
|
environment,
|
|
@@ -8328,7 +8439,7 @@ triggersCommand.command("fire <slug>").description("Manually fire a trigger").op
|
|
|
8328
8439
|
data
|
|
8329
8440
|
});
|
|
8330
8441
|
if (error) {
|
|
8331
|
-
spinner
|
|
8442
|
+
spinner?.fail("Trigger execution failed");
|
|
8332
8443
|
if (opts.json) {
|
|
8333
8444
|
console.log(JSON.stringify({ success: false, error }));
|
|
8334
8445
|
} else {
|
|
@@ -8337,13 +8448,13 @@ triggersCommand.command("fire <slug>").description("Manually fire a trigger").op
|
|
|
8337
8448
|
process.exit(1);
|
|
8338
8449
|
}
|
|
8339
8450
|
if (!result) {
|
|
8340
|
-
spinner
|
|
8451
|
+
spinner?.fail("No result returned");
|
|
8341
8452
|
process.exit(1);
|
|
8342
8453
|
}
|
|
8343
8454
|
if (result.success) {
|
|
8344
|
-
spinner
|
|
8455
|
+
spinner?.succeed(chalk20.green(`Trigger ${chalk20.cyan(slug)} fired successfully`));
|
|
8345
8456
|
} else {
|
|
8346
|
-
spinner
|
|
8457
|
+
spinner?.fail(chalk20.red(`Trigger ${chalk20.cyan(slug)} execution failed`));
|
|
8347
8458
|
}
|
|
8348
8459
|
if (opts.json) {
|
|
8349
8460
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -8361,7 +8472,7 @@ triggersCommand.command("fire <slug>").description("Manually fire a trigger").op
|
|
|
8361
8472
|
}
|
|
8362
8473
|
} catch (err) {
|
|
8363
8474
|
const message = err instanceof Error ? err.message : String(err);
|
|
8364
|
-
spinner
|
|
8475
|
+
spinner?.fail("Failed to fire trigger");
|
|
8365
8476
|
if (opts.json) {
|
|
8366
8477
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
8367
8478
|
} else {
|
|
@@ -8599,6 +8710,8 @@ function channelColor(channel) {
|
|
|
8599
8710
|
return chalk21.magenta(channel);
|
|
8600
8711
|
case "dashboard":
|
|
8601
8712
|
return chalk21.cyan(channel);
|
|
8713
|
+
case "voice":
|
|
8714
|
+
return chalk21.yellow(channel);
|
|
8602
8715
|
default:
|
|
8603
8716
|
return chalk21.gray(channel ?? "-");
|
|
8604
8717
|
}
|
|
@@ -8618,17 +8731,17 @@ function roleColor(role) {
|
|
|
8618
8731
|
}
|
|
8619
8732
|
}
|
|
8620
8733
|
var threadsCommand = new Command19("threads").description("Manage conversation threads");
|
|
8621
|
-
threadsCommand.command("list", { isDefault: true }).description("List conversation threads").option("--env <environment>", "Environment (development|production|eval)", "development").option("--channel <channel>", "Filter by channel (whatsapp|api|widget|dashboard)").option("--limit <n>", "Maximum results", "25").option("--json", "Output raw JSON").action(async (opts) => {
|
|
8734
|
+
threadsCommand.command("list", { isDefault: true }).description("List conversation threads").option("--env <environment>", "Environment (development|production|eval)", "development").option("--channel <channel>", "Filter by channel (whatsapp|api|widget|dashboard|voice)").option("--limit <n>", "Maximum results", "25").option("--json", "Output raw JSON").action(async (opts) => {
|
|
8622
8735
|
await ensureAuth6();
|
|
8623
|
-
const spinner = ora15();
|
|
8736
|
+
const spinner = opts.json ? null : ora15();
|
|
8624
8737
|
try {
|
|
8625
|
-
spinner
|
|
8738
|
+
spinner?.start("Fetching threads");
|
|
8626
8739
|
const threads = await listThreads({
|
|
8627
8740
|
environment: opts.env,
|
|
8628
8741
|
channel: opts.channel,
|
|
8629
8742
|
limit: parseInt(opts.limit, 10)
|
|
8630
8743
|
});
|
|
8631
|
-
spinner
|
|
8744
|
+
spinner?.succeed(`Found ${threads.length} threads`);
|
|
8632
8745
|
if (opts.json) {
|
|
8633
8746
|
console.log(JSON.stringify(threads, null, 2));
|
|
8634
8747
|
return;
|
|
@@ -8652,7 +8765,7 @@ threadsCommand.command("list", { isDefault: true }).description("List conversati
|
|
|
8652
8765
|
console.log();
|
|
8653
8766
|
} catch (err) {
|
|
8654
8767
|
const message = err instanceof Error ? err.message : String(err);
|
|
8655
|
-
spinner
|
|
8768
|
+
spinner?.fail("Failed to fetch threads");
|
|
8656
8769
|
if (opts.json) {
|
|
8657
8770
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
8658
8771
|
} else {
|
|
@@ -8663,21 +8776,21 @@ threadsCommand.command("list", { isDefault: true }).description("List conversati
|
|
|
8663
8776
|
});
|
|
8664
8777
|
threadsCommand.command("view <id>").description("View thread details and messages").option("--env <environment>", "Environment", "development").option("--json", "Output raw JSON").action(async (id, opts) => {
|
|
8665
8778
|
await ensureAuth6();
|
|
8666
|
-
const spinner = ora15();
|
|
8779
|
+
const spinner = opts.json ? null : ora15();
|
|
8667
8780
|
try {
|
|
8668
|
-
spinner
|
|
8781
|
+
spinner?.start("Fetching thread");
|
|
8669
8782
|
const thread = await getThreadWithMessages({
|
|
8670
8783
|
threadId: id,
|
|
8671
8784
|
environment: opts.env
|
|
8672
8785
|
});
|
|
8673
8786
|
if (!thread) {
|
|
8674
|
-
spinner
|
|
8787
|
+
spinner?.fail("Thread not found");
|
|
8675
8788
|
if (opts.json) {
|
|
8676
8789
|
console.log(JSON.stringify({ success: false, error: "Thread not found" }));
|
|
8677
8790
|
}
|
|
8678
8791
|
process.exit(1);
|
|
8679
8792
|
}
|
|
8680
|
-
spinner
|
|
8793
|
+
spinner?.succeed("Thread loaded");
|
|
8681
8794
|
if (opts.json) {
|
|
8682
8795
|
console.log(JSON.stringify(thread, null, 2));
|
|
8683
8796
|
return;
|
|
@@ -8710,7 +8823,7 @@ threadsCommand.command("view <id>").description("View thread details and message
|
|
|
8710
8823
|
console.log();
|
|
8711
8824
|
} catch (err) {
|
|
8712
8825
|
const message = err instanceof Error ? err.message : String(err);
|
|
8713
|
-
spinner
|
|
8826
|
+
spinner?.fail("Failed to fetch thread");
|
|
8714
8827
|
if (opts.json) {
|
|
8715
8828
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
8716
8829
|
} else {
|
|
@@ -8721,7 +8834,7 @@ threadsCommand.command("view <id>").description("View thread details and message
|
|
|
8721
8834
|
});
|
|
8722
8835
|
threadsCommand.command("archive <id>").description("Archive a thread (frees its externalId)").option("--env <environment>", "Environment", "development").option("--confirm", "Skip production confirmation").option("--json", "Output raw JSON").action(async (id, opts) => {
|
|
8723
8836
|
await ensureAuth6();
|
|
8724
|
-
const spinner = ora15();
|
|
8837
|
+
const spinner = opts.json ? null : ora15();
|
|
8725
8838
|
const environment = opts.env;
|
|
8726
8839
|
if (environment === "production" && !opts.confirm && isInteractive()) {
|
|
8727
8840
|
const readline = await import("readline");
|
|
@@ -8733,18 +8846,18 @@ threadsCommand.command("archive <id>").description("Archive a thread (frees its
|
|
|
8733
8846
|
rl.close();
|
|
8734
8847
|
}
|
|
8735
8848
|
try {
|
|
8736
|
-
spinner
|
|
8849
|
+
spinner?.start("Archiving thread...");
|
|
8737
8850
|
const result = await archiveThread({
|
|
8738
8851
|
threadId: id,
|
|
8739
8852
|
environment
|
|
8740
8853
|
});
|
|
8741
|
-
spinner
|
|
8854
|
+
spinner?.succeed(chalk21.green(`Thread ${id} archived`));
|
|
8742
8855
|
if (opts.json) {
|
|
8743
8856
|
console.log(JSON.stringify({ success: true, threadId: id }));
|
|
8744
8857
|
}
|
|
8745
8858
|
} catch (err) {
|
|
8746
8859
|
const message = err instanceof Error ? err.message : String(err);
|
|
8747
|
-
spinner
|
|
8860
|
+
spinner?.fail("Failed to archive thread");
|
|
8748
8861
|
if (opts.json) {
|
|
8749
8862
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
8750
8863
|
} else {
|
|
@@ -8755,7 +8868,7 @@ threadsCommand.command("archive <id>").description("Archive a thread (frees its
|
|
|
8755
8868
|
});
|
|
8756
8869
|
threadsCommand.command("reset").description("Archive a thread by phone number").requiredOption("--phone <number>", "Phone number to find and archive").option("--env <environment>", "Environment", "production").option("--confirm", "Skip production confirmation").option("--json", "Output raw JSON").action(async (opts) => {
|
|
8757
8870
|
await ensureAuth6();
|
|
8758
|
-
const spinner = ora15();
|
|
8871
|
+
const spinner = opts.json ? null : ora15();
|
|
8759
8872
|
const environment = opts.env;
|
|
8760
8873
|
if (environment === "production" && !opts.confirm && isInteractive()) {
|
|
8761
8874
|
const readline = await import("readline");
|
|
@@ -8767,30 +8880,31 @@ threadsCommand.command("reset").description("Archive a thread by phone number").
|
|
|
8767
8880
|
rl.close();
|
|
8768
8881
|
}
|
|
8769
8882
|
try {
|
|
8770
|
-
spinner
|
|
8883
|
+
spinner?.start(`Finding thread for phone ${opts.phone}...`);
|
|
8771
8884
|
const thread = await findThreadByPhone({
|
|
8772
8885
|
phone: opts.phone,
|
|
8773
8886
|
environment
|
|
8774
8887
|
});
|
|
8775
8888
|
if (!thread) {
|
|
8776
|
-
spinner
|
|
8889
|
+
spinner?.fail(`No thread found for phone number ${opts.phone}`);
|
|
8777
8890
|
if (opts.json) {
|
|
8778
8891
|
console.log(JSON.stringify({ success: false, error: "Thread not found for phone number" }));
|
|
8779
8892
|
}
|
|
8780
8893
|
process.exit(1);
|
|
8781
8894
|
}
|
|
8782
|
-
spinner
|
|
8895
|
+
if (spinner)
|
|
8896
|
+
spinner.text = `Archiving thread ${thread._id}...`;
|
|
8783
8897
|
await archiveThread({
|
|
8784
8898
|
threadId: thread._id,
|
|
8785
8899
|
environment
|
|
8786
8900
|
});
|
|
8787
|
-
spinner
|
|
8901
|
+
spinner?.succeed(chalk21.green(`Thread ${thread._id} archived (phone: ${opts.phone})`));
|
|
8788
8902
|
if (opts.json) {
|
|
8789
8903
|
console.log(JSON.stringify({ success: true, threadId: thread._id, phone: opts.phone }));
|
|
8790
8904
|
}
|
|
8791
8905
|
} catch (err) {
|
|
8792
8906
|
const message = err instanceof Error ? err.message : String(err);
|
|
8793
|
-
spinner
|
|
8907
|
+
spinner?.fail("Failed to reset thread");
|
|
8794
8908
|
if (opts.json) {
|
|
8795
8909
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
8796
8910
|
} else {
|
|
@@ -9502,7 +9616,7 @@ var whatsappCommand = new Command23("whatsapp").description("Manage WhatsApp con
|
|
|
9502
9616
|
whatsappCommand.command("list").description("List WhatsApp connections with routing assignments").option("--env <environment>", "Environment (development|production)", "production").option("--json", "Output raw JSON").action(async (opts) => {
|
|
9503
9617
|
await ensureAuth7();
|
|
9504
9618
|
const env = opts.env;
|
|
9505
|
-
const out = createOutput();
|
|
9619
|
+
const out = opts.json ? createSilentOutput() : createOutput();
|
|
9506
9620
|
out.start("Fetching WhatsApp connections");
|
|
9507
9621
|
const { data, error } = await listWhatsAppConnections(env);
|
|
9508
9622
|
if (error || !data) {
|
|
@@ -10448,14 +10562,14 @@ async function runCheck(fn) {
|
|
|
10448
10562
|
}
|
|
10449
10563
|
var doctorCommand = new Command25("doctor").description("Run diagnostic checks on your Struere project").option("--env <environment>", "Environment to check", "development").option("--json", "Output raw JSON").action(async (opts) => {
|
|
10450
10564
|
await ensureAuth8();
|
|
10451
|
-
const spinner = ora20();
|
|
10565
|
+
const spinner = opts.json ? null : ora20();
|
|
10452
10566
|
const cwd = process.cwd();
|
|
10453
10567
|
const environment = opts.env;
|
|
10454
10568
|
try {
|
|
10455
|
-
spinner
|
|
10569
|
+
spinner?.start("Loading resources...");
|
|
10456
10570
|
const resources = await loadAllResources(cwd);
|
|
10457
|
-
spinner
|
|
10458
|
-
spinner
|
|
10571
|
+
spinner?.succeed("Resources loaded");
|
|
10572
|
+
spinner?.start("Running diagnostics...");
|
|
10459
10573
|
const results = await Promise.allSettled([
|
|
10460
10574
|
runCheck(() => checkWhatsAppConnection(resources)),
|
|
10461
10575
|
runCheck(() => checkTemplateApprovals(resources)),
|
|
@@ -10465,7 +10579,7 @@ var doctorCommand = new Command25("doctor").description("Run diagnostic checks o
|
|
|
10465
10579
|
runCheck(() => checkTriggerHealth(environment)),
|
|
10466
10580
|
runCheck(() => checkSyncDrift(resources, environment))
|
|
10467
10581
|
]);
|
|
10468
|
-
spinner
|
|
10582
|
+
spinner?.stop();
|
|
10469
10583
|
const checks = results.map((r) => r.status === "fulfilled" ? r.value : { id: "unknown", label: "Unknown", status: "warn", message: `Check failed: ${r.reason}` });
|
|
10470
10584
|
const summary = {
|
|
10471
10585
|
ok: checks.filter((c) => c.status === "ok").length,
|
|
@@ -10508,7 +10622,7 @@ var doctorCommand = new Command25("doctor").description("Run diagnostic checks o
|
|
|
10508
10622
|
}
|
|
10509
10623
|
} catch (err) {
|
|
10510
10624
|
const message = err instanceof Error ? err.message : String(err);
|
|
10511
|
-
spinner
|
|
10625
|
+
spinner?.fail("Diagnostics failed");
|
|
10512
10626
|
if (opts.json) {
|
|
10513
10627
|
console.log(JSON.stringify({ success: false, error: message }));
|
|
10514
10628
|
} else {
|
|
@@ -10520,7 +10634,7 @@ var doctorCommand = new Command25("doctor").description("Run diagnostic checks o
|
|
|
10520
10634
|
// package.json
|
|
10521
10635
|
var package_default = {
|
|
10522
10636
|
name: "struere",
|
|
10523
|
-
version: "0.
|
|
10637
|
+
version: "0.14.1",
|
|
10524
10638
|
description: "Build, test, and deploy AI agents",
|
|
10525
10639
|
keywords: [
|
|
10526
10640
|
"ai",
|