struere 0.10.5 → 0.10.6
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 +464 -191
- package/dist/cli/commands/logs.d.ts.map +1 -1
- package/dist/cli/index.js +464 -191
- package/dist/cli/utils/logs.d.ts +22 -0
- package/dist/cli/utils/logs.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/bin/struere.js
CHANGED
|
@@ -2718,13 +2718,14 @@ function getBuiltinToolParameters(name) {
|
|
|
2718
2718
|
userId: { type: "string", description: "User ID (Convex or Clerk) whose calendar to create the event on" },
|
|
2719
2719
|
summary: { type: "string", description: "Event title" },
|
|
2720
2720
|
startTime: { type: "string", description: "Event start time (ISO 8601 datetime)" },
|
|
2721
|
-
endTime: { type: "string", description: "Event end time (ISO 8601 datetime)" },
|
|
2721
|
+
endTime: { type: "string", description: "Event end time (ISO 8601 datetime). Provide either endTime or durationMinutes" },
|
|
2722
|
+
durationMinutes: { type: "number", description: "Duration in minutes. Used to calculate endTime if endTime is not provided" },
|
|
2722
2723
|
description: { type: "string", description: "Event description" },
|
|
2723
2724
|
attendees: { type: "array", items: { type: "string" }, description: "List of attendee email addresses" },
|
|
2724
2725
|
timeZone: { type: "string", description: 'Time zone (e.g., "America/Santiago")' },
|
|
2725
2726
|
addGoogleMeet: { type: "boolean", description: "Set to true to automatically create a Google Meet video conference link for this event" }
|
|
2726
2727
|
},
|
|
2727
|
-
required: ["userId", "summary", "startTime"
|
|
2728
|
+
required: ["userId", "summary", "startTime"]
|
|
2728
2729
|
},
|
|
2729
2730
|
"calendar.update": {
|
|
2730
2731
|
type: "object",
|
|
@@ -5306,15 +5307,286 @@ entitiesCommand.command("search <type> <query>").description("Search records").o
|
|
|
5306
5307
|
console.log();
|
|
5307
5308
|
});
|
|
5308
5309
|
|
|
5309
|
-
// src/cli/commands/
|
|
5310
|
+
// src/cli/commands/logs.ts
|
|
5310
5311
|
import { Command as Command14 } from "commander";
|
|
5311
5312
|
import chalk16 from "chalk";
|
|
5312
5313
|
import ora12 from "ora";
|
|
5314
|
+
|
|
5315
|
+
// src/cli/utils/logs.ts
|
|
5316
|
+
function getToken2() {
|
|
5317
|
+
const credentials = loadCredentials();
|
|
5318
|
+
const apiKey = getApiKey();
|
|
5319
|
+
return apiKey || credentials?.token || null;
|
|
5320
|
+
}
|
|
5321
|
+
async function convexQuery2(path, args) {
|
|
5322
|
+
const token = getToken2();
|
|
5323
|
+
if (!token)
|
|
5324
|
+
return { error: "Not authenticated" };
|
|
5325
|
+
const response = await fetch(`${CONVEX_URL}/api/query`, {
|
|
5326
|
+
method: "POST",
|
|
5327
|
+
headers: {
|
|
5328
|
+
"Content-Type": "application/json",
|
|
5329
|
+
Authorization: `Bearer ${token}`
|
|
5330
|
+
},
|
|
5331
|
+
body: JSON.stringify({ path, args })
|
|
5332
|
+
});
|
|
5333
|
+
const text = await response.text();
|
|
5334
|
+
let json;
|
|
5335
|
+
try {
|
|
5336
|
+
json = JSON.parse(text);
|
|
5337
|
+
} catch {
|
|
5338
|
+
return { error: text || `HTTP ${response.status}` };
|
|
5339
|
+
}
|
|
5340
|
+
if (!response.ok) {
|
|
5341
|
+
const msg = json.errorData?.message || json.message || json.errorMessage || text;
|
|
5342
|
+
return { error: String(msg) };
|
|
5343
|
+
}
|
|
5344
|
+
if (json.status === "success")
|
|
5345
|
+
return { data: json.value };
|
|
5346
|
+
if (json.status === "error")
|
|
5347
|
+
return { error: String(json.errorMessage || "Unknown error") };
|
|
5348
|
+
return { error: `Unexpected response: ${text}` };
|
|
5349
|
+
}
|
|
5350
|
+
async function queryThreads(options) {
|
|
5351
|
+
return convexQuery2("threads:listWithPreviews", {
|
|
5352
|
+
environment: options.environment,
|
|
5353
|
+
...options.agentId && { agentId: options.agentId },
|
|
5354
|
+
...options.channel && { channel: options.channel },
|
|
5355
|
+
...options.limit && { limit: options.limit }
|
|
5356
|
+
});
|
|
5357
|
+
}
|
|
5358
|
+
async function queryThreadDetail(threadId, messageLimit) {
|
|
5359
|
+
return convexQuery2("threads:getWithMessages", {
|
|
5360
|
+
id: threadId,
|
|
5361
|
+
...messageLimit && { messageLimit }
|
|
5362
|
+
});
|
|
5363
|
+
}
|
|
5364
|
+
async function queryThreadExecutions(threadId) {
|
|
5365
|
+
return convexQuery2("executions:getByThread", { threadId });
|
|
5366
|
+
}
|
|
5367
|
+
async function resolveAgentSlug(slug, organizationId) {
|
|
5368
|
+
const result = await convexQuery2("agents:getBySlug", { slug, ...organizationId && { organizationId } });
|
|
5369
|
+
if (result.error)
|
|
5370
|
+
return { error: result.error };
|
|
5371
|
+
if (!result.data)
|
|
5372
|
+
return { error: `No agent found with slug "${slug}"` };
|
|
5373
|
+
const agent = result.data;
|
|
5374
|
+
return { data: agent._id };
|
|
5375
|
+
}
|
|
5376
|
+
|
|
5377
|
+
// src/cli/commands/logs.ts
|
|
5378
|
+
function getOrgId2() {
|
|
5379
|
+
const project = loadProject(process.cwd());
|
|
5380
|
+
return project?.organization.id;
|
|
5381
|
+
}
|
|
5382
|
+
async function ensureAuth2() {
|
|
5383
|
+
const cwd = process.cwd();
|
|
5384
|
+
const nonInteractive = !isInteractive();
|
|
5385
|
+
if (!hasProject(cwd)) {
|
|
5386
|
+
if (nonInteractive) {
|
|
5387
|
+
console.error(chalk16.red("No struere.json found. Run struere init first."));
|
|
5388
|
+
process.exit(1);
|
|
5389
|
+
}
|
|
5390
|
+
console.log(chalk16.yellow("No struere.json found - initializing project..."));
|
|
5391
|
+
console.log();
|
|
5392
|
+
const success = await runInit(cwd);
|
|
5393
|
+
if (!success) {
|
|
5394
|
+
process.exit(1);
|
|
5395
|
+
}
|
|
5396
|
+
console.log();
|
|
5397
|
+
}
|
|
5398
|
+
let credentials = loadCredentials();
|
|
5399
|
+
const apiKey = getApiKey();
|
|
5400
|
+
if (!credentials && !apiKey) {
|
|
5401
|
+
if (nonInteractive) {
|
|
5402
|
+
console.error(chalk16.red("Not authenticated. Set STRUERE_API_KEY or run struere login."));
|
|
5403
|
+
process.exit(1);
|
|
5404
|
+
}
|
|
5405
|
+
console.log(chalk16.yellow("Not logged in - authenticating..."));
|
|
5406
|
+
console.log();
|
|
5407
|
+
credentials = await performLogin();
|
|
5408
|
+
if (!credentials) {
|
|
5409
|
+
console.log(chalk16.red("Authentication failed"));
|
|
5410
|
+
process.exit(1);
|
|
5411
|
+
}
|
|
5412
|
+
console.log();
|
|
5413
|
+
}
|
|
5414
|
+
return true;
|
|
5415
|
+
}
|
|
5416
|
+
function relativeTime(ts) {
|
|
5417
|
+
const diff = Date.now() - ts;
|
|
5418
|
+
const seconds = Math.floor(diff / 1000);
|
|
5419
|
+
if (seconds < 60)
|
|
5420
|
+
return `${seconds}s ago`;
|
|
5421
|
+
const minutes = Math.floor(seconds / 60);
|
|
5422
|
+
if (minutes < 60)
|
|
5423
|
+
return `${minutes}m ago`;
|
|
5424
|
+
const hours = Math.floor(minutes / 60);
|
|
5425
|
+
if (hours < 24)
|
|
5426
|
+
return `${hours}h ago`;
|
|
5427
|
+
const days = Math.floor(hours / 24);
|
|
5428
|
+
return `${days}d ago`;
|
|
5429
|
+
}
|
|
5430
|
+
function formatTimestamp(ts) {
|
|
5431
|
+
const d = new Date(ts);
|
|
5432
|
+
return d.toTimeString().slice(0, 8);
|
|
5433
|
+
}
|
|
5434
|
+
var logsCommand = new Command14("logs").description("View and debug agent conversations");
|
|
5435
|
+
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("--limit <n>", "Maximum results", "20").option("--json", "Output raw JSON").action(async (opts) => {
|
|
5436
|
+
await ensureAuth2();
|
|
5437
|
+
const spinner = ora12();
|
|
5438
|
+
const orgId = getOrgId2();
|
|
5439
|
+
let agentId;
|
|
5440
|
+
if (opts.agent) {
|
|
5441
|
+
spinner.start(`Resolving agent "${opts.agent}"`);
|
|
5442
|
+
const resolved = await resolveAgentSlug(opts.agent, orgId);
|
|
5443
|
+
if (resolved.error || !resolved.data) {
|
|
5444
|
+
spinner.fail("Agent not found");
|
|
5445
|
+
console.log(chalk16.red("Error:"), resolved.error || `No agent matched "${opts.agent}"`);
|
|
5446
|
+
process.exit(1);
|
|
5447
|
+
}
|
|
5448
|
+
agentId = resolved.data;
|
|
5449
|
+
spinner.succeed(`Agent resolved: ${opts.agent}`);
|
|
5450
|
+
}
|
|
5451
|
+
spinner.start("Fetching conversations");
|
|
5452
|
+
const { data, error } = await queryThreads({
|
|
5453
|
+
environment: opts.env,
|
|
5454
|
+
agentId,
|
|
5455
|
+
channel: opts.channel,
|
|
5456
|
+
limit: parseInt(opts.limit, 10)
|
|
5457
|
+
});
|
|
5458
|
+
if (error || !data) {
|
|
5459
|
+
spinner.fail("Failed to fetch conversations");
|
|
5460
|
+
console.log(chalk16.red("Error:"), error);
|
|
5461
|
+
process.exit(1);
|
|
5462
|
+
}
|
|
5463
|
+
const threads = data;
|
|
5464
|
+
spinner.succeed(`Found ${threads.length} conversations`);
|
|
5465
|
+
if (opts.json) {
|
|
5466
|
+
console.log(JSON.stringify(threads, null, 2));
|
|
5467
|
+
return;
|
|
5468
|
+
}
|
|
5469
|
+
console.log();
|
|
5470
|
+
renderTable([
|
|
5471
|
+
{ key: "id", label: "ID", width: 14 },
|
|
5472
|
+
{ key: "agent", label: "Agent", width: 18 },
|
|
5473
|
+
{ key: "channel", label: "Channel", width: 10 },
|
|
5474
|
+
{ key: "participant", label: "Participant", width: 18 },
|
|
5475
|
+
{ key: "lastMessage", label: "Last Message", width: 40 },
|
|
5476
|
+
{ key: "time", label: "Time", width: 10 }
|
|
5477
|
+
], threads.map((t) => {
|
|
5478
|
+
const lastMsg = t.lastMessage;
|
|
5479
|
+
return {
|
|
5480
|
+
id: t._id?.slice(-12) ?? "",
|
|
5481
|
+
agent: t.agentName ?? "",
|
|
5482
|
+
channel: t.channel ?? "api",
|
|
5483
|
+
participant: t.participantName ?? "",
|
|
5484
|
+
lastMessage: lastMsg?.content ? String(lastMsg.content).slice(0, 60) : "",
|
|
5485
|
+
time: relativeTime(t.updatedAt ?? t.createdAt ?? Date.now())
|
|
5486
|
+
};
|
|
5487
|
+
}));
|
|
5488
|
+
console.log();
|
|
5489
|
+
});
|
|
5490
|
+
logsCommand.command("view <thread-id>").description("View conversation messages").option("--exec", "Include execution details").option("--json", "Output raw JSON").option("--limit <n>", "Message limit", "100").action(async (threadId, opts) => {
|
|
5491
|
+
await ensureAuth2();
|
|
5492
|
+
const spinner = ora12();
|
|
5493
|
+
spinner.start("Fetching conversation");
|
|
5494
|
+
const { data, error } = await queryThreadDetail(threadId, parseInt(opts.limit, 10));
|
|
5495
|
+
if (error || !data) {
|
|
5496
|
+
spinner.fail("Failed to fetch conversation");
|
|
5497
|
+
console.log(chalk16.red("Error:"), error || "Thread not found");
|
|
5498
|
+
process.exit(1);
|
|
5499
|
+
}
|
|
5500
|
+
spinner.succeed("Conversation loaded");
|
|
5501
|
+
const result = data;
|
|
5502
|
+
if (opts.json) {
|
|
5503
|
+
console.log(JSON.stringify(result, null, 2));
|
|
5504
|
+
return;
|
|
5505
|
+
}
|
|
5506
|
+
console.log();
|
|
5507
|
+
console.log(chalk16.bold(`Thread: ${result._id}`));
|
|
5508
|
+
console.log(chalk16.gray(` Environment: ${result.environment ?? "unknown"} Channel: ${result.channel ?? "api"}`));
|
|
5509
|
+
console.log(chalk16.gray("\u2500".repeat(60)));
|
|
5510
|
+
const messages = result.messages ?? [];
|
|
5511
|
+
for (let i = 0;i < messages.length; i++) {
|
|
5512
|
+
const msg = messages[i];
|
|
5513
|
+
const ts = formatTimestamp(msg.createdAt ?? msg._creationTime ?? Date.now());
|
|
5514
|
+
const role = msg.role;
|
|
5515
|
+
const content = msg.content ?? "";
|
|
5516
|
+
const toolCalls = msg.toolCalls;
|
|
5517
|
+
if (role === "user") {
|
|
5518
|
+
console.log();
|
|
5519
|
+
console.log(` ${chalk16.gray(`[${ts}]`)} ${chalk16.cyan("User")}`);
|
|
5520
|
+
console.log(` ${content}`);
|
|
5521
|
+
} else if (role === "assistant" && toolCalls?.length) {
|
|
5522
|
+
console.log();
|
|
5523
|
+
console.log(` ${chalk16.gray(`[${ts}]`)} ${chalk16.green("Agent")}`);
|
|
5524
|
+
if (content)
|
|
5525
|
+
console.log(` ${content}`);
|
|
5526
|
+
for (const call of toolCalls) {
|
|
5527
|
+
console.log(` ${chalk16.yellow("Tool: " + call.name)}`);
|
|
5528
|
+
console.log(` ${chalk16.dim("\u2192 " + JSON.stringify(call.arguments).slice(0, 200))}`);
|
|
5529
|
+
}
|
|
5530
|
+
} else if (role === "assistant") {
|
|
5531
|
+
console.log();
|
|
5532
|
+
console.log(` ${chalk16.gray(`[${ts}]`)} ${chalk16.green("Agent")}`);
|
|
5533
|
+
console.log(` ${content}`);
|
|
5534
|
+
} else if (role === "tool") {
|
|
5535
|
+
console.log(` ${chalk16.dim("\u2190 " + content.slice(0, 200))}`);
|
|
5536
|
+
} else if (role === "system") {
|
|
5537
|
+
console.log();
|
|
5538
|
+
console.log(` ${chalk16.dim("[System] " + content.slice(0, 100))}`);
|
|
5539
|
+
}
|
|
5540
|
+
}
|
|
5541
|
+
console.log();
|
|
5542
|
+
if (opts.exec) {
|
|
5543
|
+
spinner.start("Fetching executions");
|
|
5544
|
+
const execResult = await queryThreadExecutions(threadId);
|
|
5545
|
+
if (execResult.error || !execResult.data) {
|
|
5546
|
+
spinner.fail("Failed to fetch executions");
|
|
5547
|
+
console.log(chalk16.red("Error:"), execResult.error);
|
|
5548
|
+
return;
|
|
5549
|
+
}
|
|
5550
|
+
spinner.succeed("Executions loaded");
|
|
5551
|
+
const executions = execResult.data;
|
|
5552
|
+
console.log();
|
|
5553
|
+
console.log(chalk16.bold("Executions"));
|
|
5554
|
+
console.log(chalk16.gray("\u2500".repeat(60)));
|
|
5555
|
+
for (const exec of executions) {
|
|
5556
|
+
const status = exec.status;
|
|
5557
|
+
const statusColor = status === "success" ? chalk16.green : status === "error" ? chalk16.red : chalk16.yellow;
|
|
5558
|
+
const toolCallDetails = exec.toolCallDetails;
|
|
5559
|
+
console.log();
|
|
5560
|
+
console.log(` ${chalk16.gray("Status:")} ${statusColor(status)}`);
|
|
5561
|
+
if (exec.model)
|
|
5562
|
+
console.log(` ${chalk16.gray("Model:")} ${exec.model}`);
|
|
5563
|
+
if (exec.inputTokens || exec.outputTokens)
|
|
5564
|
+
console.log(` ${chalk16.gray("Tokens:")} ${exec.inputTokens ?? 0} in / ${exec.outputTokens ?? 0} out`);
|
|
5565
|
+
if (exec.durationMs)
|
|
5566
|
+
console.log(` ${chalk16.gray("Duration:")} ${exec.durationMs}ms`);
|
|
5567
|
+
if (toolCallDetails?.length) {
|
|
5568
|
+
console.log(` ${chalk16.gray("Tools:")} ${toolCallDetails.length} calls`);
|
|
5569
|
+
for (const tc of toolCallDetails) {
|
|
5570
|
+
console.log(` ${tc.name} (${tc.durationMs}ms) -> ${tc.status}`);
|
|
5571
|
+
}
|
|
5572
|
+
}
|
|
5573
|
+
if (exec.errorMessage) {
|
|
5574
|
+
console.log(` ${chalk16.red("Error:")} ${exec.errorMessage}`);
|
|
5575
|
+
}
|
|
5576
|
+
}
|
|
5577
|
+
console.log();
|
|
5578
|
+
}
|
|
5579
|
+
});
|
|
5580
|
+
|
|
5581
|
+
// src/cli/commands/eval.ts
|
|
5582
|
+
import { Command as Command15 } from "commander";
|
|
5583
|
+
import chalk17 from "chalk";
|
|
5584
|
+
import ora13 from "ora";
|
|
5313
5585
|
import { join as join9 } from "path";
|
|
5314
5586
|
import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync6 } from "fs";
|
|
5315
5587
|
|
|
5316
5588
|
// src/cli/utils/evals.ts
|
|
5317
|
-
function
|
|
5589
|
+
function getToken3() {
|
|
5318
5590
|
const credentials = loadCredentials();
|
|
5319
5591
|
const apiKey = getApiKey();
|
|
5320
5592
|
const token = apiKey || credentials?.token;
|
|
@@ -5322,8 +5594,8 @@ function getToken2() {
|
|
|
5322
5594
|
throw new Error("Not authenticated");
|
|
5323
5595
|
return token;
|
|
5324
5596
|
}
|
|
5325
|
-
async function
|
|
5326
|
-
const token =
|
|
5597
|
+
async function convexQuery3(path, args) {
|
|
5598
|
+
const token = getToken3();
|
|
5327
5599
|
const response = await fetch(`${CONVEX_URL}/api/query`, {
|
|
5328
5600
|
method: "POST",
|
|
5329
5601
|
headers: {
|
|
@@ -5348,7 +5620,7 @@ async function convexQuery2(path, args) {
|
|
|
5348
5620
|
return json.value;
|
|
5349
5621
|
}
|
|
5350
5622
|
async function convexMutation2(path, args) {
|
|
5351
|
-
const token =
|
|
5623
|
+
const token = getToken3();
|
|
5352
5624
|
const response = await fetch(`${CONVEX_URL}/api/mutation`, {
|
|
5353
5625
|
method: "POST",
|
|
5354
5626
|
headers: {
|
|
@@ -5373,10 +5645,10 @@ async function convexMutation2(path, args) {
|
|
|
5373
5645
|
return json.value;
|
|
5374
5646
|
}
|
|
5375
5647
|
async function listAllSuites(environment, organizationId) {
|
|
5376
|
-
return
|
|
5648
|
+
return convexQuery3("evals:listAllSuites", { environment, organizationId });
|
|
5377
5649
|
}
|
|
5378
5650
|
async function listCases(suiteId, organizationId) {
|
|
5379
|
-
return
|
|
5651
|
+
return convexQuery3("evals:listCases", { suiteId, organizationId });
|
|
5380
5652
|
}
|
|
5381
5653
|
async function startRun(suiteId, caseIds, organizationId) {
|
|
5382
5654
|
return convexMutation2("evals:startRun", {
|
|
@@ -5387,10 +5659,10 @@ async function startRun(suiteId, caseIds, organizationId) {
|
|
|
5387
5659
|
});
|
|
5388
5660
|
}
|
|
5389
5661
|
async function getRun(runId, organizationId) {
|
|
5390
|
-
return
|
|
5662
|
+
return convexQuery3("evals:getRun", { id: runId, organizationId });
|
|
5391
5663
|
}
|
|
5392
5664
|
async function getRunResults(runId, organizationId) {
|
|
5393
|
-
return
|
|
5665
|
+
return convexQuery3("evals:getRunResults", { runId, organizationId });
|
|
5394
5666
|
}
|
|
5395
5667
|
|
|
5396
5668
|
// src/cli/commands/eval.ts
|
|
@@ -5412,10 +5684,10 @@ function statusLabel(result) {
|
|
|
5412
5684
|
}
|
|
5413
5685
|
function statusColor(status) {
|
|
5414
5686
|
if (status === "PASS")
|
|
5415
|
-
return
|
|
5687
|
+
return chalk17.green;
|
|
5416
5688
|
if (status === "FAIL")
|
|
5417
|
-
return
|
|
5418
|
-
return
|
|
5689
|
+
return chalk17.red;
|
|
5690
|
+
return chalk17.yellow;
|
|
5419
5691
|
}
|
|
5420
5692
|
function generateSummaryMd(suiteName, suiteSlug, agentSlug, run, results) {
|
|
5421
5693
|
const timestamp = run.startedAt ? new Date(run.startedAt).toISOString() : new Date().toISOString();
|
|
@@ -5558,43 +5830,43 @@ ${turn.assistantResponse}
|
|
|
5558
5830
|
}
|
|
5559
5831
|
return md;
|
|
5560
5832
|
}
|
|
5561
|
-
var runCommand = new
|
|
5562
|
-
const spinner =
|
|
5833
|
+
var runCommand = new Command15("run").description("Run an eval suite").argument("<suite-slug>", "Eval suite slug to run").option("--case <name...>", "Run specific case(s) by name").option("--tag <tag...>", "Run cases matching tag(s)").option("--timeout <seconds>", "Max seconds to wait for results (default: 300)").action(async (suiteSlug, options) => {
|
|
5834
|
+
const spinner = ora13();
|
|
5563
5835
|
const cwd = process.cwd();
|
|
5564
5836
|
console.log();
|
|
5565
|
-
console.log(
|
|
5837
|
+
console.log(chalk17.bold("Struere Eval Run"));
|
|
5566
5838
|
console.log();
|
|
5567
5839
|
if (!hasProject(cwd)) {
|
|
5568
|
-
console.log(
|
|
5840
|
+
console.log(chalk17.yellow("No struere.json found - initializing project..."));
|
|
5569
5841
|
console.log();
|
|
5570
5842
|
await runInit(cwd);
|
|
5571
5843
|
console.log();
|
|
5572
5844
|
}
|
|
5573
5845
|
const project = loadProject(cwd);
|
|
5574
5846
|
if (!project) {
|
|
5575
|
-
console.log(
|
|
5847
|
+
console.log(chalk17.red("Failed to load struere.json"));
|
|
5576
5848
|
process.exit(1);
|
|
5577
5849
|
}
|
|
5578
5850
|
let credentials = loadCredentials();
|
|
5579
5851
|
const apiKey = getApiKey();
|
|
5580
5852
|
if (!credentials && !apiKey) {
|
|
5581
|
-
console.log(
|
|
5853
|
+
console.log(chalk17.yellow("Not logged in - authenticating..."));
|
|
5582
5854
|
console.log();
|
|
5583
5855
|
credentials = await performLogin();
|
|
5584
5856
|
if (!credentials) {
|
|
5585
|
-
console.log(
|
|
5857
|
+
console.log(chalk17.red("Authentication failed"));
|
|
5586
5858
|
process.exit(1);
|
|
5587
5859
|
}
|
|
5588
5860
|
console.log();
|
|
5589
5861
|
}
|
|
5590
|
-
console.log(
|
|
5862
|
+
console.log(chalk17.gray("Organization:"), chalk17.cyan(project.organization.name));
|
|
5591
5863
|
spinner.start("Syncing to eval environment");
|
|
5592
5864
|
try {
|
|
5593
5865
|
const resources = await loadAllResources(cwd);
|
|
5594
5866
|
if (resources.errors.length > 0) {
|
|
5595
5867
|
spinner.fail("Failed to load resources");
|
|
5596
5868
|
for (const err of resources.errors) {
|
|
5597
|
-
console.log(
|
|
5869
|
+
console.log(chalk17.red(" \u2716"), err);
|
|
5598
5870
|
}
|
|
5599
5871
|
process.exit(1);
|
|
5600
5872
|
}
|
|
@@ -5614,7 +5886,7 @@ var runCommand = new Command14("run").description("Run an eval suite").argument(
|
|
|
5614
5886
|
spinner.succeed("Synced to eval environment");
|
|
5615
5887
|
} catch (error) {
|
|
5616
5888
|
spinner.fail("Sync failed");
|
|
5617
|
-
console.log(
|
|
5889
|
+
console.log(chalk17.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
5618
5890
|
process.exit(1);
|
|
5619
5891
|
}
|
|
5620
5892
|
spinner.start("Resolving suite");
|
|
@@ -5623,30 +5895,30 @@ var runCommand = new Command14("run").description("Run an eval suite").argument(
|
|
|
5623
5895
|
suites = await listAllSuites("eval", project.organization.id);
|
|
5624
5896
|
} catch (error) {
|
|
5625
5897
|
spinner.fail("Failed to list suites");
|
|
5626
|
-
console.log(
|
|
5898
|
+
console.log(chalk17.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
5627
5899
|
process.exit(1);
|
|
5628
5900
|
}
|
|
5629
5901
|
const suite = suites.find((s) => s.slug === suiteSlug);
|
|
5630
5902
|
if (!suite) {
|
|
5631
5903
|
spinner.fail(`Suite "${suiteSlug}" not found`);
|
|
5632
5904
|
if (suites.length > 0) {
|
|
5633
|
-
console.log(
|
|
5905
|
+
console.log(chalk17.gray(" Available suites:"));
|
|
5634
5906
|
for (const s of suites) {
|
|
5635
|
-
console.log(
|
|
5907
|
+
console.log(chalk17.gray(` - ${s.slug}`), chalk17.dim(`(${s.name})`));
|
|
5636
5908
|
}
|
|
5637
5909
|
} else {
|
|
5638
|
-
console.log(
|
|
5910
|
+
console.log(chalk17.gray(" No eval suites found. Create one in evals/*.eval.yaml"));
|
|
5639
5911
|
}
|
|
5640
5912
|
process.exit(1);
|
|
5641
5913
|
}
|
|
5642
|
-
console.log(
|
|
5914
|
+
console.log(chalk17.gray("Suite:"), chalk17.cyan(`${suite.name} (${suite.slug})`));
|
|
5643
5915
|
console.log();
|
|
5644
5916
|
let cases;
|
|
5645
5917
|
try {
|
|
5646
5918
|
cases = await listCases(suite._id, project.organization.id);
|
|
5647
5919
|
} catch (error) {
|
|
5648
5920
|
spinner.fail("Failed to list cases");
|
|
5649
|
-
console.log(
|
|
5921
|
+
console.log(chalk17.red("Error:"), error instanceof Error ? error.message : String(error));
|
|
5650
5922
|
process.exit(1);
|
|
5651
5923
|
}
|
|
5652
5924
|
let filteredCaseIds;
|
|
@@ -5658,9 +5930,9 @@ var runCommand = new Command14("run").description("Run an eval suite").argument(
|
|
|
5658
5930
|
});
|
|
5659
5931
|
if (matched.length === 0) {
|
|
5660
5932
|
spinner.fail("No cases matched");
|
|
5661
|
-
console.log(
|
|
5933
|
+
console.log(chalk17.gray(" Available cases:"));
|
|
5662
5934
|
for (const c of cases) {
|
|
5663
|
-
console.log(
|
|
5935
|
+
console.log(chalk17.gray(` - "${c.name}"`));
|
|
5664
5936
|
}
|
|
5665
5937
|
process.exit(1);
|
|
5666
5938
|
}
|
|
@@ -5673,9 +5945,9 @@ var runCommand = new Command14("run").description("Run an eval suite").argument(
|
|
|
5673
5945
|
spinner.fail("No cases matched tags");
|
|
5674
5946
|
const allTags = new Set(cases.flatMap((c) => c.tags || []));
|
|
5675
5947
|
if (allTags.size > 0) {
|
|
5676
|
-
console.log(
|
|
5948
|
+
console.log(chalk17.gray(" Available tags:"));
|
|
5677
5949
|
for (const t of allTags) {
|
|
5678
|
-
console.log(
|
|
5950
|
+
console.log(chalk17.gray(` - "${t}"`));
|
|
5679
5951
|
}
|
|
5680
5952
|
}
|
|
5681
5953
|
process.exit(1);
|
|
@@ -5689,10 +5961,10 @@ var runCommand = new Command14("run").description("Run an eval suite").argument(
|
|
|
5689
5961
|
try {
|
|
5690
5962
|
runId = await startRun(suite._id, filteredCaseIds, project.organization.id);
|
|
5691
5963
|
} catch (error) {
|
|
5692
|
-
console.log(
|
|
5964
|
+
console.log(chalk17.red("Failed to start run:"), error instanceof Error ? error.message : String(error));
|
|
5693
5965
|
process.exit(1);
|
|
5694
5966
|
}
|
|
5695
|
-
console.log(
|
|
5967
|
+
console.log(chalk17.gray("Run ID:"), chalk17.cyan(runId));
|
|
5696
5968
|
const timeoutMs = (options.timeout ? parseInt(options.timeout, 10) : 300) * 1000;
|
|
5697
5969
|
const startTime = Date.now();
|
|
5698
5970
|
spinner.start("Running...");
|
|
@@ -5709,7 +5981,7 @@ var runCommand = new Command14("run").description("Run an eval suite").argument(
|
|
|
5709
5981
|
}
|
|
5710
5982
|
if (Date.now() - startTime > timeoutMs) {
|
|
5711
5983
|
spinner.fail(`Timed out after ${options.timeout || 300}s \u2014 run is still in progress`);
|
|
5712
|
-
console.log(
|
|
5984
|
+
console.log(chalk17.gray("Run ID:"), chalk17.cyan(runId));
|
|
5713
5985
|
process.exit(2);
|
|
5714
5986
|
}
|
|
5715
5987
|
spinner.text = `Running: ${run.completedCases}/${run.totalCases} cases (${run.passedCases} passed, ${run.failedCases} failed)`;
|
|
@@ -5727,7 +5999,7 @@ var runCommand = new Command14("run").description("Run an eval suite").argument(
|
|
|
5727
5999
|
return (caseA?.order ?? 0) - (caseB?.order ?? 0);
|
|
5728
6000
|
});
|
|
5729
6001
|
console.log();
|
|
5730
|
-
console.log(
|
|
6002
|
+
console.log(chalk17.bold("Results:"));
|
|
5731
6003
|
for (const r of results) {
|
|
5732
6004
|
const label = statusLabel(r);
|
|
5733
6005
|
const color = statusColor(label);
|
|
@@ -5756,21 +6028,21 @@ var runCommand = new Command14("run").description("Run an eval suite").argument(
|
|
|
5756
6028
|
}
|
|
5757
6029
|
const relativePath = `evals/runs/${folderName}/`;
|
|
5758
6030
|
console.log();
|
|
5759
|
-
console.log(`Results saved to ${
|
|
6031
|
+
console.log(`Results saved to ${chalk17.cyan(relativePath)}`);
|
|
5760
6032
|
const hasFailures = failed > 0 || errors > 0;
|
|
5761
6033
|
process.exit(hasFailures ? 1 : 0);
|
|
5762
6034
|
});
|
|
5763
|
-
var evalCommand = new
|
|
6035
|
+
var evalCommand = new Command15("eval").description("Eval suite management");
|
|
5764
6036
|
evalCommand.addCommand(runCommand);
|
|
5765
6037
|
|
|
5766
6038
|
// src/cli/commands/templates.ts
|
|
5767
|
-
import { Command as
|
|
5768
|
-
import
|
|
6039
|
+
import { Command as Command16 } from "commander";
|
|
6040
|
+
import chalk18 from "chalk";
|
|
5769
6041
|
import { readFileSync as readFileSync5 } from "fs";
|
|
5770
6042
|
import { confirm as confirm6 } from "@inquirer/prompts";
|
|
5771
6043
|
|
|
5772
6044
|
// src/cli/utils/whatsapp.ts
|
|
5773
|
-
function
|
|
6045
|
+
function getToken4() {
|
|
5774
6046
|
const credentials = loadCredentials();
|
|
5775
6047
|
const apiKey = getApiKey();
|
|
5776
6048
|
return apiKey || credentials?.token || null;
|
|
@@ -5809,7 +6081,7 @@ async function httpPost(path, body) {
|
|
|
5809
6081
|
}
|
|
5810
6082
|
}
|
|
5811
6083
|
async function convexAction(path, args) {
|
|
5812
|
-
const token =
|
|
6084
|
+
const token = getToken4();
|
|
5813
6085
|
if (!token)
|
|
5814
6086
|
return { error: "Not authenticated" };
|
|
5815
6087
|
const response = await fetch(`${CONVEX_URL}/api/action`, {
|
|
@@ -5837,8 +6109,8 @@ async function convexAction(path, args) {
|
|
|
5837
6109
|
return { error: String(json.errorMessage || "Unknown error") };
|
|
5838
6110
|
return { error: `Unexpected response: ${text}` };
|
|
5839
6111
|
}
|
|
5840
|
-
async function
|
|
5841
|
-
const token =
|
|
6112
|
+
async function convexQuery4(path, args) {
|
|
6113
|
+
const token = getToken4();
|
|
5842
6114
|
if (!token)
|
|
5843
6115
|
return { error: "Not authenticated" };
|
|
5844
6116
|
const response = await fetch(`${CONVEX_URL}/api/query`, {
|
|
@@ -5873,7 +6145,7 @@ async function listWhatsAppConnections(env) {
|
|
|
5873
6145
|
return result;
|
|
5874
6146
|
return { data: result.data.data };
|
|
5875
6147
|
}
|
|
5876
|
-
return
|
|
6148
|
+
return convexQuery4("whatsapp:listConnections", { environment: env });
|
|
5877
6149
|
}
|
|
5878
6150
|
async function listTemplates(connectionId) {
|
|
5879
6151
|
if (getApiKey()) {
|
|
@@ -5923,15 +6195,15 @@ async function getTemplateStatus(connectionId, name) {
|
|
|
5923
6195
|
}
|
|
5924
6196
|
|
|
5925
6197
|
// src/cli/commands/templates.ts
|
|
5926
|
-
async function
|
|
6198
|
+
async function ensureAuth3() {
|
|
5927
6199
|
const cwd = process.cwd();
|
|
5928
6200
|
const nonInteractive = !isInteractive();
|
|
5929
6201
|
if (!hasProject(cwd)) {
|
|
5930
6202
|
if (nonInteractive) {
|
|
5931
|
-
console.error(
|
|
6203
|
+
console.error(chalk18.red("No struere.json found. Run struere init first."));
|
|
5932
6204
|
process.exit(1);
|
|
5933
6205
|
}
|
|
5934
|
-
console.log(
|
|
6206
|
+
console.log(chalk18.yellow("No struere.json found - initializing project..."));
|
|
5935
6207
|
console.log();
|
|
5936
6208
|
const success = await runInit(cwd);
|
|
5937
6209
|
if (!success) {
|
|
@@ -5943,14 +6215,14 @@ async function ensureAuth2() {
|
|
|
5943
6215
|
const apiKey = getApiKey();
|
|
5944
6216
|
if (!credentials && !apiKey) {
|
|
5945
6217
|
if (nonInteractive) {
|
|
5946
|
-
console.error(
|
|
6218
|
+
console.error(chalk18.red("Not authenticated. Set STRUERE_API_KEY or run struere login."));
|
|
5947
6219
|
process.exit(1);
|
|
5948
6220
|
}
|
|
5949
|
-
console.log(
|
|
6221
|
+
console.log(chalk18.yellow("Not logged in - authenticating..."));
|
|
5950
6222
|
console.log();
|
|
5951
6223
|
credentials = await performLogin();
|
|
5952
6224
|
if (!credentials) {
|
|
5953
|
-
console.log(
|
|
6225
|
+
console.log(chalk18.red("Authentication failed"));
|
|
5954
6226
|
process.exit(1);
|
|
5955
6227
|
}
|
|
5956
6228
|
console.log();
|
|
@@ -5992,29 +6264,29 @@ async function resolveConnectionId(env, connectionIdFlag) {
|
|
|
5992
6264
|
for (let i = 0;i < connected.length; i++) {
|
|
5993
6265
|
const c = connected[i];
|
|
5994
6266
|
const label = c.label || (c.phoneNumber ? `+${c.phoneNumber}` : "Unknown");
|
|
5995
|
-
console.log(` ${
|
|
6267
|
+
console.log(` ${chalk18.cyan(String(i + 1))}. ${label} ${chalk18.gray(`(${c._id.slice(-12)})`)}`);
|
|
5996
6268
|
}
|
|
5997
6269
|
console.log();
|
|
5998
|
-
console.log(
|
|
6270
|
+
console.log(chalk18.yellow("Multiple connections found. Use --connection <id> to specify one."));
|
|
5999
6271
|
process.exit(1);
|
|
6000
6272
|
}
|
|
6001
6273
|
function statusColor2(status) {
|
|
6002
6274
|
switch (status?.toUpperCase()) {
|
|
6003
6275
|
case "APPROVED":
|
|
6004
|
-
return
|
|
6276
|
+
return chalk18.green(status);
|
|
6005
6277
|
case "PENDING":
|
|
6006
|
-
return
|
|
6278
|
+
return chalk18.yellow(status);
|
|
6007
6279
|
case "REJECTED":
|
|
6008
|
-
return
|
|
6280
|
+
return chalk18.red(status);
|
|
6009
6281
|
case "PAUSED":
|
|
6010
|
-
return
|
|
6282
|
+
return chalk18.hex("#FF8800")(status);
|
|
6011
6283
|
default:
|
|
6012
|
-
return
|
|
6284
|
+
return chalk18.gray(status);
|
|
6013
6285
|
}
|
|
6014
6286
|
}
|
|
6015
|
-
var templatesCommand = new
|
|
6287
|
+
var templatesCommand = new Command16("templates").description("Manage WhatsApp message templates");
|
|
6016
6288
|
templatesCommand.command("list").description("List all message templates").option("--connection <id>", "WhatsApp connection ID").option("--json", "Output raw JSON").action(async (opts) => {
|
|
6017
|
-
await
|
|
6289
|
+
await ensureAuth3();
|
|
6018
6290
|
const connectionId = await resolveConnectionId("development", opts.connection);
|
|
6019
6291
|
const out = createOutput();
|
|
6020
6292
|
out.start("Fetching templates");
|
|
@@ -6033,7 +6305,7 @@ templatesCommand.command("list").description("List all message templates").optio
|
|
|
6033
6305
|
}
|
|
6034
6306
|
console.log();
|
|
6035
6307
|
if (templates.length === 0) {
|
|
6036
|
-
console.log(
|
|
6308
|
+
console.log(chalk18.gray(" No templates found"));
|
|
6037
6309
|
console.log();
|
|
6038
6310
|
return;
|
|
6039
6311
|
}
|
|
@@ -6051,7 +6323,7 @@ templatesCommand.command("list").description("List all message templates").optio
|
|
|
6051
6323
|
console.log();
|
|
6052
6324
|
});
|
|
6053
6325
|
templatesCommand.command("create <name>").description("Create a new message template").option("--connection <id>", "WhatsApp connection ID").option("--language <code>", "Language code", "en_US").option("--category <cat>", "Category (UTILITY|MARKETING|AUTHENTICATION)", "UTILITY").option("--components <json>", "Components as JSON string").option("--file <path>", "Read components from a JSON file").option("--allow-category-change", "Allow Meta to reassign category").option("--json", "Output raw JSON").action(async (name, opts) => {
|
|
6054
|
-
await
|
|
6326
|
+
await ensureAuth3();
|
|
6055
6327
|
const connectionId = await resolveConnectionId("development", opts.connection);
|
|
6056
6328
|
let components;
|
|
6057
6329
|
if (opts.file) {
|
|
@@ -6060,22 +6332,22 @@ templatesCommand.command("create <name>").description("Create a new message temp
|
|
|
6060
6332
|
const parsed = JSON.parse(fileContent);
|
|
6061
6333
|
components = Array.isArray(parsed) ? parsed : parsed.components ?? [parsed];
|
|
6062
6334
|
} catch (err) {
|
|
6063
|
-
console.log(
|
|
6335
|
+
console.log(chalk18.red("Failed to read components file:"), err instanceof Error ? err.message : String(err));
|
|
6064
6336
|
process.exit(1);
|
|
6065
6337
|
}
|
|
6066
6338
|
} else if (opts.components) {
|
|
6067
6339
|
try {
|
|
6068
6340
|
components = JSON.parse(opts.components);
|
|
6069
6341
|
} catch {
|
|
6070
|
-
console.log(
|
|
6342
|
+
console.log(chalk18.red("Invalid JSON in --components"));
|
|
6071
6343
|
process.exit(1);
|
|
6072
6344
|
}
|
|
6073
6345
|
} else {
|
|
6074
|
-
console.log(
|
|
6346
|
+
console.log(chalk18.red("Provide --components <json> or --file <path>"));
|
|
6075
6347
|
process.exit(1);
|
|
6076
6348
|
}
|
|
6077
6349
|
if (!Array.isArray(components)) {
|
|
6078
|
-
console.log(
|
|
6350
|
+
console.log(chalk18.red("Components must be a JSON array"));
|
|
6079
6351
|
process.exit(1);
|
|
6080
6352
|
}
|
|
6081
6353
|
const out = createOutput();
|
|
@@ -6092,14 +6364,14 @@ templatesCommand.command("create <name>").description("Create a new message temp
|
|
|
6092
6364
|
console.log(JSON.stringify(result, null, 2));
|
|
6093
6365
|
} else {
|
|
6094
6366
|
console.log();
|
|
6095
|
-
console.log(` ${
|
|
6096
|
-
console.log(` ${
|
|
6097
|
-
console.log(` ${
|
|
6367
|
+
console.log(` ${chalk18.gray("ID:")} ${result.id}`);
|
|
6368
|
+
console.log(` ${chalk18.gray("Status:")} ${statusColor2(result.status)}`);
|
|
6369
|
+
console.log(` ${chalk18.gray("Category:")} ${result.category}`);
|
|
6098
6370
|
console.log();
|
|
6099
6371
|
}
|
|
6100
6372
|
});
|
|
6101
6373
|
templatesCommand.command("delete <name>").description("Delete a message template").option("--connection <id>", "WhatsApp connection ID").option("--yes", "Skip confirmation").action(async (name, opts) => {
|
|
6102
|
-
await
|
|
6374
|
+
await ensureAuth3();
|
|
6103
6375
|
const connectionId = await resolveConnectionId("development", opts.connection);
|
|
6104
6376
|
if (!opts.yes && isInteractive()) {
|
|
6105
6377
|
const confirmed = await confirm6({
|
|
@@ -6107,7 +6379,7 @@ templatesCommand.command("delete <name>").description("Delete a message template
|
|
|
6107
6379
|
default: false
|
|
6108
6380
|
});
|
|
6109
6381
|
if (!confirmed) {
|
|
6110
|
-
console.log(
|
|
6382
|
+
console.log(chalk18.gray("Cancelled"));
|
|
6111
6383
|
return;
|
|
6112
6384
|
}
|
|
6113
6385
|
}
|
|
@@ -6123,7 +6395,7 @@ templatesCommand.command("delete <name>").description("Delete a message template
|
|
|
6123
6395
|
console.log();
|
|
6124
6396
|
});
|
|
6125
6397
|
templatesCommand.command("status <name>").description("Check template approval status").option("--connection <id>", "WhatsApp connection ID").option("--json", "Output raw JSON").action(async (name, opts) => {
|
|
6126
|
-
await
|
|
6398
|
+
await ensureAuth3();
|
|
6127
6399
|
const connectionId = await resolveConnectionId("development", opts.connection);
|
|
6128
6400
|
const out = createOutput();
|
|
6129
6401
|
out.start(`Checking status for "${name}"`);
|
|
@@ -6146,12 +6418,12 @@ templatesCommand.command("status <name>").description("Check template approval s
|
|
|
6146
6418
|
}
|
|
6147
6419
|
console.log();
|
|
6148
6420
|
for (const t of templates) {
|
|
6149
|
-
console.log(` ${
|
|
6150
|
-
console.log(` ${
|
|
6151
|
-
console.log(` ${
|
|
6152
|
-
console.log(` ${
|
|
6421
|
+
console.log(` ${chalk18.gray("Name:")} ${t.name}`);
|
|
6422
|
+
console.log(` ${chalk18.gray("Status:")} ${statusColor2(String(t.status ?? ""))}`);
|
|
6423
|
+
console.log(` ${chalk18.gray("Category:")} ${t.category}`);
|
|
6424
|
+
console.log(` ${chalk18.gray("Language:")} ${t.language}`);
|
|
6153
6425
|
if (t.components) {
|
|
6154
|
-
console.log(` ${
|
|
6426
|
+
console.log(` ${chalk18.gray("Components:")} ${JSON.stringify(t.components, null, 2).split(`
|
|
6155
6427
|
`).join(`
|
|
6156
6428
|
`)}`);
|
|
6157
6429
|
}
|
|
@@ -6160,18 +6432,18 @@ templatesCommand.command("status <name>").description("Check template approval s
|
|
|
6160
6432
|
});
|
|
6161
6433
|
|
|
6162
6434
|
// src/cli/commands/integration.ts
|
|
6163
|
-
import { Command as
|
|
6164
|
-
import
|
|
6435
|
+
import { Command as Command17 } from "commander";
|
|
6436
|
+
import chalk19 from "chalk";
|
|
6165
6437
|
import { confirm as confirm7 } from "@inquirer/prompts";
|
|
6166
6438
|
|
|
6167
6439
|
// src/cli/utils/integrations.ts
|
|
6168
|
-
function
|
|
6440
|
+
function getToken5() {
|
|
6169
6441
|
const credentials = loadCredentials();
|
|
6170
6442
|
const apiKey = getApiKey();
|
|
6171
6443
|
return apiKey || credentials?.token || null;
|
|
6172
6444
|
}
|
|
6173
|
-
async function
|
|
6174
|
-
const token =
|
|
6445
|
+
async function convexQuery5(path, args) {
|
|
6446
|
+
const token = getToken5();
|
|
6175
6447
|
if (!token)
|
|
6176
6448
|
return { error: "Not authenticated" };
|
|
6177
6449
|
const response = await fetch(`${CONVEX_URL}/api/query`, {
|
|
@@ -6200,7 +6472,7 @@ async function convexQuery4(path, args) {
|
|
|
6200
6472
|
return { error: `Unexpected response: ${text}` };
|
|
6201
6473
|
}
|
|
6202
6474
|
async function convexMutation3(path, args) {
|
|
6203
|
-
const token =
|
|
6475
|
+
const token = getToken5();
|
|
6204
6476
|
if (!token)
|
|
6205
6477
|
return { error: "Not authenticated" };
|
|
6206
6478
|
const response = await fetch(`${CONVEX_URL}/api/mutation`, {
|
|
@@ -6229,7 +6501,7 @@ async function convexMutation3(path, args) {
|
|
|
6229
6501
|
return { error: `Unexpected response: ${text}` };
|
|
6230
6502
|
}
|
|
6231
6503
|
async function convexAction2(path, args) {
|
|
6232
|
-
const token =
|
|
6504
|
+
const token = getToken5();
|
|
6233
6505
|
if (!token)
|
|
6234
6506
|
return { error: "Not authenticated" };
|
|
6235
6507
|
const response = await fetch(`${CONVEX_URL}/api/action`, {
|
|
@@ -6258,7 +6530,7 @@ async function convexAction2(path, args) {
|
|
|
6258
6530
|
return { error: `Unexpected response: ${text}` };
|
|
6259
6531
|
}
|
|
6260
6532
|
async function getIntegrationConfig(provider, env) {
|
|
6261
|
-
return
|
|
6533
|
+
return convexQuery5("integrations:getConfig", { provider, environment: env });
|
|
6262
6534
|
}
|
|
6263
6535
|
async function updateIntegrationConfig(provider, env, config) {
|
|
6264
6536
|
return convexMutation3("integrations:updateConfig", { provider, environment: env, config });
|
|
@@ -6270,7 +6542,7 @@ async function deleteIntegrationConfig(provider, env) {
|
|
|
6270
6542
|
return convexMutation3("integrations:deleteConfig", { provider, environment: env });
|
|
6271
6543
|
}
|
|
6272
6544
|
async function listIntegrationConfigs(env) {
|
|
6273
|
-
return
|
|
6545
|
+
return convexQuery5("integrations:listConfigs", { environment: env });
|
|
6274
6546
|
}
|
|
6275
6547
|
async function setIntegrationStatus(provider, env, status) {
|
|
6276
6548
|
return convexMutation3("integrations:setConfigStatus", { provider, environment: env, status });
|
|
@@ -6278,15 +6550,15 @@ async function setIntegrationStatus(provider, env, status) {
|
|
|
6278
6550
|
|
|
6279
6551
|
// src/cli/commands/integration.ts
|
|
6280
6552
|
var VALID_PROVIDERS = ["airtable", "resend", "flow"];
|
|
6281
|
-
async function
|
|
6553
|
+
async function ensureAuth4() {
|
|
6282
6554
|
const cwd = process.cwd();
|
|
6283
6555
|
const nonInteractive = !isInteractive();
|
|
6284
6556
|
if (!hasProject(cwd)) {
|
|
6285
6557
|
if (nonInteractive) {
|
|
6286
|
-
console.error(
|
|
6558
|
+
console.error(chalk19.red("No struere.json found. Run struere init first."));
|
|
6287
6559
|
process.exit(1);
|
|
6288
6560
|
}
|
|
6289
|
-
console.log(
|
|
6561
|
+
console.log(chalk19.yellow("No struere.json found - initializing project..."));
|
|
6290
6562
|
console.log();
|
|
6291
6563
|
const success = await runInit(cwd);
|
|
6292
6564
|
if (!success) {
|
|
@@ -6298,14 +6570,14 @@ async function ensureAuth3() {
|
|
|
6298
6570
|
const apiKey = getApiKey();
|
|
6299
6571
|
if (!credentials && !apiKey) {
|
|
6300
6572
|
if (nonInteractive) {
|
|
6301
|
-
console.error(
|
|
6573
|
+
console.error(chalk19.red("Not authenticated. Set STRUERE_API_KEY or run struere login."));
|
|
6302
6574
|
process.exit(1);
|
|
6303
6575
|
}
|
|
6304
|
-
console.log(
|
|
6576
|
+
console.log(chalk19.yellow("Not logged in - authenticating..."));
|
|
6305
6577
|
console.log();
|
|
6306
6578
|
credentials = await performLogin();
|
|
6307
6579
|
if (!credentials) {
|
|
6308
|
-
console.log(
|
|
6580
|
+
console.log(chalk19.red("Authentication failed"));
|
|
6309
6581
|
process.exit(1);
|
|
6310
6582
|
}
|
|
6311
6583
|
console.log();
|
|
@@ -6315,13 +6587,13 @@ async function ensureAuth3() {
|
|
|
6315
6587
|
function statusColor3(status) {
|
|
6316
6588
|
switch (status) {
|
|
6317
6589
|
case "active":
|
|
6318
|
-
return
|
|
6590
|
+
return chalk19.green(status);
|
|
6319
6591
|
case "inactive":
|
|
6320
|
-
return
|
|
6592
|
+
return chalk19.yellow(status);
|
|
6321
6593
|
case "error":
|
|
6322
|
-
return
|
|
6594
|
+
return chalk19.red(status);
|
|
6323
6595
|
default:
|
|
6324
|
-
return
|
|
6596
|
+
return chalk19.gray(status);
|
|
6325
6597
|
}
|
|
6326
6598
|
}
|
|
6327
6599
|
function getProviderHelp(provider) {
|
|
@@ -6375,8 +6647,8 @@ function buildConfigFromOpts(provider, opts) {
|
|
|
6375
6647
|
}
|
|
6376
6648
|
return null;
|
|
6377
6649
|
}
|
|
6378
|
-
var integrationCommand = new
|
|
6379
|
-
await
|
|
6650
|
+
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) => {
|
|
6651
|
+
await ensureAuth4();
|
|
6380
6652
|
const env = opts.env;
|
|
6381
6653
|
const out = createOutput();
|
|
6382
6654
|
if (!provider || provider === "list") {
|
|
@@ -6395,10 +6667,10 @@ var integrationCommand = new Command16("integration").description("Manage integr
|
|
|
6395
6667
|
}
|
|
6396
6668
|
console.log();
|
|
6397
6669
|
if (configs.length === 0) {
|
|
6398
|
-
console.log(
|
|
6670
|
+
console.log(chalk19.gray(" No integrations configured"));
|
|
6399
6671
|
console.log();
|
|
6400
|
-
console.log(` ${
|
|
6401
|
-
console.log(` ${
|
|
6672
|
+
console.log(` ${chalk19.gray("Available:")} ${VALID_PROVIDERS.join(", ")}`);
|
|
6673
|
+
console.log(` ${chalk19.gray("Example:")} struere integration airtable --token <pat>`);
|
|
6402
6674
|
console.log();
|
|
6403
6675
|
return;
|
|
6404
6676
|
}
|
|
@@ -6409,14 +6681,14 @@ var integrationCommand = new Command16("integration").description("Manage integr
|
|
|
6409
6681
|
], configs.map((c) => ({
|
|
6410
6682
|
provider: c.provider,
|
|
6411
6683
|
status: statusColor3(String(c.status ?? "")),
|
|
6412
|
-
lastVerified: c.lastVerifiedAt ? new Date(c.lastVerifiedAt).toLocaleString() :
|
|
6684
|
+
lastVerified: c.lastVerifiedAt ? new Date(c.lastVerifiedAt).toLocaleString() : chalk19.gray("never")
|
|
6413
6685
|
})));
|
|
6414
6686
|
console.log();
|
|
6415
6687
|
return;
|
|
6416
6688
|
}
|
|
6417
6689
|
if (!VALID_PROVIDERS.includes(provider)) {
|
|
6418
6690
|
out.fail(`Unknown provider: ${provider}`);
|
|
6419
|
-
console.log(` ${
|
|
6691
|
+
console.log(` ${chalk19.gray("Available:")} ${VALID_PROVIDERS.join(", ")}`);
|
|
6420
6692
|
process.exit(1);
|
|
6421
6693
|
}
|
|
6422
6694
|
if (opts.remove) {
|
|
@@ -6426,7 +6698,7 @@ var integrationCommand = new Command16("integration").description("Manage integr
|
|
|
6426
6698
|
default: false
|
|
6427
6699
|
});
|
|
6428
6700
|
if (!confirmed) {
|
|
6429
|
-
console.log(
|
|
6701
|
+
console.log(chalk19.gray("Cancelled"));
|
|
6430
6702
|
return;
|
|
6431
6703
|
}
|
|
6432
6704
|
}
|
|
@@ -6521,7 +6793,7 @@ var integrationCommand = new Command16("integration").description("Manage integr
|
|
|
6521
6793
|
if (!configData) {
|
|
6522
6794
|
out.fail(`No ${provider} config found`);
|
|
6523
6795
|
console.log();
|
|
6524
|
-
console.log(` ${
|
|
6796
|
+
console.log(` ${chalk19.gray(getProviderHelp(provider))}`);
|
|
6525
6797
|
console.log();
|
|
6526
6798
|
return;
|
|
6527
6799
|
}
|
|
@@ -6533,33 +6805,33 @@ var integrationCommand = new Command16("integration").description("Manage integr
|
|
|
6533
6805
|
const cfg = configData;
|
|
6534
6806
|
const cfgData = cfg.config;
|
|
6535
6807
|
console.log();
|
|
6536
|
-
console.log(
|
|
6537
|
-
console.log(
|
|
6538
|
-
console.log(` ${
|
|
6539
|
-
console.log(` ${
|
|
6540
|
-
console.log(` ${
|
|
6541
|
-
console.log(` ${
|
|
6808
|
+
console.log(chalk19.bold(` ${provider}`));
|
|
6809
|
+
console.log(chalk19.gray(" " + "\u2500".repeat(48)));
|
|
6810
|
+
console.log(` ${chalk19.gray("Status:")} ${statusColor3(String(cfg.status ?? ""))}`);
|
|
6811
|
+
console.log(` ${chalk19.gray("Environment:")} ${cfg.environment}`);
|
|
6812
|
+
console.log(` ${chalk19.gray("Last Verified:")} ${cfg.lastVerifiedAt ? new Date(cfg.lastVerifiedAt).toLocaleString() : chalk19.gray("never")}`);
|
|
6813
|
+
console.log(` ${chalk19.gray("Updated:")} ${new Date(cfg.updatedAt).toLocaleString()}`);
|
|
6542
6814
|
if (cfgData && Object.keys(cfgData).length > 0) {
|
|
6543
6815
|
console.log();
|
|
6544
|
-
console.log(
|
|
6545
|
-
console.log(
|
|
6816
|
+
console.log(chalk19.bold(" Config"));
|
|
6817
|
+
console.log(chalk19.gray(" " + "\u2500".repeat(48)));
|
|
6546
6818
|
const maxKeyLen = Math.max(...Object.keys(cfgData).map((k) => k.length));
|
|
6547
6819
|
for (const [key, value] of Object.entries(cfgData)) {
|
|
6548
|
-
console.log(` ${
|
|
6820
|
+
console.log(` ${chalk19.gray(key.padEnd(maxKeyLen))} ${String(value ?? "")}`);
|
|
6549
6821
|
}
|
|
6550
6822
|
}
|
|
6551
6823
|
console.log();
|
|
6552
6824
|
});
|
|
6553
6825
|
|
|
6554
6826
|
// src/cli/commands/compile-prompt.ts
|
|
6555
|
-
import { Command as
|
|
6556
|
-
import
|
|
6557
|
-
import
|
|
6558
|
-
var compilePromptCommand = new
|
|
6827
|
+
import { Command as Command18 } from "commander";
|
|
6828
|
+
import chalk20 from "chalk";
|
|
6829
|
+
import ora14 from "ora";
|
|
6830
|
+
var compilePromptCommand = new Command18("compile-prompt").description("Compile and preview an agent's system prompt after template processing").argument("<agent-slug>", "Agent slug to compile prompt for").option("--env <env>", "Environment: development | production", "development").option("--message <msg>", "Sample message for template context").option("--channel <channel>", "Sample channel (whatsapp, widget, api, dashboard)").option("--param <key=value...>", "Custom thread param (repeatable)", (val, acc) => {
|
|
6559
6831
|
acc.push(val);
|
|
6560
6832
|
return acc;
|
|
6561
6833
|
}, []).option("--json", "Output full JSON (raw + compiled + context)").option("--raw", "Show raw uncompiled template instead of compiled").action(async (agentSlug, options) => {
|
|
6562
|
-
const spinner =
|
|
6834
|
+
const spinner = ora14();
|
|
6563
6835
|
const cwd = process.cwd();
|
|
6564
6836
|
const nonInteractive = !isInteractive();
|
|
6565
6837
|
const jsonMode = !!options.json;
|
|
@@ -6568,11 +6840,11 @@ var compilePromptCommand = new Command17("compile-prompt").description("Compile
|
|
|
6568
6840
|
if (jsonMode) {
|
|
6569
6841
|
console.log(JSON.stringify({ success: false, error: "No struere.json found" }));
|
|
6570
6842
|
} else {
|
|
6571
|
-
console.log(
|
|
6843
|
+
console.log(chalk20.red("No struere.json found. Run struere init first."));
|
|
6572
6844
|
}
|
|
6573
6845
|
process.exit(1);
|
|
6574
6846
|
}
|
|
6575
|
-
console.log(
|
|
6847
|
+
console.log(chalk20.yellow("No struere.json found - initializing project..."));
|
|
6576
6848
|
console.log();
|
|
6577
6849
|
const success = await runInit(cwd);
|
|
6578
6850
|
if (!success) {
|
|
@@ -6585,7 +6857,7 @@ var compilePromptCommand = new Command17("compile-prompt").description("Compile
|
|
|
6585
6857
|
if (jsonMode) {
|
|
6586
6858
|
console.log(JSON.stringify({ success: false, error: "Failed to load struere.json" }));
|
|
6587
6859
|
} else {
|
|
6588
|
-
console.log(
|
|
6860
|
+
console.log(chalk20.red("Failed to load struere.json"));
|
|
6589
6861
|
}
|
|
6590
6862
|
process.exit(1);
|
|
6591
6863
|
}
|
|
@@ -6596,15 +6868,15 @@ var compilePromptCommand = new Command17("compile-prompt").description("Compile
|
|
|
6596
6868
|
if (jsonMode) {
|
|
6597
6869
|
console.log(JSON.stringify({ success: false, error: "Not authenticated. Set STRUERE_API_KEY or run struere login." }));
|
|
6598
6870
|
} else {
|
|
6599
|
-
console.log(
|
|
6871
|
+
console.log(chalk20.red("Not authenticated. Set STRUERE_API_KEY or run struere login."));
|
|
6600
6872
|
}
|
|
6601
6873
|
process.exit(1);
|
|
6602
6874
|
}
|
|
6603
|
-
console.log(
|
|
6875
|
+
console.log(chalk20.yellow("Not logged in - authenticating..."));
|
|
6604
6876
|
console.log();
|
|
6605
6877
|
credentials = await performLogin();
|
|
6606
6878
|
if (!credentials) {
|
|
6607
|
-
console.log(
|
|
6879
|
+
console.log(chalk20.red("Authentication failed"));
|
|
6608
6880
|
process.exit(1);
|
|
6609
6881
|
}
|
|
6610
6882
|
console.log();
|
|
@@ -6616,7 +6888,7 @@ var compilePromptCommand = new Command17("compile-prompt").description("Compile
|
|
|
6616
6888
|
if (jsonMode) {
|
|
6617
6889
|
console.log(JSON.stringify({ success: false, error: `Invalid param format: ${param}. Use key=value.` }));
|
|
6618
6890
|
} else {
|
|
6619
|
-
console.log(
|
|
6891
|
+
console.log(chalk20.red(`Invalid param format: ${param}. Use key=value.`));
|
|
6620
6892
|
}
|
|
6621
6893
|
process.exit(1);
|
|
6622
6894
|
}
|
|
@@ -6626,7 +6898,7 @@ var compilePromptCommand = new Command17("compile-prompt").description("Compile
|
|
|
6626
6898
|
}
|
|
6627
6899
|
const environment = options.env;
|
|
6628
6900
|
if (!jsonMode) {
|
|
6629
|
-
spinner.start(`Compiling prompt for ${
|
|
6901
|
+
spinner.start(`Compiling prompt for ${chalk20.cyan(agentSlug)} (${environment})`);
|
|
6630
6902
|
}
|
|
6631
6903
|
const doCompile = async () => {
|
|
6632
6904
|
return compilePrompt({
|
|
@@ -6648,7 +6920,7 @@ var compilePromptCommand = new Command17("compile-prompt").description("Compile
|
|
|
6648
6920
|
if (jsonMode) {
|
|
6649
6921
|
console.log(JSON.stringify({ success: false, error: "Authentication failed" }));
|
|
6650
6922
|
} else {
|
|
6651
|
-
console.log(
|
|
6923
|
+
console.log(chalk20.red("Authentication failed"));
|
|
6652
6924
|
}
|
|
6653
6925
|
process.exit(1);
|
|
6654
6926
|
}
|
|
@@ -6663,7 +6935,7 @@ var compilePromptCommand = new Command17("compile-prompt").description("Compile
|
|
|
6663
6935
|
console.log(JSON.stringify({ success: false, error }));
|
|
6664
6936
|
} else {
|
|
6665
6937
|
spinner.fail("Failed to compile prompt");
|
|
6666
|
-
console.log(
|
|
6938
|
+
console.log(chalk20.red("Error:"), error);
|
|
6667
6939
|
}
|
|
6668
6940
|
process.exit(1);
|
|
6669
6941
|
}
|
|
@@ -6686,25 +6958,25 @@ var compilePromptCommand = new Command17("compile-prompt").description("Compile
|
|
|
6686
6958
|
}, null, 2));
|
|
6687
6959
|
} else if (options.raw) {
|
|
6688
6960
|
console.log();
|
|
6689
|
-
console.log(
|
|
6690
|
-
console.log(
|
|
6961
|
+
console.log(chalk20.bold("Raw System Prompt"));
|
|
6962
|
+
console.log(chalk20.gray("\u2500".repeat(60)));
|
|
6691
6963
|
console.log(result.raw);
|
|
6692
|
-
console.log(
|
|
6964
|
+
console.log(chalk20.gray("\u2500".repeat(60)));
|
|
6693
6965
|
} else {
|
|
6694
6966
|
console.log();
|
|
6695
|
-
console.log(
|
|
6696
|
-
console.log(
|
|
6967
|
+
console.log(chalk20.bold("Compiled System Prompt"));
|
|
6968
|
+
console.log(chalk20.gray("\u2500".repeat(60)));
|
|
6697
6969
|
console.log(result.compiled);
|
|
6698
|
-
console.log(
|
|
6970
|
+
console.log(chalk20.gray("\u2500".repeat(60)));
|
|
6699
6971
|
}
|
|
6700
6972
|
});
|
|
6701
6973
|
|
|
6702
6974
|
// src/cli/commands/run-tool.ts
|
|
6703
|
-
import { Command as
|
|
6704
|
-
import
|
|
6705
|
-
import
|
|
6706
|
-
var runToolCommand = new
|
|
6707
|
-
const spinner =
|
|
6975
|
+
import { Command as Command19 } from "commander";
|
|
6976
|
+
import chalk21 from "chalk";
|
|
6977
|
+
import ora15 from "ora";
|
|
6978
|
+
var runToolCommand = new Command19("run-tool").description("Run a tool as it would execute during a real agent conversation").argument("<agent-slug>", "Agent slug").argument("<tool-name>", "Tool name (e.g., entity.query)").option("--env <environment>", "Environment: development | production | eval", "development").option("--args <json>", "Tool arguments as JSON string", "{}").option("--args-file <path>", "Read tool arguments from a JSON file").option("--json", "Output full JSON result").option("--confirm", "Skip production confirmation prompt").action(async (agentSlug, toolName, options) => {
|
|
6979
|
+
const spinner = ora15();
|
|
6708
6980
|
const cwd = process.cwd();
|
|
6709
6981
|
const nonInteractive = !isInteractive();
|
|
6710
6982
|
const jsonMode = !!options.json;
|
|
@@ -6713,11 +6985,11 @@ var runToolCommand = new Command18("run-tool").description("Run a tool as it wou
|
|
|
6713
6985
|
if (jsonMode) {
|
|
6714
6986
|
console.log(JSON.stringify({ success: false, error: "No struere.json found" }));
|
|
6715
6987
|
} else {
|
|
6716
|
-
console.log(
|
|
6988
|
+
console.log(chalk21.red("No struere.json found. Run struere init first."));
|
|
6717
6989
|
}
|
|
6718
6990
|
process.exit(1);
|
|
6719
6991
|
}
|
|
6720
|
-
console.log(
|
|
6992
|
+
console.log(chalk21.yellow("No struere.json found - initializing project..."));
|
|
6721
6993
|
console.log();
|
|
6722
6994
|
const success = await runInit(cwd);
|
|
6723
6995
|
if (!success) {
|
|
@@ -6730,7 +7002,7 @@ var runToolCommand = new Command18("run-tool").description("Run a tool as it wou
|
|
|
6730
7002
|
if (jsonMode) {
|
|
6731
7003
|
console.log(JSON.stringify({ success: false, error: "Failed to load struere.json" }));
|
|
6732
7004
|
} else {
|
|
6733
|
-
console.log(
|
|
7005
|
+
console.log(chalk21.red("Failed to load struere.json"));
|
|
6734
7006
|
}
|
|
6735
7007
|
process.exit(1);
|
|
6736
7008
|
}
|
|
@@ -6741,15 +7013,15 @@ var runToolCommand = new Command18("run-tool").description("Run a tool as it wou
|
|
|
6741
7013
|
if (jsonMode) {
|
|
6742
7014
|
console.log(JSON.stringify({ success: false, error: "Not authenticated. Set STRUERE_API_KEY or run struere login." }));
|
|
6743
7015
|
} else {
|
|
6744
|
-
console.log(
|
|
7016
|
+
console.log(chalk21.red("Not authenticated. Set STRUERE_API_KEY or run struere login."));
|
|
6745
7017
|
}
|
|
6746
7018
|
process.exit(1);
|
|
6747
7019
|
}
|
|
6748
|
-
console.log(
|
|
7020
|
+
console.log(chalk21.yellow("Not logged in - authenticating..."));
|
|
6749
7021
|
console.log();
|
|
6750
7022
|
credentials = await performLogin();
|
|
6751
7023
|
if (!credentials) {
|
|
6752
|
-
console.log(
|
|
7024
|
+
console.log(chalk21.red("Authentication failed"));
|
|
6753
7025
|
process.exit(1);
|
|
6754
7026
|
}
|
|
6755
7027
|
console.log();
|
|
@@ -6767,7 +7039,7 @@ var runToolCommand = new Command18("run-tool").description("Run a tool as it wou
|
|
|
6767
7039
|
if (jsonMode) {
|
|
6768
7040
|
console.log(JSON.stringify({ success: false, error: `Invalid JSON: ${err instanceof Error ? err.message : String(err)}` }));
|
|
6769
7041
|
} else {
|
|
6770
|
-
console.log(
|
|
7042
|
+
console.log(chalk21.red(`Invalid JSON: ${err instanceof Error ? err.message : String(err)}`));
|
|
6771
7043
|
}
|
|
6772
7044
|
process.exit(1);
|
|
6773
7045
|
}
|
|
@@ -6776,14 +7048,14 @@ var runToolCommand = new Command18("run-tool").description("Run a tool as it wou
|
|
|
6776
7048
|
const readline = await import("readline");
|
|
6777
7049
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
6778
7050
|
await new Promise((resolve) => {
|
|
6779
|
-
rl.question(
|
|
7051
|
+
rl.question(chalk21.yellow(`WARNING: Running tool against PRODUCTION environment.
|
|
6780
7052
|
This will execute real operations with real data.
|
|
6781
7053
|
Press Enter to continue or Ctrl+C to cancel: `), resolve);
|
|
6782
7054
|
});
|
|
6783
7055
|
rl.close();
|
|
6784
7056
|
}
|
|
6785
7057
|
if (!jsonMode) {
|
|
6786
|
-
spinner.start(`Running ${
|
|
7058
|
+
spinner.start(`Running ${chalk21.cyan(toolName)} on ${chalk21.cyan(agentSlug)} (${environment})`);
|
|
6787
7059
|
}
|
|
6788
7060
|
const doRunTool = async () => {
|
|
6789
7061
|
return runTool({
|
|
@@ -6804,7 +7076,7 @@ var runToolCommand = new Command18("run-tool").description("Run a tool as it wou
|
|
|
6804
7076
|
if (jsonMode) {
|
|
6805
7077
|
console.log(JSON.stringify({ success: false, error: "Authentication failed" }));
|
|
6806
7078
|
} else {
|
|
6807
|
-
console.log(
|
|
7079
|
+
console.log(chalk21.red("Authentication failed"));
|
|
6808
7080
|
}
|
|
6809
7081
|
process.exit(1);
|
|
6810
7082
|
}
|
|
@@ -6812,14 +7084,14 @@ var runToolCommand = new Command18("run-tool").description("Run a tool as it wou
|
|
|
6812
7084
|
result = retry.result;
|
|
6813
7085
|
error = retry.error;
|
|
6814
7086
|
if (!jsonMode && !error)
|
|
6815
|
-
spinner.succeed(`Ran ${
|
|
7087
|
+
spinner.succeed(`Ran ${chalk21.cyan(toolName)}`);
|
|
6816
7088
|
}
|
|
6817
7089
|
if (error) {
|
|
6818
7090
|
if (jsonMode) {
|
|
6819
7091
|
console.log(JSON.stringify({ success: false, error }));
|
|
6820
7092
|
} else {
|
|
6821
7093
|
spinner.fail("Failed to run tool");
|
|
6822
|
-
console.log(
|
|
7094
|
+
console.log(chalk21.red("Error:"), error);
|
|
6823
7095
|
}
|
|
6824
7096
|
process.exit(1);
|
|
6825
7097
|
}
|
|
@@ -6835,32 +7107,32 @@ var runToolCommand = new Command18("run-tool").description("Run a tool as it wou
|
|
|
6835
7107
|
if (jsonMode) {
|
|
6836
7108
|
console.log(JSON.stringify({ success: false, error: `${result.errorType}: ${result.message}`, result }));
|
|
6837
7109
|
} else {
|
|
6838
|
-
spinner.fail(
|
|
7110
|
+
spinner.fail(chalk21.red(`${result.errorType}: ${result.message}`));
|
|
6839
7111
|
}
|
|
6840
7112
|
process.exit(1);
|
|
6841
7113
|
}
|
|
6842
7114
|
if (!jsonMode) {
|
|
6843
|
-
spinner.succeed(`Ran ${
|
|
7115
|
+
spinner.succeed(`Ran ${chalk21.cyan(toolName)} on ${chalk21.cyan(result.agent.slug)} (${result.environment}) in ${result.durationMs}ms`);
|
|
6844
7116
|
}
|
|
6845
7117
|
if (jsonMode) {
|
|
6846
7118
|
console.log(JSON.stringify(result, null, 2));
|
|
6847
7119
|
} else {
|
|
6848
7120
|
console.log();
|
|
6849
|
-
console.log(
|
|
7121
|
+
console.log(chalk21.dim("\u2500".repeat(50)));
|
|
6850
7122
|
console.log(JSON.stringify(result.result, null, 2));
|
|
6851
|
-
console.log(
|
|
7123
|
+
console.log(chalk21.dim("\u2500".repeat(50)));
|
|
6852
7124
|
console.log();
|
|
6853
|
-
console.log(
|
|
7125
|
+
console.log(chalk21.dim(`Identity: ${result.identity.actorType} (${result.identity.identityMode} mode)`));
|
|
6854
7126
|
}
|
|
6855
7127
|
});
|
|
6856
7128
|
|
|
6857
7129
|
// src/cli/commands/chat.ts
|
|
6858
|
-
import { Command as
|
|
6859
|
-
import
|
|
6860
|
-
import
|
|
7130
|
+
import { Command as Command20 } from "commander";
|
|
7131
|
+
import chalk22 from "chalk";
|
|
7132
|
+
import ora16 from "ora";
|
|
6861
7133
|
import readline from "readline";
|
|
6862
|
-
var chatCommand = new
|
|
6863
|
-
const spinner =
|
|
7134
|
+
var chatCommand = new Command20("chat").description("Chat with an agent").argument("<agent-slug>", "Agent slug").option("--env <environment>", "Environment: development | production | eval", "development").option("--thread <id>", "Continue an existing thread").option("--message <msg>", "Single message mode (send and exit)").option("--json", "Output JSON").option("--channel <channel>", "Channel identifier", "api").option("-v, --verbose", "Show detailed response info").option("--confirm", "Skip production warning prompt").action(async (agentSlug, options) => {
|
|
7135
|
+
const spinner = ora16();
|
|
6864
7136
|
const cwd = process.cwd();
|
|
6865
7137
|
const nonInteractive = !isInteractive();
|
|
6866
7138
|
const jsonMode = !!options.json;
|
|
@@ -6869,11 +7141,11 @@ var chatCommand = new Command19("chat").description("Chat with an agent").argume
|
|
|
6869
7141
|
if (jsonMode) {
|
|
6870
7142
|
console.log(JSON.stringify({ success: false, error: "No struere.json found" }));
|
|
6871
7143
|
} else {
|
|
6872
|
-
console.log(
|
|
7144
|
+
console.log(chalk22.red("No struere.json found. Run struere init first."));
|
|
6873
7145
|
}
|
|
6874
7146
|
process.exit(1);
|
|
6875
7147
|
}
|
|
6876
|
-
console.log(
|
|
7148
|
+
console.log(chalk22.yellow("No struere.json found - initializing project..."));
|
|
6877
7149
|
console.log();
|
|
6878
7150
|
const success = await runInit(cwd);
|
|
6879
7151
|
if (!success) {
|
|
@@ -6886,7 +7158,7 @@ var chatCommand = new Command19("chat").description("Chat with an agent").argume
|
|
|
6886
7158
|
if (jsonMode) {
|
|
6887
7159
|
console.log(JSON.stringify({ success: false, error: "Failed to load struere.json" }));
|
|
6888
7160
|
} else {
|
|
6889
|
-
console.log(
|
|
7161
|
+
console.log(chalk22.red("Failed to load struere.json"));
|
|
6890
7162
|
}
|
|
6891
7163
|
process.exit(1);
|
|
6892
7164
|
}
|
|
@@ -6897,15 +7169,15 @@ var chatCommand = new Command19("chat").description("Chat with an agent").argume
|
|
|
6897
7169
|
if (jsonMode) {
|
|
6898
7170
|
console.log(JSON.stringify({ success: false, error: "Not authenticated. Set STRUERE_API_KEY or run struere login." }));
|
|
6899
7171
|
} else {
|
|
6900
|
-
console.log(
|
|
7172
|
+
console.log(chalk22.red("Not authenticated. Set STRUERE_API_KEY or run struere login."));
|
|
6901
7173
|
}
|
|
6902
7174
|
process.exit(1);
|
|
6903
7175
|
}
|
|
6904
|
-
console.log(
|
|
7176
|
+
console.log(chalk22.yellow("Not logged in - authenticating..."));
|
|
6905
7177
|
console.log();
|
|
6906
7178
|
credentials = await performLogin();
|
|
6907
7179
|
if (!credentials) {
|
|
6908
|
-
console.log(
|
|
7180
|
+
console.log(chalk22.red("Authentication failed"));
|
|
6909
7181
|
process.exit(1);
|
|
6910
7182
|
}
|
|
6911
7183
|
console.log();
|
|
@@ -6914,7 +7186,7 @@ var chatCommand = new Command19("chat").description("Chat with an agent").argume
|
|
|
6914
7186
|
if (environment === "production" && !nonInteractive && !options.confirm) {
|
|
6915
7187
|
const confirmRl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
6916
7188
|
await new Promise((resolve) => {
|
|
6917
|
-
confirmRl.question(
|
|
7189
|
+
confirmRl.question(chalk22.yellow(`WARNING: Chatting with agent in PRODUCTION environment.
|
|
6918
7190
|
Press Enter to continue or Ctrl+C to cancel: `), resolve);
|
|
6919
7191
|
});
|
|
6920
7192
|
confirmRl.close();
|
|
@@ -6944,7 +7216,7 @@ var chatCommand = new Command19("chat").description("Chat with an agent").argume
|
|
|
6944
7216
|
if (jsonMode) {
|
|
6945
7217
|
console.log(JSON.stringify({ success: false, error: "Authentication failed" }));
|
|
6946
7218
|
} else {
|
|
6947
|
-
console.log(
|
|
7219
|
+
console.log(chalk22.red("Authentication failed"));
|
|
6948
7220
|
}
|
|
6949
7221
|
process.exit(1);
|
|
6950
7222
|
}
|
|
@@ -6959,7 +7231,7 @@ var chatCommand = new Command19("chat").description("Chat with an agent").argume
|
|
|
6959
7231
|
console.log(JSON.stringify({ success: false, error }));
|
|
6960
7232
|
} else {
|
|
6961
7233
|
spinner.fail("Failed to send message");
|
|
6962
|
-
console.log(
|
|
7234
|
+
console.log(chalk22.red("Error:"), error);
|
|
6963
7235
|
}
|
|
6964
7236
|
process.exit(1);
|
|
6965
7237
|
}
|
|
@@ -6979,30 +7251,30 @@ var chatCommand = new Command19("chat").description("Chat with an agent").argume
|
|
|
6979
7251
|
console.log();
|
|
6980
7252
|
console.log("\u2500".repeat(60));
|
|
6981
7253
|
console.log();
|
|
6982
|
-
console.log(
|
|
7254
|
+
console.log(chalk22.green("Agent:"));
|
|
6983
7255
|
console.log(result.message);
|
|
6984
7256
|
console.log();
|
|
6985
7257
|
if (options.verbose) {
|
|
6986
|
-
console.log(
|
|
6987
|
-
console.log(
|
|
6988
|
-
console.log(
|
|
7258
|
+
console.log(chalk22.dim(`Thread: ${result.threadId}`));
|
|
7259
|
+
console.log(chalk22.dim(`Tokens: ${result.usage.inputTokens} in / ${result.usage.outputTokens} out (${result.usage.totalTokens} total)`));
|
|
7260
|
+
console.log(chalk22.dim("Tool call details available in dashboard"));
|
|
6989
7261
|
} else {
|
|
6990
|
-
console.log(
|
|
7262
|
+
console.log(chalk22.dim(`Thread: ${result.threadId} | Tokens: ${result.usage.totalTokens}`));
|
|
6991
7263
|
}
|
|
6992
7264
|
console.log();
|
|
6993
7265
|
console.log("\u2500".repeat(60));
|
|
6994
7266
|
}
|
|
6995
7267
|
return;
|
|
6996
7268
|
}
|
|
6997
|
-
console.log(
|
|
6998
|
-
console.log(
|
|
7269
|
+
console.log(chalk22.bold(`Chat with ${chalk22.cyan(agentSlug)} (${environment})`));
|
|
7270
|
+
console.log(chalk22.dim("Type 'exit' to quit"));
|
|
6999
7271
|
console.log();
|
|
7000
7272
|
let threadId = options.thread;
|
|
7001
7273
|
let processing = false;
|
|
7002
7274
|
let generation = 0;
|
|
7003
7275
|
let currentAbort = null;
|
|
7004
7276
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
7005
|
-
rl.setPrompt(
|
|
7277
|
+
rl.setPrompt(chalk22.cyan("You: "));
|
|
7006
7278
|
rl.prompt();
|
|
7007
7279
|
rl.on("SIGINT", () => {
|
|
7008
7280
|
if (processing) {
|
|
@@ -7014,7 +7286,7 @@ var chatCommand = new Command19("chat").description("Chat with an agent").argume
|
|
|
7014
7286
|
spinner.stop();
|
|
7015
7287
|
processing = false;
|
|
7016
7288
|
console.log();
|
|
7017
|
-
console.log(
|
|
7289
|
+
console.log(chalk22.yellow("Cancelled"));
|
|
7018
7290
|
console.log();
|
|
7019
7291
|
rl.resume();
|
|
7020
7292
|
rl.prompt();
|
|
@@ -7052,7 +7324,7 @@ var chatCommand = new Command19("chat").description("Chat with an agent").argume
|
|
|
7052
7324
|
if (thisGeneration !== generation)
|
|
7053
7325
|
return;
|
|
7054
7326
|
if (!credentials) {
|
|
7055
|
-
console.log(
|
|
7327
|
+
console.log(chalk22.red("Authentication failed"));
|
|
7056
7328
|
rl.close();
|
|
7057
7329
|
return;
|
|
7058
7330
|
}
|
|
@@ -7066,7 +7338,7 @@ var chatCommand = new Command19("chat").description("Chat with an agent").argume
|
|
|
7066
7338
|
}
|
|
7067
7339
|
if (error) {
|
|
7068
7340
|
spinner.fail("");
|
|
7069
|
-
console.log(
|
|
7341
|
+
console.log(chalk22.red("Error:"), error);
|
|
7070
7342
|
processing = false;
|
|
7071
7343
|
currentAbort = null;
|
|
7072
7344
|
rl.resume();
|
|
@@ -7084,15 +7356,15 @@ var chatCommand = new Command19("chat").description("Chat with an agent").argume
|
|
|
7084
7356
|
spinner.stop();
|
|
7085
7357
|
threadId = result.threadId;
|
|
7086
7358
|
console.log();
|
|
7087
|
-
console.log(
|
|
7359
|
+
console.log(chalk22.green("Agent:"));
|
|
7088
7360
|
console.log(result.message);
|
|
7089
7361
|
console.log();
|
|
7090
7362
|
if (options.verbose) {
|
|
7091
|
-
console.log(
|
|
7092
|
-
console.log(
|
|
7093
|
-
console.log(
|
|
7363
|
+
console.log(chalk22.dim(`Thread: ${result.threadId}`));
|
|
7364
|
+
console.log(chalk22.dim(`Tokens: ${result.usage.inputTokens} in / ${result.usage.outputTokens} out (${result.usage.totalTokens} total)`));
|
|
7365
|
+
console.log(chalk22.dim("Tool call details available in dashboard"));
|
|
7094
7366
|
} else {
|
|
7095
|
-
console.log(
|
|
7367
|
+
console.log(chalk22.dim(`Tokens: ${result.usage.totalTokens}`));
|
|
7096
7368
|
}
|
|
7097
7369
|
console.log();
|
|
7098
7370
|
processing = false;
|
|
@@ -7102,14 +7374,14 @@ var chatCommand = new Command19("chat").description("Chat with an agent").argume
|
|
|
7102
7374
|
});
|
|
7103
7375
|
rl.on("close", () => {
|
|
7104
7376
|
console.log();
|
|
7105
|
-
console.log(
|
|
7377
|
+
console.log(chalk22.dim("Goodbye!"));
|
|
7106
7378
|
process.exit(0);
|
|
7107
7379
|
});
|
|
7108
7380
|
});
|
|
7109
7381
|
// package.json
|
|
7110
7382
|
var package_default = {
|
|
7111
7383
|
name: "struere",
|
|
7112
|
-
version: "0.10.
|
|
7384
|
+
version: "0.10.6",
|
|
7113
7385
|
description: "Build, test, and deploy AI agents",
|
|
7114
7386
|
keywords: [
|
|
7115
7387
|
"ai",
|
|
@@ -7221,6 +7493,7 @@ program.addCommand(addCommand);
|
|
|
7221
7493
|
program.addCommand(statusCommand);
|
|
7222
7494
|
program.addCommand(pullCommand);
|
|
7223
7495
|
program.addCommand(entitiesCommand);
|
|
7496
|
+
program.addCommand(logsCommand);
|
|
7224
7497
|
program.addCommand(docsCommand);
|
|
7225
7498
|
program.addCommand(evalCommand);
|
|
7226
7499
|
program.addCommand(templatesCommand);
|