struere 0.16.1 → 0.16.3
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
CHANGED
|
@@ -73596,6 +73596,144 @@ async function findThreadByPhone(options) {
|
|
|
73596
73596
|
return false;
|
|
73597
73597
|
}) ?? null;
|
|
73598
73598
|
}
|
|
73599
|
+
async function replyToThread(options) {
|
|
73600
|
+
const apiKey = getApiKey();
|
|
73601
|
+
const credentials = loadCredentials();
|
|
73602
|
+
if (apiKey && !credentials?.token) {
|
|
73603
|
+
return threadsApiCall("/v1/threads/reply", {
|
|
73604
|
+
threadId: options.threadId,
|
|
73605
|
+
message: options.message
|
|
73606
|
+
});
|
|
73607
|
+
}
|
|
73608
|
+
const token = getToken5();
|
|
73609
|
+
const response = await fetch(`${CONVEX_URL}/api/action`, {
|
|
73610
|
+
method: "POST",
|
|
73611
|
+
headers: {
|
|
73612
|
+
"Content-Type": "application/json",
|
|
73613
|
+
Authorization: `Bearer ${token}`
|
|
73614
|
+
},
|
|
73615
|
+
body: JSON.stringify({
|
|
73616
|
+
path: "chat:replyToThreadCli",
|
|
73617
|
+
args: { threadId: options.threadId, message: options.message }
|
|
73618
|
+
}),
|
|
73619
|
+
signal: AbortSignal.timeout(30000)
|
|
73620
|
+
});
|
|
73621
|
+
const text = await response.text();
|
|
73622
|
+
let json;
|
|
73623
|
+
try {
|
|
73624
|
+
json = JSON.parse(text);
|
|
73625
|
+
} catch {
|
|
73626
|
+
throw new Error(text || `HTTP ${response.status}`);
|
|
73627
|
+
}
|
|
73628
|
+
if (!response.ok) {
|
|
73629
|
+
throw new Error(json.errorData?.message || json.errorMessage || text);
|
|
73630
|
+
}
|
|
73631
|
+
if (json.status === "error") {
|
|
73632
|
+
throw new Error(json.errorData?.message || json.errorMessage || "Unknown error from Convex");
|
|
73633
|
+
}
|
|
73634
|
+
return json.value;
|
|
73635
|
+
}
|
|
73636
|
+
async function pauseThread(options) {
|
|
73637
|
+
const apiKey = getApiKey();
|
|
73638
|
+
const credentials = loadCredentials();
|
|
73639
|
+
if (apiKey && !credentials?.token) {
|
|
73640
|
+
return threadsApiCall("/v1/threads/pause", {
|
|
73641
|
+
threadId: options.threadId
|
|
73642
|
+
});
|
|
73643
|
+
}
|
|
73644
|
+
const token = getToken5();
|
|
73645
|
+
const response = await fetch(`${CONVEX_URL}/api/mutation`, {
|
|
73646
|
+
method: "POST",
|
|
73647
|
+
headers: {
|
|
73648
|
+
"Content-Type": "application/json",
|
|
73649
|
+
Authorization: `Bearer ${token}`
|
|
73650
|
+
},
|
|
73651
|
+
body: JSON.stringify({
|
|
73652
|
+
path: "threads:setAgentPaused",
|
|
73653
|
+
args: { threadId: options.threadId, paused: true }
|
|
73654
|
+
}),
|
|
73655
|
+
signal: AbortSignal.timeout(30000)
|
|
73656
|
+
});
|
|
73657
|
+
const text = await response.text();
|
|
73658
|
+
let json;
|
|
73659
|
+
try {
|
|
73660
|
+
json = JSON.parse(text);
|
|
73661
|
+
} catch {
|
|
73662
|
+
throw new Error(text || `HTTP ${response.status}`);
|
|
73663
|
+
}
|
|
73664
|
+
if (!response.ok) {
|
|
73665
|
+
throw new Error(json.errorData?.message || json.errorMessage || text);
|
|
73666
|
+
}
|
|
73667
|
+
if (json.status === "error") {
|
|
73668
|
+
throw new Error(json.errorData?.message || json.errorMessage || "Unknown error from Convex");
|
|
73669
|
+
}
|
|
73670
|
+
return { success: true, paused: true };
|
|
73671
|
+
}
|
|
73672
|
+
async function resumeThread(options) {
|
|
73673
|
+
const apiKey = getApiKey();
|
|
73674
|
+
const credentials = loadCredentials();
|
|
73675
|
+
if (apiKey && !credentials?.token) {
|
|
73676
|
+
return threadsApiCall("/v1/threads/resume", {
|
|
73677
|
+
threadId: options.threadId
|
|
73678
|
+
});
|
|
73679
|
+
}
|
|
73680
|
+
const token = getToken5();
|
|
73681
|
+
const response = await fetch(`${CONVEX_URL}/api/mutation`, {
|
|
73682
|
+
method: "POST",
|
|
73683
|
+
headers: {
|
|
73684
|
+
"Content-Type": "application/json",
|
|
73685
|
+
Authorization: `Bearer ${token}`
|
|
73686
|
+
},
|
|
73687
|
+
body: JSON.stringify({
|
|
73688
|
+
path: "threads:setAgentPaused",
|
|
73689
|
+
args: { threadId: options.threadId, paused: false }
|
|
73690
|
+
}),
|
|
73691
|
+
signal: AbortSignal.timeout(30000)
|
|
73692
|
+
});
|
|
73693
|
+
const text = await response.text();
|
|
73694
|
+
let json;
|
|
73695
|
+
try {
|
|
73696
|
+
json = JSON.parse(text);
|
|
73697
|
+
} catch {
|
|
73698
|
+
throw new Error(text || `HTTP ${response.status}`);
|
|
73699
|
+
}
|
|
73700
|
+
if (!response.ok) {
|
|
73701
|
+
throw new Error(json.errorData?.message || json.errorMessage || text);
|
|
73702
|
+
}
|
|
73703
|
+
if (json.status === "error") {
|
|
73704
|
+
throw new Error(json.errorData?.message || json.errorMessage || "Unknown error from Convex");
|
|
73705
|
+
}
|
|
73706
|
+
return { success: true, paused: false };
|
|
73707
|
+
}
|
|
73708
|
+
async function resolveActiveWhatsAppThread(options) {
|
|
73709
|
+
const threads = await listThreads({
|
|
73710
|
+
environment: options.environment,
|
|
73711
|
+
organizationId: options.organizationId,
|
|
73712
|
+
limit: 100
|
|
73713
|
+
});
|
|
73714
|
+
const isPhone = options.target.startsWith("+") || /^\d+$/.test(options.target);
|
|
73715
|
+
let matches;
|
|
73716
|
+
if (isPhone) {
|
|
73717
|
+
const normalize = (p) => p.replace(/\D/g, "");
|
|
73718
|
+
const normalizedInput = normalize(options.target);
|
|
73719
|
+
matches = threads.filter((t2) => {
|
|
73720
|
+
const phoneNumber = t2.channelParams?.phoneNumber;
|
|
73721
|
+
if (phoneNumber && normalize(phoneNumber) === normalizedInput)
|
|
73722
|
+
return true;
|
|
73723
|
+
if (t2.externalId && t2.externalId.includes(normalizedInput))
|
|
73724
|
+
return true;
|
|
73725
|
+
return false;
|
|
73726
|
+
});
|
|
73727
|
+
} else {
|
|
73728
|
+
matches = threads.filter((t2) => t2._id === options.target);
|
|
73729
|
+
}
|
|
73730
|
+
const active = matches.filter((t2) => !t2.externalId?.includes(":archived:"));
|
|
73731
|
+
if (active.length === 0)
|
|
73732
|
+
return { kind: "none" };
|
|
73733
|
+
if (active.length === 1)
|
|
73734
|
+
return { kind: "ok", thread: active[0] };
|
|
73735
|
+
return { kind: "multiple", candidates: active };
|
|
73736
|
+
}
|
|
73599
73737
|
|
|
73600
73738
|
// src/cli/commands/threads.ts
|
|
73601
73739
|
async function ensureAuth7() {
|
|
@@ -73676,6 +73814,16 @@ function roleColor(role) {
|
|
|
73676
73814
|
return chalk22.gray(role);
|
|
73677
73815
|
}
|
|
73678
73816
|
}
|
|
73817
|
+
function threadPhone(thread) {
|
|
73818
|
+
const phoneNumber = thread.channelParams?.phoneNumber;
|
|
73819
|
+
if (phoneNumber)
|
|
73820
|
+
return phoneNumber;
|
|
73821
|
+
if (thread.externalId) {
|
|
73822
|
+
const parts = thread.externalId.split(":");
|
|
73823
|
+
return parts[parts.length - 1];
|
|
73824
|
+
}
|
|
73825
|
+
return "unknown";
|
|
73826
|
+
}
|
|
73679
73827
|
var threadsCommand = new Command20("threads").description("Manage conversation threads");
|
|
73680
73828
|
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) => {
|
|
73681
73829
|
await ensureAuth7();
|
|
@@ -73703,7 +73851,7 @@ threadsCommand.command("list", { isDefault: true }).description("List conversati
|
|
|
73703
73851
|
], threads.map((t2) => ({
|
|
73704
73852
|
id: t2._id,
|
|
73705
73853
|
channel: channelColor(t2.channel),
|
|
73706
|
-
participant: t2.participantName ?? "Unknown",
|
|
73854
|
+
participant: t2.agentPaused ? `${t2.participantName ?? "Unknown"} ${chalk22.yellow("PAUSED")}` : t2.participantName ?? "Unknown",
|
|
73707
73855
|
agent: t2.agentName ?? "Unknown",
|
|
73708
73856
|
lastMessage: t2.lastMessage ? t2.lastMessage.content.slice(0, 40) : chalk22.gray("-"),
|
|
73709
73857
|
time: relativeTime4(t2.updatedAt ?? t2.createdAt)
|
|
@@ -73859,6 +74007,138 @@ threadsCommand.command("reset").description("Archive a thread by phone number").
|
|
|
73859
74007
|
process.exit(1);
|
|
73860
74008
|
}
|
|
73861
74009
|
});
|
|
74010
|
+
async function resolveOrExit(target, environment, json, spinner) {
|
|
74011
|
+
const project = loadProject(process.cwd());
|
|
74012
|
+
const resolution = await resolveActiveWhatsAppThread({
|
|
74013
|
+
target,
|
|
74014
|
+
environment,
|
|
74015
|
+
organizationId: project?.organization.id
|
|
74016
|
+
});
|
|
74017
|
+
if (resolution.kind === "none") {
|
|
74018
|
+
const error = `No active WhatsApp thread found for "${target}" in ${environment}. Did you mean --env production?`;
|
|
74019
|
+
spinner?.fail(error);
|
|
74020
|
+
if (json) {
|
|
74021
|
+
console.log(JSON.stringify({ success: false, error }));
|
|
74022
|
+
} else {
|
|
74023
|
+
console.log(chalk22.red("Error:"), error);
|
|
74024
|
+
}
|
|
74025
|
+
process.exit(1);
|
|
74026
|
+
}
|
|
74027
|
+
if (resolution.kind === "multiple") {
|
|
74028
|
+
spinner?.stop();
|
|
74029
|
+
if (json) {
|
|
74030
|
+
console.log(JSON.stringify({ success: false, error: `Multiple active threads match ${target}` }));
|
|
74031
|
+
} else {
|
|
74032
|
+
console.log(chalk22.yellow(`Multiple active threads match ${target}:`));
|
|
74033
|
+
for (const candidate of resolution.candidates) {
|
|
74034
|
+
console.log(` ${chalk22.cyan(candidate._id)} ${candidate.agentName ?? "Unknown"} ${threadPhone(candidate)}`);
|
|
74035
|
+
}
|
|
74036
|
+
console.log(chalk22.gray("Re-run with an explicit thread id."));
|
|
74037
|
+
}
|
|
74038
|
+
process.exit(1);
|
|
74039
|
+
}
|
|
74040
|
+
const thread = resolution.thread;
|
|
74041
|
+
if (!thread.externalId?.startsWith("whatsapp:")) {
|
|
74042
|
+
const error = `Thread ${thread._id} is not a WhatsApp conversation (reply/pause/resume only support WhatsApp).`;
|
|
74043
|
+
spinner?.fail(error);
|
|
74044
|
+
if (json) {
|
|
74045
|
+
console.log(JSON.stringify({ success: false, error }));
|
|
74046
|
+
} else {
|
|
74047
|
+
console.log(chalk22.red("Error:"), error);
|
|
74048
|
+
}
|
|
74049
|
+
process.exit(1);
|
|
74050
|
+
}
|
|
74051
|
+
return thread;
|
|
74052
|
+
}
|
|
74053
|
+
threadsCommand.command("reply").description("Send a WhatsApp message directly to a user as a human operator (does not pause the agent)").argument("<target>", "Thread id or phone number").requiredOption("-m, --message <text>", "Message to send to the user").option("--env <environment>", "Environment: development | production | eval", "development").option("--json", "Output raw JSON").action(async (target, opts) => {
|
|
74054
|
+
await ensureAuth7();
|
|
74055
|
+
const spinner = opts.json ? null : ora16();
|
|
74056
|
+
const environment = opts.env;
|
|
74057
|
+
try {
|
|
74058
|
+
spinner?.start(`Resolving thread for ${target}...`);
|
|
74059
|
+
const thread = await resolveOrExit(target, environment, !!opts.json, spinner);
|
|
74060
|
+
const phone = threadPhone(thread);
|
|
74061
|
+
if (spinner)
|
|
74062
|
+
spinner.text = `Sending to ${phone}...`;
|
|
74063
|
+
const result = await replyToThread({
|
|
74064
|
+
threadId: thread._id,
|
|
74065
|
+
message: opts.message,
|
|
74066
|
+
environment
|
|
74067
|
+
});
|
|
74068
|
+
if (result.whatsappStatus === "failed") {
|
|
74069
|
+
spinner?.fail(`Failed to send to ${phone} (env: ${environment})`);
|
|
74070
|
+
if (opts.json) {
|
|
74071
|
+
console.log(JSON.stringify({ success: false, threadId: thread._id, whatsappStatus: result.whatsappStatus, environment }));
|
|
74072
|
+
} else {
|
|
74073
|
+
console.log(chalk22.gray(`Tip: the 24h window may be closed or the connection is not connected. Re-open with a template: struere run-tool whatsapp.sendTemplate --args '{"to":"${phone}","templateName":"...","language":"..."}'`));
|
|
74074
|
+
}
|
|
74075
|
+
process.exit(1);
|
|
74076
|
+
}
|
|
74077
|
+
spinner?.succeed(chalk22.green(`Sent to ${phone} (env: ${environment})`));
|
|
74078
|
+
if (opts.json) {
|
|
74079
|
+
console.log(JSON.stringify({ success: true, threadId: thread._id, whatsappStatus: result.whatsappStatus, environment }));
|
|
74080
|
+
}
|
|
74081
|
+
} catch (err) {
|
|
74082
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
74083
|
+
spinner?.fail("Failed to reply to thread");
|
|
74084
|
+
if (opts.json) {
|
|
74085
|
+
console.log(JSON.stringify({ success: false, error: message }));
|
|
74086
|
+
} else {
|
|
74087
|
+
console.log(chalk22.red("Error:"), message);
|
|
74088
|
+
}
|
|
74089
|
+
process.exit(1);
|
|
74090
|
+
}
|
|
74091
|
+
});
|
|
74092
|
+
threadsCommand.command("pause").description("Pause the agent on a conversation so it stops auto-responding").argument("<target>", "Thread id or phone number").option("--env <environment>", "Environment: development | production | eval", "development").option("--json", "Output raw JSON").action(async (target, opts) => {
|
|
74093
|
+
await ensureAuth7();
|
|
74094
|
+
const spinner = opts.json ? null : ora16();
|
|
74095
|
+
const environment = opts.env;
|
|
74096
|
+
try {
|
|
74097
|
+
spinner?.start(`Resolving thread for ${target}...`);
|
|
74098
|
+
const thread = await resolveOrExit(target, environment, !!opts.json, spinner);
|
|
74099
|
+
if (spinner)
|
|
74100
|
+
spinner.text = `Pausing agent for thread ${thread._id}...`;
|
|
74101
|
+
await pauseThread({ threadId: thread._id, environment });
|
|
74102
|
+
spinner?.succeed(chalk22.green(`Agent paused for thread ${thread._id} (env: ${environment})`));
|
|
74103
|
+
if (opts.json) {
|
|
74104
|
+
console.log(JSON.stringify({ success: true, threadId: thread._id, paused: true, environment }));
|
|
74105
|
+
}
|
|
74106
|
+
} catch (err) {
|
|
74107
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
74108
|
+
spinner?.fail("Failed to pause thread");
|
|
74109
|
+
if (opts.json) {
|
|
74110
|
+
console.log(JSON.stringify({ success: false, error: message }));
|
|
74111
|
+
} else {
|
|
74112
|
+
console.log(chalk22.red("Error:"), message);
|
|
74113
|
+
}
|
|
74114
|
+
process.exit(1);
|
|
74115
|
+
}
|
|
74116
|
+
});
|
|
74117
|
+
threadsCommand.command("resume").description("Resume the agent on a paused conversation").argument("<target>", "Thread id or phone number").option("--env <environment>", "Environment: development | production | eval", "development").option("--json", "Output raw JSON").action(async (target, opts) => {
|
|
74118
|
+
await ensureAuth7();
|
|
74119
|
+
const spinner = opts.json ? null : ora16();
|
|
74120
|
+
const environment = opts.env;
|
|
74121
|
+
try {
|
|
74122
|
+
spinner?.start(`Resolving thread for ${target}...`);
|
|
74123
|
+
const thread = await resolveOrExit(target, environment, !!opts.json, spinner);
|
|
74124
|
+
if (spinner)
|
|
74125
|
+
spinner.text = `Resuming agent for thread ${thread._id}...`;
|
|
74126
|
+
await resumeThread({ threadId: thread._id, environment });
|
|
74127
|
+
spinner?.succeed(chalk22.green(`Agent resumed for thread ${thread._id} (env: ${environment})`));
|
|
74128
|
+
if (opts.json) {
|
|
74129
|
+
console.log(JSON.stringify({ success: true, threadId: thread._id, paused: false, environment }));
|
|
74130
|
+
}
|
|
74131
|
+
} catch (err) {
|
|
74132
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
74133
|
+
spinner?.fail("Failed to resume thread");
|
|
74134
|
+
if (opts.json) {
|
|
74135
|
+
console.log(JSON.stringify({ success: false, error: message }));
|
|
74136
|
+
} else {
|
|
74137
|
+
console.log(chalk22.red("Error:"), message);
|
|
74138
|
+
}
|
|
74139
|
+
process.exit(1);
|
|
74140
|
+
}
|
|
74141
|
+
});
|
|
73862
74142
|
|
|
73863
74143
|
// src/cli/commands/compile-prompt.ts
|
|
73864
74144
|
init_credentials();
|
|
@@ -75914,7 +76194,7 @@ keysCommand.command("revoke <id-or-prefix>").description("Revoke an API key (del
|
|
|
75914
76194
|
// package.json
|
|
75915
76195
|
var package_default = {
|
|
75916
76196
|
name: "struere",
|
|
75917
|
-
version: "0.16.
|
|
76197
|
+
version: "0.16.3",
|
|
75918
76198
|
description: "Build, test, and deploy AI agents",
|
|
75919
76199
|
keywords: [
|
|
75920
76200
|
"ai",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"threads.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/threads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"threads.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/threads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AA0GnC,eAAO,MAAM,cAAc,SACkB,CAAA"}
|
package/dist/cli/index.js
CHANGED
|
@@ -74586,6 +74586,144 @@ async function findThreadByPhone(options) {
|
|
|
74586
74586
|
return false;
|
|
74587
74587
|
}) ?? null;
|
|
74588
74588
|
}
|
|
74589
|
+
async function replyToThread(options) {
|
|
74590
|
+
const apiKey = getApiKey();
|
|
74591
|
+
const credentials = loadCredentials();
|
|
74592
|
+
if (apiKey && !credentials?.token) {
|
|
74593
|
+
return threadsApiCall("/v1/threads/reply", {
|
|
74594
|
+
threadId: options.threadId,
|
|
74595
|
+
message: options.message
|
|
74596
|
+
});
|
|
74597
|
+
}
|
|
74598
|
+
const token = getToken5();
|
|
74599
|
+
const response = await fetch(`${CONVEX_URL}/api/action`, {
|
|
74600
|
+
method: "POST",
|
|
74601
|
+
headers: {
|
|
74602
|
+
"Content-Type": "application/json",
|
|
74603
|
+
Authorization: `Bearer ${token}`
|
|
74604
|
+
},
|
|
74605
|
+
body: JSON.stringify({
|
|
74606
|
+
path: "chat:replyToThreadCli",
|
|
74607
|
+
args: { threadId: options.threadId, message: options.message }
|
|
74608
|
+
}),
|
|
74609
|
+
signal: AbortSignal.timeout(30000)
|
|
74610
|
+
});
|
|
74611
|
+
const text = await response.text();
|
|
74612
|
+
let json;
|
|
74613
|
+
try {
|
|
74614
|
+
json = JSON.parse(text);
|
|
74615
|
+
} catch {
|
|
74616
|
+
throw new Error(text || `HTTP ${response.status}`);
|
|
74617
|
+
}
|
|
74618
|
+
if (!response.ok) {
|
|
74619
|
+
throw new Error(json.errorData?.message || json.errorMessage || text);
|
|
74620
|
+
}
|
|
74621
|
+
if (json.status === "error") {
|
|
74622
|
+
throw new Error(json.errorData?.message || json.errorMessage || "Unknown error from Convex");
|
|
74623
|
+
}
|
|
74624
|
+
return json.value;
|
|
74625
|
+
}
|
|
74626
|
+
async function pauseThread(options) {
|
|
74627
|
+
const apiKey = getApiKey();
|
|
74628
|
+
const credentials = loadCredentials();
|
|
74629
|
+
if (apiKey && !credentials?.token) {
|
|
74630
|
+
return threadsApiCall("/v1/threads/pause", {
|
|
74631
|
+
threadId: options.threadId
|
|
74632
|
+
});
|
|
74633
|
+
}
|
|
74634
|
+
const token = getToken5();
|
|
74635
|
+
const response = await fetch(`${CONVEX_URL}/api/mutation`, {
|
|
74636
|
+
method: "POST",
|
|
74637
|
+
headers: {
|
|
74638
|
+
"Content-Type": "application/json",
|
|
74639
|
+
Authorization: `Bearer ${token}`
|
|
74640
|
+
},
|
|
74641
|
+
body: JSON.stringify({
|
|
74642
|
+
path: "threads:setAgentPaused",
|
|
74643
|
+
args: { threadId: options.threadId, paused: true }
|
|
74644
|
+
}),
|
|
74645
|
+
signal: AbortSignal.timeout(30000)
|
|
74646
|
+
});
|
|
74647
|
+
const text = await response.text();
|
|
74648
|
+
let json;
|
|
74649
|
+
try {
|
|
74650
|
+
json = JSON.parse(text);
|
|
74651
|
+
} catch {
|
|
74652
|
+
throw new Error(text || `HTTP ${response.status}`);
|
|
74653
|
+
}
|
|
74654
|
+
if (!response.ok) {
|
|
74655
|
+
throw new Error(json.errorData?.message || json.errorMessage || text);
|
|
74656
|
+
}
|
|
74657
|
+
if (json.status === "error") {
|
|
74658
|
+
throw new Error(json.errorData?.message || json.errorMessage || "Unknown error from Convex");
|
|
74659
|
+
}
|
|
74660
|
+
return { success: true, paused: true };
|
|
74661
|
+
}
|
|
74662
|
+
async function resumeThread(options) {
|
|
74663
|
+
const apiKey = getApiKey();
|
|
74664
|
+
const credentials = loadCredentials();
|
|
74665
|
+
if (apiKey && !credentials?.token) {
|
|
74666
|
+
return threadsApiCall("/v1/threads/resume", {
|
|
74667
|
+
threadId: options.threadId
|
|
74668
|
+
});
|
|
74669
|
+
}
|
|
74670
|
+
const token = getToken5();
|
|
74671
|
+
const response = await fetch(`${CONVEX_URL}/api/mutation`, {
|
|
74672
|
+
method: "POST",
|
|
74673
|
+
headers: {
|
|
74674
|
+
"Content-Type": "application/json",
|
|
74675
|
+
Authorization: `Bearer ${token}`
|
|
74676
|
+
},
|
|
74677
|
+
body: JSON.stringify({
|
|
74678
|
+
path: "threads:setAgentPaused",
|
|
74679
|
+
args: { threadId: options.threadId, paused: false }
|
|
74680
|
+
}),
|
|
74681
|
+
signal: AbortSignal.timeout(30000)
|
|
74682
|
+
});
|
|
74683
|
+
const text = await response.text();
|
|
74684
|
+
let json;
|
|
74685
|
+
try {
|
|
74686
|
+
json = JSON.parse(text);
|
|
74687
|
+
} catch {
|
|
74688
|
+
throw new Error(text || `HTTP ${response.status}`);
|
|
74689
|
+
}
|
|
74690
|
+
if (!response.ok) {
|
|
74691
|
+
throw new Error(json.errorData?.message || json.errorMessage || text);
|
|
74692
|
+
}
|
|
74693
|
+
if (json.status === "error") {
|
|
74694
|
+
throw new Error(json.errorData?.message || json.errorMessage || "Unknown error from Convex");
|
|
74695
|
+
}
|
|
74696
|
+
return { success: true, paused: false };
|
|
74697
|
+
}
|
|
74698
|
+
async function resolveActiveWhatsAppThread(options) {
|
|
74699
|
+
const threads = await listThreads({
|
|
74700
|
+
environment: options.environment,
|
|
74701
|
+
organizationId: options.organizationId,
|
|
74702
|
+
limit: 100
|
|
74703
|
+
});
|
|
74704
|
+
const isPhone = options.target.startsWith("+") || /^\d+$/.test(options.target);
|
|
74705
|
+
let matches;
|
|
74706
|
+
if (isPhone) {
|
|
74707
|
+
const normalize = (p) => p.replace(/\D/g, "");
|
|
74708
|
+
const normalizedInput = normalize(options.target);
|
|
74709
|
+
matches = threads.filter((t2) => {
|
|
74710
|
+
const phoneNumber = t2.channelParams?.phoneNumber;
|
|
74711
|
+
if (phoneNumber && normalize(phoneNumber) === normalizedInput)
|
|
74712
|
+
return true;
|
|
74713
|
+
if (t2.externalId && t2.externalId.includes(normalizedInput))
|
|
74714
|
+
return true;
|
|
74715
|
+
return false;
|
|
74716
|
+
});
|
|
74717
|
+
} else {
|
|
74718
|
+
matches = threads.filter((t2) => t2._id === options.target);
|
|
74719
|
+
}
|
|
74720
|
+
const active = matches.filter((t2) => !t2.externalId?.includes(":archived:"));
|
|
74721
|
+
if (active.length === 0)
|
|
74722
|
+
return { kind: "none" };
|
|
74723
|
+
if (active.length === 1)
|
|
74724
|
+
return { kind: "ok", thread: active[0] };
|
|
74725
|
+
return { kind: "multiple", candidates: active };
|
|
74726
|
+
}
|
|
74589
74727
|
|
|
74590
74728
|
// src/cli/commands/threads.ts
|
|
74591
74729
|
async function ensureAuth7() {
|
|
@@ -74666,6 +74804,16 @@ function roleColor(role) {
|
|
|
74666
74804
|
return chalk27.gray(role);
|
|
74667
74805
|
}
|
|
74668
74806
|
}
|
|
74807
|
+
function threadPhone(thread) {
|
|
74808
|
+
const phoneNumber = thread.channelParams?.phoneNumber;
|
|
74809
|
+
if (phoneNumber)
|
|
74810
|
+
return phoneNumber;
|
|
74811
|
+
if (thread.externalId) {
|
|
74812
|
+
const parts = thread.externalId.split(":");
|
|
74813
|
+
return parts[parts.length - 1];
|
|
74814
|
+
}
|
|
74815
|
+
return "unknown";
|
|
74816
|
+
}
|
|
74669
74817
|
var threadsCommand = new Command25("threads").description("Manage conversation threads");
|
|
74670
74818
|
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) => {
|
|
74671
74819
|
await ensureAuth7();
|
|
@@ -74693,7 +74841,7 @@ threadsCommand.command("list", { isDefault: true }).description("List conversati
|
|
|
74693
74841
|
], threads.map((t2) => ({
|
|
74694
74842
|
id: t2._id,
|
|
74695
74843
|
channel: channelColor(t2.channel),
|
|
74696
|
-
participant: t2.participantName ?? "Unknown",
|
|
74844
|
+
participant: t2.agentPaused ? `${t2.participantName ?? "Unknown"} ${chalk27.yellow("PAUSED")}` : t2.participantName ?? "Unknown",
|
|
74697
74845
|
agent: t2.agentName ?? "Unknown",
|
|
74698
74846
|
lastMessage: t2.lastMessage ? t2.lastMessage.content.slice(0, 40) : chalk27.gray("-"),
|
|
74699
74847
|
time: relativeTime4(t2.updatedAt ?? t2.createdAt)
|
|
@@ -74849,6 +74997,138 @@ threadsCommand.command("reset").description("Archive a thread by phone number").
|
|
|
74849
74997
|
process.exit(1);
|
|
74850
74998
|
}
|
|
74851
74999
|
});
|
|
75000
|
+
async function resolveOrExit(target, environment, json, spinner) {
|
|
75001
|
+
const project = loadProject(process.cwd());
|
|
75002
|
+
const resolution = await resolveActiveWhatsAppThread({
|
|
75003
|
+
target,
|
|
75004
|
+
environment,
|
|
75005
|
+
organizationId: project?.organization.id
|
|
75006
|
+
});
|
|
75007
|
+
if (resolution.kind === "none") {
|
|
75008
|
+
const error = `No active WhatsApp thread found for "${target}" in ${environment}. Did you mean --env production?`;
|
|
75009
|
+
spinner?.fail(error);
|
|
75010
|
+
if (json) {
|
|
75011
|
+
console.log(JSON.stringify({ success: false, error }));
|
|
75012
|
+
} else {
|
|
75013
|
+
console.log(chalk27.red("Error:"), error);
|
|
75014
|
+
}
|
|
75015
|
+
process.exit(1);
|
|
75016
|
+
}
|
|
75017
|
+
if (resolution.kind === "multiple") {
|
|
75018
|
+
spinner?.stop();
|
|
75019
|
+
if (json) {
|
|
75020
|
+
console.log(JSON.stringify({ success: false, error: `Multiple active threads match ${target}` }));
|
|
75021
|
+
} else {
|
|
75022
|
+
console.log(chalk27.yellow(`Multiple active threads match ${target}:`));
|
|
75023
|
+
for (const candidate of resolution.candidates) {
|
|
75024
|
+
console.log(` ${chalk27.cyan(candidate._id)} ${candidate.agentName ?? "Unknown"} ${threadPhone(candidate)}`);
|
|
75025
|
+
}
|
|
75026
|
+
console.log(chalk27.gray("Re-run with an explicit thread id."));
|
|
75027
|
+
}
|
|
75028
|
+
process.exit(1);
|
|
75029
|
+
}
|
|
75030
|
+
const thread = resolution.thread;
|
|
75031
|
+
if (!thread.externalId?.startsWith("whatsapp:")) {
|
|
75032
|
+
const error = `Thread ${thread._id} is not a WhatsApp conversation (reply/pause/resume only support WhatsApp).`;
|
|
75033
|
+
spinner?.fail(error);
|
|
75034
|
+
if (json) {
|
|
75035
|
+
console.log(JSON.stringify({ success: false, error }));
|
|
75036
|
+
} else {
|
|
75037
|
+
console.log(chalk27.red("Error:"), error);
|
|
75038
|
+
}
|
|
75039
|
+
process.exit(1);
|
|
75040
|
+
}
|
|
75041
|
+
return thread;
|
|
75042
|
+
}
|
|
75043
|
+
threadsCommand.command("reply").description("Send a WhatsApp message directly to a user as a human operator (does not pause the agent)").argument("<target>", "Thread id or phone number").requiredOption("-m, --message <text>", "Message to send to the user").option("--env <environment>", "Environment: development | production | eval", "development").option("--json", "Output raw JSON").action(async (target, opts) => {
|
|
75044
|
+
await ensureAuth7();
|
|
75045
|
+
const spinner = opts.json ? null : ora20();
|
|
75046
|
+
const environment = opts.env;
|
|
75047
|
+
try {
|
|
75048
|
+
spinner?.start(`Resolving thread for ${target}...`);
|
|
75049
|
+
const thread = await resolveOrExit(target, environment, !!opts.json, spinner);
|
|
75050
|
+
const phone = threadPhone(thread);
|
|
75051
|
+
if (spinner)
|
|
75052
|
+
spinner.text = `Sending to ${phone}...`;
|
|
75053
|
+
const result = await replyToThread({
|
|
75054
|
+
threadId: thread._id,
|
|
75055
|
+
message: opts.message,
|
|
75056
|
+
environment
|
|
75057
|
+
});
|
|
75058
|
+
if (result.whatsappStatus === "failed") {
|
|
75059
|
+
spinner?.fail(`Failed to send to ${phone} (env: ${environment})`);
|
|
75060
|
+
if (opts.json) {
|
|
75061
|
+
console.log(JSON.stringify({ success: false, threadId: thread._id, whatsappStatus: result.whatsappStatus, environment }));
|
|
75062
|
+
} else {
|
|
75063
|
+
console.log(chalk27.gray(`Tip: the 24h window may be closed or the connection is not connected. Re-open with a template: struere run-tool whatsapp.sendTemplate --args '{"to":"${phone}","templateName":"...","language":"..."}'`));
|
|
75064
|
+
}
|
|
75065
|
+
process.exit(1);
|
|
75066
|
+
}
|
|
75067
|
+
spinner?.succeed(chalk27.green(`Sent to ${phone} (env: ${environment})`));
|
|
75068
|
+
if (opts.json) {
|
|
75069
|
+
console.log(JSON.stringify({ success: true, threadId: thread._id, whatsappStatus: result.whatsappStatus, environment }));
|
|
75070
|
+
}
|
|
75071
|
+
} catch (err) {
|
|
75072
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
75073
|
+
spinner?.fail("Failed to reply to thread");
|
|
75074
|
+
if (opts.json) {
|
|
75075
|
+
console.log(JSON.stringify({ success: false, error: message }));
|
|
75076
|
+
} else {
|
|
75077
|
+
console.log(chalk27.red("Error:"), message);
|
|
75078
|
+
}
|
|
75079
|
+
process.exit(1);
|
|
75080
|
+
}
|
|
75081
|
+
});
|
|
75082
|
+
threadsCommand.command("pause").description("Pause the agent on a conversation so it stops auto-responding").argument("<target>", "Thread id or phone number").option("--env <environment>", "Environment: development | production | eval", "development").option("--json", "Output raw JSON").action(async (target, opts) => {
|
|
75083
|
+
await ensureAuth7();
|
|
75084
|
+
const spinner = opts.json ? null : ora20();
|
|
75085
|
+
const environment = opts.env;
|
|
75086
|
+
try {
|
|
75087
|
+
spinner?.start(`Resolving thread for ${target}...`);
|
|
75088
|
+
const thread = await resolveOrExit(target, environment, !!opts.json, spinner);
|
|
75089
|
+
if (spinner)
|
|
75090
|
+
spinner.text = `Pausing agent for thread ${thread._id}...`;
|
|
75091
|
+
await pauseThread({ threadId: thread._id, environment });
|
|
75092
|
+
spinner?.succeed(chalk27.green(`Agent paused for thread ${thread._id} (env: ${environment})`));
|
|
75093
|
+
if (opts.json) {
|
|
75094
|
+
console.log(JSON.stringify({ success: true, threadId: thread._id, paused: true, environment }));
|
|
75095
|
+
}
|
|
75096
|
+
} catch (err) {
|
|
75097
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
75098
|
+
spinner?.fail("Failed to pause thread");
|
|
75099
|
+
if (opts.json) {
|
|
75100
|
+
console.log(JSON.stringify({ success: false, error: message }));
|
|
75101
|
+
} else {
|
|
75102
|
+
console.log(chalk27.red("Error:"), message);
|
|
75103
|
+
}
|
|
75104
|
+
process.exit(1);
|
|
75105
|
+
}
|
|
75106
|
+
});
|
|
75107
|
+
threadsCommand.command("resume").description("Resume the agent on a paused conversation").argument("<target>", "Thread id or phone number").option("--env <environment>", "Environment: development | production | eval", "development").option("--json", "Output raw JSON").action(async (target, opts) => {
|
|
75108
|
+
await ensureAuth7();
|
|
75109
|
+
const spinner = opts.json ? null : ora20();
|
|
75110
|
+
const environment = opts.env;
|
|
75111
|
+
try {
|
|
75112
|
+
spinner?.start(`Resolving thread for ${target}...`);
|
|
75113
|
+
const thread = await resolveOrExit(target, environment, !!opts.json, spinner);
|
|
75114
|
+
if (spinner)
|
|
75115
|
+
spinner.text = `Resuming agent for thread ${thread._id}...`;
|
|
75116
|
+
await resumeThread({ threadId: thread._id, environment });
|
|
75117
|
+
spinner?.succeed(chalk27.green(`Agent resumed for thread ${thread._id} (env: ${environment})`));
|
|
75118
|
+
if (opts.json) {
|
|
75119
|
+
console.log(JSON.stringify({ success: true, threadId: thread._id, paused: false, environment }));
|
|
75120
|
+
}
|
|
75121
|
+
} catch (err) {
|
|
75122
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
75123
|
+
spinner?.fail("Failed to resume thread");
|
|
75124
|
+
if (opts.json) {
|
|
75125
|
+
console.log(JSON.stringify({ success: false, error: message }));
|
|
75126
|
+
} else {
|
|
75127
|
+
console.log(chalk27.red("Error:"), message);
|
|
75128
|
+
}
|
|
75129
|
+
process.exit(1);
|
|
75130
|
+
}
|
|
75131
|
+
});
|
|
74852
75132
|
|
|
74853
75133
|
// src/cli/commands/compile-prompt.ts
|
|
74854
75134
|
init_credentials();
|
|
@@ -76904,7 +77184,7 @@ keysCommand.command("revoke <id-or-prefix>").description("Revoke an API key (del
|
|
|
76904
77184
|
// package.json
|
|
76905
77185
|
var package_default = {
|
|
76906
77186
|
name: "struere",
|
|
76907
|
-
version: "0.16.
|
|
77187
|
+
version: "0.16.3",
|
|
76908
77188
|
description: "Build, test, and deploy AI agents",
|
|
76909
77189
|
keywords: [
|
|
76910
77190
|
"ai",
|
|
@@ -12,6 +12,7 @@ export interface ThreadPreview {
|
|
|
12
12
|
} | null;
|
|
13
13
|
participantName: string;
|
|
14
14
|
messageCount: number;
|
|
15
|
+
agentPaused?: boolean;
|
|
15
16
|
createdAt: number;
|
|
16
17
|
updatedAt: number;
|
|
17
18
|
}
|
|
@@ -58,4 +59,40 @@ export declare function findThreadByPhone(options: {
|
|
|
58
59
|
environment: string;
|
|
59
60
|
organizationId?: string;
|
|
60
61
|
}): Promise<ThreadPreview | null>;
|
|
62
|
+
export declare function replyToThread(options: {
|
|
63
|
+
threadId: string;
|
|
64
|
+
message: string;
|
|
65
|
+
environment: string;
|
|
66
|
+
}): Promise<{
|
|
67
|
+
success: boolean;
|
|
68
|
+
whatsappStatus: 'sent' | 'failed' | 'skipped';
|
|
69
|
+
}>;
|
|
70
|
+
export declare function pauseThread(options: {
|
|
71
|
+
threadId: string;
|
|
72
|
+
environment: string;
|
|
73
|
+
}): Promise<{
|
|
74
|
+
success: boolean;
|
|
75
|
+
paused: boolean;
|
|
76
|
+
}>;
|
|
77
|
+
export declare function resumeThread(options: {
|
|
78
|
+
threadId: string;
|
|
79
|
+
environment: string;
|
|
80
|
+
}): Promise<{
|
|
81
|
+
success: boolean;
|
|
82
|
+
paused: boolean;
|
|
83
|
+
}>;
|
|
84
|
+
export type ResolveResult = {
|
|
85
|
+
kind: 'ok';
|
|
86
|
+
thread: ThreadPreview;
|
|
87
|
+
} | {
|
|
88
|
+
kind: 'none';
|
|
89
|
+
} | {
|
|
90
|
+
kind: 'multiple';
|
|
91
|
+
candidates: ThreadPreview[];
|
|
92
|
+
};
|
|
93
|
+
export declare function resolveActiveWhatsAppThread(options: {
|
|
94
|
+
target: string;
|
|
95
|
+
environment: string;
|
|
96
|
+
organizationId?: string;
|
|
97
|
+
}): Promise<ResolveResult>;
|
|
61
98
|
//# sourceMappingURL=threads.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"threads.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/threads.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACvC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACzE,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AA4GD,wBAAsB,WAAW,CAAC,OAAO,EAAE;IACzC,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAkB3B;AAED,wBAAsB,qBAAqB,CAAC,OAAO,EAAE;IACnD,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,GAAG,OAAO,CAAC;IACV,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACvC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,KAAK,CAAC;QACd,GAAG,EAAE,MAAM,CAAA;QACX,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,EAAE,MAAM,CAAA;QACf,SAAS,EAAE,MAAM,CAAA;QACjB,SAAS,CAAC,EAAE,KAAK,CAAC;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,OAAO,CAAA;SAAE,CAAC,CAAA;KACpE,CAAC,CAAA;CACH,GAAG,IAAI,CAAC,CAKR;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAC3C,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAmChC;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE;IAC/C,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAgBhC"}
|
|
1
|
+
{"version":3,"file":"threads.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/threads.ts"],"names":[],"mappings":"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"}
|