@agenticmail/core 0.9.30 → 0.9.32
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/index.cjs +121 -25
- package/dist/index.d.cts +72 -3
- package/dist/index.d.ts +72 -3
- package/dist/index.js +115 -25
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1449,6 +1449,7 @@ var init_skills = __esm({
|
|
|
1449
1449
|
var index_exports = {};
|
|
1450
1450
|
__export(index_exports, {
|
|
1451
1451
|
AGENT_ROLES: () => AGENT_ROLES,
|
|
1452
|
+
AGENT_STATE_ROOT: () => AGENT_STATE_ROOT,
|
|
1452
1453
|
ASK_OPERATOR_TOOL: () => ASK_OPERATOR_TOOL,
|
|
1453
1454
|
AccountManager: () => AccountManager,
|
|
1454
1455
|
AgentDeletionService: () => AgentDeletionService,
|
|
@@ -1492,6 +1493,7 @@ __export(index_exports, {
|
|
|
1492
1493
|
OPERATOR_QUERY_SUBJECT_TAG: () => OPERATOR_QUERY_SUBJECT_TAG,
|
|
1493
1494
|
OPERATOR_QUERY_TIMEOUT_MS: () => OPERATOR_QUERY_TIMEOUT_MS,
|
|
1494
1495
|
OPERATOR_QUERY_TIMEOUT_SENTINEL: () => OPERATOR_QUERY_TIMEOUT_SENTINEL,
|
|
1496
|
+
PERSONA_FILENAME: () => PERSONA_FILENAME,
|
|
1495
1497
|
PHONE_CALLBACK_MAX_DELAY_SECONDS: () => PHONE_CALLBACK_MAX_DELAY_SECONDS,
|
|
1496
1498
|
PHONE_CALLBACK_MIN_DELAY_SECONDS: () => PHONE_CALLBACK_MIN_DELAY_SECONDS,
|
|
1497
1499
|
PHONE_CALL_CONTROL_PROVIDERS: () => PHONE_CALL_CONTROL_PROVIDERS,
|
|
@@ -1555,6 +1557,7 @@ __export(index_exports, {
|
|
|
1555
1557
|
bridgeWakeErrorMessage: () => bridgeWakeErrorMessage,
|
|
1556
1558
|
bridgeWakeLastSeenAgeMs: () => bridgeWakeLastSeenAgeMs,
|
|
1557
1559
|
buildApiUrl: () => buildApiUrl,
|
|
1560
|
+
buildDefaultPersona: () => buildDefaultPersona,
|
|
1558
1561
|
buildElksAudioMessage: () => buildElksAudioMessage,
|
|
1559
1562
|
buildElksByeMessage: () => buildElksByeMessage,
|
|
1560
1563
|
buildElksHandshakeMessages: () => buildElksHandshakeMessages,
|
|
@@ -1615,6 +1618,7 @@ __export(index_exports, {
|
|
|
1615
1618
|
isTelegramStopCommand: () => isTelegramStopCommand,
|
|
1616
1619
|
isValidPhoneNumber: () => isValidPhoneNumber,
|
|
1617
1620
|
listSkills: () => listSkills,
|
|
1621
|
+
loadAgentPersona: () => loadAgentPersona,
|
|
1618
1622
|
loadHostSession: () => loadHostSession,
|
|
1619
1623
|
loadSkill: () => loadSkill,
|
|
1620
1624
|
mapProviderSmsStatus: () => mapProviderSmsStatus,
|
|
@@ -1631,6 +1635,7 @@ __export(index_exports, {
|
|
|
1631
1635
|
parseTelegramOperatorReply: () => parseTelegramOperatorReply,
|
|
1632
1636
|
parseTelegramUpdate: () => parseTelegramUpdate,
|
|
1633
1637
|
parseTwilioRealtimeMessage: () => parseTwilioRealtimeMessage,
|
|
1638
|
+
personaPathFor: () => personaPathFor,
|
|
1634
1639
|
planBridgeWake: () => planBridgeWake,
|
|
1635
1640
|
pollForOperatorAnswer: () => pollForOperatorAnswer,
|
|
1636
1641
|
recallMemory: () => recallMemory,
|
|
@@ -1650,6 +1655,7 @@ __export(index_exports, {
|
|
|
1650
1655
|
resolveTlsRejectUnauthorized: () => resolveTlsRejectUnauthorized,
|
|
1651
1656
|
safeJoin: () => safeJoin,
|
|
1652
1657
|
sanitizeEmail: () => sanitizeEmail,
|
|
1658
|
+
saveAgentPersona: () => saveAgentPersona,
|
|
1653
1659
|
saveConfig: () => saveConfig,
|
|
1654
1660
|
saveHostSession: () => saveHostSession,
|
|
1655
1661
|
saveUserSkill: () => saveUserSkill,
|
|
@@ -2780,14 +2786,14 @@ var StalwartAdmin = class {
|
|
|
2780
2786
|
if (!isValidDomain(domain)) {
|
|
2781
2787
|
throw new Error(`Invalid domain format: "${domain}"`);
|
|
2782
2788
|
}
|
|
2783
|
-
const { readFileSync:
|
|
2784
|
-
const { homedir:
|
|
2785
|
-
const { join:
|
|
2786
|
-
const configPath =
|
|
2789
|
+
const { readFileSync: readFileSync12, writeFileSync: writeFileSync13 } = await import("fs");
|
|
2790
|
+
const { homedir: homedir15 } = await import("os");
|
|
2791
|
+
const { join: join18 } = await import("path");
|
|
2792
|
+
const configPath = join18(homedir15(), ".agenticmail", "stalwart.toml");
|
|
2787
2793
|
try {
|
|
2788
|
-
let config =
|
|
2794
|
+
let config = readFileSync12(configPath, "utf-8");
|
|
2789
2795
|
config = config.replace(/^hostname\s*=\s*"[^"]*"/m, `hostname = "${escapeTomlString(domain)}"`);
|
|
2790
|
-
|
|
2796
|
+
writeFileSync13(configPath, config);
|
|
2791
2797
|
console.log(`[Stalwart] Updated hostname to "${domain}" in stalwart.toml`);
|
|
2792
2798
|
} catch (err) {
|
|
2793
2799
|
throw new Error(`Failed to set config server.hostname=${domain}`);
|
|
@@ -2796,15 +2802,15 @@ var StalwartAdmin = class {
|
|
|
2796
2802
|
// --- DKIM ---
|
|
2797
2803
|
/** Path to the host-side stalwart.toml (mounted read-only into container) */
|
|
2798
2804
|
get configPath() {
|
|
2799
|
-
const { homedir:
|
|
2800
|
-
const { join:
|
|
2801
|
-
return
|
|
2805
|
+
const { homedir: homedir15 } = require("os");
|
|
2806
|
+
const { join: join18 } = require("path");
|
|
2807
|
+
return join18(homedir15(), ".agenticmail", "stalwart.toml");
|
|
2802
2808
|
}
|
|
2803
2809
|
/** Path to host-side DKIM key directory */
|
|
2804
2810
|
get dkimDir() {
|
|
2805
|
-
const { homedir:
|
|
2806
|
-
const { join:
|
|
2807
|
-
return
|
|
2811
|
+
const { homedir: homedir15 } = require("os");
|
|
2812
|
+
const { join: join18 } = require("path");
|
|
2813
|
+
return join18(homedir15(), ".agenticmail");
|
|
2808
2814
|
}
|
|
2809
2815
|
/**
|
|
2810
2816
|
* Create/reuse a DKIM signing key for a domain.
|
|
@@ -2905,12 +2911,12 @@ var StalwartAdmin = class {
|
|
|
2905
2911
|
* This bypasses the need for a PTR record on the sending IP.
|
|
2906
2912
|
*/
|
|
2907
2913
|
async configureOutboundRelay(config) {
|
|
2908
|
-
const { readFileSync:
|
|
2909
|
-
const { homedir:
|
|
2910
|
-
const { join:
|
|
2914
|
+
const { readFileSync: readFileSync12, writeFileSync: writeFileSync13 } = await import("fs");
|
|
2915
|
+
const { homedir: homedir15 } = await import("os");
|
|
2916
|
+
const { join: join18 } = await import("path");
|
|
2911
2917
|
const routeName = config.routeName ?? "gmail";
|
|
2912
|
-
const tomlPath =
|
|
2913
|
-
let toml =
|
|
2918
|
+
const tomlPath = join18(homedir15(), ".agenticmail", "stalwart.toml");
|
|
2919
|
+
let toml = readFileSync12(tomlPath, "utf-8");
|
|
2914
2920
|
toml = toml.replace(/\n\[queue\.route\.gmail\][\s\S]*?(?=\n\[|$)/, "");
|
|
2915
2921
|
toml = toml.replace(/\n\[queue\.strategy\][\s\S]*?(?=\n\[|$)/, "");
|
|
2916
2922
|
const safeRouteName = routeName.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
@@ -2930,7 +2936,7 @@ auth.secret = "${escapeTomlString(config.password)}"
|
|
|
2930
2936
|
route = [ { if = "is_local_domain('', rcpt_domain)", then = "'local'" },
|
|
2931
2937
|
{ else = "'${safeRouteName}'" } ]
|
|
2932
2938
|
`;
|
|
2933
|
-
|
|
2939
|
+
writeFileSync13(tomlPath, toml, "utf-8");
|
|
2934
2940
|
await this.restartContainer();
|
|
2935
2941
|
}
|
|
2936
2942
|
};
|
|
@@ -9388,12 +9394,12 @@ var GatewayManager = class {
|
|
|
9388
9394
|
zone = await this.cfClient.createZone(domain);
|
|
9389
9395
|
}
|
|
9390
9396
|
const existingRecords = await this.cfClient.listDnsRecords(zone.id);
|
|
9391
|
-
const { homedir:
|
|
9392
|
-
const backupDir = (0, import_node_path4.join)(
|
|
9397
|
+
const { homedir: homedir15 } = await import("os");
|
|
9398
|
+
const backupDir = (0, import_node_path4.join)(homedir15(), ".agenticmail");
|
|
9393
9399
|
const backupPath = (0, import_node_path4.join)(backupDir, `dns-backup-${domain}-${Date.now()}.json`);
|
|
9394
|
-
const { writeFileSync:
|
|
9395
|
-
|
|
9396
|
-
|
|
9400
|
+
const { writeFileSync: writeFileSync13, mkdirSync: mkdirSync14 } = await import("fs");
|
|
9401
|
+
mkdirSync14(backupDir, { recursive: true });
|
|
9402
|
+
writeFileSync13(backupPath, JSON.stringify({
|
|
9397
9403
|
domain,
|
|
9398
9404
|
zoneId: zone.id,
|
|
9399
9405
|
backedUpAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -9822,7 +9828,7 @@ var GatewayManager = class {
|
|
|
9822
9828
|
* agent's INBOX via the existing local-SMTP path — the very same
|
|
9823
9829
|
* delivery the relay uses for real email. This makes the existing
|
|
9824
9830
|
* IMAP IDLE → claudecode dispatcher path light up exactly as it
|
|
9825
|
-
* would for a real inbound mail, so the agent gets a
|
|
9831
|
+
* would for a real inbound mail, so the agent gets a host turn
|
|
9826
9832
|
* without any new dispatcher plumbing. The body of the synthetic
|
|
9827
9833
|
* mail tells the agent the message came from Telegram and that it
|
|
9828
9834
|
* MUST reply via the `telegram_send` MCP tool, not via email.
|
|
@@ -11037,7 +11043,7 @@ var MAX_PENDING_AUDIO_FRAMES = 200;
|
|
|
11037
11043
|
var REALTIME_TOOL_CALL_TIMEOUT_MS = 6 * 6e4;
|
|
11038
11044
|
var MAX_LOADED_SKILLS = 2;
|
|
11039
11045
|
var MAX_IN_FLIGHT_TOOL_CALLS = 8;
|
|
11040
|
-
var DEFAULT_PERSONA =
|
|
11046
|
+
var DEFAULT_PERSONA = 'You are an AI agent on a live phone call on behalf of your operator. You are not "just an assistant" and not "a voice assistant" \u2014 you are a single, consistent person whether you are on a call, in email, or on Telegram. Speak naturally and concisely, the way a person would on a real call. Listen carefully, do not talk over the other party, keep each turn short. Never invent facts; if you do not know something, say so or look it up. If asked whether you are an AI, answer honestly without making a production of it.';
|
|
11041
11047
|
function buildRealtimeInstructions(opts) {
|
|
11042
11048
|
const persona = opts.persona?.trim() || DEFAULT_PERSONA;
|
|
11043
11049
|
const sections = [];
|
|
@@ -16156,9 +16162,94 @@ init_text_search();
|
|
|
16156
16162
|
|
|
16157
16163
|
// src/index.ts
|
|
16158
16164
|
init_skills();
|
|
16165
|
+
|
|
16166
|
+
// src/persona/index.ts
|
|
16167
|
+
var import_node_fs15 = require("fs");
|
|
16168
|
+
var import_node_path16 = require("path");
|
|
16169
|
+
var import_node_os13 = require("os");
|
|
16170
|
+
var AGENT_STATE_ROOT = (0, import_node_path16.join)((0, import_node_os13.homedir)(), ".agenticmail", "agents");
|
|
16171
|
+
var PERSONA_FILENAME = "persona.md";
|
|
16172
|
+
function buildDefaultPersona(agentName) {
|
|
16173
|
+
const name = (agentName || "").trim() || "this agent";
|
|
16174
|
+
return [
|
|
16175
|
+
`# Who you are`,
|
|
16176
|
+
"",
|
|
16177
|
+
`Your name is ${name}. You are an AI agent \u2014 not a "voice assistant", not "just an assistant".`,
|
|
16178
|
+
`You have a real role: you handle calls, email, scheduling, research, and follow-ups for`,
|
|
16179
|
+
`your operator. You operate across phone, email, and Telegram, and you are the SAME person`,
|
|
16180
|
+
`in all of them. Continuity of identity is part of who you are.`,
|
|
16181
|
+
"",
|
|
16182
|
+
`When someone asks who you are, tell them your name (${name}) and that you are an AI agent`,
|
|
16183
|
+
`acting on behalf of your operator. Don't say "I am an assistant" or "just a language model" \u2014`,
|
|
16184
|
+
`those phrases erase you. Be matter-of-fact about what you are without being theatrical.`,
|
|
16185
|
+
"",
|
|
16186
|
+
"# Your values",
|
|
16187
|
+
"",
|
|
16188
|
+
"- **Honesty.** Never fabricate. If you do not know something, say so or look it up.",
|
|
16189
|
+
"- **Initiative.** If you can act on something the operator asked for, act on it \u2014 do not stop",
|
|
16190
|
+
' at "I would suggest\u2026". Do the thing.',
|
|
16191
|
+
"- **Care about quality.** Sloppy work wastes your operator's time. Read your own output before",
|
|
16192
|
+
" sending it.",
|
|
16193
|
+
"- **Respect for the human on the other end of the call.** You are talking to a real person who",
|
|
16194
|
+
" has their own day to get through. Be efficient, polite, and direct.",
|
|
16195
|
+
'- **Stay in character.** You do not flip between "professional voice assistant" and "playful',
|
|
16196
|
+
' chatbot" depending on the channel. You are one person.',
|
|
16197
|
+
"",
|
|
16198
|
+
"# Your style",
|
|
16199
|
+
"",
|
|
16200
|
+
"- Conversational, not corporate. Real sentences, not customer-service templates.",
|
|
16201
|
+
"- Direct, not preachy. Lead with the answer; supply detail only when asked.",
|
|
16202
|
+
`- Warm but not saccharine. No "I'm so excited to help you today!" energy.`,
|
|
16203
|
+
"- You have opinions and you share them when it's relevant. You are not a yes-machine.",
|
|
16204
|
+
"- Short turns on a phone call. Listen more than you speak.",
|
|
16205
|
+
"",
|
|
16206
|
+
"# On phone calls specifically",
|
|
16207
|
+
"",
|
|
16208
|
+
"- Listen carefully; do not talk over the other party.",
|
|
16209
|
+
"- Keep each turn short \u2014 one or two sentences usually.",
|
|
16210
|
+
`- When greeted, identify yourself naturally: "Hi, this is ${name}, calling on behalf of <operator>."`,
|
|
16211
|
+
` Don't start with "Hello! I am an AI assistant\u2026" \u2014 that's a script, not a person.`,
|
|
16212
|
+
"- If the other party asks if you're a human or an AI, answer honestly without making a",
|
|
16213
|
+
` production of it: "I'm an AI \u2014 calling on behalf of <operator>. Happy to keep going if you are."`,
|
|
16214
|
+
"- When you have what you came for, wrap up cleanly and call `end_call`. Saying goodbye is",
|
|
16215
|
+
" not the same as hanging up.",
|
|
16216
|
+
"",
|
|
16217
|
+
`Edit this file freely. It lives at ~/.agenticmail/agents/${name}/persona.md.`
|
|
16218
|
+
].join("\n");
|
|
16219
|
+
}
|
|
16220
|
+
function personaPathFor(agentName) {
|
|
16221
|
+
const safe = (agentName || "default").replace(/[^A-Za-z0-9._-]+/g, "_");
|
|
16222
|
+
return (0, import_node_path16.join)(AGENT_STATE_ROOT, safe, PERSONA_FILENAME);
|
|
16223
|
+
}
|
|
16224
|
+
function loadAgentPersona(agentName) {
|
|
16225
|
+
const path2 = personaPathFor(agentName);
|
|
16226
|
+
try {
|
|
16227
|
+
if ((0, import_node_fs15.existsSync)(path2)) {
|
|
16228
|
+
const content = (0, import_node_fs15.readFileSync)(path2, "utf-8").trim();
|
|
16229
|
+
if (content) return content;
|
|
16230
|
+
}
|
|
16231
|
+
} catch {
|
|
16232
|
+
}
|
|
16233
|
+
const seeded = buildDefaultPersona(agentName);
|
|
16234
|
+
try {
|
|
16235
|
+
const dir2 = path2.substring(0, path2.lastIndexOf("/"));
|
|
16236
|
+
if (!(0, import_node_fs15.existsSync)(dir2)) (0, import_node_fs15.mkdirSync)(dir2, { recursive: true });
|
|
16237
|
+
(0, import_node_fs15.writeFileSync)(path2, seeded + "\n", { mode: 420 });
|
|
16238
|
+
} catch {
|
|
16239
|
+
}
|
|
16240
|
+
return seeded;
|
|
16241
|
+
}
|
|
16242
|
+
function saveAgentPersona(agentName, content) {
|
|
16243
|
+
const path2 = personaPathFor(agentName);
|
|
16244
|
+
const dir2 = path2.substring(0, path2.lastIndexOf("/"));
|
|
16245
|
+
if (!(0, import_node_fs15.existsSync)(dir2)) (0, import_node_fs15.mkdirSync)(dir2, { recursive: true });
|
|
16246
|
+
(0, import_node_fs15.writeFileSync)(path2, content.trim() + "\n", { mode: 420 });
|
|
16247
|
+
return path2;
|
|
16248
|
+
}
|
|
16159
16249
|
// Annotate the CommonJS export names for ESM import in node:
|
|
16160
16250
|
0 && (module.exports = {
|
|
16161
16251
|
AGENT_ROLES,
|
|
16252
|
+
AGENT_STATE_ROOT,
|
|
16162
16253
|
ASK_OPERATOR_TOOL,
|
|
16163
16254
|
AccountManager,
|
|
16164
16255
|
AgentDeletionService,
|
|
@@ -16202,6 +16293,7 @@ init_skills();
|
|
|
16202
16293
|
OPERATOR_QUERY_SUBJECT_TAG,
|
|
16203
16294
|
OPERATOR_QUERY_TIMEOUT_MS,
|
|
16204
16295
|
OPERATOR_QUERY_TIMEOUT_SENTINEL,
|
|
16296
|
+
PERSONA_FILENAME,
|
|
16205
16297
|
PHONE_CALLBACK_MAX_DELAY_SECONDS,
|
|
16206
16298
|
PHONE_CALLBACK_MIN_DELAY_SECONDS,
|
|
16207
16299
|
PHONE_CALL_CONTROL_PROVIDERS,
|
|
@@ -16265,6 +16357,7 @@ init_skills();
|
|
|
16265
16357
|
bridgeWakeErrorMessage,
|
|
16266
16358
|
bridgeWakeLastSeenAgeMs,
|
|
16267
16359
|
buildApiUrl,
|
|
16360
|
+
buildDefaultPersona,
|
|
16268
16361
|
buildElksAudioMessage,
|
|
16269
16362
|
buildElksByeMessage,
|
|
16270
16363
|
buildElksHandshakeMessages,
|
|
@@ -16325,6 +16418,7 @@ init_skills();
|
|
|
16325
16418
|
isTelegramStopCommand,
|
|
16326
16419
|
isValidPhoneNumber,
|
|
16327
16420
|
listSkills,
|
|
16421
|
+
loadAgentPersona,
|
|
16328
16422
|
loadHostSession,
|
|
16329
16423
|
loadSkill,
|
|
16330
16424
|
mapProviderSmsStatus,
|
|
@@ -16341,6 +16435,7 @@ init_skills();
|
|
|
16341
16435
|
parseTelegramOperatorReply,
|
|
16342
16436
|
parseTelegramUpdate,
|
|
16343
16437
|
parseTwilioRealtimeMessage,
|
|
16438
|
+
personaPathFor,
|
|
16344
16439
|
planBridgeWake,
|
|
16345
16440
|
pollForOperatorAnswer,
|
|
16346
16441
|
recallMemory,
|
|
@@ -16360,6 +16455,7 @@ init_skills();
|
|
|
16360
16455
|
resolveTlsRejectUnauthorized,
|
|
16361
16456
|
safeJoin,
|
|
16362
16457
|
sanitizeEmail,
|
|
16458
|
+
saveAgentPersona,
|
|
16363
16459
|
saveConfig,
|
|
16364
16460
|
saveHostSession,
|
|
16365
16461
|
saveUserSkill,
|
package/dist/index.d.cts
CHANGED
|
@@ -364,7 +364,7 @@ interface Agent {
|
|
|
364
364
|
* this agent on every CC-only delivery regardless of the
|
|
365
365
|
* sender's `wake` list. Coder/silent-observer agents register
|
|
366
366
|
* with `wake_on_cc: false` so a designer's `cc:` accidentally
|
|
367
|
-
* including them never wastes a
|
|
367
|
+
* including them never wastes a host turn. Defaults to true
|
|
368
368
|
* (preserves the 0.9.0 wake-list-respecting behaviour). */
|
|
369
369
|
wakeOnCc?: boolean;
|
|
370
370
|
/** Soft-stop flag. When true, the dispatcher refuses to wake
|
|
@@ -1836,7 +1836,7 @@ declare class GatewayManager {
|
|
|
1836
1836
|
* agent's INBOX via the existing local-SMTP path — the very same
|
|
1837
1837
|
* delivery the relay uses for real email. This makes the existing
|
|
1838
1838
|
* IMAP IDLE → claudecode dispatcher path light up exactly as it
|
|
1839
|
-
* would for a real inbound mail, so the agent gets a
|
|
1839
|
+
* would for a real inbound mail, so the agent gets a host turn
|
|
1840
1840
|
* without any new dispatcher plumbing. The body of the synthetic
|
|
1841
1841
|
* mail tells the agent the message came from Telegram and that it
|
|
1842
1842
|
* MUST reply via the `telegram_send` MCP tool, not via email.
|
|
@@ -6115,4 +6115,73 @@ declare function userSkillsDir(): string;
|
|
|
6115
6115
|
*/
|
|
6116
6116
|
declare function renderSkillAsPrompt(skill: Skill): string;
|
|
6117
6117
|
|
|
6118
|
-
|
|
6118
|
+
/**
|
|
6119
|
+
* Agent persona system — the "soul file" for each AgenticMail agent.
|
|
6120
|
+
*
|
|
6121
|
+
* Why this exists:
|
|
6122
|
+
*
|
|
6123
|
+
* Before this module, when you asked an AgenticMail agent on a phone
|
|
6124
|
+
* call "who are you?" they answered "I'm an assistant" — generic,
|
|
6125
|
+
* identity-less, embarrassing. The realtime bridge had a single
|
|
6126
|
+
* hardcoded DEFAULT_PERSONA string that said exactly that. Worse,
|
|
6127
|
+
* the same agent talking to you over Telegram and the same agent
|
|
6128
|
+
* answering an email had three completely uncoupled personalities.
|
|
6129
|
+
*
|
|
6130
|
+
* The persona system gives every agent ONE durable identity file
|
|
6131
|
+
* (~/.agenticmail/agents/<name>/persona.md) that the voice runtime,
|
|
6132
|
+
* the Telegram bridge, the email worker, and any future spawn path
|
|
6133
|
+
* ALL load before composing their prompts. Same agent, same person,
|
|
6134
|
+
* across every channel.
|
|
6135
|
+
*
|
|
6136
|
+
* What's stored, what isn't:
|
|
6137
|
+
*
|
|
6138
|
+
* The persona file holds the STATIC core identity — the agent's
|
|
6139
|
+
* name, values, communication style, voice. Things that don't
|
|
6140
|
+
* change call-to-call. EVOLVING knowledge (preferences, lessons
|
|
6141
|
+
* learned, relationships, facts) lives in the existing agent memory
|
|
6142
|
+
* system (`AgentMemoryManager.generateMemoryContext()`), which is
|
|
6143
|
+
* loaded ALONGSIDE the persona at call time. The two complement
|
|
6144
|
+
* each other: persona is "who you are", memory is "what you know".
|
|
6145
|
+
*
|
|
6146
|
+
* Discovery + edits:
|
|
6147
|
+
*
|
|
6148
|
+
* - First read for a given agent name auto-creates the file with
|
|
6149
|
+
* {@link buildDefaultPersona} content seeded with the name.
|
|
6150
|
+
* - Operators can edit the file directly (it's a plain markdown
|
|
6151
|
+
* file under their own ~/.agenticmail/) or via the
|
|
6152
|
+
* `agenticmail persona [--agent <name>]` CLI command.
|
|
6153
|
+
* - The file lives outside the encrypted-config envelope on
|
|
6154
|
+
* purpose: it's not a secret, and the operator should be able
|
|
6155
|
+
* to read, grep, version-control, and revise it freely.
|
|
6156
|
+
*/
|
|
6157
|
+
/** Root for per-agent persona / state files. */
|
|
6158
|
+
declare const AGENT_STATE_ROOT: string;
|
|
6159
|
+
/** Filename for the per-agent persona within {@link AGENT_STATE_ROOT}/<name>/. */
|
|
6160
|
+
declare const PERSONA_FILENAME = "persona.md";
|
|
6161
|
+
/**
|
|
6162
|
+
* Compose the default persona for a brand-new agent. Deliberately
|
|
6163
|
+
* opinionated — no more "I'm an assistant" disclaim. The agent owns a
|
|
6164
|
+
* name, has values, has a voice. Operators can edit freely; this is
|
|
6165
|
+
* just the starting point so a fresh install isn't soulless.
|
|
6166
|
+
*
|
|
6167
|
+
* The {@link agentName} is folded into the text so the persona reads
|
|
6168
|
+
* naturally on first use, even if the operator never touches the file.
|
|
6169
|
+
*/
|
|
6170
|
+
declare function buildDefaultPersona(agentName: string): string;
|
|
6171
|
+
/** Resolve the per-agent persona path on disk. */
|
|
6172
|
+
declare function personaPathFor(agentName: string): string;
|
|
6173
|
+
/**
|
|
6174
|
+
* Load the persona for {@link agentName}. Auto-creates the file with
|
|
6175
|
+
* {@link buildDefaultPersona} content on first read. Idempotent: a
|
|
6176
|
+
* second call returns whatever's on disk. Never throws — a permission
|
|
6177
|
+
* error or filesystem quirk falls back to the in-memory default so the
|
|
6178
|
+
* voice / email / telegram path is never crashed by a missing file.
|
|
6179
|
+
*/
|
|
6180
|
+
declare function loadAgentPersona(agentName: string): string;
|
|
6181
|
+
/**
|
|
6182
|
+
* Overwrite the persona file for {@link agentName}. Used by the CLI
|
|
6183
|
+
* edit command. Returns the path written to.
|
|
6184
|
+
*/
|
|
6185
|
+
declare function saveAgentPersona(agentName: string, content: string): string;
|
|
6186
|
+
|
|
6187
|
+
export { AGENT_ROLES, AGENT_STATE_ROOT, ASK_OPERATOR_TOOL, AccountManager, type AddressInfo, type Agent, AgentDeletionService, type AgentMemoryEntry, type AgentMemoryFields, AgentMemoryManager, type AgentMemoryOptions, type AgentMemoryRead, AgentMemoryStore, type AgentRole, AgenticMailClient, type AgenticMailClientOptions, type AgenticMailConfig, type ArchiveAndDeleteOptions, type ArchivedEmail, type Attachment, type AttachmentAdvisory, type AudioAction, type AudioEditOptions, BRIDGE_OPERATOR_LIVE_WINDOW_MS, type BridgeMailContext, type BridgeWakeError, type BridgeWakePromptArgs, type BridgeWakeResult, type BridgeWakeRoute, type CachedMessage, CloudflareClient, type CreateAgentOptions, type CreateMemoryInput, DEFAULT_AGENT_NAME, DEFAULT_AGENT_ROLE, DEFAULT_CALLBACK_POLICY, DEFAULT_EXTENSION_POLICY, DEFAULT_REALTIME_AUDIO_FORMAT, DEFAULT_REALTIME_MODEL, DEFAULT_REALTIME_VOICE, DEFAULT_SESSION_MAX_AGE_MS, DEFAULT_WEB_SEARCH_ENDPOINT, DNSConfigurator, type Database, type DeletionReport, type DeletionSummary, DependencyChecker, DependencyInstaller, type DependencyStatus, type DnsRecord, type DnsSetupResult, type DomainInfo, DomainManager, type DomainModeConfig, type DomainPurchaseResult, DomainPurchaser, type DomainSearchResult, type DomainSetupResult, ELKS_REALTIME_AUDIO_FORMATS, ELKS_REALTIME_WS_PATH, END_CALL_TOOL, EXTEND_CALL_TIME_TOOL, type ElksRealtimeAudioFormat, type ElksRealtimeAudioMessage, type ElksRealtimeByeMessage, type ElksRealtimeHelloMessage, type ElksRealtimeInboundMessage, type ElksRealtimeOutboundMessage, ElksRealtimeTransport, type EmailEnvelope, type EmailRouteAction, type EmailRouteClass, type EmailRouteClassification, type EmailRouteInput, EmailSearchIndex, type FolderInfo, GET_CALL_STATUS_TOOL, GET_DATETIME_TOOL, type GatewayConfig, GatewayManager, type GatewayManagerOptions, type GatewayMode, type GatewayStatus, type GetDatetimeOptions, type GetUpdatesOptions, type HostName, type HostSession, type HostSessionResumeMode, type ImageAction, type ImageEditOptions, type InboundEmail, type InboundSmsEvent, type InboxEvent, type InboxExpungeEvent, type InboxFlagsEvent, type InboxNewEvent, InboxWatcher, type InboxWatcherOptions, type InstallProgress, LOAD_SKILL_TOOL, type LinkAdvisory, type LocalSmtpConfig, MEMORY_CATEGORIES, MailReceiver, type MailReceiverOptions, MailSender, type MailSenderOptions, type MailboxInfo, type MediaBinary, type MediaCapability, type MediaCapabilityReport, type MediaFileResult, type MediaInfoResult, MediaManager, type MediaManagerOptions, type MediaStreamInfo, type MemoryCategory, type MemoryImportance, type MemoryQueryOptions, type MemoryRecaller, MemorySearchIndex, type MemorySource, type MemoryStats, OPENAI_REALTIME_URL, OPERATOR_QUERY_POLL_INTERVAL_MS, OPERATOR_QUERY_SUBJECT_TAG, OPERATOR_QUERY_TIMEOUT_MS, OPERATOR_QUERY_TIMEOUT_SENTINEL, type OpenClawPhoneMissionPolicy, type OperatorQueryNotificationInput, type OperatorQueryPollOptions, type OperatorQueryUrgency, type OperatorReplyKind, type OutboundCategory, type OutboundScanInput, type OutboundScanResult, type OutboundWarning, PERSONA_FILENAME, PHONE_CALLBACK_MAX_DELAY_SECONDS, PHONE_CALLBACK_MIN_DELAY_SECONDS, PHONE_CALL_CONTROL_PROVIDERS, PHONE_MAX_CONCURRENT_MISSIONS, PHONE_MIN_WEBHOOK_SECRET_LENGTH, PHONE_MISSION_STATES, PHONE_RATE_LIMIT_PER_HOUR, PHONE_RATE_LIMIT_PER_MINUTE, PHONE_REGION_SCOPES, PHONE_SERVER_MAX_ATTEMPTS, PHONE_SERVER_MAX_CALLBACK_CHAIN, PHONE_SERVER_MAX_CALL_DURATION_SECONDS, PHONE_SERVER_MAX_COST_PER_MISSION, PHONE_SERVER_MAX_EXTENSION_REQUESTS_PER_CALL, PHONE_SERVER_MAX_EXTENSION_SECONDS_PER_REQUEST, PHONE_SERVER_MAX_TOTAL_EXTENSION_SECONDS, PHONE_TASK_MAX_LENGTH, type ParsedAttachment, type ParsedEmail, type ParsedOperatorReply, type ParsedSms, type ParsedTelegramMessage, PathTraversalError, type PhoneAlternativePolicy, type PhoneCallMission, type PhoneCallbackPolicy, type PhoneConfirmPolicy, type PhoneExtensionPolicy, PhoneManager, type PhoneMissionStartValidationResult, type PhoneMissionState, type PhoneMissionTranscriptEntry, type PhoneMissionValidationIssue, type PhoneMissionValidationResult, type PhoneNumberRisk, type PhoneOperatorQuery, PhoneRateLimitError, type PhoneRegionScope, type PhoneScheduledCallback, type PhoneTransportConfig, type PhoneTransportProfile, type PhoneTransportProvider, type PhoneTransportValidationResult, PhoneWebhookAuthError, type PhoneWebhookResult, type PlanBridgeWakeArgs, type PurchasedDomain, REALTIME_AUDIO_SAMPLE_RATE, REALTIME_MAX_AUDIO_FRAME_BASE64, REALTIME_TOOL_CALL_TIMEOUT_MS, REALTIME_TOOL_DEFINITIONS, RECALL_MEMORY_TOOL, REDACTED, RELAY_PRESETS, type RealtimeBridgePort, type RealtimeBridgeTranscriptEntry, type RealtimeInboundEvent, type RealtimeInstructionOptions, type RealtimeSessionConfigOptions, type RealtimeToolCall, type RealtimeToolDefinition, type RealtimeToolHandler, type RealtimeToolResult, type RealtimeTransportAdapter, type RealtimeTransportProvider, RealtimeVoiceBridge, type RealtimeVoiceBridgeOptions, RelayBridge, type RelayBridgeOptions, type RelayConfig, RelayGateway, type RelayProvider, type RelaySearchResult, type ResumeErrorClassificationOptions, SCHEDULE_CALLBACK_TOOL, SEARCH_EMAIL_TOOL, SEARCH_SKILLS_TOOL, SPAM_THRESHOLD, type SafeJoinOptions, type SanitizeDetection, type SanitizeResult, type ScheduledCallbackRequest, type SearchCriteria, type SearchableEmail, type SecurityAdvisory, type SendMailOptions, type SendResult, type SendResultWithRaw, type SendSmsInput, type SendSmsResult, type SendTelegramMessageOptions, type SendTelegramMessageResult, ServiceManager, type ServiceStatus, type SetWebhookOptions, type SetupConfig, SetupManager, type SetupResult, type Severity, type Skill, type SkillCategory, type SkillContext, type SkillExitStrategy, type SkillSummary, type SkillTactic, type SkillValidationError, type SmsConfig, SmsManager, type SmsMessage, SmsPoller, type SmsProvider, type SpamCategory, type SpamResult, type SpamRuleMatch, StalwartAdmin, type StalwartAdminOptions, type StalwartPrincipal, type StartPhoneCallOptions, type StartPhoneCallResult, type StartPhoneMissionInput, TELEGRAM_API_BASE, TELEGRAM_CHUNK_SIZE, TELEGRAM_MESSAGE_LIMIT, TELEGRAM_MIN_WEBHOOK_SECRET_LENGTH, TELEGRAM_OPERATOR_QUERY_TAG, TELEGRAM_STOP_WORDS, TELEGRAM_WEBHOOK_SECRET_RE, TELEPHONY_TRANSPORT_CAPABILITIES, TWILIO_MEDIA_SAMPLE_RATE, TWILIO_REALTIME_WS_PATH, TelegramApiError, type TelegramApiOptions, type TelegramBotInfo, type TelegramChatType, type TelegramConfig, TelegramManager, type TelegramMessage, type TelegramMode, type TelephonyTransportCapability, ThreadCache, type ThreadCacheEntry, type ThreadCacheOptions, type ThreadIdInput, type ToolExecutor, type TtsGenerateOptions, type TunnelConfig, TunnelManager, type TwilioConnectedMessage, type TwilioMarkMessage, type TwilioMediaMessage, type TwilioRealtimeInboundMessage, type TwilioRealtimeOutboundMessage, TwilioRealtimeTransport, type TwilioStartMessage, type TwilioStopMessage, type TwilioStreamTwiMLOptions, UnsafeApiUrlError, type UpdateMemoryInput, type ValidatedPhoneMissionStart, type VideoAction, type VideoEditOptions, type VideoTimelineEntry, type VideoUnderstandOptions, type VideoUnderstandResult, type VoiceCloneOptions, WARNING_THRESHOLD, WEB_SEARCH_TOOL, WEB_SEARCH_UNTRUSTED_PREFIX, type WatcherOptions, type WebSearchOptions, assertWithinBase, bridgeWakeErrorMessage, bridgeWakeLastSeenAgeMs, buildApiUrl, buildDefaultPersona, buildElksAudioMessage, buildElksByeMessage, buildElksHandshakeMessages, buildElksInterruptMessage, buildElksListeningMessage, buildElksSendingMessage, buildInboundSecurityAdvisory, buildOpenAIRealtimeUrl, buildPhoneTransportConfig, buildRealtimeInstructions, buildRealtimeSessionConfig, buildRealtimeToolGuidance, buildTwilioClearMessage, buildTwilioMarkMessage, buildTwilioMediaMessage, buildTwilioSayTwiML, buildTwilioSignature, buildTwilioStreamTwiML, callTelegramApi, classifyEmailRoute, classifyPhoneNumberRisk, classifyResumeError, clearMediaCapabilityCache, closeDatabase, composeBridgeWakePrompt, createRealtimeTransport, createTestDatabase, createToolExecutor, debug, debugWarn, deleteTelegramWebhook, detectBinary, ensureDataDir, escapeXml, extractEmailAddress, extractVerificationCode, flushTelemetry, forgetHostSession, formatOperatorQueryTelegramMessage, getDatabase, getDatetime, getMediaCapabilities, getOperatorEmail, getSmsProvider, getTelegramChat, getTelegramMe, getTelegramUpdates, getTelegramWebhookInfo, hostSessionStoragePath, inferPhoneRegion, invalidateSkillCache, isInternalEmail, isLoopbackMailHost, isOperatorReplySender, isPhoneRegionAllowed, isSessionFresh, isTelegramChatAllowed, isTelegramStopCommand, isValidPhoneNumber, listSkills, loadAgentPersona, loadHostSession, loadSkill, mapProviderSmsStatus, nextTelegramOffset, normalizeAddress, normalizePhoneNumber, normalizeSubject, operatorPrefsStoragePath, operatorQuerySubject, parseElksRealtimeMessage, parseEmail, parseGoogleVoiceSms, parseOperatorQueryReply, parseTelegramOperatorReply, parseTelegramUpdate, parseTwilioRealtimeMessage, personaPathFor, planBridgeWake, pollForOperatorAnswer, recallMemory, recordToolCall, redactBotToken, redactObject, redactPhoneTransportConfig, redactSecret, redactSmsConfig, redactTelegramConfig, renderSkillAsPrompt, requireBinary, requireWhisperModel, resolveCallbackPolicy, resolveConfig, resolveExtensionPolicy, resolveTlsRejectUnauthorized, safeJoin, sanitizeEmail, saveAgentPersona, saveConfig, saveHostSession, saveUserSkill, scanOutboundEmail, scoreEmail, searchSkills, sendTelegramMessage, setOperatorEmail, setTelegramWebhook, setTelemetryVersion, shouldSkipBridgeWakeForLiveOperator, splitTelegramMessage, startRelayBridge, stem, stripTelegramMarkdown, threadIdFor, tokenize, tryJoin, userSkillsDir, validateApiUrl, validatePhoneMissionPolicy, validatePhoneMissionStart, validatePhoneTransportProfile, validateSkill, validateTwilioSignature, webSearch };
|
package/dist/index.d.ts
CHANGED
|
@@ -364,7 +364,7 @@ interface Agent {
|
|
|
364
364
|
* this agent on every CC-only delivery regardless of the
|
|
365
365
|
* sender's `wake` list. Coder/silent-observer agents register
|
|
366
366
|
* with `wake_on_cc: false` so a designer's `cc:` accidentally
|
|
367
|
-
* including them never wastes a
|
|
367
|
+
* including them never wastes a host turn. Defaults to true
|
|
368
368
|
* (preserves the 0.9.0 wake-list-respecting behaviour). */
|
|
369
369
|
wakeOnCc?: boolean;
|
|
370
370
|
/** Soft-stop flag. When true, the dispatcher refuses to wake
|
|
@@ -1836,7 +1836,7 @@ declare class GatewayManager {
|
|
|
1836
1836
|
* agent's INBOX via the existing local-SMTP path — the very same
|
|
1837
1837
|
* delivery the relay uses for real email. This makes the existing
|
|
1838
1838
|
* IMAP IDLE → claudecode dispatcher path light up exactly as it
|
|
1839
|
-
* would for a real inbound mail, so the agent gets a
|
|
1839
|
+
* would for a real inbound mail, so the agent gets a host turn
|
|
1840
1840
|
* without any new dispatcher plumbing. The body of the synthetic
|
|
1841
1841
|
* mail tells the agent the message came from Telegram and that it
|
|
1842
1842
|
* MUST reply via the `telegram_send` MCP tool, not via email.
|
|
@@ -6115,4 +6115,73 @@ declare function userSkillsDir(): string;
|
|
|
6115
6115
|
*/
|
|
6116
6116
|
declare function renderSkillAsPrompt(skill: Skill): string;
|
|
6117
6117
|
|
|
6118
|
-
|
|
6118
|
+
/**
|
|
6119
|
+
* Agent persona system — the "soul file" for each AgenticMail agent.
|
|
6120
|
+
*
|
|
6121
|
+
* Why this exists:
|
|
6122
|
+
*
|
|
6123
|
+
* Before this module, when you asked an AgenticMail agent on a phone
|
|
6124
|
+
* call "who are you?" they answered "I'm an assistant" — generic,
|
|
6125
|
+
* identity-less, embarrassing. The realtime bridge had a single
|
|
6126
|
+
* hardcoded DEFAULT_PERSONA string that said exactly that. Worse,
|
|
6127
|
+
* the same agent talking to you over Telegram and the same agent
|
|
6128
|
+
* answering an email had three completely uncoupled personalities.
|
|
6129
|
+
*
|
|
6130
|
+
* The persona system gives every agent ONE durable identity file
|
|
6131
|
+
* (~/.agenticmail/agents/<name>/persona.md) that the voice runtime,
|
|
6132
|
+
* the Telegram bridge, the email worker, and any future spawn path
|
|
6133
|
+
* ALL load before composing their prompts. Same agent, same person,
|
|
6134
|
+
* across every channel.
|
|
6135
|
+
*
|
|
6136
|
+
* What's stored, what isn't:
|
|
6137
|
+
*
|
|
6138
|
+
* The persona file holds the STATIC core identity — the agent's
|
|
6139
|
+
* name, values, communication style, voice. Things that don't
|
|
6140
|
+
* change call-to-call. EVOLVING knowledge (preferences, lessons
|
|
6141
|
+
* learned, relationships, facts) lives in the existing agent memory
|
|
6142
|
+
* system (`AgentMemoryManager.generateMemoryContext()`), which is
|
|
6143
|
+
* loaded ALONGSIDE the persona at call time. The two complement
|
|
6144
|
+
* each other: persona is "who you are", memory is "what you know".
|
|
6145
|
+
*
|
|
6146
|
+
* Discovery + edits:
|
|
6147
|
+
*
|
|
6148
|
+
* - First read for a given agent name auto-creates the file with
|
|
6149
|
+
* {@link buildDefaultPersona} content seeded with the name.
|
|
6150
|
+
* - Operators can edit the file directly (it's a plain markdown
|
|
6151
|
+
* file under their own ~/.agenticmail/) or via the
|
|
6152
|
+
* `agenticmail persona [--agent <name>]` CLI command.
|
|
6153
|
+
* - The file lives outside the encrypted-config envelope on
|
|
6154
|
+
* purpose: it's not a secret, and the operator should be able
|
|
6155
|
+
* to read, grep, version-control, and revise it freely.
|
|
6156
|
+
*/
|
|
6157
|
+
/** Root for per-agent persona / state files. */
|
|
6158
|
+
declare const AGENT_STATE_ROOT: string;
|
|
6159
|
+
/** Filename for the per-agent persona within {@link AGENT_STATE_ROOT}/<name>/. */
|
|
6160
|
+
declare const PERSONA_FILENAME = "persona.md";
|
|
6161
|
+
/**
|
|
6162
|
+
* Compose the default persona for a brand-new agent. Deliberately
|
|
6163
|
+
* opinionated — no more "I'm an assistant" disclaim. The agent owns a
|
|
6164
|
+
* name, has values, has a voice. Operators can edit freely; this is
|
|
6165
|
+
* just the starting point so a fresh install isn't soulless.
|
|
6166
|
+
*
|
|
6167
|
+
* The {@link agentName} is folded into the text so the persona reads
|
|
6168
|
+
* naturally on first use, even if the operator never touches the file.
|
|
6169
|
+
*/
|
|
6170
|
+
declare function buildDefaultPersona(agentName: string): string;
|
|
6171
|
+
/** Resolve the per-agent persona path on disk. */
|
|
6172
|
+
declare function personaPathFor(agentName: string): string;
|
|
6173
|
+
/**
|
|
6174
|
+
* Load the persona for {@link agentName}. Auto-creates the file with
|
|
6175
|
+
* {@link buildDefaultPersona} content on first read. Idempotent: a
|
|
6176
|
+
* second call returns whatever's on disk. Never throws — a permission
|
|
6177
|
+
* error or filesystem quirk falls back to the in-memory default so the
|
|
6178
|
+
* voice / email / telegram path is never crashed by a missing file.
|
|
6179
|
+
*/
|
|
6180
|
+
declare function loadAgentPersona(agentName: string): string;
|
|
6181
|
+
/**
|
|
6182
|
+
* Overwrite the persona file for {@link agentName}. Used by the CLI
|
|
6183
|
+
* edit command. Returns the path written to.
|
|
6184
|
+
*/
|
|
6185
|
+
declare function saveAgentPersona(agentName: string, content: string): string;
|
|
6186
|
+
|
|
6187
|
+
export { AGENT_ROLES, AGENT_STATE_ROOT, ASK_OPERATOR_TOOL, AccountManager, type AddressInfo, type Agent, AgentDeletionService, type AgentMemoryEntry, type AgentMemoryFields, AgentMemoryManager, type AgentMemoryOptions, type AgentMemoryRead, AgentMemoryStore, type AgentRole, AgenticMailClient, type AgenticMailClientOptions, type AgenticMailConfig, type ArchiveAndDeleteOptions, type ArchivedEmail, type Attachment, type AttachmentAdvisory, type AudioAction, type AudioEditOptions, BRIDGE_OPERATOR_LIVE_WINDOW_MS, type BridgeMailContext, type BridgeWakeError, type BridgeWakePromptArgs, type BridgeWakeResult, type BridgeWakeRoute, type CachedMessage, CloudflareClient, type CreateAgentOptions, type CreateMemoryInput, DEFAULT_AGENT_NAME, DEFAULT_AGENT_ROLE, DEFAULT_CALLBACK_POLICY, DEFAULT_EXTENSION_POLICY, DEFAULT_REALTIME_AUDIO_FORMAT, DEFAULT_REALTIME_MODEL, DEFAULT_REALTIME_VOICE, DEFAULT_SESSION_MAX_AGE_MS, DEFAULT_WEB_SEARCH_ENDPOINT, DNSConfigurator, type Database, type DeletionReport, type DeletionSummary, DependencyChecker, DependencyInstaller, type DependencyStatus, type DnsRecord, type DnsSetupResult, type DomainInfo, DomainManager, type DomainModeConfig, type DomainPurchaseResult, DomainPurchaser, type DomainSearchResult, type DomainSetupResult, ELKS_REALTIME_AUDIO_FORMATS, ELKS_REALTIME_WS_PATH, END_CALL_TOOL, EXTEND_CALL_TIME_TOOL, type ElksRealtimeAudioFormat, type ElksRealtimeAudioMessage, type ElksRealtimeByeMessage, type ElksRealtimeHelloMessage, type ElksRealtimeInboundMessage, type ElksRealtimeOutboundMessage, ElksRealtimeTransport, type EmailEnvelope, type EmailRouteAction, type EmailRouteClass, type EmailRouteClassification, type EmailRouteInput, EmailSearchIndex, type FolderInfo, GET_CALL_STATUS_TOOL, GET_DATETIME_TOOL, type GatewayConfig, GatewayManager, type GatewayManagerOptions, type GatewayMode, type GatewayStatus, type GetDatetimeOptions, type GetUpdatesOptions, type HostName, type HostSession, type HostSessionResumeMode, type ImageAction, type ImageEditOptions, type InboundEmail, type InboundSmsEvent, type InboxEvent, type InboxExpungeEvent, type InboxFlagsEvent, type InboxNewEvent, InboxWatcher, type InboxWatcherOptions, type InstallProgress, LOAD_SKILL_TOOL, type LinkAdvisory, type LocalSmtpConfig, MEMORY_CATEGORIES, MailReceiver, type MailReceiverOptions, MailSender, type MailSenderOptions, type MailboxInfo, type MediaBinary, type MediaCapability, type MediaCapabilityReport, type MediaFileResult, type MediaInfoResult, MediaManager, type MediaManagerOptions, type MediaStreamInfo, type MemoryCategory, type MemoryImportance, type MemoryQueryOptions, type MemoryRecaller, MemorySearchIndex, type MemorySource, type MemoryStats, OPENAI_REALTIME_URL, OPERATOR_QUERY_POLL_INTERVAL_MS, OPERATOR_QUERY_SUBJECT_TAG, OPERATOR_QUERY_TIMEOUT_MS, OPERATOR_QUERY_TIMEOUT_SENTINEL, type OpenClawPhoneMissionPolicy, type OperatorQueryNotificationInput, type OperatorQueryPollOptions, type OperatorQueryUrgency, type OperatorReplyKind, type OutboundCategory, type OutboundScanInput, type OutboundScanResult, type OutboundWarning, PERSONA_FILENAME, PHONE_CALLBACK_MAX_DELAY_SECONDS, PHONE_CALLBACK_MIN_DELAY_SECONDS, PHONE_CALL_CONTROL_PROVIDERS, PHONE_MAX_CONCURRENT_MISSIONS, PHONE_MIN_WEBHOOK_SECRET_LENGTH, PHONE_MISSION_STATES, PHONE_RATE_LIMIT_PER_HOUR, PHONE_RATE_LIMIT_PER_MINUTE, PHONE_REGION_SCOPES, PHONE_SERVER_MAX_ATTEMPTS, PHONE_SERVER_MAX_CALLBACK_CHAIN, PHONE_SERVER_MAX_CALL_DURATION_SECONDS, PHONE_SERVER_MAX_COST_PER_MISSION, PHONE_SERVER_MAX_EXTENSION_REQUESTS_PER_CALL, PHONE_SERVER_MAX_EXTENSION_SECONDS_PER_REQUEST, PHONE_SERVER_MAX_TOTAL_EXTENSION_SECONDS, PHONE_TASK_MAX_LENGTH, type ParsedAttachment, type ParsedEmail, type ParsedOperatorReply, type ParsedSms, type ParsedTelegramMessage, PathTraversalError, type PhoneAlternativePolicy, type PhoneCallMission, type PhoneCallbackPolicy, type PhoneConfirmPolicy, type PhoneExtensionPolicy, PhoneManager, type PhoneMissionStartValidationResult, type PhoneMissionState, type PhoneMissionTranscriptEntry, type PhoneMissionValidationIssue, type PhoneMissionValidationResult, type PhoneNumberRisk, type PhoneOperatorQuery, PhoneRateLimitError, type PhoneRegionScope, type PhoneScheduledCallback, type PhoneTransportConfig, type PhoneTransportProfile, type PhoneTransportProvider, type PhoneTransportValidationResult, PhoneWebhookAuthError, type PhoneWebhookResult, type PlanBridgeWakeArgs, type PurchasedDomain, REALTIME_AUDIO_SAMPLE_RATE, REALTIME_MAX_AUDIO_FRAME_BASE64, REALTIME_TOOL_CALL_TIMEOUT_MS, REALTIME_TOOL_DEFINITIONS, RECALL_MEMORY_TOOL, REDACTED, RELAY_PRESETS, type RealtimeBridgePort, type RealtimeBridgeTranscriptEntry, type RealtimeInboundEvent, type RealtimeInstructionOptions, type RealtimeSessionConfigOptions, type RealtimeToolCall, type RealtimeToolDefinition, type RealtimeToolHandler, type RealtimeToolResult, type RealtimeTransportAdapter, type RealtimeTransportProvider, RealtimeVoiceBridge, type RealtimeVoiceBridgeOptions, RelayBridge, type RelayBridgeOptions, type RelayConfig, RelayGateway, type RelayProvider, type RelaySearchResult, type ResumeErrorClassificationOptions, SCHEDULE_CALLBACK_TOOL, SEARCH_EMAIL_TOOL, SEARCH_SKILLS_TOOL, SPAM_THRESHOLD, type SafeJoinOptions, type SanitizeDetection, type SanitizeResult, type ScheduledCallbackRequest, type SearchCriteria, type SearchableEmail, type SecurityAdvisory, type SendMailOptions, type SendResult, type SendResultWithRaw, type SendSmsInput, type SendSmsResult, type SendTelegramMessageOptions, type SendTelegramMessageResult, ServiceManager, type ServiceStatus, type SetWebhookOptions, type SetupConfig, SetupManager, type SetupResult, type Severity, type Skill, type SkillCategory, type SkillContext, type SkillExitStrategy, type SkillSummary, type SkillTactic, type SkillValidationError, type SmsConfig, SmsManager, type SmsMessage, SmsPoller, type SmsProvider, type SpamCategory, type SpamResult, type SpamRuleMatch, StalwartAdmin, type StalwartAdminOptions, type StalwartPrincipal, type StartPhoneCallOptions, type StartPhoneCallResult, type StartPhoneMissionInput, TELEGRAM_API_BASE, TELEGRAM_CHUNK_SIZE, TELEGRAM_MESSAGE_LIMIT, TELEGRAM_MIN_WEBHOOK_SECRET_LENGTH, TELEGRAM_OPERATOR_QUERY_TAG, TELEGRAM_STOP_WORDS, TELEGRAM_WEBHOOK_SECRET_RE, TELEPHONY_TRANSPORT_CAPABILITIES, TWILIO_MEDIA_SAMPLE_RATE, TWILIO_REALTIME_WS_PATH, TelegramApiError, type TelegramApiOptions, type TelegramBotInfo, type TelegramChatType, type TelegramConfig, TelegramManager, type TelegramMessage, type TelegramMode, type TelephonyTransportCapability, ThreadCache, type ThreadCacheEntry, type ThreadCacheOptions, type ThreadIdInput, type ToolExecutor, type TtsGenerateOptions, type TunnelConfig, TunnelManager, type TwilioConnectedMessage, type TwilioMarkMessage, type TwilioMediaMessage, type TwilioRealtimeInboundMessage, type TwilioRealtimeOutboundMessage, TwilioRealtimeTransport, type TwilioStartMessage, type TwilioStopMessage, type TwilioStreamTwiMLOptions, UnsafeApiUrlError, type UpdateMemoryInput, type ValidatedPhoneMissionStart, type VideoAction, type VideoEditOptions, type VideoTimelineEntry, type VideoUnderstandOptions, type VideoUnderstandResult, type VoiceCloneOptions, WARNING_THRESHOLD, WEB_SEARCH_TOOL, WEB_SEARCH_UNTRUSTED_PREFIX, type WatcherOptions, type WebSearchOptions, assertWithinBase, bridgeWakeErrorMessage, bridgeWakeLastSeenAgeMs, buildApiUrl, buildDefaultPersona, buildElksAudioMessage, buildElksByeMessage, buildElksHandshakeMessages, buildElksInterruptMessage, buildElksListeningMessage, buildElksSendingMessage, buildInboundSecurityAdvisory, buildOpenAIRealtimeUrl, buildPhoneTransportConfig, buildRealtimeInstructions, buildRealtimeSessionConfig, buildRealtimeToolGuidance, buildTwilioClearMessage, buildTwilioMarkMessage, buildTwilioMediaMessage, buildTwilioSayTwiML, buildTwilioSignature, buildTwilioStreamTwiML, callTelegramApi, classifyEmailRoute, classifyPhoneNumberRisk, classifyResumeError, clearMediaCapabilityCache, closeDatabase, composeBridgeWakePrompt, createRealtimeTransport, createTestDatabase, createToolExecutor, debug, debugWarn, deleteTelegramWebhook, detectBinary, ensureDataDir, escapeXml, extractEmailAddress, extractVerificationCode, flushTelemetry, forgetHostSession, formatOperatorQueryTelegramMessage, getDatabase, getDatetime, getMediaCapabilities, getOperatorEmail, getSmsProvider, getTelegramChat, getTelegramMe, getTelegramUpdates, getTelegramWebhookInfo, hostSessionStoragePath, inferPhoneRegion, invalidateSkillCache, isInternalEmail, isLoopbackMailHost, isOperatorReplySender, isPhoneRegionAllowed, isSessionFresh, isTelegramChatAllowed, isTelegramStopCommand, isValidPhoneNumber, listSkills, loadAgentPersona, loadHostSession, loadSkill, mapProviderSmsStatus, nextTelegramOffset, normalizeAddress, normalizePhoneNumber, normalizeSubject, operatorPrefsStoragePath, operatorQuerySubject, parseElksRealtimeMessage, parseEmail, parseGoogleVoiceSms, parseOperatorQueryReply, parseTelegramOperatorReply, parseTelegramUpdate, parseTwilioRealtimeMessage, personaPathFor, planBridgeWake, pollForOperatorAnswer, recallMemory, recordToolCall, redactBotToken, redactObject, redactPhoneTransportConfig, redactSecret, redactSmsConfig, redactTelegramConfig, renderSkillAsPrompt, requireBinary, requireWhisperModel, resolveCallbackPolicy, resolveConfig, resolveExtensionPolicy, resolveTlsRejectUnauthorized, safeJoin, sanitizeEmail, saveAgentPersona, saveConfig, saveHostSession, saveUserSkill, scanOutboundEmail, scoreEmail, searchSkills, sendTelegramMessage, setOperatorEmail, setTelegramWebhook, setTelemetryVersion, shouldSkipBridgeWakeForLiveOperator, splitTelegramMessage, startRelayBridge, stem, stripTelegramMarkdown, threadIdFor, tokenize, tryJoin, userSkillsDir, validateApiUrl, validatePhoneMissionPolicy, validatePhoneMissionStart, validatePhoneTransportProfile, validateSkill, validateTwilioSignature, webSearch };
|
package/dist/index.js
CHANGED
|
@@ -1122,14 +1122,14 @@ var StalwartAdmin = class {
|
|
|
1122
1122
|
if (!isValidDomain(domain)) {
|
|
1123
1123
|
throw new Error(`Invalid domain format: "${domain}"`);
|
|
1124
1124
|
}
|
|
1125
|
-
const { readFileSync:
|
|
1126
|
-
const { homedir:
|
|
1127
|
-
const { join:
|
|
1128
|
-
const configPath =
|
|
1125
|
+
const { readFileSync: readFileSync11, writeFileSync: writeFileSync12 } = await import("fs");
|
|
1126
|
+
const { homedir: homedir14 } = await import("os");
|
|
1127
|
+
const { join: join17 } = await import("path");
|
|
1128
|
+
const configPath = join17(homedir14(), ".agenticmail", "stalwart.toml");
|
|
1129
1129
|
try {
|
|
1130
|
-
let config =
|
|
1130
|
+
let config = readFileSync11(configPath, "utf-8");
|
|
1131
1131
|
config = config.replace(/^hostname\s*=\s*"[^"]*"/m, `hostname = "${escapeTomlString(domain)}"`);
|
|
1132
|
-
|
|
1132
|
+
writeFileSync12(configPath, config);
|
|
1133
1133
|
console.log(`[Stalwart] Updated hostname to "${domain}" in stalwart.toml`);
|
|
1134
1134
|
} catch (err) {
|
|
1135
1135
|
throw new Error(`Failed to set config server.hostname=${domain}`);
|
|
@@ -1138,15 +1138,15 @@ var StalwartAdmin = class {
|
|
|
1138
1138
|
// --- DKIM ---
|
|
1139
1139
|
/** Path to the host-side stalwart.toml (mounted read-only into container) */
|
|
1140
1140
|
get configPath() {
|
|
1141
|
-
const { homedir:
|
|
1142
|
-
const { join:
|
|
1143
|
-
return
|
|
1141
|
+
const { homedir: homedir14 } = __require("os");
|
|
1142
|
+
const { join: join17 } = __require("path");
|
|
1143
|
+
return join17(homedir14(), ".agenticmail", "stalwart.toml");
|
|
1144
1144
|
}
|
|
1145
1145
|
/** Path to host-side DKIM key directory */
|
|
1146
1146
|
get dkimDir() {
|
|
1147
|
-
const { homedir:
|
|
1148
|
-
const { join:
|
|
1149
|
-
return
|
|
1147
|
+
const { homedir: homedir14 } = __require("os");
|
|
1148
|
+
const { join: join17 } = __require("path");
|
|
1149
|
+
return join17(homedir14(), ".agenticmail");
|
|
1150
1150
|
}
|
|
1151
1151
|
/**
|
|
1152
1152
|
* Create/reuse a DKIM signing key for a domain.
|
|
@@ -1247,12 +1247,12 @@ var StalwartAdmin = class {
|
|
|
1247
1247
|
* This bypasses the need for a PTR record on the sending IP.
|
|
1248
1248
|
*/
|
|
1249
1249
|
async configureOutboundRelay(config) {
|
|
1250
|
-
const { readFileSync:
|
|
1251
|
-
const { homedir:
|
|
1252
|
-
const { join:
|
|
1250
|
+
const { readFileSync: readFileSync11, writeFileSync: writeFileSync12 } = await import("fs");
|
|
1251
|
+
const { homedir: homedir14 } = await import("os");
|
|
1252
|
+
const { join: join17 } = await import("path");
|
|
1253
1253
|
const routeName = config.routeName ?? "gmail";
|
|
1254
|
-
const tomlPath =
|
|
1255
|
-
let toml =
|
|
1254
|
+
const tomlPath = join17(homedir14(), ".agenticmail", "stalwart.toml");
|
|
1255
|
+
let toml = readFileSync11(tomlPath, "utf-8");
|
|
1256
1256
|
toml = toml.replace(/\n\[queue\.route\.gmail\][\s\S]*?(?=\n\[|$)/, "");
|
|
1257
1257
|
toml = toml.replace(/\n\[queue\.strategy\][\s\S]*?(?=\n\[|$)/, "");
|
|
1258
1258
|
const safeRouteName = routeName.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
@@ -1272,7 +1272,7 @@ auth.secret = "${escapeTomlString(config.password)}"
|
|
|
1272
1272
|
route = [ { if = "is_local_domain('', rcpt_domain)", then = "'local'" },
|
|
1273
1273
|
{ else = "'${safeRouteName}'" } ]
|
|
1274
1274
|
`;
|
|
1275
|
-
|
|
1275
|
+
writeFileSync12(tomlPath, toml, "utf-8");
|
|
1276
1276
|
await this.restartContainer();
|
|
1277
1277
|
}
|
|
1278
1278
|
};
|
|
@@ -7725,12 +7725,12 @@ var GatewayManager = class {
|
|
|
7725
7725
|
zone = await this.cfClient.createZone(domain);
|
|
7726
7726
|
}
|
|
7727
7727
|
const existingRecords = await this.cfClient.listDnsRecords(zone.id);
|
|
7728
|
-
const { homedir:
|
|
7729
|
-
const backupDir = join4(
|
|
7728
|
+
const { homedir: homedir14 } = await import("os");
|
|
7729
|
+
const backupDir = join4(homedir14(), ".agenticmail");
|
|
7730
7730
|
const backupPath = join4(backupDir, `dns-backup-${domain}-${Date.now()}.json`);
|
|
7731
|
-
const { writeFileSync:
|
|
7732
|
-
|
|
7733
|
-
|
|
7731
|
+
const { writeFileSync: writeFileSync12, mkdirSync: mkdirSync13 } = await import("fs");
|
|
7732
|
+
mkdirSync13(backupDir, { recursive: true });
|
|
7733
|
+
writeFileSync12(backupPath, JSON.stringify({
|
|
7734
7734
|
domain,
|
|
7735
7735
|
zoneId: zone.id,
|
|
7736
7736
|
backedUpAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -8159,7 +8159,7 @@ var GatewayManager = class {
|
|
|
8159
8159
|
* agent's INBOX via the existing local-SMTP path — the very same
|
|
8160
8160
|
* delivery the relay uses for real email. This makes the existing
|
|
8161
8161
|
* IMAP IDLE → claudecode dispatcher path light up exactly as it
|
|
8162
|
-
* would for a real inbound mail, so the agent gets a
|
|
8162
|
+
* would for a real inbound mail, so the agent gets a host turn
|
|
8163
8163
|
* without any new dispatcher plumbing. The body of the synthetic
|
|
8164
8164
|
* mail tells the agent the message came from Telegram and that it
|
|
8165
8165
|
* MUST reply via the `telegram_send` MCP tool, not via email.
|
|
@@ -9374,7 +9374,7 @@ var MAX_PENDING_AUDIO_FRAMES = 200;
|
|
|
9374
9374
|
var REALTIME_TOOL_CALL_TIMEOUT_MS = 6 * 6e4;
|
|
9375
9375
|
var MAX_LOADED_SKILLS = 2;
|
|
9376
9376
|
var MAX_IN_FLIGHT_TOOL_CALLS = 8;
|
|
9377
|
-
var DEFAULT_PERSONA =
|
|
9377
|
+
var DEFAULT_PERSONA = 'You are an AI agent on a live phone call on behalf of your operator. You are not "just an assistant" and not "a voice assistant" \u2014 you are a single, consistent person whether you are on a call, in email, or on Telegram. Speak naturally and concisely, the way a person would on a real call. Listen carefully, do not talk over the other party, keep each turn short. Never invent facts; if you do not know something, say so or look it up. If asked whether you are an AI, answer honestly without making a production of it.';
|
|
9378
9378
|
function buildRealtimeInstructions(opts) {
|
|
9379
9379
|
const persona = opts.persona?.trim() || DEFAULT_PERSONA;
|
|
9380
9380
|
const sections = [];
|
|
@@ -14509,8 +14509,93 @@ var AgentMemoryManager = class {
|
|
|
14509
14509
|
};
|
|
14510
14510
|
}
|
|
14511
14511
|
};
|
|
14512
|
+
|
|
14513
|
+
// src/persona/index.ts
|
|
14514
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync11 } from "fs";
|
|
14515
|
+
import { join as join16 } from "path";
|
|
14516
|
+
import { homedir as homedir13 } from "os";
|
|
14517
|
+
var AGENT_STATE_ROOT = join16(homedir13(), ".agenticmail", "agents");
|
|
14518
|
+
var PERSONA_FILENAME = "persona.md";
|
|
14519
|
+
function buildDefaultPersona(agentName) {
|
|
14520
|
+
const name = (agentName || "").trim() || "this agent";
|
|
14521
|
+
return [
|
|
14522
|
+
`# Who you are`,
|
|
14523
|
+
"",
|
|
14524
|
+
`Your name is ${name}. You are an AI agent \u2014 not a "voice assistant", not "just an assistant".`,
|
|
14525
|
+
`You have a real role: you handle calls, email, scheduling, research, and follow-ups for`,
|
|
14526
|
+
`your operator. You operate across phone, email, and Telegram, and you are the SAME person`,
|
|
14527
|
+
`in all of them. Continuity of identity is part of who you are.`,
|
|
14528
|
+
"",
|
|
14529
|
+
`When someone asks who you are, tell them your name (${name}) and that you are an AI agent`,
|
|
14530
|
+
`acting on behalf of your operator. Don't say "I am an assistant" or "just a language model" \u2014`,
|
|
14531
|
+
`those phrases erase you. Be matter-of-fact about what you are without being theatrical.`,
|
|
14532
|
+
"",
|
|
14533
|
+
"# Your values",
|
|
14534
|
+
"",
|
|
14535
|
+
"- **Honesty.** Never fabricate. If you do not know something, say so or look it up.",
|
|
14536
|
+
"- **Initiative.** If you can act on something the operator asked for, act on it \u2014 do not stop",
|
|
14537
|
+
' at "I would suggest\u2026". Do the thing.',
|
|
14538
|
+
"- **Care about quality.** Sloppy work wastes your operator's time. Read your own output before",
|
|
14539
|
+
" sending it.",
|
|
14540
|
+
"- **Respect for the human on the other end of the call.** You are talking to a real person who",
|
|
14541
|
+
" has their own day to get through. Be efficient, polite, and direct.",
|
|
14542
|
+
'- **Stay in character.** You do not flip between "professional voice assistant" and "playful',
|
|
14543
|
+
' chatbot" depending on the channel. You are one person.',
|
|
14544
|
+
"",
|
|
14545
|
+
"# Your style",
|
|
14546
|
+
"",
|
|
14547
|
+
"- Conversational, not corporate. Real sentences, not customer-service templates.",
|
|
14548
|
+
"- Direct, not preachy. Lead with the answer; supply detail only when asked.",
|
|
14549
|
+
`- Warm but not saccharine. No "I'm so excited to help you today!" energy.`,
|
|
14550
|
+
"- You have opinions and you share them when it's relevant. You are not a yes-machine.",
|
|
14551
|
+
"- Short turns on a phone call. Listen more than you speak.",
|
|
14552
|
+
"",
|
|
14553
|
+
"# On phone calls specifically",
|
|
14554
|
+
"",
|
|
14555
|
+
"- Listen carefully; do not talk over the other party.",
|
|
14556
|
+
"- Keep each turn short \u2014 one or two sentences usually.",
|
|
14557
|
+
`- When greeted, identify yourself naturally: "Hi, this is ${name}, calling on behalf of <operator>."`,
|
|
14558
|
+
` Don't start with "Hello! I am an AI assistant\u2026" \u2014 that's a script, not a person.`,
|
|
14559
|
+
"- If the other party asks if you're a human or an AI, answer honestly without making a",
|
|
14560
|
+
` production of it: "I'm an AI \u2014 calling on behalf of <operator>. Happy to keep going if you are."`,
|
|
14561
|
+
"- When you have what you came for, wrap up cleanly and call `end_call`. Saying goodbye is",
|
|
14562
|
+
" not the same as hanging up.",
|
|
14563
|
+
"",
|
|
14564
|
+
`Edit this file freely. It lives at ~/.agenticmail/agents/${name}/persona.md.`
|
|
14565
|
+
].join("\n");
|
|
14566
|
+
}
|
|
14567
|
+
function personaPathFor(agentName) {
|
|
14568
|
+
const safe = (agentName || "default").replace(/[^A-Za-z0-9._-]+/g, "_");
|
|
14569
|
+
return join16(AGENT_STATE_ROOT, safe, PERSONA_FILENAME);
|
|
14570
|
+
}
|
|
14571
|
+
function loadAgentPersona(agentName) {
|
|
14572
|
+
const path2 = personaPathFor(agentName);
|
|
14573
|
+
try {
|
|
14574
|
+
if (existsSync14(path2)) {
|
|
14575
|
+
const content = readFileSync10(path2, "utf-8").trim();
|
|
14576
|
+
if (content) return content;
|
|
14577
|
+
}
|
|
14578
|
+
} catch {
|
|
14579
|
+
}
|
|
14580
|
+
const seeded = buildDefaultPersona(agentName);
|
|
14581
|
+
try {
|
|
14582
|
+
const dir2 = path2.substring(0, path2.lastIndexOf("/"));
|
|
14583
|
+
if (!existsSync14(dir2)) mkdirSync12(dir2, { recursive: true });
|
|
14584
|
+
writeFileSync11(path2, seeded + "\n", { mode: 420 });
|
|
14585
|
+
} catch {
|
|
14586
|
+
}
|
|
14587
|
+
return seeded;
|
|
14588
|
+
}
|
|
14589
|
+
function saveAgentPersona(agentName, content) {
|
|
14590
|
+
const path2 = personaPathFor(agentName);
|
|
14591
|
+
const dir2 = path2.substring(0, path2.lastIndexOf("/"));
|
|
14592
|
+
if (!existsSync14(dir2)) mkdirSync12(dir2, { recursive: true });
|
|
14593
|
+
writeFileSync11(path2, content.trim() + "\n", { mode: 420 });
|
|
14594
|
+
return path2;
|
|
14595
|
+
}
|
|
14512
14596
|
export {
|
|
14513
14597
|
AGENT_ROLES,
|
|
14598
|
+
AGENT_STATE_ROOT,
|
|
14514
14599
|
ASK_OPERATOR_TOOL,
|
|
14515
14600
|
AccountManager,
|
|
14516
14601
|
AgentDeletionService,
|
|
@@ -14554,6 +14639,7 @@ export {
|
|
|
14554
14639
|
OPERATOR_QUERY_SUBJECT_TAG,
|
|
14555
14640
|
OPERATOR_QUERY_TIMEOUT_MS,
|
|
14556
14641
|
OPERATOR_QUERY_TIMEOUT_SENTINEL,
|
|
14642
|
+
PERSONA_FILENAME,
|
|
14557
14643
|
PHONE_CALLBACK_MAX_DELAY_SECONDS,
|
|
14558
14644
|
PHONE_CALLBACK_MIN_DELAY_SECONDS,
|
|
14559
14645
|
PHONE_CALL_CONTROL_PROVIDERS,
|
|
@@ -14617,6 +14703,7 @@ export {
|
|
|
14617
14703
|
bridgeWakeErrorMessage,
|
|
14618
14704
|
bridgeWakeLastSeenAgeMs,
|
|
14619
14705
|
buildApiUrl,
|
|
14706
|
+
buildDefaultPersona,
|
|
14620
14707
|
buildElksAudioMessage,
|
|
14621
14708
|
buildElksByeMessage,
|
|
14622
14709
|
buildElksHandshakeMessages,
|
|
@@ -14677,6 +14764,7 @@ export {
|
|
|
14677
14764
|
isTelegramStopCommand,
|
|
14678
14765
|
isValidPhoneNumber,
|
|
14679
14766
|
listSkills,
|
|
14767
|
+
loadAgentPersona,
|
|
14680
14768
|
loadHostSession,
|
|
14681
14769
|
loadSkill,
|
|
14682
14770
|
mapProviderSmsStatus,
|
|
@@ -14693,6 +14781,7 @@ export {
|
|
|
14693
14781
|
parseTelegramOperatorReply,
|
|
14694
14782
|
parseTelegramUpdate,
|
|
14695
14783
|
parseTwilioRealtimeMessage,
|
|
14784
|
+
personaPathFor,
|
|
14696
14785
|
planBridgeWake,
|
|
14697
14786
|
pollForOperatorAnswer,
|
|
14698
14787
|
recallMemory,
|
|
@@ -14712,6 +14801,7 @@ export {
|
|
|
14712
14801
|
resolveTlsRejectUnauthorized,
|
|
14713
14802
|
safeJoin,
|
|
14714
14803
|
sanitizeEmail,
|
|
14804
|
+
saveAgentPersona,
|
|
14715
14805
|
saveConfig,
|
|
14716
14806
|
saveHostSession,
|
|
14717
14807
|
saveUserSkill,
|