@agentcomms/events-daemon 0.18.0 → 0.18.1

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/README.md CHANGED
@@ -40,19 +40,23 @@ safe way to see what a rule would send before you point it at a webhook.
40
40
  agent-events target add '{"targetId":"log","version":1,"kind":"dry-run","retentionMs":86400000}'
41
41
 
42
42
  # 2. a rule: every received Gmail message with a subject, mapped to its subject only
43
- agent-events sources list # the Gmail account ids you can name in a rule
43
+ agent-events sources list # every connected account a rule can name: its source, id and name
44
44
  agent-events rule create "$(cat rule.json)"
45
45
 
46
46
  # 3. turn it on: each step prints an approval, which you approve by typing its challenge
47
- agent-events rule enable mail-subjects 1
48
- agent-events approve <approval-id>
49
47
  agent-events enable-all # the standing approval that starts collection
50
48
  agent-events approve <approval-id>
49
+ agent-events rule enable mail-subjects 1
50
+ agent-events approve <approval-id> # offers to test the target first; answering no is fine
51
51
 
52
- # 4. read what matched
52
+ # 4. read what matched: the list gives each record's id, and show prints that record
53
53
  agent-events dryrun list
54
+ agent-events dryrun show <record-id>
54
55
  ```
55
56
 
57
+ Switch collection on before approving the rule: a pending target can be tested only while collection is on. If a test
58
+ cannot run, the approval says why and still asks for its challenge.
59
+
56
60
  `rule.json`:
57
61
 
58
62
  ```json
@@ -832,7 +832,7 @@ async function removeTarget(targetId, options = {}) {
832
832
  //#endregion
833
833
  //#region src/version.ts
834
834
  /** The package version, read from package.json at build time. */
835
- const VERSION = "0.18.0";
835
+ const VERSION = "0.18.1";
836
836
  //#endregion
837
837
  //#region src/mcp/server.ts
838
838
  function reply(data) {
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { $ as sourcesList, $t as assertControlSupported, A as normaliseWhatsAppSourceOptions, At as decideHeld, B as addTarget, Bt as CONTROL_PROTOCOL_VERSIONS, C as canonicalSseSubscriber, Ct as enableAll, D as normaliseResendSourceOptions, Dt as ACTIVATION_FAILURE, E as normaliseGmailSourceOptions, Et as doctor, F as canonicalJudgeBudget, Ft as catalogueList, G as addSubscriber, Gt as isControlRequest, H as targetsList, Ht as controlFailure, I as canonicalJudgeKindEnablement, It as catalogueShow, J as updateSubscriber, Jt as newInstanceRecord, K as removeSubscriber, Kt as negotiateVersion, L as judgeKindDefinition, Lt as approvalView, M as JUDGE_BUDGET_ID, Mt as dropDelivery, N as JUDGE_KIND_DEFINITIONS, Nt as heldList, O as normaliseSlackSourceOptions, Ot as isActivationFailureCode, P as canonicalJudge, Pt as retryDelivery, Q as sourceShow$1, Qt as writeInstance, R as createEventsMcpServer, Rt as EventControlClient, S as normaliseActivationDocument, St as updateJudge, T as classifySourceOptionChange, Tt as assertDoctorReportV2, U as updateTarget, Ut as encodeControlFrame, V as removeTarget$1, Vt as ControlFrameReader, W as targetTest, Wt as isControlHello, X as status, Xt as readInstance, Y as stop, Yt as processIsLive, Z as loadSqlite, Zt as removeInstance, _ as activationDocumentDigest, _t as judgeTest, an as ensureEventSocketDirectory, at as rulesList, b as canonicalTarget, bt as removeJudgeModel, cn as installErrorSink, ct as ruleTestRetained, d as B3_SECRET_TERMINAL_ORIGIN, dt as addJudge, en as assertSocketPathFits, et as createRule$1, f as isB3ControlOperation, ft as budgetShow, g as isOwnerControlWireOperation, gt as judgeModelStatus, h as OWNER_CONTROL_WIRES, ht as judgeKindsList, in as ensureEventPaths, it as ruleShow$1, j as APPROVED_TYPESAFE_MODELS, jt as deliveriesList, k as normaliseSourceOptions, kt as disableAll, lt as pause, m as renderB3ApprovalPreviewV1, mt as enableJudgeKind, nn as verifyControlSocket, nt as enableRule, on as ensureOwnerOnlyFile, ot as updateRule, p as isB3SecretOperation, pt as disableJudgeKind, q as subscribersList, qt as mayRecoverStaleInstance, rn as verifyPrivateSocketDirectory, rt as removeRule, sn as eventPaths, st as ruleTest, tn as controlEndpoint, tt as disableRule$1, ut as resume, v as canonicalFullRuleDocument, vt as judgesList, w as sseDeliveryTarget, wt as assertDoctorReportV1, x as disclosureBindingFor, xt as updateBudget, y as canonicalSubscriber, yt as removeJudge, z as VERSION, zt as probeControl } from "./b3-contract-B6UBBK7F.mjs";
2
+ import { $ as sourcesList, $t as assertControlSupported, A as normaliseWhatsAppSourceOptions, At as decideHeld, B as addTarget, Bt as CONTROL_PROTOCOL_VERSIONS, C as canonicalSseSubscriber, Ct as enableAll, D as normaliseResendSourceOptions, Dt as ACTIVATION_FAILURE, E as normaliseGmailSourceOptions, Et as doctor, F as canonicalJudgeBudget, Ft as catalogueList, G as addSubscriber, Gt as isControlRequest, H as targetsList, Ht as controlFailure, I as canonicalJudgeKindEnablement, It as catalogueShow, J as updateSubscriber, Jt as newInstanceRecord, K as removeSubscriber, Kt as negotiateVersion, L as judgeKindDefinition, Lt as approvalView, M as JUDGE_BUDGET_ID, Mt as dropDelivery, N as JUDGE_KIND_DEFINITIONS, Nt as heldList, O as normaliseSlackSourceOptions, Ot as isActivationFailureCode, P as canonicalJudge, Pt as retryDelivery, Q as sourceShow$1, Qt as writeInstance, R as createEventsMcpServer, Rt as EventControlClient, S as normaliseActivationDocument, St as updateJudge, T as classifySourceOptionChange, Tt as assertDoctorReportV2, U as updateTarget, Ut as encodeControlFrame, V as removeTarget$1, Vt as ControlFrameReader, W as targetTest, Wt as isControlHello, X as status, Xt as readInstance, Y as stop, Yt as processIsLive, Z as loadSqlite, Zt as removeInstance, _ as activationDocumentDigest, _t as judgeTest, an as ensureEventSocketDirectory, at as rulesList, b as canonicalTarget, bt as removeJudgeModel, cn as installErrorSink, ct as ruleTestRetained, d as B3_SECRET_TERMINAL_ORIGIN, dt as addJudge, en as assertSocketPathFits, et as createRule$1, f as isB3ControlOperation, ft as budgetShow, g as isOwnerControlWireOperation, gt as judgeModelStatus, h as OWNER_CONTROL_WIRES, ht as judgeKindsList, in as ensureEventPaths, it as ruleShow$1, j as APPROVED_TYPESAFE_MODELS, jt as deliveriesList, k as normaliseSourceOptions, kt as disableAll, lt as pause, m as renderB3ApprovalPreviewV1, mt as enableJudgeKind, nn as verifyControlSocket, nt as enableRule, on as ensureOwnerOnlyFile, ot as updateRule, p as isB3SecretOperation, pt as disableJudgeKind, q as subscribersList, qt as mayRecoverStaleInstance, rn as verifyPrivateSocketDirectory, rt as removeRule, sn as eventPaths, st as ruleTest, tn as controlEndpoint, tt as disableRule$1, ut as resume, v as canonicalFullRuleDocument, vt as judgesList, w as sseDeliveryTarget, wt as assertDoctorReportV1, x as disclosureBindingFor, xt as updateBudget, y as canonicalSubscriber, yt as removeJudge, z as VERSION, zt as probeControl } from "./b3-contract-BZIj-LWV.mjs";
3
3
  import { a as EventDomainError, d as isJudgeKind, f as validateLocalEndpoint, g as parseIpLiteral, h as assertApprovedAddressSet, i as webhookDeliveryTarget, l as JUDGE_KIND_TYPESAFE, m as assertAddressAllowed, n as canonicalWebhookTarget, o as JUDGE_KINDS, p as AddressPolicyError, r as secretWebhookUrlDescriptor, s as JUDGE_KIND_LAYA, t as canonicalSecretWebhookUrl, u as assertJudgeKindEnabled } from "./webhook-target-DyDTwWhV.mjs";
4
4
  import { a as WriterQuiescer, c as openEventSecretStore, o as withEventWriterLease, r as RecordStorageError, s as migrateEventSecrets, t as EventRecordCipher } from "./records-DsUxYBwb.mjs";
5
5
  import process$1 from "node:process";
@@ -9555,6 +9555,26 @@ async function assertLiveEventAccount(config, scope) {
9555
9555
  source: scope.source
9556
9556
  } });
9557
9557
  }
9558
+ /**
9559
+ * Every connected account a rule may name, loaded afresh: Gmail's inboxes by their stable `ibx_…` id and the other
9560
+ * channels' accounts by their `acc_…` id, each beside the name a person knows it by. What `sources list` shows, so
9561
+ * a first rule's account id can be read from it before any rule is active (CUE-474).
9562
+ */
9563
+ async function connectedEventAccounts(config) {
9564
+ const current = await config.load();
9565
+ const found = [];
9566
+ for (const [account, inbox] of Object.entries(current.inboxes)) if (inbox.provider === "gmail") found.push({
9567
+ source: "gmail",
9568
+ accountId: inbox.id,
9569
+ account
9570
+ });
9571
+ for (const [account, entry] of Object.entries(current.accounts)) if (entry.platform === "slack" || entry.platform === "resend" || entry.platform === "whatsapp") found.push({
9572
+ source: entry.platform,
9573
+ accountId: entry.id,
9574
+ account
9575
+ });
9576
+ return found.sort((left, right) => `${left.source}\u0000${left.account}`.localeCompare(`${right.source}\u0000${right.account}`));
9577
+ }
9558
9578
  /** The current stable ids for one source, loaded afresh at the boundary. */
9559
9579
  async function liveEventAccountIds(config, source) {
9560
9580
  const current = await config.load();
@@ -14543,7 +14563,8 @@ var B3TargetTestControl = class {
14543
14563
  SELECT 1 FROM object_revocations AS revoked
14544
14564
  WHERE revoked.kind = 'target' AND revoked.object_id = target.target_id AND revoked.version = target.version
14545
14565
  )`).get(targetId, targetVersion);
14546
- if (row === void 0 || row.enabled !== 1) return refuse("the exact target version is not live");
14566
+ if (row === void 0) return refuse("the exact target version is not live");
14567
+ if (row.enabled !== 1) return refuse("collection is switched off: switch it on with enable-all first, or approve without the test");
14547
14568
  if (selectorKind === "active") {
14548
14569
  if (this.#store.database.prepare(`SELECT 1 AS present
14549
14570
  FROM target_version_references AS reference
@@ -21069,7 +21090,7 @@ async function startOwnerWithLock(options, stateDir, paths, lock, started, onDat
21069
21090
  control = await (options.startControlServer ?? startControlServer)({
21070
21091
  endpoint: instance.endpoint,
21071
21092
  token,
21072
- handle: async (request) => handleControl(owner, lifecycle, database, activations, dryrun, sourceRegistry, writerQuiescer, request, ownerB3Service, doctorReport),
21093
+ handle: async (request) => handleControl(owner, lifecycle, database, activations, dryrun, sourceRegistry, writerQuiescer, request, ownerB3Service, doctorReport, () => connectedEventAccounts(core.config)),
21073
21094
  verifyEndpoint: () => verifyPrivateSocketDirectory(paths)
21074
21095
  });
21075
21096
  if (options.startControlServer === void 0) {
@@ -21100,7 +21121,7 @@ async function runEventOwner(options = {}) {
21100
21121
  await owner.stop();
21101
21122
  }
21102
21123
  }
21103
- async function handleControl(owner, lifecycle, database, activations, dispatcher, sourceRegistry, writerQuiescer, request, b3OwnerService, doctorReport) {
21124
+ async function handleControl(owner, lifecycle, database, activations, dispatcher, sourceRegistry, writerQuiescer, request, b3OwnerService, doctorReport, connectedAccounts = async () => []) {
21104
21125
  if (!isOwnerControlWireOperation(request.operation)) throw new CommsError("USAGE", "the local event control operation is not recognised");
21105
21126
  if (isB3ControlOperation(request.operation)) {
21106
21127
  if (!b3OwnerService) throw new CommsError("USAGE", "the local B3 control operation is not available");
@@ -21143,8 +21164,8 @@ async function handleControl(owner, lifecycle, database, activations, dispatcher
21143
21164
  channel: definition.type.split(".")[0]
21144
21165
  };
21145
21166
  }
21146
- case OWNER_CONTROL_WIRES.sourcesList: return sourceRows(database, sourceRegistry);
21147
- case OWNER_CONTROL_WIRES.sourceShow: return sourceShow(database, sourceRegistry, requiredText(request.args.source, "source"));
21167
+ case OWNER_CONTROL_WIRES.sourcesList: return sourceRows(database, sourceRegistry, await connectedAccounts());
21168
+ case OWNER_CONTROL_WIRES.sourceShow: return sourceShow(database, sourceRegistry, requiredText(request.args.source, "source"), await connectedAccounts());
21148
21169
  case OWNER_CONTROL_WIRES.rulesList: return ruleRows(database);
21149
21170
  case OWNER_CONTROL_WIRES.ruleShow: return ruleShow(database, requiredText(request.args.ruleId, "rule id"));
21150
21171
  case OWNER_CONTROL_WIRES.createRule:
@@ -21217,7 +21238,12 @@ function targetRows(database) {
21217
21238
  function createTarget(database, document) {
21218
21239
  return domain(() => new ImmutableVersions(database.database).createTarget(document));
21219
21240
  }
21220
- function sourceRows(database, sourceRegistry) {
21241
+ /**
21242
+ * Each source's accounts: the scopes active rules read, and every connected account a rule may name, which has no
21243
+ * cursor scope until a rule reads it. Each carries the name it was connected under, so a person, or an agent writing
21244
+ * a first rule, can tell `ibx_…` from `ibx_…` (CUE-474).
21245
+ */
21246
+ function sourceRows(database, sourceRegistry, connected = []) {
21221
21247
  const rows = database.database.prepare("SELECT document FROM rule_versions WHERE state IN ('active', 'superseded')").all();
21222
21248
  const scopes = /* @__PURE__ */ new Map();
21223
21249
  for (const row of rows) {
@@ -21239,17 +21265,28 @@ function sourceRows(database, sourceRegistry) {
21239
21265
  } catch {}
21240
21266
  }
21241
21267
  }
21242
- const ordered = [...scopes.values()].sort((left, right) => `${left.source}\u0000${left.accountId}\u0000${left.cursorScope}`.localeCompare(`${right.source}\u0000${right.accountId}\u0000${right.cursorScope}`));
21268
+ const nameOf = new Map(connected.map((entry) => [`${entry.source}\u0000${entry.accountId}`, entry.account]));
21269
+ const accounts = [...scopes.values()].map((scope) => ({
21270
+ ...scope,
21271
+ account: nameOf.get(`${scope.source}\u0000${scope.accountId}`) ?? null
21272
+ }));
21273
+ for (const entry of connected) if (!accounts.some((row) => row.source === entry.source && row.accountId === entry.accountId)) accounts.push({
21274
+ source: entry.source,
21275
+ accountId: entry.accountId,
21276
+ account: entry.account,
21277
+ cursorScope: null
21278
+ });
21279
+ const ordered = accounts.sort((left, right) => `${left.source}\u0000${left.accountId}\u0000${left.cursorScope ?? ""}`.localeCompare(`${right.source}\u0000${right.accountId}\u0000${right.cursorScope ?? ""}`));
21243
21280
  return sourceRegistry.sources().map((source) => ({
21244
21281
  source,
21245
21282
  accounts: ordered.filter((scope) => scope.source === source)
21246
21283
  }));
21247
21284
  }
21248
- function sourceShow(database, sourceRegistry, source) {
21285
+ function sourceShow(database, sourceRegistry, source, connected = []) {
21249
21286
  if (!sourceRegistry.sources().includes(source)) throw new CommsError("NOT_FOUND", "the requested source is not configured");
21250
21287
  return {
21251
21288
  source,
21252
- accounts: sourceRows(database, sourceRegistry).find((row) => row.source === source).accounts
21289
+ accounts: sourceRows(database, sourceRegistry, connected).find((row) => row.source === source).accounts
21253
21290
  };
21254
21291
  }
21255
21292
  async function acquireWithStaleRecovery(paths) {
@@ -21397,6 +21434,22 @@ function terminalSafeJson(value) {
21397
21434
  function renderApprovalViewForTerminal(result) {
21398
21435
  return escapeForDisplay(renderB3ApprovalPreviewV1(result).terminal);
21399
21436
  }
21437
+ /**
21438
+ * An optional test the owner refused is reported and the approval goes on to its challenge (CUE-475): declining the
21439
+ * test was always allowed, so a test that could not run must not end the approval for the person.
21440
+ */
21441
+ async function optionalTest(label, test) {
21442
+ try {
21443
+ return await test();
21444
+ } catch (error) {
21445
+ if (!isCommsError(error)) throw error;
21446
+ return {
21447
+ ...label,
21448
+ test: "not run",
21449
+ reason: error.message
21450
+ };
21451
+ }
21452
+ }
21400
21453
  /** Runs the only interactive terminal approval path; the owner, not this client, made every pending-target selector. */
21401
21454
  async function runTerminalApprovalFlow(input) {
21402
21455
  const start = await input.start(input.approvalId);
@@ -21404,13 +21457,14 @@ async function runTerminalApprovalFlow(input) {
21404
21457
  const selector = start.pendingTargetSelectors[index];
21405
21458
  if (selector === void 0) continue;
21406
21459
  const answer = await input.terminal.question(`Test pending target ${index + 1} with the fixed synthetic payload before approving? [y/N] `);
21407
- if (/^\s*(?:y|yes)\s*$/iu.test(answer)) input.print(await input.testPendingTarget(selector));
21460
+ if (/^\s*(?:y|yes)\s*$/iu.test(answer)) input.print(await optionalTest({ pendingTarget: index + 1 }, () => input.testPendingTarget(selector)));
21408
21461
  }
21409
21462
  for (let index = 0; index < start.pendingRuleJudgeTestSelectors.length; index += 1) {
21410
21463
  const selector = start.pendingRuleJudgeTestSelectors[index];
21411
21464
  if (selector === void 0) continue;
21412
21465
  const answer = await input.terminal.question(`Test pending rule judge ${index + 1} with the fixed synthetic payload before approving? [y/N] `);
21413
- if (/^\s*(?:y|yes)\s*$/iu.test(answer) && input.testPendingRuleJudge !== void 0) input.print(await input.testPendingRuleJudge(selector));
21466
+ const testPendingRuleJudge = input.testPendingRuleJudge;
21467
+ if (/^\s*(?:y|yes)\s*$/iu.test(answer) && testPendingRuleJudge !== void 0) input.print(await optionalTest({ pendingRuleJudge: index + 1 }, () => testPendingRuleJudge(selector)));
21414
21468
  }
21415
21469
  const answer = await input.terminal.question(`Type this approval challenge: ${escapeForDisplay(start.challenge)}\n> `);
21416
21470
  input.print(await input.approve(input.approvalId, answer));
@@ -21436,6 +21490,7 @@ async function run(argv, deps = {}) {
21436
21490
  }
21437
21491
  const env = deps.env ?? process.env;
21438
21492
  const program = new Command();
21493
+ runEnvironment.set(program, env);
21439
21494
  let ran = false;
21440
21495
  program.name("agent-events").description("The local event-emission service: one foreground owner and local control clients.").option("--json", "write machine-readable output").option("--no-color", "never colour the output").option("--config-dir <dir>", "pin the configuration directory for this run").option("--state-dir <dir>", "pin the state directory for this run").option("--data-dir <dir>", "pin the data directory for this run").option("--secrets-dir <dir>", "pin the secrets directory for this run").option("--downloads-dir <dir>", "pin the downloads directory for this run").configureOutput({
21441
21496
  writeOut: (text) => streams.stdout.write(escapeForDisplay(text)),
@@ -21868,10 +21923,19 @@ async function run(argv, deps = {}) {
21868
21923
  return 1;
21869
21924
  }
21870
21925
  }
21926
+ /**
21927
+ * The state directory a control client looks in: the one pinned for this run, or the one the environment this CLI was
21928
+ * given resolves to. A caller that passes its own `env` to `run` reaches its own owner, never the one the process
21929
+ * environment names.
21930
+ */
21871
21931
  function controlOptions(program) {
21872
21932
  const { stateDir } = program.opts();
21873
- return stateDir === void 0 ? {} : { stateDir };
21933
+ if (stateDir !== void 0) return { stateDir };
21934
+ const env = runEnvironment.get(program);
21935
+ return env === void 0 ? {} : { stateDir: resolvePaths({ env }).stateDir };
21874
21936
  }
21937
+ /** The environment each program was made with, read by `controlOptions` outside `run`'s closure. */
21938
+ const runEnvironment = /* @__PURE__ */ new WeakMap();
21875
21939
  function parseVersion(value) {
21876
21940
  const version = Number(value);
21877
21941
  if (!Number.isSafeInteger(version) || version < 1) throw new CommsError("USAGE", "rule version must be a positive integer");
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { R as createEventsMcpServer, X as status, a as B3_CONTROL_V1_OPERATION_SPECS, c as B3_CONTROL_V1_SUCCESSOR_REQUIREMENT, d as B3_SECRET_TERMINAL_ORIGIN, i as B3_CONTROL_ERROR_CODES, l as B3_DESKTOP_CONTROL_OPERATIONS, m as renderB3ApprovalPreviewV1, n as B3_CAPABILITIES, o as B3_CONTROL_V1_RESULT_OPERATIONS, r as B3_CONTROL_CONTRACT, s as B3_CONTROL_V1_SCHEMA_VERSION, t as B3_APPROVAL_VIEW_VARIANTS, u as B3_JUDGE_UNAVAILABLE_VARIANTS } from "./b3-contract-B6UBBK7F.mjs";
1
+ import { R as createEventsMcpServer, X as status, a as B3_CONTROL_V1_OPERATION_SPECS, c as B3_CONTROL_V1_SUCCESSOR_REQUIREMENT, d as B3_SECRET_TERMINAL_ORIGIN, i as B3_CONTROL_ERROR_CODES, l as B3_DESKTOP_CONTROL_OPERATIONS, m as renderB3ApprovalPreviewV1, n as B3_CAPABILITIES, o as B3_CONTROL_V1_RESULT_OPERATIONS, r as B3_CONTROL_CONTRACT, s as B3_CONTROL_V1_SCHEMA_VERSION, t as B3_APPROVAL_VIEW_VARIANTS, u as B3_JUDGE_UNAVAILABLE_VARIANTS } from "./b3-contract-BZIj-LWV.mjs";
2
2
  export { B3_APPROVAL_VIEW_VARIANTS, B3_CAPABILITIES, B3_CONTROL_CONTRACT, B3_CONTROL_ERROR_CODES, B3_CONTROL_V1_OPERATION_SPECS, B3_CONTROL_V1_RESULT_OPERATIONS, B3_CONTROL_V1_SCHEMA_VERSION, B3_CONTROL_V1_SUCCESSOR_REQUIREMENT, B3_DESKTOP_CONTROL_OPERATIONS, B3_JUDGE_UNAVAILABLE_VARIANTS, B3_SECRET_TERMINAL_ORIGIN, createEventsMcpServer, renderB3ApprovalPreviewV1, status };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentcomms/events-daemon",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
4
4
  "description": "The local event service for agent-communications: rules you approve deliver Gmail, Slack, Resend and WhatsApp events to a signed webhook, a local live stream or a dry-run log.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,12 +34,12 @@
34
34
  "access": "public"
35
35
  },
36
36
  "dependencies": {
37
- "@agentcomms/events": "0.18.0",
38
- "@agentcomms/resend": "0.18.0",
39
- "@agentcomms/gmail": "0.18.0",
40
- "@agentcomms/slack": "0.18.0",
41
- "@agentcomms/core": "0.18.0",
42
- "@agentcomms/whatsapp": "0.18.0"
37
+ "@agentcomms/core": "0.18.1",
38
+ "@agentcomms/gmail": "0.18.1",
39
+ "@agentcomms/events": "0.18.1",
40
+ "@agentcomms/whatsapp": "0.18.1",
41
+ "@agentcomms/slack": "0.18.1",
42
+ "@agentcomms/resend": "0.18.1"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@modelcontextprotocol/client": "2.3.1",
@@ -70,5 +70,5 @@
70
70
  "typecheck": "tsc -p tsconfig.json",
71
71
  "test": "node --import ../../test/helpers/loopback-seal-preload.mjs --experimental-strip-types --disable-warning=ExperimentalWarning --test \"test/**/*.test.ts\""
72
72
  },
73
- "gitHead": "a55c5383b35a8214b9e481e2a148b0e29a663a9f"
73
+ "gitHead": "fc398edc67287e411f8c5cb821f434220cb83aa5"
74
74
  }