@agentcomms/whatsapp 0.18.2 → 0.20.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 exemptFromUpdateGate, A as requireAccount, B as PATH_OPTIONS, Ct as writeResult, Et as VERSION, F as expandSource, G as approveAndWaitSentence, H as absoluteSearchPath, J as childEnvironment, K as approveChangeAtTerminal, L as CHANNEL_SERVERS, M as storeIdentity, N as checkStorePath, O as PLATFORM, P as defaultStorePath, Q as escapeForDisplay, R as CommsError, S as chatRefOf, St as withFileLock, U as agentMarker, W as approvalsOf, X as colorEnabled, Y as cliHandoffs, Z as commandPathOf, _ as WhatsAppContext, a as CHAT_KINDS, at as lookupName, b as requireSupportedNode, c as searchMessages, ct as openCore, dt as renderInstall, et as gatedChangeAtTerminal, f as draftMessage, ft as renderPrune, gt as serverPruneChange, ht as serverInstallChange, i as probeStore, it as isCommsError, j as requireNamedConfig, k as newWhatsAppAccount, l as Presenter, lt as paint, m as listKey, mt as runCommand, nt as handoffText, o as listChats, ot as nameAvailable, p as Visibility, pt as resolvePaths, q as canPrompt, r as whatsappStatus, rt as installExitStatus, s as readChat, st as nameShapeProblem, t as syncAccount, tt as handoffSentence, u as innerText, ut as pathOverridesFromCliOptions, v as WhatsAppIndex, vt as truncateDisplay, wt as CALLER, xt as windowsSystemProgram, yt as updateGateAtTerminal, z as EXIT_CODES } from "./sync-D5RWl-ZJ.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-Coys7_vB.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";
@@ -3374,8 +3374,7 @@ Getting started — a person runs these with this CLI, in a terminal:
3374
3374
 
3375
3375
  Nothing here connects to WhatsApp or any other server, and nothing here can send. Needs Node 22.16 or newer.
3376
3376
 
3377
- Exit codes: 0 ok · 1 unexpected · 10 only a person may do that, or a change needs approval · 11 an update
3378
- is out: update first, or put it off (the stop names both commands) · 64 usage
3377
+ Exit codes: 0 ok · 1 unexpected · 10 only a person may do that, or a change needs approval · 64 usage
3379
3378
  · 65 bad data (a store whose layout changed) · 66 not found · 69 unavailable · 75 temporary (retry;
3380
3379
  a macOS dialog may be waiting) · 77 permission needed (macOS privacy) · 78 configuration problem.`).exitOverride();
3381
3380
  for (const { flag } of PATH_OPTIONS) program.addOption(new Option(`${flag} <dir>`, "pin this suite directory for this run").argParser((value) => {
@@ -3421,34 +3420,22 @@ a macOS dialog may be waiting) · 77 permission needed (macOS privacy) · 78 con
3421
3420
  * start — where the result *is* the output and `--json` must still print one envelope.
3422
3421
  */
3423
3422
  let softExit = null;
3424
- let gated = null;
3425
3423
  program.hook("preAction", async (_program, command) => {
3426
3424
  const path = commandPathOf(command);
3427
- if (exemptFromUpdateGate(path, ["status"])) return;
3425
+ if (exemptFromUpdateNotice(path, ["status"])) return;
3428
3426
  const core = coreForInvocation();
3429
- let ended = null;
3430
- const code = await runCommand(output(), async () => {
3431
- ended = await updateGateAtTerminal({
3432
- core,
3433
- env,
3434
- binary: "agent-whatsapp",
3435
- channel: "whatsapp",
3436
- running: VERSION,
3437
- output: output(),
3438
- noInput: false,
3439
- streams,
3440
- approvals: approvalsOf(command)
3441
- });
3442
- }, streams);
3443
- gated = code !== 0 ? code : ended;
3427
+ await updateNoticeAtTerminal({
3428
+ core,
3429
+ env,
3430
+ channel: "whatsapp",
3431
+ running: VERSION,
3432
+ output: output(),
3433
+ streams
3434
+ });
3444
3435
  });
3445
3436
  const act = (body) => async (...args) => {
3446
3437
  ran = true;
3447
3438
  softExit = null;
3448
- if (gated !== null) {
3449
- exitCode = gated;
3450
- return;
3451
- }
3452
3439
  exitCode = await runCommand(output(), async () => {
3453
3440
  requireSupportedNode();
3454
3441
  await body(new WhatsAppContext({
@@ -3582,7 +3569,7 @@ a macOS dialog may be waiting) · 77 permission needed (macOS privacy) · 78 con
3582
3569
  ran = true;
3583
3570
  exitCode = await runCommand(output(), async () => {
3584
3571
  requireSupportedNode();
3585
- await (deps.startMcp ?? (await import("./stdio-entry-CH_b3o13.mjs")).startWhatsAppStdioServer)({
3572
+ await (deps.startMcp ?? (await import("./stdio-entry-83qlMjK3.mjs")).startWhatsAppStdioServer)({
3586
3573
  env,
3587
3574
  platform,
3588
3575
  ...deps,
package/dist/index.d.mts CHANGED
@@ -4277,7 +4277,8 @@ 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/change-flow-j65bYTxL.d.mts
4280
+ //#region ../core/dist/launcher-VgihcM7Q.d.mts
4281
+ //#endregion
4281
4282
  //#region src/config-hooks.d.ts
4282
4283
  /**
4283
4284
  * Test-only pauses inside `ConfigStore.convertToVersion3`, for the tests that prove a write racing the conversion is
@@ -4369,7 +4370,7 @@ interface ResolvedPaths {
4369
4370
  */
4370
4371
  downloadsDir: string;
4371
4372
  }
4372
- type ErrorCode = "UNEXPECTED" | "APPROVAL_REQUIRED" | "APPROVAL_PENDING" | "APPROVAL_EXPIRED" | "APPROVAL_VOID" | "SEND_OUTCOME_UNKNOWN" | "SEND_REFUSED" | "POLICY_NEVER" | "RATE_CAPPED" | "UNSENDABLE_HTML" | "LOOSENING_REFUSED" | "UPDATE_REQUIRED" | "USAGE" | "CURSOR_MISMATCH" | "BAD_DATA" | "REPLY_INVALID" | "NOT_FOUND" | "PROVIDER_UNAVAILABLE" | "SOURCE_UNAVAILABLE" | "SECRET_STORE_UNAVAILABLE" | "TRANSIENT" | "KEYCHAIN_APPROVAL_PENDING" | "LOCK_TIMEOUT" | "AUTH_REQUIRED" | "SCOPE_MISSING" | "WHATSAPP_VISIBILITY_SEAM_REQUIRED" | "CONFIG";
4373
+ type ErrorCode = "UNEXPECTED" | "APPROVAL_REQUIRED" | "APPROVAL_PENDING" | "APPROVAL_EXPIRED" | "APPROVAL_VOID" | "SEND_OUTCOME_UNKNOWN" | "SEND_REFUSED" | "POLICY_NEVER" | "RATE_CAPPED" | "UNSENDABLE_HTML" | "LOOSENING_REFUSED" | "USAGE" | "CURSOR_MISMATCH" | "BAD_DATA" | "REPLY_INVALID" | "NOT_FOUND" | "PROVIDER_UNAVAILABLE" | "SOURCE_UNAVAILABLE" | "SECRET_STORE_UNAVAILABLE" | "TRANSIENT" | "KEYCHAIN_APPROVAL_PENDING" | "LOCK_TIMEOUT" | "AUTH_REQUIRED" | "SCOPE_MISSING" | "WHATSAPP_VISIBILITY_SEAM_REQUIRED" | "CONFIG";
4373
4374
  interface CommsErrorOptions {
4374
4375
  hint?: string;
4375
4376
  details?: Record<string, unknown>;
@@ -4549,7 +4550,7 @@ type SendPolicy = "chat" | "confirm" | "never";
4549
4550
  * way to change it, and that passes no gate at all.
4550
4551
  */
4551
4552
  type ChangePolicy = "chat" | "confirm";
4552
- /** Whether this machine checks for a newer release once a day, and stops until it is updated or put off. */
4553
+ /** 0.18's switch for the daily update check: what `defaults.updates` reads from until a level is set. */
4553
4554
  type UpdateCheckSetting = "on" | "off";
4554
4555
  type StoreKind = "keychain" | "file";
4555
4556
  interface ClientConfig {
@@ -4622,6 +4623,16 @@ interface Defaults {
4622
4623
  * it is what keeps a machine from quietly falling behind a release — so it is approved like one; on applies at once.
4623
4624
  */
4624
4625
  updateCheck?: UpdateCheckSetting | undefined;
4626
+ /**
4627
+ * How this machine updates (design 2026-10-16, U2): `auto`, `every-14-days` or `never`. Absent reads from
4628
+ * `updateCheck` — `on` as `auto`, `off` as `never` — and both absent as `auto`. A word this release does not know
4629
+ * reads as `auto`, and the file stays readable: a later release may add a level.
4630
+ *
4631
+ * Moving to a level that updates less is a loosening, approved like one; moving back applies at once. Every write of
4632
+ * a level writes `updateCheck` beside it, `off` for `never` and `on` otherwise, so a release before 0.20 sharing the
4633
+ * file checks, or does not, as the person chose.
4634
+ */
4635
+ updates?: string | undefined;
4625
4636
  }
4626
4637
  /**
4627
4638
  * A connected account on a platform that is not mail: a Slack workspace, and every channel after it (design
@@ -4735,6 +4746,16 @@ interface ConfigBody {
4735
4746
  /** Superseded rotating credentials which still need conclusive per-token cleanup. */
4736
4747
  pendingRevocations?: PendingRevocation[] | undefined;
4737
4748
  defaults: Defaults;
4749
+ /**
4750
+ * How what an agent sends is labelled (design 2026-10-15-agent-label, L5): the word, the name, the rules that say
4751
+ * who a message appears to come from, and each Slack account's agent emoji.
4752
+ *
4753
+ * `unknown` here, on purpose: it is read only through `agentLabelOf`, which reads a value it does not understand
4754
+ * as the stricter one — an unknown word as `agent`, a rule list it cannot read as no rules — so a hand edit or a
4755
+ * later release's key can only tighten. Kept through every write as the schemas keep every key they do not name, and
4756
+ * judged by `classifyChange`.
4757
+ */
4758
+ agentLabel?: unknown;
4738
4759
  }
4739
4760
  interface ConfigV1 extends ConfigBody {
4740
4761
  version: 1;
@@ -4779,6 +4800,25 @@ interface OrganisationSlackApp {
4779
4800
  clientId: string;
4780
4801
  appId?: string | undefined;
4781
4802
  }
4803
+ /**
4804
+ * An organisation's update caps, as the file beside its profile names them (design 2026-10-16, U8), and the SHA-256 of
4805
+ * that file, so `org update` can tell the organisation changing them from the record drifting. A `max` word this release
4806
+ * does not know reads as `never`, the strictest it could mean: caps only ever tighten.
4807
+ */
4808
+ interface OrganisationUpdates {
4809
+ max?: string | undefined;
4810
+ background?: boolean | undefined;
4811
+ sha256: string;
4812
+ }
4813
+ /**
4814
+ * The organisation's bot-only agent app, as its profile's agent-app file names it (CUE-493): the app's id, and the
4815
+ * SHA-256 of that file, so `org update` can tell the organisation changing it from the record drifting. No client id:
4816
+ * nobody signs in through it — its administrator installs it once and its members paste its bot token.
4817
+ */
4818
+ interface OrganisationAgentApp {
4819
+ appId: string;
4820
+ sha256: string;
4821
+ }
4782
4822
  /**
4783
4823
  * What this machine records of one organisation profile: never its bytes and never its secret — where it was read
4784
4824
  * from, the SHA-256 of what was read and when, the generations of its Google client, and its Slack apps.
@@ -4807,8 +4847,11 @@ interface OrganisationRecord {
4807
4847
  apps: {
4808
4848
  read?: OrganisationSlackApp | undefined;
4809
4849
  send?: OrganisationSlackApp | undefined;
4850
+ agent?: OrganisationAgentApp | undefined;
4810
4851
  };
4811
4852
  } | undefined;
4853
+ /** The organisation's update caps, from the file beside its profile; absent when it names none. */
4854
+ updates?: OrganisationUpdates | undefined;
4812
4855
  }
4813
4856
  interface ConfigV2 extends ConfigBody {
4814
4857
  version: 2;
@@ -5735,10 +5778,19 @@ interface ApprovalStoreOptions {
5735
5778
  * count and interrupt every step. Every other read and write of the store is unaffected.
5736
5779
  */
5737
5780
  io?: ApprovalIo | undefined;
5781
+ /**
5782
+ * Told when a person has answered a send or post: approved at a terminal, or claimed to be sent — the person's yes
5783
+ * under the chat policy (design 2026-10-16, U7: the security line a preview carried counts as asked once its approval
5784
+ * is answered). Never when it is only prepared, refused or revoked. Awaited, and whatever it throws is ignored:
5785
+ * nothing it does may stop a send. `openCore` passes `securityAnswered`.
5786
+ */
5787
+ answered?: ((approvalId: string) => Promise<void>) | undefined;
5738
5788
  }
5739
5789
  declare class ApprovalStore {
5740
5790
  #private;
5741
5791
  readonly directory: string;
5792
+ /** `ApprovalStoreOptions.answered`, never throwing. */
5793
+ readonly answered: ((approvalId: string) => Promise<void>) | undefined;
5742
5794
  constructor(stateDir: string, options?: ApprovalStoreOptions);
5743
5795
  /**
5744
5796
  * Daily retention (design 2026-10-05 §D9): once a day per state directory, a bounded batch deletes valid finished
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { C as chatKindOf, D as text, E as numeric, Et as VERSION, R as CommsError, T as kindOf, Tt as PACKAGE_NAME, _ as WhatsAppContext, d as composeDraft, g as visibilityUnitKey, h as statusAuthor, m as listKey, n as withCheckedCopy, p as Visibility, w as coreDataToIso, x as inspectSchema, y as rebuildIndex } from "./sync-D5RWl-ZJ.mjs";
2
- import { t as createWhatsAppMcpServer } from "./server-CRhBErHD.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-Coys7_vB.mjs";
2
+ import { t as createWhatsAppMcpServer } from "./server-DP6vz_rw.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 { Et as VERSION, I as strictToolArguments, V as UNTRUSTED_NOTICE, _ as WhatsAppContext, _t as toCommsError, a as CHAT_KINDS, bt as updateToolGate, c as searchMessages, f as draftMessage, o as listChats, r as whatsappStatus, s as readChat, t as syncAccount } from "./sync-D5RWl-ZJ.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-Coys7_vB.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
@@ -70,10 +70,9 @@ async function createWhatsAppMcpServer(options = {}) {
70
70
  }]
71
71
  };
72
72
  };
73
- strictToolArguments(server, fail, updateToolGate({
73
+ strictToolArguments(server, fail, updateToolNotice({
74
74
  core: context.core,
75
75
  env: context.env,
76
- server: "agent-whatsapp",
77
76
  channel: "whatsapp",
78
77
  running: VERSION,
79
78
  exempt: ["whatsapp_status"],
@@ -1,4 +1,4 @@
1
- import { t as createWhatsAppMcpServer } from "./server-CRhBErHD.mjs";
1
+ import { t as createWhatsAppMcpServer } from "./server-DP6vz_rw.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