@agentcomms/whatsapp 0.23.0 → 0.25.0

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,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { $ as gatedChangeAtTerminal, A as requireAccount, B as PATH_OPTIONS, Ct as CALLER, F as expandSource, G as approveChangeAtTerminal, H as absoluteSearchPath, J as cliHandoffs, K as canPrompt, L as CHANNEL_SERVERS, M as storeIdentity, N as checkStorePath, O as PLATFORM, P as defaultStorePath, Q as exemptFromUpdateNotice, R as CommsError, S as chatRefOf, St as writeResult, Tt as VERSION, U as agentMarker, W as approveAndWaitSentence, X as commandPathOf, Y as colorEnabled, Z as escapeForDisplay, _ as WhatsAppContext, _t as truncateDisplay, a as CHAT_KINDS, at as nameAvailable, b as requireSupportedNode, bt as windowsSystemProgram, c as searchMessages, ct as paint, dt as renderPrune, et as handoffSentence, f as draftMessage, ft as resolvePaths, ht as serverPruneChange, i as probeStore, it as lookupName, j as requireNamedConfig, k as newWhatsAppAccount, l as Presenter, lt as pathOverridesFromCliOptions, m as listKey, mt as serverInstallChange, nt as installExitStatus, o as listChats, ot as nameShapeProblem, p as Visibility, pt as runCommand, q as childEnvironment, r as whatsappStatus, rt as isCommsError, s as readChat, st as openCore, t as syncAccount, tt as handoffText, u as innerText, ut as renderInstall, v as WhatsAppIndex, vt as updateNoticeAtTerminal, xt as withFileLock, z as EXIT_CODES } from "./sync-DbKvzaLA.mjs";
2
+ import { $ as gatedChangeAtTerminal, A as requireAccount, B as PATH_OPTIONS, Ct as CALLER, F as expandSource, G as approveChangeAtTerminal, H as absoluteSearchPath, J as cliHandoffs, K as canPrompt, L as CHANNEL_SERVERS, M as storeIdentity, N as checkStorePath, O as PLATFORM, P as defaultStorePath, Q as exemptFromUpdateNotice, R as CommsError, S as chatRefOf, St as writeResult, Tt as VERSION, U as agentMarker, W as approveAndWaitSentence, X as commandPathOf, Y as colorEnabled, Z as escapeForDisplay, _ as WhatsAppContext, _t as truncateDisplay, a as CHAT_KINDS, at as nameAvailable, b as requireSupportedNode, bt as windowsSystemProgram, c as searchMessages, ct as paint, dt as renderPrune, et as handoffSentence, f as draftMessage, ft as resolvePaths, ht as serverPruneChange, i as probeStore, it as lookupName, j as requireNamedConfig, k as newWhatsAppAccount, l as Presenter, lt as pathOverridesFromCliOptions, m as listKey, mt as serverInstallChange, nt as installExitStatus, o as listChats, ot as nameShapeProblem, p as Visibility, pt as runCommand, q as childEnvironment, r as whatsappStatus, rt as isCommsError, s as readChat, st as openCore, t as syncAccount, tt as handoffText, u as innerText, ut as renderInstall, v as WhatsAppIndex, vt as updateNoticeAtTerminal, xt as withFileLock, z as EXIT_CODES } from "./sync-DEG2YdIm.mjs";
3
3
  import { rm } from "node:fs/promises";
4
4
  import path, { delimiter, join } from "node:path";
5
5
  import { stripVTControlCharacters } from "node:util";
@@ -3569,7 +3569,7 @@ a macOS dialog may be waiting) · 77 permission needed (macOS privacy) · 78 con
3569
3569
  ran = true;
3570
3570
  exitCode = await runCommand(output(), async () => {
3571
3571
  requireSupportedNode();
3572
- await (deps.startMcp ?? (await import("./stdio-entry-Du-O-1sR.mjs")).startWhatsAppStdioServer)({
3572
+ await (deps.startMcp ?? (await import("./stdio-entry-CYFb_dWj.mjs")).startWhatsAppStdioServer)({
3573
3573
  env,
3574
3574
  platform,
3575
3575
  ...deps,
package/dist/index.d.mts CHANGED
@@ -4277,7 +4277,7 @@ declare namespace external_d_exports {
4277
4277
  export { $brand, $input, $output, BRAND, CompileOptions, GlobalMeta, INVALID, Infer$1 as Infer, IssueData, JSONType, NEVER, $RefinementCtx as RefinementCtx, SafeExtendShape, Schema, TimePrecision, TypeOf, ZodAny, ZodArray, ZodBase64, ZodBase64URL, ZodBigInt, ZodBigIntFormat, ZodBoolean, ZodCIDRv4, ZodCIDRv6, ZodCUID, ZodCUID2, ZodCatch, ZodCodec, ZodCoercedBigInt, ZodCoercedBoolean, ZodCoercedDate, ZodCoercedNumber, ZodCoercedString, ZodCompileAsyncError, ZodCompileUnsupportedError, ZodCreditCard, ZodCustom, ZodCustomStringFormat, ZodDate, ZodDefault, ZodDiscriminatedUnion, ZodE164, ZodEmail, ZodEmoji, ZodEnum, ZodError, ZodErrorMap, ZodExactOptional, ZodFile, ZodFirstPartySchemaTypes, ZodFirstPartyTypeKind, ZodFlattenedError, ZodFloat32, ZodFloat64, ZodFormattedError, ZodFunction, ZodGUID, ZodIBAN, ZodIPv4, ZodIPv6, ZodISODate, ZodISODateTime, ZodISODuration, ZodISOTime, ZodInstanceOf, ZodInt, ZodInt32, ZodInt64, ZodIntersection, ZodIssue, ZodIssueCode, ZodJSONSchema, ZodJSONSchemaInternals, ZodJWT, ZodKSUID, ZodLazy, ZodLiteral, ZodMAC, ZodMap, ZodNaN, ZodNanoID, ZodNever, ZodNonOptional, ZodNull, ZodNullable, ZodNumber, ZodNumberFormat, ZodObject, ZodOptional, ZodPipe, ZodPrefault, ZodPreprocess, ZodPromise, ZodRawShape$1 as ZodRawShape, ZodReadonly, ZodRealError, ZodRecord, ZodSafeParseError, ZodSafeParseResult, ZodSafeParseSuccess, ZodSchema, ZodSet, ZodStandardSchemaWithJSON, ZodString, ZodStringFormat, ZodSuccess, ZodSymbol, ZodTemplateLiteral, ZodTransform, ZodTuple, ZodType, ZodTypeAny, ZodUInt32, ZodUInt64, ZodULID, ZodURL, ZodUUID, ZodUndefined, ZodUnion, ZodUnknown, ZodVoid, ZodXID, ZodXor, _ZodBigInt, _ZodBoolean, _ZodDate, _ZodNumber, _ZodString, _ZodType, _default, _function, any, array, base64, base64url, bigint$1 as bigint, boolean$1 as boolean, _catch as catch, check, cidrv4, cidrv6, clone, codec, coerce_d_exports as coerce, compile, config, index_d_exports$1 as core, creditCard, cuid, cuid2, currencyCode, custom, date$2 as date, decode, decodeAsync, deepPartial, describe, discriminatedUnion, e164, email, emoji, encode, encodeAsync, _endsWith as endsWith, _enum as enum, exactOptional, file, flattenError, float32, float64, formatError, fromJSONSchema, _function as function, getDiscriminatedOption, getErrorMap, globalRegistry, _gt as gt, _gte as gte, guid, hash, hex, hostname, httpUrl, iban, _includes as includes, output$1 as infer, inferFlattenedErrors, inferFormattedError, input, _instanceof as instanceof, int, int32, int64, intersection, invertCodec, ipv4, ipv6, iso_d_exports as iso, json, jwt, keyof, ksuid, lazy, _length as length, literal, index_d_exports$2 as locales, looseObject, looseRecord, _lowercase as lowercase, _lt as lt, _lte as lte, mac, map, _maxLength as maxLength, _maxSize as maxSize, memoizer, meta, _mime as mime, _minLength as minLength, _minSize as minSize, _multipleOf as multipleOf, nan, nanoid, nativeEnum, _negative as negative, never, _nonnegative as nonnegative, nonoptional, _nonpositive as nonpositive, _normalize as normalize, _null as null, nullable, nullish, number$1 as number, object, optional, output, _overwrite as overwrite, parse, parseAsync, partialRecord, pipe, _positive as positive, prefault, preprocess, prettifyError, promise, _properties as properties, _property as property, readonly, record, refine, _regex as regex, regexes_d_exports as regexes, registry, safeDecode, safeDecodeAsync, safeEncode, safeEncodeAsync, safeParse, safeParseAsync, set, setErrorMap, _size as size, _slugify as slugify, _startsWith as startsWith, strictObject, string$1 as string, stringFormat, stringbool, success, superRefine, symbol, templateLiteral, toJSONSchema, _toLowerCase as toLowerCase, _toUpperCase as toUpperCase, toZod, transform, treeifyError, _trim as trim, tuple, uint32, uint64, ulid, _undefined as undefined, union, unknown, _uppercase as uppercase, url, util_d_exports as util, uuid, uuidv4, uuidv6, uuidv7, validate, validateAsync, _void as void, withParser, xid, xor };
4278
4278
  }
4279
4279
  //#endregion
4280
- //#region ../core/dist/launcher-CD40rL4F.d.mts
4280
+ //#region ../core/dist/launcher-B8pYW7eG.d.mts
4281
4281
  interface RegisteredServer {
4282
4282
  client: string;
4283
4283
  path: string;
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { C as chatKindOf, D as text, E as numeric, R as CommsError, T as kindOf, Tt as VERSION, _ as WhatsAppContext, d as composeDraft, g as visibilityUnitKey, h as statusAuthor, m as listKey, n as withCheckedCopy, p as Visibility, w as coreDataToIso, wt as PACKAGE_NAME, x as inspectSchema, y as rebuildIndex } from "./sync-DbKvzaLA.mjs";
2
- import { t as createWhatsAppMcpServer } from "./server-CR8PrBjk.mjs";
1
+ import { C as chatKindOf, D as text, E as numeric, R as CommsError, T as kindOf, Tt as VERSION, _ as WhatsAppContext, d as composeDraft, g as visibilityUnitKey, h as statusAuthor, m as listKey, n as withCheckedCopy, p as Visibility, w as coreDataToIso, wt as PACKAGE_NAME, x as inspectSchema, y as rebuildIndex } from "./sync-DEG2YdIm.mjs";
2
+ import { t as createWhatsAppMcpServer } from "./server-DtDXnPRw.mjs";
3
3
  //#region src/source/event-reader.ts
4
4
  function rawFromMe(value) {
5
5
  const number = numeric(value);
@@ -1,4 +1,4 @@
1
- import { I as strictToolArguments, Tt as VERSION, V as UNTRUSTED_NOTICE, _ as WhatsAppContext, a as CHAT_KINDS, c as searchMessages, f as draftMessage, gt as toCommsError, o as listChats, r as whatsappStatus, s as readChat, t as syncAccount, yt as updateToolNotice } from "./sync-DbKvzaLA.mjs";
1
+ import { I as strictToolArguments, Tt as VERSION, V as UNTRUSTED_NOTICE, _ as WhatsAppContext, a as CHAT_KINDS, c as searchMessages, f as draftMessage, gt as toCommsError, o as listChats, r as whatsappStatus, s as readChat, t as syncAccount, yt as updateToolNotice } from "./sync-DEG2YdIm.mjs";
2
2
  import { c as boolean, h as number, x as string } from "./iso-USuVU_sk.mjs";
3
3
  import { t as McpServer } from "./mcp-DIH4cS6P-CIWWZQbz.mjs";
4
4
  //#region src/mcp/server.ts
@@ -1,4 +1,4 @@
1
- import { t as createWhatsAppMcpServer } from "./server-CR8PrBjk.mjs";
1
+ import { t as createWhatsAppMcpServer } from "./server-DtDXnPRw.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
@@ -11,7 +11,7 @@ import { execFile, spawn } from "node:child_process";
11
11
  //#endregion
12
12
  //#region src/version.ts
13
13
  /** The package version, read from package.json at build time. */
14
- const VERSION$2 = "0.23.0";
14
+ const VERSION$2 = "0.25.0";
15
15
  //#endregion
16
16
  //#region src/caller.ts
17
17
  /** This package's name, as its manifest has it. */
@@ -28,7 +28,7 @@ const CALLER = Object.freeze({
28
28
  packageName: PACKAGE_NAME
29
29
  });
30
30
  //#endregion
31
- //#region ../core/dist/update-check-BrR1qAfk.mjs
31
+ //#region ../core/dist/update-check-CMD_Te5S.mjs
32
32
  /**
33
33
  * Every failure a user or an agent can act on carries a specific, stable code from this registry, a message, an
34
34
  * optional one-line hint and structured `details`. The code decides the process exit status; agents and skills branch
@@ -1695,8 +1695,12 @@ function programNeedsQuotes(command) {
1695
1695
  const [program] = command.words;
1696
1696
  return command.platform === "win32" && program !== void 0 && windowsShellWord(program) !== program;
1697
1697
  }
1698
+ /**
1699
+ * One word for a POSIX shell: as it is when nothing in it is special, otherwise in single quotes. A word that starts
1700
+ * with `=` or `~` is quoted too: zsh reads `=ls` as the path of `ls`, and `~` as a home.
1701
+ */
1698
1702
  function posixShellWord(word) {
1699
- return /^[\w@%+=:,./-]+$/.test(word) ? word : `'${word.replace(/'/g, `'\\''`)}'`;
1703
+ return /^(?![=~])[\w@%+=:,./-]+$/.test(word) ? word : `'${word.replace(/'/g, `'\\''`)}'`;
1700
1704
  }
1701
1705
  /**
1702
1706
  * The word as cmd.exe, Windows PowerShell and PowerShell 7 all hand it to a program, or null when no printing of it
@@ -7153,6 +7157,24 @@ function parseConfig(text, source = "config.json") {
7153
7157
  if (!parsed.success) throw new CommsError("CONFIG", `${source} is invalid: ${describeIssues(parsed.error, naming === 1 ? 1 : 2)}`);
7154
7158
  return parsed.data;
7155
7159
  }
7160
+ /**
7161
+ * How a config write waits for the config lock: five seconds for each holder, thirty seconds in all.
7162
+ *
7163
+ * The lock is a queue. Every send prepare, claim and approval on every channel runs `ensureSendEpochConfig` first, and
7164
+ * while a legacy drain is open that is a config write or two per call, so an agent's parallel calls across several MCP
7165
+ * servers arrive at this lock together, each holding it for one read, check and fsynced rename (and the drain's, for a
7166
+ * list of the approvals too). Counted from when each waiter began, the lock's five seconds were a budget for the whole
7167
+ * line ahead: on the Windows runner a line of twelve writes gave up at the ninth, "another agent-communications process
7168
+ * is holding", while the lock was being handed on exactly as it should be. A holder there took about half a second, and
7169
+ * on Windows a rename alone may retry for one. Counted per holder, as Resend's throttle and Gmail's history caches count
7170
+ * theirs, a write gives up only on a holder that keeps the lock for the whole five seconds: the stuck lock the timeout is
7171
+ * for. The lock is polled rather than queued, so thirty seconds in all bounds the rest, and leaves room inside the minute
7172
+ * an MCP client waits for a tool call.
7173
+ */
7174
+ const CONFIG_WRITE_LOCK = {
7175
+ timeoutPerHolder: true,
7176
+ maxWaitMs: 3e4
7177
+ };
7156
7178
  var ConfigStore = class {
7157
7179
  path;
7158
7180
  #lockPath;
@@ -7173,6 +7195,10 @@ var ConfigStore = class {
7173
7195
  #namesMigrateAgain(why) {
7174
7196
  return handoffSentence(requiredHandoffs(this.#handoffs).core(["names", "migrate"]), (command) => `Run ${command} again ${why}.`, { instead: `Call comms_names_migrate again ${why}.` });
7175
7197
  }
7198
+ /** Runs `fn` holding the config lock, waited for as a write waits for it (`CONFIG_WRITE_LOCK`). */
7199
+ #withWriteLock(fn) {
7200
+ return withFileLock(this.#lockPath, fn, CONFIG_WRITE_LOCK);
7201
+ }
7176
7202
  /** The current config; an empty one when the file does not exist yet. */
7177
7203
  async load() {
7178
7204
  let key;
@@ -7199,7 +7225,7 @@ var ConfigStore = class {
7199
7225
  let committed;
7200
7226
  let result;
7201
7227
  try {
7202
- result = await withFileLock(this.#lockPath, async () => {
7228
+ result = await this.#withWriteLock(async () => {
7203
7229
  options.signal?.throwIfAborted();
7204
7230
  this.#cache = null;
7205
7231
  const current = structuredClone(await this.load());
@@ -12000,7 +12026,7 @@ function folding(platform) {
12000
12026
  return platform === "win32" ? (text) => text.toLowerCase() : (text) => text;
12001
12027
  }
12002
12028
  /** The package version, read from package.json at build time. */
12003
- const VERSION = "0.23.0";
12029
+ const VERSION = "0.25.0";
12004
12030
  /**
12005
12031
  * The command a person is told to run for one of this suite's own CLIs (design 2026-10-04, D1 and D5; CUE-403).
12006
12032
  *
@@ -15663,7 +15689,7 @@ function serverPruneChange(core, env, request, own) {
15663
15689
  };
15664
15690
  const { packageName, version } = ownProduct(request.channel, own) ?? {
15665
15691
  packageName: serverFacts(request.channel).packageName,
15666
- version: "0.23.0"
15692
+ version: "0.25.0"
15667
15693
  };
15668
15694
  const product = {
15669
15695
  packageName,
@@ -15870,8 +15896,9 @@ function updateToolNotice(options) {
15870
15896
  let running = null;
15871
15897
  let given = false;
15872
15898
  let turn = Promise.resolve();
15873
- return (tool) => {
15899
+ return (tool, args) => {
15874
15900
  if (updateCheckSwitchedOff(options.env) !== null) return Promise.resolve(null);
15901
+ if (options.quiet?.(tool, args)) return Promise.resolve(null);
15875
15902
  if (options.refresh && running === null) running = options.refresh().catch(() => void 0).finally(() => {
15876
15903
  running = null;
15877
15904
  });
@@ -16201,7 +16228,7 @@ function commandDecisionLine(core, decision, channel, platform) {
16201
16228
  }
16202
16229
  channelServer("core").packageName;
16203
16230
  //#endregion
16204
- //#region ../core/dist/tool-arguments-C2vEASTA.mjs
16231
+ //#region ../core/dist/tool-arguments-BW3WUyxT.mjs
16205
16232
  const APPLIED = Symbol.for("agentcomms.strictToolArguments");
16206
16233
  const TARGET = "draft-2020-12";
16207
16234
  /**
@@ -16244,7 +16271,7 @@ function strictToolArguments(server, refuse, notice, retired = {}) {
16244
16271
  const parsed = await schema.safeParseAsync(input ?? {});
16245
16272
  if (!parsed.success) return refuse(refusal(name, published, input, parsed.error.issues, retired[name] ?? {}));
16246
16273
  const result = await (declared ? handler(parsed.data, context) : handler(context));
16247
- const line = notice ? await notice(name).catch(() => null) : null;
16274
+ const line = notice ? await notice(name, parsed.data).catch(() => null) : null;
16248
16275
  return line === null ? result : withUpdateNotice(result, line, room);
16249
16276
  });
16250
16277
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentcomms/whatsapp",
3
- "version": "0.23.0",
3
+ "version": "0.25.0",
4
4
  "description": "WhatsApp for coding agents, read-only: list, read and search the chats WhatsApp for Mac keeps on this Mac, and draft replies as links the person sends. No network client; it never sends.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,7 +34,7 @@
34
34
  "access": "public"
35
35
  },
36
36
  "dependencies": {
37
- "@agentcomms/core": "0.23.0"
37
+ "@agentcomms/core": "0.25.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@modelcontextprotocol/client": "2.3.1",
@@ -98,5 +98,5 @@
98
98
  "typecheck": "tsc -p tsconfig.json",
99
99
  "test": "node --experimental-strip-types --disable-warning=ExperimentalWarning --test --test-timeout=600000 \"test/**/*.test.ts\""
100
100
  },
101
- "gitHead": "2431f1f1ffe5dd6dc02a1285a09fe3704b0caeb2"
101
+ "gitHead": "1aca79f8c2674add5086fe4f05a52c8fb2719657"
102
102
  }