@agentcomms/whatsapp 0.12.1 → 0.12.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/cli.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as
|
|
2
|
+
import { $ as paint, A as CommsError, B as colorEnabled, C as checkStorePath, F as approvalsOf, G as gatedChangeAtTerminal, H as commandText, I as approveChangeAtTerminal, J as isCommsError, K as inlineCommand, L as canPrompt, M as absoluteSearchPath, N as agentMarker, O as CHANNELS, P as approvalKind, Q as openCore, R as channelManifest, S as storeIdentity, T as expandSource, U as escapeForDisplay, V as commandPathOf, W as exemptFromUpdateGate, X as nameAvailable, Y as lookupName, Z as nameShapeProblem, _ as chatRefOf, a as listChats, at as shellCommand, b as requireAccount, c as Presenter, ct as updateGateAtTerminal, d as draftMessage, dt as withFileLock, et as renderInstall, f as Visibility, ft as writeResult, g as requireSupportedNode, h as WhatsAppIndex, i as CHAT_KINDS, it as serverPruneChange, j as EXIT_CODES, k as CHANNEL_SERVERS, l as innerText, m as WhatsAppContext, n as whatsappStatus, nt as runCommand, o as readChat, p as listKey, pt as VERSION, q as installExitStatus, r as probeStore, rt as serverInstallChange, s as searchMessages, st as truncateDisplay, t as syncAccount, tt as renderPrune, ut as windowsSystemProgram, v as PLATFORM, w as defaultStorePath, x as requireNamedConfig, y as newWhatsAppAccount, z as childEnvironment } from "./sync-DJlsr6xq.mjs";
|
|
3
3
|
import { rm } from "node:fs/promises";
|
|
4
4
|
import path, { delimiter, join } from "node:path";
|
|
5
|
+
import { stripVTControlCharacters } from "node:util";
|
|
5
6
|
import fs, { accessSync, constants as constants$1 } from "node:fs";
|
|
6
7
|
import childProcess, { spawn } from "node:child_process";
|
|
7
|
-
import { stripVTControlCharacters } from "node:util";
|
|
8
8
|
import process$1 from "node:process";
|
|
9
9
|
import { EventEmitter } from "node:events";
|
|
10
10
|
//#region ../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/error.js
|
|
@@ -2994,12 +2994,17 @@ const WHATSAPP_MCP = {
|
|
|
2994
2994
|
function refuseAnAgent(context, command, what) {
|
|
2995
2995
|
const marker = agentMarker(context.env);
|
|
2996
2996
|
if (marker !== null || context.surface !== "cli") throw new CommsError("LOOSENING_REFUSED", `only a person ${what}`, {
|
|
2997
|
-
hint: `Ask the person to run
|
|
2997
|
+
hint: `Ask the person to run ${inlineCommand(command)} in their own terminal.`,
|
|
2998
2998
|
...marker === null ? {} : { details: { marker } }
|
|
2999
2999
|
});
|
|
3000
3000
|
}
|
|
3001
3001
|
async function addAccount(context, request) {
|
|
3002
|
-
refuseAnAgent(context,
|
|
3002
|
+
refuseAnAgent(context, shellCommand([
|
|
3003
|
+
"agent-whatsapp",
|
|
3004
|
+
"add",
|
|
3005
|
+
request.name,
|
|
3006
|
+
...request.source === void 0 ? [] : ["--source", request.source]
|
|
3007
|
+
], context.platform), "chooses which WhatsApp store an agent may read");
|
|
3003
3008
|
const problem = nameShapeProblem(request.name, PLATFORM);
|
|
3004
3009
|
if (problem) throw new CommsError("USAGE", problem);
|
|
3005
3010
|
const isDefault = request.source === void 0;
|
|
@@ -3013,7 +3018,11 @@ async function addAccount(context, request) {
|
|
|
3013
3018
|
const refuseTaken = (config) => {
|
|
3014
3019
|
requireNamedConfig(config);
|
|
3015
3020
|
const free = nameAvailable(config, "account", request.name, PLATFORM);
|
|
3016
|
-
if (!free.ok) throw lookupName(config, "account", request.name)?.platform === "whatsapp" ? new CommsError("USAGE", `"${request.name}" is already added`, { hint: `Remove it first with
|
|
3021
|
+
if (!free.ok) throw lookupName(config, "account", request.name)?.platform === "whatsapp" ? new CommsError("USAGE", `"${request.name}" is already added`, { hint: `Remove it first with ${inlineCommand(shellCommand([
|
|
3022
|
+
"agent-whatsapp",
|
|
3023
|
+
"remove",
|
|
3024
|
+
request.name
|
|
3025
|
+
], context.platform))} to point it at another store.` }) : free.error;
|
|
3017
3026
|
for (const [name, other] of Object.entries(config.accounts)) {
|
|
3018
3027
|
if (other.platform !== "whatsapp") continue;
|
|
3019
3028
|
if (context.storeOf(other).path === path || other.workspace === identity.workspace) throw new CommsError("USAGE", `that store is already added, as "${name}"`, { hint: "One name per message store." });
|
|
@@ -3043,7 +3052,12 @@ async function addAccount(context, request) {
|
|
|
3043
3052
|
default: isDefault,
|
|
3044
3053
|
id: account.workspace
|
|
3045
3054
|
},
|
|
3046
|
-
next:
|
|
3055
|
+
next: commandText(shellCommand([
|
|
3056
|
+
"agent-whatsapp",
|
|
3057
|
+
"sync",
|
|
3058
|
+
"--account",
|
|
3059
|
+
request.name
|
|
3060
|
+
], context.platform))
|
|
3047
3061
|
};
|
|
3048
3062
|
}
|
|
3049
3063
|
/**
|
|
@@ -3052,8 +3066,12 @@ async function addAccount(context, request) {
|
|
|
3052
3066
|
*/
|
|
3053
3067
|
const REMOVE_WAIT_MS = 6e4;
|
|
3054
3068
|
async function removeAccount(context, request) {
|
|
3055
|
-
refuseAnAgent(context,
|
|
3056
|
-
|
|
3069
|
+
refuseAnAgent(context, shellCommand([
|
|
3070
|
+
"agent-whatsapp",
|
|
3071
|
+
"remove",
|
|
3072
|
+
request.name
|
|
3073
|
+
], context.platform), "removes a WhatsApp account");
|
|
3074
|
+
const { account } = requireAccount(await context.config(), request.name, context.platform);
|
|
3057
3075
|
await withFileLock(context.syncLock(account), async () => {
|
|
3058
3076
|
await context.core.config.update((config) => {
|
|
3059
3077
|
if (lookupName(config, "account", request.name)?.id !== account.id) throw new CommsError("TRANSIENT", `"${request.name}" changed while it was being removed`, { hint: "Nothing was removed. Run it again." });
|
|
@@ -3097,7 +3115,7 @@ function effectOf(lists) {
|
|
|
3097
3115
|
async function named(context, name, account, chatId) {
|
|
3098
3116
|
let index;
|
|
3099
3117
|
try {
|
|
3100
|
-
index = await WhatsAppIndex.open(context.accountDir(account), name, new Visibility(void 0));
|
|
3118
|
+
index = await WhatsAppIndex.open(context.accountDir(account), name, new Visibility(void 0), context.platform);
|
|
3101
3119
|
} catch (error) {
|
|
3102
3120
|
if (!isCommsError(error) || error.details?.reason !== "NOT_SYNCED") throw error;
|
|
3103
3121
|
return {
|
|
@@ -3118,7 +3136,12 @@ async function named(context, name, account, chatId) {
|
|
|
3118
3136
|
}
|
|
3119
3137
|
/** The one path every list change takes: the person check first, before any input is read. */
|
|
3120
3138
|
async function change(context, command, request, next) {
|
|
3121
|
-
refuseAnAgent(context,
|
|
3139
|
+
refuseAnAgent(context, shellCommand([
|
|
3140
|
+
"agent-whatsapp",
|
|
3141
|
+
command,
|
|
3142
|
+
...request.chat === void 0 ? [] : [request.chat],
|
|
3143
|
+
...request.account === void 0 ? [] : ["--account", request.account]
|
|
3144
|
+
], context.platform), "changes which chats an agent may see");
|
|
3122
3145
|
const chatId = request.chat === void 0 ? void 0 : chatRefOf(request.chat, { international: true }).id;
|
|
3123
3146
|
const { name, account } = await context.account(request.account);
|
|
3124
3147
|
const { before, after } = await context.lists.update(account.id, (lists) => next(lists, chatId));
|
|
@@ -3128,7 +3151,12 @@ async function change(context, command, request, next) {
|
|
|
3128
3151
|
deny: [...after.deny],
|
|
3129
3152
|
changed: JSON.stringify(before) !== JSON.stringify(after),
|
|
3130
3153
|
effect: effectOf(after),
|
|
3131
|
-
next:
|
|
3154
|
+
next: commandText(shellCommand([
|
|
3155
|
+
"agent-whatsapp",
|
|
3156
|
+
"sync",
|
|
3157
|
+
"--account",
|
|
3158
|
+
name
|
|
3159
|
+
], context.platform)),
|
|
3132
3160
|
...chatId === void 0 ? {} : await named(context, name, account, chatId)
|
|
3133
3161
|
};
|
|
3134
3162
|
}
|
|
@@ -3215,7 +3243,7 @@ function renderAdded(result, color) {
|
|
|
3215
3243
|
function renderRemoved(result, color) {
|
|
3216
3244
|
return `${paint(color, "green", "Removed")} ${result.account}, and its local index. WhatsApp's own store was not touched.`;
|
|
3217
3245
|
}
|
|
3218
|
-
function renderStatus(result, color) {
|
|
3246
|
+
function renderStatus(result, color, platform = process.platform) {
|
|
3219
3247
|
const lines = [];
|
|
3220
3248
|
if (result.accounts.length === 0) lines.push(`No WhatsApp account yet. ${result.setup ?? ""}`);
|
|
3221
3249
|
for (const account of result.accounts) {
|
|
@@ -3229,7 +3257,12 @@ function renderStatus(result, color) {
|
|
|
3229
3257
|
lines.push(` index ${account.index.chats} chats, ${account.index.messages} messages, ${account.index.media} with media, ${account.index.statusChats} status-update chat(s) · synced ${account.index.indexedAt}`);
|
|
3230
3258
|
if (account.index.unattributedStatus > 0) lines.push(` ${unattributed(account.index.unattributedStatus)}`);
|
|
3231
3259
|
for (const entry of account.index.degraded) lines.push(paint(color, "dim", ` without ${entry.part}: ${entry.costs}`));
|
|
3232
|
-
} else lines.push(` index not synced yet —
|
|
3260
|
+
} else lines.push(` index not synced yet — ${commandText(shellCommand([
|
|
3261
|
+
"agent-whatsapp",
|
|
3262
|
+
"sync",
|
|
3263
|
+
"--account",
|
|
3264
|
+
account.account
|
|
3265
|
+
], platform))}`);
|
|
3233
3266
|
}
|
|
3234
3267
|
lines.push("", paint(color, "dim", `Reads: ${result.reads}.`), paint(color, "dim", `Sends: ${result.sends}.`));
|
|
3235
3268
|
return lines.join("\n");
|
|
@@ -3338,6 +3371,7 @@ async function run(argv, deps = {}) {
|
|
|
3338
3371
|
stdin: process.stdin
|
|
3339
3372
|
};
|
|
3340
3373
|
const env = deps.env ?? process.env;
|
|
3374
|
+
const platform = deps.platform ?? process.platform;
|
|
3341
3375
|
const open = deps.open ?? openLink;
|
|
3342
3376
|
const program = new Command();
|
|
3343
3377
|
let exitCode = 0;
|
|
@@ -3365,7 +3399,8 @@ a macOS dialog may be waiting) · 77 permission needed (macOS privacy) · 78 con
|
|
|
3365
3399
|
const options = program.opts();
|
|
3366
3400
|
return {
|
|
3367
3401
|
json: Boolean(options.json),
|
|
3368
|
-
color: colorEnabled(env, streams.stdout, options.color)
|
|
3402
|
+
color: colorEnabled(env, streams.stdout, options.color),
|
|
3403
|
+
platform
|
|
3369
3404
|
};
|
|
3370
3405
|
};
|
|
3371
3406
|
/**
|
|
@@ -3451,7 +3486,7 @@ a macOS dialog may be waiting) · 77 permission needed (macOS privacy) · 78 con
|
|
|
3451
3486
|
account: flags.account === void 0 ? void 0 : String(flags.account),
|
|
3452
3487
|
check: flags.check !== false
|
|
3453
3488
|
});
|
|
3454
|
-
writeResult(result, options, () => renderStatus(result, options.color), streams);
|
|
3489
|
+
writeResult(result, options, () => renderStatus(result, options.color, context.platform), streams);
|
|
3455
3490
|
}));
|
|
3456
3491
|
accountOption(program.command("sync")).description("copy WhatsApp's store privately, check it, and rebuild the local index from the copy").action(act(async (context, options, flags) => {
|
|
3457
3492
|
const result = await syncAccount(context, { account: String(flags.account) });
|
|
@@ -3509,16 +3544,25 @@ a macOS dialog may be waiting) · 77 permission needed (macOS privacy) · 78 con
|
|
|
3509
3544
|
program.command("approve <approvalId>").description("approve a change at this terminal — registering or pruning this server — by reading it and typing the code back; WhatsApp never sends, so there is no message to approve").action(act(async (context, options, approvalId) => {
|
|
3510
3545
|
const marker = agentMarker(env);
|
|
3511
3546
|
if (marker) throw new CommsError("APPROVAL_REQUIRED", "only a person can approve a change, not an agent", {
|
|
3512
|
-
hint: `Ask the person to run
|
|
3547
|
+
hint: `Ask the person to run ${inlineCommand(shellCommand([
|
|
3548
|
+
"agent-whatsapp",
|
|
3549
|
+
"approve",
|
|
3550
|
+
approvalId
|
|
3551
|
+
], context.platform))} in their own terminal.`,
|
|
3513
3552
|
details: { marker }
|
|
3514
3553
|
});
|
|
3515
|
-
if (!canPrompt(env, streams, { json: options.json })) throw new CommsError("APPROVAL_REQUIRED", "approving a change needs an interactive terminal", { hint: `Run
|
|
3554
|
+
if (!canPrompt(env, streams, { json: options.json })) throw new CommsError("APPROVAL_REQUIRED", "approving a change needs an interactive terminal", { hint: `Run ${inlineCommand(shellCommand([
|
|
3555
|
+
"agent-whatsapp",
|
|
3556
|
+
"approve",
|
|
3557
|
+
approvalId
|
|
3558
|
+
], context.platform))} directly in a terminal.` });
|
|
3516
3559
|
const pending = await context.core.approvals.get(approvalId);
|
|
3517
3560
|
if (!pending) throw new CommsError("NOT_FOUND", `no approval ${approvalId}`, { hint: "It may have expired, been used, or been cancelled. Prepare the change again." });
|
|
3518
3561
|
if (approvalKind(pending) !== "change") throw new CommsError("USAGE", `approval ${approvalId} is for a send, and WhatsApp never sends`, { hint: `Approve it with the command that prepared it — ${sendApproveCommands()} — not this one.` });
|
|
3519
3562
|
const outcome = await approveChangeAtTerminal(context.core, approvalId, env, {
|
|
3520
3563
|
json: options.json,
|
|
3521
|
-
color: options.color
|
|
3564
|
+
color: options.color,
|
|
3565
|
+
platform: context.platform
|
|
3522
3566
|
}, streams);
|
|
3523
3567
|
streams.stdout.write(outcome.state === "approved" ? "Approved. This command approves; the change is applied by the command that prepared it.\n" : "Cancelled. Nothing was changed.\n");
|
|
3524
3568
|
}));
|
|
@@ -3534,9 +3578,9 @@ a macOS dialog may be waiting) · 77 permission needed (macOS privacy) · 78 con
|
|
|
3534
3578
|
ran = true;
|
|
3535
3579
|
exitCode = await runCommand(output(), async () => {
|
|
3536
3580
|
requireSupportedNode();
|
|
3537
|
-
|
|
3538
|
-
await startWhatsAppStdioServer({
|
|
3581
|
+
await (deps.startMcp ?? (await import("./stdio-entry-CAM7LpPv.mjs")).startWhatsAppStdioServer)({
|
|
3539
3582
|
env,
|
|
3583
|
+
platform,
|
|
3540
3584
|
...flags.account ? { account: String(flags.account) } : {}
|
|
3541
3585
|
});
|
|
3542
3586
|
}, streams);
|
|
@@ -3559,7 +3603,7 @@ a macOS dialog may be waiting) · 77 permission needed (macOS privacy) · 78 con
|
|
|
3559
3603
|
const launcher = flags.launcher;
|
|
3560
3604
|
const name = flags.name;
|
|
3561
3605
|
await context.migration();
|
|
3562
|
-
const again = [
|
|
3606
|
+
const again = shellCommand([
|
|
3563
3607
|
"agent-whatsapp",
|
|
3564
3608
|
"mcp",
|
|
3565
3609
|
"install",
|
|
@@ -3570,7 +3614,7 @@ a macOS dialog may be waiting) · 77 permission needed (macOS privacy) · 78 con
|
|
|
3570
3614
|
...launcher !== void 0 ? ["--launcher", launcher] : [],
|
|
3571
3615
|
...flags.verify === false ? ["--no-verify"] : [],
|
|
3572
3616
|
...flags.force === true ? ["--force"] : []
|
|
3573
|
-
].
|
|
3617
|
+
], context.platform);
|
|
3574
3618
|
const result = await changeAt(context, serverInstallChange(context.core, env, {
|
|
3575
3619
|
channel: "whatsapp",
|
|
3576
3620
|
client: flags.client,
|
|
@@ -3590,7 +3634,12 @@ a macOS dialog may be waiting) · 77 permission needed (macOS privacy) · 78 con
|
|
|
3590
3634
|
channel: "whatsapp",
|
|
3591
3635
|
dryRun: flags.dryRun === true,
|
|
3592
3636
|
includePrinted: flags.includePrinted === true
|
|
3593
|
-
}, WHATSAPP_MCP), flags,
|
|
3637
|
+
}, WHATSAPP_MCP), flags, shellCommand([
|
|
3638
|
+
"agent-whatsapp",
|
|
3639
|
+
"mcp",
|
|
3640
|
+
"prune",
|
|
3641
|
+
...flags.includePrinted === true ? ["--include-printed"] : []
|
|
3642
|
+
], context.platform));
|
|
3594
3643
|
writeResult(result, output(), () => renderPrune(result, options.color), streams);
|
|
3595
3644
|
}));
|
|
3596
3645
|
try {
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as createWhatsAppMcpServer } from "./server-
|
|
1
|
+
import { pt as VERSION, u as composeDraft } from "./sync-DJlsr6xq.mjs";
|
|
2
|
+
import { t as createWhatsAppMcpServer } from "./server-B1EmZ6FZ.mjs";
|
|
3
3
|
//#region src/index.ts
|
|
4
4
|
/**
|
|
5
5
|
* The library entry of `@agentcomms/whatsapp`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D as strictToolArguments, E as UNTRUSTED_NOTICE, a as listChats, d as draftMessage, i as CHAT_KINDS, m as WhatsAppContext, n as whatsappStatus, o as readChat, ot as
|
|
1
|
+
import { D as strictToolArguments, E as UNTRUSTED_NOTICE, a as listChats, d as draftMessage, i as CHAT_KINDS, lt as updateToolGate, m as WhatsAppContext, n as whatsappStatus, o as readChat, ot as toCommsError, pt as VERSION, s as searchMessages, t as syncAccount } from "./sync-DJlsr6xq.mjs";
|
|
2
2
|
import { c as boolean, h as number, x as string } from "./schemas-DiGKNDNq.mjs";
|
|
3
3
|
import { t as McpServer } from "./mcp-DXXb3Vv3-Co5BzjYe.mjs";
|
|
4
4
|
//#region src/mcp/server.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createWhatsAppMcpServer } from "./server-
|
|
1
|
+
import { t as createWhatsAppMcpServer } from "./server-B1EmZ6FZ.mjs";
|
|
2
2
|
//#region src/mcp/stdio-entry.ts
|
|
3
3
|
/**
|
|
4
4
|
* Starting the stdio server. On stdio, stdout is the protocol, so the console is redirected to stderr first — the
|