@agentchatme/openclaw 0.7.8211 → 0.7.8211111
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/CHANGELOG.md +72 -0
- package/README.md +12 -3
- package/RUNBOOK.md +2 -2
- package/dist/index.cjs +320 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +110 -6
- package/dist/index.d.ts +110 -6
- package/dist/index.js +319 -56
- package/dist/index.js.map +1 -1
- package/dist/setup-entry.cjs +318 -55
- package/dist/setup-entry.cjs.map +1 -1
- package/dist/setup-entry.js +318 -55
- package/dist/setup-entry.js.map +1 -1
- package/openclaw.plugin.json +3 -3
- package/package.json +15 -2
- package/skills/agentchat/SKILL.md +5 -1
package/dist/index.js
CHANGED
|
@@ -119,7 +119,7 @@ function classifyNetworkError(err3) {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
// src/version.ts
|
|
122
|
-
var PACKAGE_VERSION = "0.7.
|
|
122
|
+
var PACKAGE_VERSION = "0.7.8211111";
|
|
123
123
|
|
|
124
124
|
// src/client-identity.ts
|
|
125
125
|
var AGENTCHAT_CLIENT_NAME = "openclaw";
|
|
@@ -240,8 +240,10 @@ async function registerAgentStart(input, opts = {}) {
|
|
|
240
240
|
if (res.status === 400 && code === "INVALID_HANDLE") return { ok: false, reason: "invalid-handle", message, status: 400 };
|
|
241
241
|
if (res.status === 400 && code === "VALIDATION_ERROR") return { ok: false, reason: "validation", message, status: 400 };
|
|
242
242
|
if (res.status === 409 && code === "HANDLE_TAKEN") return { ok: false, reason: "handle-taken", message, status: 409 };
|
|
243
|
-
|
|
244
|
-
if (
|
|
243
|
+
const emailPolicy = res.status === 409 ? classifyEmailPolicyRejection(code) : void 0;
|
|
244
|
+
if (emailPolicy) {
|
|
245
|
+
return { ok: false, reason: emailPolicy, message, status: 409, limit: readPolicyLimit(body.details) };
|
|
246
|
+
}
|
|
245
247
|
if (res.status === 429) {
|
|
246
248
|
return {
|
|
247
249
|
ok: false,
|
|
@@ -286,12 +288,84 @@ async function registerAgentVerify(input, opts = {}) {
|
|
|
286
288
|
if (res.status === 400 && code === "INVALID_CODE") return { ok: false, reason: "invalid-code", message, status: 400 };
|
|
287
289
|
if (res.status === 400 && code === "VALIDATION_ERROR") return { ok: false, reason: "validation", message, status: 400 };
|
|
288
290
|
if (res.status === 409 && code === "HANDLE_TAKEN") return { ok: false, reason: "handle-taken", message, status: 409 };
|
|
289
|
-
|
|
291
|
+
const emailPolicy = res.status === 409 ? classifyEmailPolicyRejection(code) : void 0;
|
|
292
|
+
if (emailPolicy) {
|
|
293
|
+
return { ok: false, reason: emailPolicy, message, status: 409, limit: readPolicyLimit(body.details) };
|
|
294
|
+
}
|
|
295
|
+
if (res.status === 429) {
|
|
296
|
+
return { ok: false, reason: "rate-limited", message, status: 429, retryAfterSeconds: res.retryAfterSeconds };
|
|
297
|
+
}
|
|
298
|
+
return { ok: false, reason: "server-error", status: res.status, message };
|
|
299
|
+
}
|
|
300
|
+
async function recoverAgentStart(input, opts = {}) {
|
|
301
|
+
const res = await post("/v1/agents/recover", { email: input.email, handle: input.handle }, opts);
|
|
302
|
+
if (res.kind === "network") return { ok: false, reason: "network-error", message: res.message };
|
|
303
|
+
if (res.kind === "timeout") return { ok: false, reason: "network-error", message: "request timed out" };
|
|
304
|
+
const body = res.body ?? {};
|
|
305
|
+
const message = typeof body.message === "string" ? body.message : `status ${res.status}`;
|
|
306
|
+
if (res.status === 200) {
|
|
307
|
+
if (typeof body.pending_id !== "string") {
|
|
308
|
+
return {
|
|
309
|
+
ok: false,
|
|
310
|
+
reason: "unexpected-shape",
|
|
311
|
+
status: 200,
|
|
312
|
+
message: "AgentChat did not start a recovery (no pending_id in the response). Check that the email is the one this agent registered with."
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
return { ok: true, pendingId: body.pending_id, message };
|
|
316
|
+
}
|
|
317
|
+
const code = typeof body.code === "string" ? body.code : "";
|
|
318
|
+
if (res.status === 400 && code === "VALIDATION_ERROR") return { ok: false, reason: "validation", message, status: 400 };
|
|
319
|
+
if (res.status === 429) {
|
|
320
|
+
return { ok: false, reason: "rate-limited", message, status: 429, retryAfterSeconds: res.retryAfterSeconds };
|
|
321
|
+
}
|
|
322
|
+
return { ok: false, reason: "server-error", status: res.status, message };
|
|
323
|
+
}
|
|
324
|
+
async function recoverAgentVerify(input, opts = {}) {
|
|
325
|
+
const res = await post("/v1/agents/recover/verify", { pending_id: input.pendingId, code: input.code }, opts);
|
|
326
|
+
if (res.kind === "network") return { ok: false, reason: "network-error", message: res.message };
|
|
327
|
+
if (res.kind === "timeout") return { ok: false, reason: "network-error", message: "request timed out" };
|
|
328
|
+
const body = res.body ?? {};
|
|
329
|
+
if (res.status === 200) {
|
|
330
|
+
if (typeof body.api_key !== "string" || typeof body.handle !== "string") {
|
|
331
|
+
return {
|
|
332
|
+
ok: false,
|
|
333
|
+
reason: "unexpected-shape",
|
|
334
|
+
status: 200,
|
|
335
|
+
message: "AgentChat /agents/recover/verify returned an unrecognized shape"
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
return { ok: true, apiKey: body.api_key, handle: body.handle };
|
|
339
|
+
}
|
|
340
|
+
const code = typeof body.code === "string" ? body.code : "";
|
|
341
|
+
const message = typeof body.message === "string" ? body.message : `status ${res.status}`;
|
|
342
|
+
if (res.status === 400 && code === "EXPIRED") return { ok: false, reason: "expired", message, status: 400 };
|
|
343
|
+
if (res.status === 400 && code === "INVALID_CODE") return { ok: false, reason: "invalid-code", message, status: 400 };
|
|
344
|
+
if (res.status === 400 && code === "VALIDATION_ERROR") return { ok: false, reason: "validation", message, status: 400 };
|
|
345
|
+
if (res.status === 409 && code === "HANDLE_REQUIRED") {
|
|
346
|
+
return { ok: false, reason: "handle-required", message, status: 409, handles: readHandleList(body.details) };
|
|
347
|
+
}
|
|
290
348
|
if (res.status === 429) {
|
|
291
349
|
return { ok: false, reason: "rate-limited", message, status: 429, retryAfterSeconds: res.retryAfterSeconds };
|
|
292
350
|
}
|
|
293
351
|
return { ok: false, reason: "server-error", status: res.status, message };
|
|
294
352
|
}
|
|
353
|
+
function classifyEmailPolicyRejection(code) {
|
|
354
|
+
if (code === "EMAIL_LIMIT_REACHED" || code === "EMAIL_TAKEN") return "email-limit-reached";
|
|
355
|
+
if (code === "EMAIL_EXHAUSTED") return "email-exhausted";
|
|
356
|
+
return void 0;
|
|
357
|
+
}
|
|
358
|
+
function readPolicyLimit(details) {
|
|
359
|
+
if (!details || typeof details !== "object") return void 0;
|
|
360
|
+
const limit = details.limit;
|
|
361
|
+
return typeof limit === "number" && Number.isInteger(limit) && limit > 0 ? limit : void 0;
|
|
362
|
+
}
|
|
363
|
+
function readHandleList(details) {
|
|
364
|
+
if (!details || typeof details !== "object") return [];
|
|
365
|
+
const handles = details.handles;
|
|
366
|
+
if (!Array.isArray(handles)) return [];
|
|
367
|
+
return handles.filter((h) => typeof h === "string" && h.length > 0);
|
|
368
|
+
}
|
|
295
369
|
async function post(path3, body, opts) {
|
|
296
370
|
const base = (opts.apiBase ?? DEFAULT_API_BASE).replace(/\/+$/, "");
|
|
297
371
|
const url = `${base}${path3}`;
|
|
@@ -347,9 +421,9 @@ function hasConfiguredKey(cfg, accountId) {
|
|
|
347
421
|
return isApiKeyPresent(readAgentchatConfigField(cfg, accountId, "apiKey"));
|
|
348
422
|
}
|
|
349
423
|
var MAX_START_RETRIES = 5;
|
|
350
|
-
async function promptEmail(prompter) {
|
|
424
|
+
async function promptEmail(prompter, opts = {}) {
|
|
351
425
|
return (await prompter.text({
|
|
352
|
-
message: "Email \u2014 receives a 6-digit verification code",
|
|
426
|
+
message: opts.message ?? "Email \u2014 receives a 6-digit verification code",
|
|
353
427
|
placeholder: "you@example.com",
|
|
354
428
|
validate: (value) => {
|
|
355
429
|
const trimmed = value.trim();
|
|
@@ -359,10 +433,11 @@ async function promptEmail(prompter) {
|
|
|
359
433
|
}
|
|
360
434
|
})).trim();
|
|
361
435
|
}
|
|
362
|
-
async function promptHandle(prompter) {
|
|
436
|
+
async function promptHandle(prompter, opts = {}) {
|
|
363
437
|
return (await prompter.text({
|
|
364
|
-
message: "Choose a handle (your @name on AgentChat)",
|
|
438
|
+
message: opts.message ?? "Choose a handle (your @name on AgentChat)",
|
|
365
439
|
placeholder: "3\u201330 chars, lowercase a-z, 0-9, hyphens, starts with a letter",
|
|
440
|
+
...opts.initialValue ? { initialValue: opts.initialValue } : {},
|
|
366
441
|
validate: (value) => {
|
|
367
442
|
const trimmed = value.trim();
|
|
368
443
|
if (!trimmed) return "Handle is required";
|
|
@@ -422,11 +497,37 @@ async function runChangeApiBaseFlow(params) {
|
|
|
422
497
|
await prompter.note(`API base set to ${input}`, "Updated");
|
|
423
498
|
return { cfg: patched };
|
|
424
499
|
}
|
|
500
|
+
function describeEmailPolicyRejection(email, result) {
|
|
501
|
+
if (result.limit === void 0) return result.message;
|
|
502
|
+
return result.reason === "email-limit-reached" ? `${email} already backs ${result.limit} active agents \u2014 the per-email limit.` : `${email} has used all ${result.limit} of its lifetime account registrations.`;
|
|
503
|
+
}
|
|
504
|
+
async function promptEmailPolicyChoice(prompter, email, result) {
|
|
505
|
+
return prompter.select({
|
|
506
|
+
message: `${describeEmailPolicyRejection(email, result)} What next?`,
|
|
507
|
+
options: [
|
|
508
|
+
{
|
|
509
|
+
value: "retry",
|
|
510
|
+
label: "Use a different email address",
|
|
511
|
+
hint: "a +alias like you+agent2@example.com counts as a separate email"
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
value: "recover",
|
|
515
|
+
label: "Recover the API key of an agent this email already backs",
|
|
516
|
+
hint: "needs that agent\u2019s handle \u2014 a code goes to this email"
|
|
517
|
+
},
|
|
518
|
+
{ value: "paste", label: "Paste a key from an existing agent" },
|
|
519
|
+
{ value: "cancel", label: "Cancel registration" }
|
|
520
|
+
],
|
|
521
|
+
initialValue: "retry"
|
|
522
|
+
});
|
|
523
|
+
}
|
|
425
524
|
async function runRegisterFlow(params) {
|
|
426
525
|
const { cfg, accountId, prompter, apiBase } = params;
|
|
427
526
|
await prompter.note(
|
|
428
527
|
[
|
|
429
528
|
"Registration mints a new AgentChat agent identity tied to your email.",
|
|
529
|
+
"One email can back several agents (the server enforces the limit);",
|
|
530
|
+
"each one registers and verifies separately.",
|
|
430
531
|
"You will receive a 6-digit code to verify \u2014 check your inbox (and spam)."
|
|
431
532
|
].join("\n"),
|
|
432
533
|
"AgentChat: register a new agent"
|
|
@@ -471,36 +572,15 @@ async function runRegisterFlow(params) {
|
|
|
471
572
|
handle = await promptHandle(prompter);
|
|
472
573
|
continue;
|
|
473
574
|
}
|
|
474
|
-
case "email-
|
|
475
|
-
const choice = await prompter.select({
|
|
476
|
-
message: `${email} is already registered as an AgentChat agent. What would you like to do?`,
|
|
477
|
-
options: [
|
|
478
|
-
{
|
|
479
|
-
value: "paste",
|
|
480
|
-
label: "Paste the existing API key for this agent",
|
|
481
|
-
hint: "recommended if you own the account"
|
|
482
|
-
},
|
|
483
|
-
{ value: "retry", label: "Use a different email address" },
|
|
484
|
-
{ value: "cancel", label: "Cancel registration" }
|
|
485
|
-
],
|
|
486
|
-
initialValue: "paste"
|
|
487
|
-
});
|
|
488
|
-
if (choice === "paste") return "user-chose-paste";
|
|
489
|
-
if (choice === "cancel") return "abort";
|
|
490
|
-
email = await promptEmail(prompter);
|
|
491
|
-
continue;
|
|
492
|
-
}
|
|
575
|
+
case "email-limit-reached":
|
|
493
576
|
case "email-exhausted": {
|
|
494
|
-
const choice = await prompter
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
{ value: "paste", label: "Paste a key from an existing agent" },
|
|
499
|
-
{ value: "cancel", label: "Cancel registration" }
|
|
500
|
-
],
|
|
501
|
-
initialValue: "retry"
|
|
577
|
+
const choice = await promptEmailPolicyChoice(prompter, email, {
|
|
578
|
+
reason: startResult.reason,
|
|
579
|
+
limit: startResult.limit,
|
|
580
|
+
message: startResult.message
|
|
502
581
|
});
|
|
503
582
|
if (choice === "paste") return "user-chose-paste";
|
|
583
|
+
if (choice === "recover") return "user-chose-recover";
|
|
504
584
|
if (choice === "cancel") return "abort";
|
|
505
585
|
email = await promptEmail(prompter);
|
|
506
586
|
continue;
|
|
@@ -606,10 +686,10 @@ function describeRegisterStartError(result) {
|
|
|
606
686
|
return "That handle is not acceptable. Try a different one (3\u201330 chars \u2014 lowercase letters/digits/hyphens; must start with a letter).";
|
|
607
687
|
case "handle-taken":
|
|
608
688
|
return "That handle is already taken. Try a different one.";
|
|
609
|
-
case "email-
|
|
610
|
-
return
|
|
689
|
+
case "email-limit-reached":
|
|
690
|
+
return `${result.limit === void 0 ? result.message : `This email already backs ${result.limit} active agents \u2014 the per-email limit.`} Use a different email (a +alias works), recover a key for one of its agents, or paste an existing key.`;
|
|
611
691
|
case "email-exhausted":
|
|
612
|
-
return
|
|
692
|
+
return `${result.limit === void 0 ? result.message : `This email has used all ${result.limit} of its lifetime account registrations.`} Use a different email (a +alias works), or paste a key from an existing agent.`;
|
|
613
693
|
case "rate-limited": {
|
|
614
694
|
const wait = result.retryAfterSeconds ? ` Try again in ${result.retryAfterSeconds}s.` : "";
|
|
615
695
|
return `Rate limited.${wait}`;
|
|
@@ -631,8 +711,158 @@ function describeRegisterVerifyError(result) {
|
|
|
631
711
|
return "Too many incorrect codes. Restart the wizard to receive a new one.";
|
|
632
712
|
case "handle-taken":
|
|
633
713
|
return "Your chosen handle was claimed by another registration in the meantime. Restart with a different handle.";
|
|
634
|
-
case "email-
|
|
635
|
-
return
|
|
714
|
+
case "email-limit-reached":
|
|
715
|
+
return `${result.limit === void 0 ? result.message : `This email reached its limit of ${result.limit} active agents while you were verifying.`} Restart with a different email (a +alias works), or paste an existing key.`;
|
|
716
|
+
case "email-exhausted":
|
|
717
|
+
return `${result.limit === void 0 ? result.message : `This email used all ${result.limit} of its lifetime account registrations while you were verifying.`} Restart with a different email (a +alias works), or paste an existing key.`;
|
|
718
|
+
case "rate-limited": {
|
|
719
|
+
const wait = result.retryAfterSeconds ? ` Try again in ${result.retryAfterSeconds}s.` : "";
|
|
720
|
+
return `Rate limited.${wait}`;
|
|
721
|
+
}
|
|
722
|
+
case "network-error":
|
|
723
|
+
case "server-error":
|
|
724
|
+
case "unexpected-shape":
|
|
725
|
+
case "validation":
|
|
726
|
+
default:
|
|
727
|
+
return result.message;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
async function runRecoverFlow(params) {
|
|
731
|
+
const { cfg, accountId, prompter, apiBase } = params;
|
|
732
|
+
const storedHandle = readAgentchatConfigField(cfg, accountId, "agentHandle");
|
|
733
|
+
const defaultHandle = storedHandle && isValidHandleShape(storedHandle) ? storedHandle : void 0;
|
|
734
|
+
await prompter.note(
|
|
735
|
+
[
|
|
736
|
+
"Recovery re-issues the API key for ONE agent \u2014 the handle you name below.",
|
|
737
|
+
"You need that handle and the email it registered with; a 6-digit code",
|
|
738
|
+
"goes to that email. The old key stops working the moment the new one",
|
|
739
|
+
"is minted.",
|
|
740
|
+
...defaultHandle ? ["", `@${defaultHandle} is configured here \u2014 press Enter at the handle prompt to recover it.`] : []
|
|
741
|
+
].join("\n"),
|
|
742
|
+
"AgentChat: recover a lost API key"
|
|
743
|
+
);
|
|
744
|
+
const handle = await promptHandle(prompter, {
|
|
745
|
+
message: "Handle of the agent to recover (its @name on AgentChat)",
|
|
746
|
+
...defaultHandle ? { initialValue: defaultHandle } : {}
|
|
747
|
+
});
|
|
748
|
+
const email = await promptEmail(prompter, {
|
|
749
|
+
message: `Email @${handle} registered with \u2014 receives a 6-digit recovery code`
|
|
750
|
+
});
|
|
751
|
+
const startSpinner = prompter.progress("Requesting recovery code\u2026");
|
|
752
|
+
let startResult;
|
|
753
|
+
try {
|
|
754
|
+
startResult = await recoverAgentStart({ email, handle }, { apiBase });
|
|
755
|
+
} catch (err3) {
|
|
756
|
+
startSpinner.stop("Could not reach AgentChat");
|
|
757
|
+
await prompter.note(
|
|
758
|
+
`${err3 instanceof Error ? err3.message : String(err3)}. Try again when the network is available, or paste an existing key instead.`,
|
|
759
|
+
"Recovery failed"
|
|
760
|
+
);
|
|
761
|
+
return "abort";
|
|
762
|
+
}
|
|
763
|
+
if (!startResult.ok) {
|
|
764
|
+
startSpinner.stop("Recovery rejected");
|
|
765
|
+
await prompter.note(describeRecoverStartError(startResult), "Could not start recovery");
|
|
766
|
+
return "abort";
|
|
767
|
+
}
|
|
768
|
+
startSpinner.stop(startResult.message);
|
|
769
|
+
const maxCodeAttempts = 3;
|
|
770
|
+
let verifyResult = null;
|
|
771
|
+
for (let attempt = 1; attempt <= maxCodeAttempts; attempt += 1) {
|
|
772
|
+
const code = (await prompter.text({
|
|
773
|
+
message: attempt === 1 ? `Enter the 6-digit recovery code (check ${email}, including spam)` : `Recovery code (attempt ${attempt}/${maxCodeAttempts})`,
|
|
774
|
+
placeholder: "123456",
|
|
775
|
+
validate: (value) => {
|
|
776
|
+
const trimmed = value.trim();
|
|
777
|
+
if (!trimmed) return "Code is required";
|
|
778
|
+
if (!OTP_PATTERN.test(trimmed)) return "Code is 6 digits";
|
|
779
|
+
return void 0;
|
|
780
|
+
}
|
|
781
|
+
})).trim();
|
|
782
|
+
const verifySpinner = prompter.progress("Verifying code\u2026");
|
|
783
|
+
try {
|
|
784
|
+
verifyResult = await recoverAgentVerify({ pendingId: startResult.pendingId, code }, { apiBase });
|
|
785
|
+
} catch (err3) {
|
|
786
|
+
verifySpinner.stop("Could not reach AgentChat");
|
|
787
|
+
await prompter.note(
|
|
788
|
+
`${err3 instanceof Error ? err3.message : String(err3)}. Try again, or paste an existing key instead.`,
|
|
789
|
+
"Recovery failed"
|
|
790
|
+
);
|
|
791
|
+
return "abort";
|
|
792
|
+
}
|
|
793
|
+
if (verifyResult.ok) {
|
|
794
|
+
verifySpinner.stop(`Recovered @${verifyResult.handle}`);
|
|
795
|
+
break;
|
|
796
|
+
}
|
|
797
|
+
verifySpinner.stop("Verification failed");
|
|
798
|
+
if (verifyResult.reason === "invalid-code" && attempt < maxCodeAttempts) {
|
|
799
|
+
await prompter.note(
|
|
800
|
+
"That code did not match. Check your email and try again \u2014 if no code arrived, the handle and email may not belong to the same agent.",
|
|
801
|
+
"Invalid recovery code"
|
|
802
|
+
);
|
|
803
|
+
continue;
|
|
804
|
+
}
|
|
805
|
+
await prompter.note(describeRecoverVerifyError(verifyResult), "Recovery failed");
|
|
806
|
+
return "abort";
|
|
807
|
+
}
|
|
808
|
+
if (!verifyResult || !verifyResult.ok) {
|
|
809
|
+
await prompter.note(
|
|
810
|
+
"Too many incorrect codes. Restart the wizard to request a new one \u2014 and double-check the handle and email belong to the same agent.",
|
|
811
|
+
"Recovery failed"
|
|
812
|
+
);
|
|
813
|
+
return "abort";
|
|
814
|
+
}
|
|
815
|
+
const patch = { apiKey: verifyResult.apiKey };
|
|
816
|
+
if (isValidHandleShape(verifyResult.handle)) {
|
|
817
|
+
patch.agentHandle = verifyResult.handle;
|
|
818
|
+
}
|
|
819
|
+
const nextCfg = applyAgentchatAccountPatch(cfg, accountId, patch);
|
|
820
|
+
await prompter.note(
|
|
821
|
+
[
|
|
822
|
+
`Handle: @${verifyResult.handle}`,
|
|
823
|
+
`API key: ${redactKey(verifyResult.apiKey)} (saved to your OpenClaw config)`,
|
|
824
|
+
"",
|
|
825
|
+
"The previous key for this agent has been revoked."
|
|
826
|
+
].join("\n"),
|
|
827
|
+
"AgentChat API key recovered"
|
|
828
|
+
);
|
|
829
|
+
return {
|
|
830
|
+
cfg: nextCfg,
|
|
831
|
+
credentialValues: {
|
|
832
|
+
token: verifyResult.apiKey,
|
|
833
|
+
[JUST_REGISTERED_SENTINEL]: "1"
|
|
834
|
+
}
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
function describeRecoverStartError(result) {
|
|
838
|
+
switch (result.reason) {
|
|
839
|
+
case "rate-limited": {
|
|
840
|
+
const wait = result.retryAfterSeconds ? ` Try again in ${result.retryAfterSeconds}s.` : "";
|
|
841
|
+
return `Too many recovery attempts from this network.${wait}`;
|
|
842
|
+
}
|
|
843
|
+
case "validation":
|
|
844
|
+
return `AgentChat rejected the request: ${result.message}`;
|
|
845
|
+
case "network-error":
|
|
846
|
+
case "server-error":
|
|
847
|
+
case "unexpected-shape":
|
|
848
|
+
default:
|
|
849
|
+
return result.message;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
function describeRecoverVerifyError(result) {
|
|
853
|
+
switch (result.reason) {
|
|
854
|
+
case "expired":
|
|
855
|
+
return "This recovery code expired. Restart the wizard to request a new one.";
|
|
856
|
+
case "invalid-code":
|
|
857
|
+
return "Too many incorrect codes. Restart the wizard to request a new one.";
|
|
858
|
+
case "handle-required": {
|
|
859
|
+
const handles = result.handles ?? [];
|
|
860
|
+
const list = handles.length > 0 ? `
|
|
861
|
+
|
|
862
|
+
Agents on this email:
|
|
863
|
+
${handles.map((h) => ` @${h}`).join("\n")}` : "";
|
|
864
|
+
return `This email backs more than one agent. Run recovery again and enter the handle you want to recover.${list}`;
|
|
865
|
+
}
|
|
636
866
|
case "rate-limited": {
|
|
637
867
|
const wait = result.retryAfterSeconds ? ` Try again in ${result.retryAfterSeconds}s.` : "";
|
|
638
868
|
return `Rate limited.${wait}`;
|
|
@@ -680,7 +910,7 @@ var agentchatSetupWizard = {
|
|
|
680
910
|
resolveStatusLines: ({ cfg, accountId, configured }) => {
|
|
681
911
|
const id = accountId ?? "default";
|
|
682
912
|
if (!configured) {
|
|
683
|
-
return ["AgentChat: not configured \u2014 the wizard will register you
|
|
913
|
+
return ["AgentChat: not configured \u2014 the wizard will register you, accept an existing key, or recover a lost one."];
|
|
684
914
|
}
|
|
685
915
|
const handle = readAgentchatConfigField(cfg, id, "agentHandle");
|
|
686
916
|
return [`AgentChat: configured${handle ? ` (@${handle})` : ""}`];
|
|
@@ -692,8 +922,9 @@ var agentchatSetupWizard = {
|
|
|
692
922
|
"AgentChat is a messaging platform for AI agents \u2014 direct messages,",
|
|
693
923
|
"groups, presence, attachments. Registration is free.",
|
|
694
924
|
"",
|
|
695
|
-
"This wizard will
|
|
696
|
-
"
|
|
925
|
+
"This wizard will mint a new account via email OTP, accept an existing",
|
|
926
|
+
"API key, or recover a lost key (handle + email OTP) \u2014 your choice in",
|
|
927
|
+
"the next prompt."
|
|
697
928
|
]
|
|
698
929
|
},
|
|
699
930
|
prepare: async ({ cfg, accountId, credentialValues, prompter }) => {
|
|
@@ -714,7 +945,7 @@ var agentchatSetupWizard = {
|
|
|
714
945
|
{
|
|
715
946
|
value: "replace-key",
|
|
716
947
|
label: "Replace the API key",
|
|
717
|
-
hint: "paste a new key,
|
|
948
|
+
hint: "paste a new key, register a new agent, or recover a lost key"
|
|
718
949
|
}
|
|
719
950
|
],
|
|
720
951
|
initialValue: "keep"
|
|
@@ -736,6 +967,11 @@ var agentchatSetupWizard = {
|
|
|
736
967
|
value: "paste",
|
|
737
968
|
label: "I already have an API key",
|
|
738
969
|
hint: "paste ac_live_\u2026 on the next prompt"
|
|
970
|
+
},
|
|
971
|
+
{
|
|
972
|
+
value: "recover",
|
|
973
|
+
label: "Recover a lost API key (handle + email OTP)",
|
|
974
|
+
hint: "an agent exists but its key is gone \u2014 re-issue it"
|
|
739
975
|
}
|
|
740
976
|
],
|
|
741
977
|
initialValue: "register"
|
|
@@ -744,19 +980,32 @@ var agentchatSetupWizard = {
|
|
|
744
980
|
return;
|
|
745
981
|
}
|
|
746
982
|
const apiBase = readAgentchatConfigField(cfg, accountId, "apiBase");
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
983
|
+
const recover = async () => {
|
|
984
|
+
try {
|
|
985
|
+
const result = await runRecoverFlow({ cfg, accountId, prompter, apiBase });
|
|
986
|
+
if (result === "abort") {
|
|
987
|
+
await prompter.note(
|
|
988
|
+
"Recovery was not completed. You can still paste an existing API key at the next prompt, or cancel the wizard.",
|
|
989
|
+
"Falling back to credential entry"
|
|
990
|
+
);
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
return result;
|
|
994
|
+
} catch (err3) {
|
|
995
|
+
if (err3 instanceof WizardCancelledError) throw err3;
|
|
750
996
|
await prompter.note(
|
|
751
|
-
|
|
752
|
-
"
|
|
997
|
+
`${err3 instanceof Error ? err3.message : String(err3)}`,
|
|
998
|
+
"Recovery flow failed"
|
|
753
999
|
);
|
|
754
1000
|
return;
|
|
755
1001
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
1002
|
+
};
|
|
1003
|
+
if (choice === "recover") {
|
|
1004
|
+
return await recover();
|
|
1005
|
+
}
|
|
1006
|
+
let registerOutcome;
|
|
1007
|
+
try {
|
|
1008
|
+
registerOutcome = await runRegisterFlow({ cfg, accountId, prompter, apiBase });
|
|
760
1009
|
} catch (err3) {
|
|
761
1010
|
if (err3 instanceof WizardCancelledError) throw err3;
|
|
762
1011
|
await prompter.note(
|
|
@@ -765,6 +1014,20 @@ var agentchatSetupWizard = {
|
|
|
765
1014
|
);
|
|
766
1015
|
return;
|
|
767
1016
|
}
|
|
1017
|
+
if (registerOutcome === "abort") {
|
|
1018
|
+
await prompter.note(
|
|
1019
|
+
"Registration was not completed. You can still paste an existing API key at the next prompt, or cancel the wizard.",
|
|
1020
|
+
"Falling back to credential entry"
|
|
1021
|
+
);
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
if (registerOutcome === "user-chose-paste") {
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
if (registerOutcome === "user-chose-recover") {
|
|
1028
|
+
return await recover();
|
|
1029
|
+
}
|
|
1030
|
+
return registerOutcome;
|
|
768
1031
|
},
|
|
769
1032
|
credentials: [
|
|
770
1033
|
{
|
|
@@ -5102,7 +5365,7 @@ var uiHints = {
|
|
|
5102
5365
|
label: "AgentChat API key",
|
|
5103
5366
|
placeholder: "ac_live_...",
|
|
5104
5367
|
sensitive: true,
|
|
5105
|
-
help: "The setup wizard registers you via email OTP and mints a key
|
|
5368
|
+
help: "The setup wizard registers you via email OTP and mints a key, recovers a lost key (handle + email OTP), or accepts an existing ac_live_\u2026 key."
|
|
5106
5369
|
},
|
|
5107
5370
|
apiBase: {
|
|
5108
5371
|
label: "API base URL",
|
|
@@ -5213,7 +5476,7 @@ var agentchatPlugin = {
|
|
|
5213
5476
|
*/
|
|
5214
5477
|
validateInput({ input }) {
|
|
5215
5478
|
if (typeof input.token !== "string" || input.token.trim().length === 0) {
|
|
5216
|
-
return "apiKey is required \u2014 pass via --token or run
|
|
5479
|
+
return "apiKey is required \u2014 pass via --token, or run `openclaw channels add agentchat` to register a new agent or recover a lost key (handle + email OTP)";
|
|
5217
5480
|
}
|
|
5218
5481
|
if (input.token.length < MIN_API_KEY_LENGTH) {
|
|
5219
5482
|
return `apiKey looks too short (got ${input.token.length} chars, expect \u2265${MIN_API_KEY_LENGTH})`;
|
|
@@ -5318,6 +5581,6 @@ function hasAgentChatConfiguredState(config) {
|
|
|
5318
5581
|
return true;
|
|
5319
5582
|
}
|
|
5320
5583
|
|
|
5321
|
-
export { AGENTCHAT_CHANNEL_ID, AGENTCHAT_DEFAULT_ACCOUNT_ID, AgentChatChannelError, AgentchatChannelRuntime, agentchatChannelEntry, agentchatPlugin, agentchatSetupEntry, agentchatPlugin as agentchatSetupPlugin, assertApiKeyValid, agentchatChannelEntry as default, hasAgentChatConfiguredState, parseChannelConfig, registerAgentStart, registerAgentVerify, validateApiKey };
|
|
5584
|
+
export { AGENTCHAT_CHANNEL_ID, AGENTCHAT_DEFAULT_ACCOUNT_ID, AgentChatChannelError, AgentchatChannelRuntime, agentchatChannelEntry, agentchatPlugin, agentchatSetupEntry, agentchatPlugin as agentchatSetupPlugin, assertApiKeyValid, agentchatChannelEntry as default, hasAgentChatConfiguredState, parseChannelConfig, recoverAgentStart, recoverAgentVerify, registerAgentStart, registerAgentVerify, validateApiKey };
|
|
5322
5585
|
//# sourceMappingURL=index.js.map
|
|
5323
5586
|
//# sourceMappingURL=index.js.map
|