@symerian/symi 2.7.9 → 2.7.10

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.
Files changed (98) hide show
  1. package/dist/{audio-preflight-D_g9Duqw.js → audio-preflight-lr-WPpc9.js} +4 -4
  2. package/dist/build-info.json +3 -3
  3. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  4. package/dist/{chrome-BUT--ob3.js → chrome-B14NNyfm.js} +7 -7
  5. package/dist/{command-registry-qqb2gJ4P.js → command-registry-CH1cn-Lz.js} +7 -7
  6. package/dist/{completion-cli-BX_yaiom.js → completion-cli-BgneZQ7D.js} +1 -1
  7. package/dist/{completion-cli-g-Vdnude.js → completion-cli-CG24rSh8.js} +2 -2
  8. package/dist/{config-cli-CnFTSv-1.js → config-cli-CXa7oMTX.js} +1 -1
  9. package/dist/{config-cli-CsCvDCZV.js → config-cli-DVEOa8P5.js} +1 -1
  10. package/dist/{configure-CAuW3YmR.js → configure-BDxyPzBl.js} +1 -1
  11. package/dist/{configure-BYd07Mo5.js → configure-U2yrALDt.js} +1 -1
  12. package/dist/{deliver-B36OzmeP.js → deliver-DrC7tG6s.js} +1 -1
  13. package/dist/{doctor-completion-Dqfl4aR1.js → doctor-completion-8zSqfzuU.js} +1 -1
  14. package/dist/{doctor-completion-Cqce5h2X.js → doctor-completion-ny9DIsuL.js} +1 -1
  15. package/dist/entry.js +1 -1
  16. package/dist/extensionAPI.js +6 -6
  17. package/dist/{gateway-cli-DA1fRZ5w.js → gateway-cli-CmfMdGhz.js} +5 -5
  18. package/dist/{gateway-cli-BUqL_Yh6.js → gateway-cli-Dg0UoYav.js} +5 -5
  19. package/dist/{glass-ui-ws-Cm-WtdFI.js → glass-ui-ws-Bgpyl16w.js} +3 -3
  20. package/dist/{glass-ui-ws-BzBtCYP7.js → glass-ui-ws-aKGCf5hN.js} +3 -3
  21. package/dist/{health-Bx8UUqFA.js → health-Bj8mUXDd.js} +46 -12
  22. package/dist/{health-C7HtwYDj.js → health-D9pKXesa.js} +46 -12
  23. package/dist/{image-BHhzdmbq.js → image-CKeN0xJL.js} +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/{onboard-C1GtzpAc.js → onboard-B7CIWmHb.js} +2 -2
  26. package/dist/{onboard-sl1Xputw.js → onboard-CYYcbEPR.js} +2 -2
  27. package/dist/{onboarding-B4qg0ZYp.js → onboarding-BHnEBXBG.js} +1 -1
  28. package/dist/{onboarding-C89rTOOy.js → onboarding-CchD1d-n.js} +1 -1
  29. package/dist/{onboarding.finalize-ClJ1HBVt.js → onboarding.finalize-BZ6tQzoC.js} +4 -4
  30. package/dist/{onboarding.finalize-CGk4vov2.js → onboarding.finalize-CnzLAjla.js} +5 -5
  31. package/dist/{pi-embedded-BaNpG0Aq.js → pi-embedded-BIATvD3R.js} +16 -16
  32. package/dist/{pi-embedded-helpers-BET359cH.js → pi-embedded-helpers-D8YgtMdl.js} +4 -4
  33. package/dist/{program-B4MbPh6k.js → program-cj70FFee.js} +2 -2
  34. package/dist/{program-context-BfdA1JM9.js → program-context-DSkr5IEn.js} +9 -9
  35. package/dist/{prompt-select-styled-bMJTZkj7.js → prompt-select-styled-C9MQv67C.js} +2 -2
  36. package/dist/{prompt-select-styled-DNhjvdZL.js → prompt-select-styled-DxtxwQmE.js} +2 -2
  37. package/dist/{pw-ai-DE8wmtet.js → pw-ai-DTmHAKPA.js} +1 -1
  38. package/dist/{register.configure-MY0P8ucP.js → register.configure-BP_a-E21.js} +2 -2
  39. package/dist/{register.configure-CVct6y53.js → register.configure-DcwAboPG.js} +2 -2
  40. package/dist/{register.maintenance-Ciblsa6H.js → register.maintenance-C4tn55a5.js} +5 -5
  41. package/dist/{register.maintenance-DpSSW9tp.js → register.maintenance-D_1D-fbi.js} +6 -6
  42. package/dist/{register.onboard-BQ-ciW9l.js → register.onboard-CHpUtNWT.js} +3 -3
  43. package/dist/{register.onboard-MIhaldvp.js → register.onboard-OXqQs97I.js} +3 -3
  44. package/dist/{register.setup-M0O0Tp-n.js → register.setup-C8FuEUO_.js} +3 -3
  45. package/dist/{register.setup-DCTamI7u.js → register.setup-DbPNjezQ.js} +3 -3
  46. package/dist/{register.status-health-sessions-DzKtjfA-.js → register.status-health-sessions-BzB_lPbR.js} +2 -2
  47. package/dist/{register.status-health-sessions-Drc5WQGq.js → register.status-health-sessions-c8vq6An_.js} +2 -2
  48. package/dist/{register.subclis-Btg8-Nnf.js → register.subclis-Dt0Az0gT.js} +3 -3
  49. package/dist/{run-main-DfxDXt2d.js → run-main-D-OIb2fr.js} +7 -7
  50. package/dist/{runner-BVgCl6yZ.js → runner-COpebDew.js} +1 -1
  51. package/dist/{server-methods-OJbQNjOJ.js → server-methods-Dph_r18S.js} +2 -2
  52. package/dist/{server-methods-BcBroG6v.js → server-methods-b55BoGQD.js} +2 -2
  53. package/dist/{status-RlJA2XzQ.js → status-Bbss-JjB.js} +1 -1
  54. package/dist/{status-Ut-dfDT0.js → status-Cg3Vn5FV.js} +1 -1
  55. package/dist/{update-cli-Cb12PjyN.js → update-cli-DO0A0UCN.js} +5 -5
  56. package/dist/{update-cli-Cm4ftHhu.js → update-cli-Dh_GPhI4.js} +6 -6
  57. package/dist/{web-f1xT-H2y.js → web-Ifwqx6Dt.js} +6 -6
  58. package/extensions/bluebubbles/package.json +1 -1
  59. package/extensions/copilot-proxy/package.json +1 -1
  60. package/extensions/diagnostics-otel/package.json +1 -1
  61. package/extensions/discord/package.json +1 -1
  62. package/extensions/feishu/package.json +1 -1
  63. package/extensions/google-antigravity-auth/package.json +1 -1
  64. package/extensions/google-gemini-cli-auth/package.json +1 -1
  65. package/extensions/googlechat/package.json +1 -1
  66. package/extensions/imessage/package.json +1 -1
  67. package/extensions/irc/package.json +1 -1
  68. package/extensions/learning-loop/package.json +1 -1
  69. package/extensions/line/package.json +1 -1
  70. package/extensions/llm-task/package.json +1 -1
  71. package/extensions/matrix/CHANGELOG.md +6 -0
  72. package/extensions/matrix/package.json +1 -1
  73. package/extensions/mattermost/package.json +1 -1
  74. package/extensions/memory-core/package.json +1 -1
  75. package/extensions/memory-lancedb/package.json +1 -1
  76. package/extensions/minimax-portal-auth/package.json +1 -1
  77. package/extensions/msteams/CHANGELOG.md +6 -0
  78. package/extensions/msteams/package.json +1 -1
  79. package/extensions/nextcloud-talk/package.json +1 -1
  80. package/extensions/nostr/CHANGELOG.md +6 -0
  81. package/extensions/nostr/package.json +1 -1
  82. package/extensions/open-prose/package.json +1 -1
  83. package/extensions/outlook/package.json +1 -1
  84. package/extensions/pipeline/package.json +1 -1
  85. package/extensions/signal/package.json +1 -1
  86. package/extensions/slack/package.json +1 -1
  87. package/extensions/telegram/package.json +1 -1
  88. package/extensions/tlon/package.json +1 -1
  89. package/extensions/twitch/CHANGELOG.md +6 -0
  90. package/extensions/twitch/package.json +1 -1
  91. package/extensions/voice-call/CHANGELOG.md +6 -0
  92. package/extensions/voice-call/package.json +1 -1
  93. package/extensions/whatsapp/package.json +1 -1
  94. package/extensions/zalo/CHANGELOG.md +6 -0
  95. package/extensions/zalo/package.json +1 -1
  96. package/extensions/zalouser/CHANGELOG.md +6 -0
  97. package/extensions/zalouser/package.json +1 -1
  98. package/package.json +1 -1
@@ -12,10 +12,10 @@ import "./accounts-8zZqL37v.js";
12
12
  import "./image-ops-ByaQt43P.js";
13
13
  import "./pi-model-discovery-j5tVLINv.js";
14
14
  import "./message-channel-BQINJQIT.js";
15
- import "./pi-embedded-helpers-BET359cH.js";
15
+ import "./pi-embedded-helpers-D8YgtMdl.js";
16
16
  import "./config-BAVNLbja.js";
17
17
  import "./manifest-registry-DWdYdchb.js";
18
- import "./chrome-BUT--ob3.js";
18
+ import "./chrome-B14NNyfm.js";
19
19
  import "./skills-XEbTRNYL.js";
20
20
  import "./redact-1NGYV_8p.js";
21
21
  import "./errors-CPfngF0S.js";
@@ -25,10 +25,10 @@ import "./thinking-W85Rb32m.js";
25
25
  import "./accounts-DImOt9jX.js";
26
26
  import "./paths-DkMamAQ-.js";
27
27
  import "./tool-images-ChC2CXaN.js";
28
- import "./image-BHhzdmbq.js";
28
+ import "./image-CKeN0xJL.js";
29
29
  import "./gemini-auth-DVcG-42i.js";
30
30
  import "./local-roots-CC8jiKDk.js";
31
- import { a as resolveMediaAttachmentLocalRoots, n as createMediaAttachmentCache, o as runCapability, r as normalizeMediaAttachments, t as buildProviderRegistry, u as isAudioAttachment } from "./runner-BVgCl6yZ.js";
31
+ import { a as resolveMediaAttachmentLocalRoots, n as createMediaAttachmentCache, o as runCapability, r as normalizeMediaAttachments, t as buildProviderRegistry, u as isAudioAttachment } from "./runner-COpebDew.js";
32
32
 
33
33
  //#region src/media-understanding/audio-preflight.ts
34
34
  /**
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.7.9",
3
- "commit": "fcb3b08d175b188c8ab23c07c8f6c72edd92cf9c",
4
- "builtAt": "2026-04-22T00:38:10.749Z"
2
+ "version": "2.7.10",
3
+ "commit": "580ed022919170285c975874560547a335612237",
4
+ "builtAt": "2026-04-22T04:54:36.394Z"
5
5
  }
@@ -1 +1 @@
1
- 672b030ea2d05a28166d35ea215709a48c4b9c6cfe0d270cea98d76fd9dd5ba4
1
+ 4b0ff209dcd7668a14180553a98792a881403e7227cdc463f26433cf1d0818f6
@@ -10,7 +10,7 @@ import fs$1 from "node:fs/promises";
10
10
  import { execFileSync, spawn } from "node:child_process";
11
11
  import net from "node:net";
12
12
  import { createServer } from "node:http";
13
- import WebSocket$1, { WebSocketServer } from "ws";
13
+ import WebSocket, { WebSocketServer } from "ws";
14
14
  import { Buffer as Buffer$1 } from "node:buffer";
15
15
 
16
16
  //#region src/browser/constants.ts
@@ -178,7 +178,7 @@ async function ensureChromeExtensionRelayServer(opts) {
178
178
  let nextExtensionId = 1;
179
179
  const sendToExtension = async (payload) => {
180
180
  const ws = extensionWs;
181
- if (!ws || ws.readyState !== WebSocket$1.OPEN) throw new Error("Chrome extension not connected");
181
+ if (!ws || ws.readyState !== WebSocket.OPEN) throw new Error("Chrome extension not connected");
182
182
  ws.send(JSON.stringify(payload));
183
183
  return await new Promise((resolve, reject) => {
184
184
  const timer = setTimeout(() => {
@@ -195,12 +195,12 @@ async function ensureChromeExtensionRelayServer(opts) {
195
195
  const broadcastToCdpClients = (evt) => {
196
196
  const msg = JSON.stringify(evt);
197
197
  for (const ws of cdpClients) {
198
- if (ws.readyState !== WebSocket$1.OPEN) continue;
198
+ if (ws.readyState !== WebSocket.OPEN) continue;
199
199
  ws.send(msg);
200
200
  }
201
201
  };
202
202
  const sendResponseToCdp = (ws, res) => {
203
- if (ws.readyState !== WebSocket$1.OPEN) return;
203
+ if (ws.readyState !== WebSocket.OPEN) return;
204
204
  ws.send(JSON.stringify(res));
205
205
  };
206
206
  const ensureTargetEventsForClient = (ws, mode) => {
@@ -425,7 +425,7 @@ async function ensureChromeExtensionRelayServer(opts) {
425
425
  wssExtension.on("connection", (ws) => {
426
426
  extensionWs = ws;
427
427
  const ping = setInterval(() => {
428
- if (ws.readyState !== WebSocket$1.OPEN) return;
428
+ if (ws.readyState !== WebSocket.OPEN) return;
429
429
  ws.send(JSON.stringify({ method: "ping" }));
430
430
  }, 5e3);
431
431
  ws.on("message", (data) => {
@@ -743,7 +743,7 @@ async function fetchOk(url, timeoutMs = 1500, init) {
743
743
  }
744
744
  async function withCdpSocket(wsUrl, fn, opts) {
745
745
  const headers = getHeadersWithAuth(wsUrl, opts?.headers ?? {});
746
- const ws = new WebSocket$1(wsUrl, {
746
+ const ws = new WebSocket(wsUrl, {
747
747
  handshakeTimeout: typeof opts?.handshakeTimeoutMs === "number" && Number.isFinite(opts.handshakeTimeoutMs) ? Math.max(1, Math.floor(opts.handshakeTimeoutMs)) : 5e3,
748
748
  ...Object.keys(headers).length ? { headers } : {}
749
749
  });
@@ -1637,7 +1637,7 @@ async function getChromeWebSocketUrl(cdpUrl, timeoutMs = 500) {
1637
1637
  async function canOpenWebSocket(wsUrl, timeoutMs = 800) {
1638
1638
  return await new Promise((resolve) => {
1639
1639
  const headers = getHeadersWithAuth(wsUrl);
1640
- const ws = new WebSocket$1(wsUrl, {
1640
+ const ws = new WebSocket(wsUrl, {
1641
1641
  handshakeTimeout: timeoutMs,
1642
1642
  ...Object.keys(headers).length ? { headers } : {}
1643
1643
  });
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js";
2
2
  import { an as getPrimaryCommand, cn as hasHelpOrVersion } from "./entry.js";
3
- import { i as registerSubCliCommands, o as reparseProgramFromActionArgs } from "./register.subclis-Btg8-Nnf.js";
3
+ import { i as registerSubCliCommands, o as reparseProgramFromActionArgs } from "./register.subclis-Dt0Az0gT.js";
4
4
 
5
5
  //#region src/cli/program/command-registry.ts
6
6
  var command_registry_exports = /* @__PURE__ */ __exportAll({
@@ -22,7 +22,7 @@ const coreEntries = [
22
22
  hasSubcommands: false
23
23
  }],
24
24
  register: async ({ program }) => {
25
- (await import("./register.setup-M0O0Tp-n.js")).registerSetupCommand(program);
25
+ (await import("./register.setup-C8FuEUO_.js")).registerSetupCommand(program);
26
26
  }
27
27
  },
28
28
  {
@@ -32,7 +32,7 @@ const coreEntries = [
32
32
  hasSubcommands: false
33
33
  }],
34
34
  register: async ({ program }) => {
35
- (await import("./register.onboard-BQ-ciW9l.js")).registerOnboardCommand(program);
35
+ (await import("./register.onboard-CHpUtNWT.js")).registerOnboardCommand(program);
36
36
  }
37
37
  },
38
38
  {
@@ -42,7 +42,7 @@ const coreEntries = [
42
42
  hasSubcommands: false
43
43
  }],
44
44
  register: async ({ program }) => {
45
- (await import("./register.configure-CVct6y53.js")).registerConfigureCommand(program);
45
+ (await import("./register.configure-DcwAboPG.js")).registerConfigureCommand(program);
46
46
  }
47
47
  },
48
48
  {
@@ -52,7 +52,7 @@ const coreEntries = [
52
52
  hasSubcommands: true
53
53
  }],
54
54
  register: async ({ program }) => {
55
- (await import("./config-cli-CsCvDCZV.js")).registerConfigCli(program);
55
+ (await import("./config-cli-DVEOa8P5.js")).registerConfigCli(program);
56
56
  }
57
57
  },
58
58
  {
@@ -79,7 +79,7 @@ const coreEntries = [
79
79
  }
80
80
  ],
81
81
  register: async ({ program }) => {
82
- (await import("./register.maintenance-DpSSW9tp.js")).registerMaintenanceCommands(program);
82
+ (await import("./register.maintenance-D_1D-fbi.js")).registerMaintenanceCommands(program);
83
83
  }
84
84
  },
85
85
  {
@@ -135,7 +135,7 @@ const coreEntries = [
135
135
  }
136
136
  ],
137
137
  register: async ({ program }) => {
138
- (await import("./register.status-health-sessions-DzKtjfA-.js")).registerStatusHealthSessionsCommands(program);
138
+ (await import("./register.status-health-sessions-BzB_lPbR.js")).registerStatusHealthSessionsCommands(program);
139
139
  }
140
140
  },
141
141
  {
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js";
2
2
  import { g as resolveStateDir } from "./paths-Cqn-zk3M.js";
3
3
  import { h as pathExists } from "./utils-B-0b9bGM.js";
4
4
  import { i as routeLogsToStderr } from "./subsystem-D9vIQve0.js";
5
- import { a as registerCoreCliByName, c as getSubCliEntries, l as registerSubCliByName, r as getCoreCliCommandNames, t as getProgramContext } from "./program-context-BfdA1JM9.js";
5
+ import { a as registerCoreCliByName, c as getSubCliEntries, l as registerSubCliByName, r as getCoreCliCommandNames, t as getProgramContext } from "./program-context-DSkr5IEn.js";
6
6
  import os from "node:os";
7
7
  import path from "node:path";
8
8
  import fs from "node:fs/promises";
@@ -1,7 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-Cbj13DAv.js";
2
2
  import { Yt as resolveStateDir, l as routeLogsToStderr, nt as pathExists } from "./entry.js";
3
- import { n as getSubCliEntries, r as registerSubCliByName } from "./register.subclis-Btg8-Nnf.js";
4
- import { i as registerCoreCliByName, n as getCoreCliCommandNames } from "./command-registry-qqb2gJ4P.js";
3
+ import { n as getSubCliEntries, r as registerSubCliByName } from "./register.subclis-Dt0Az0gT.js";
4
+ import { i as registerCoreCliByName, n as getCoreCliCommandNames } from "./command-registry-CH1cn-Lz.js";
5
5
  import { t as getProgramContext } from "./program-context-CqzR_m-7.js";
6
6
  import os from "node:os";
7
7
  import path from "node:path";
@@ -206,7 +206,7 @@ async function runConfigUnset(opts) {
206
206
  }
207
207
  function registerConfigCli(program) {
208
208
  const cmd = program.command("config").description("Non-interactive config helpers (get/set/unset). Run without subcommand for the setup wizard.").addHelpText("after", () => `\n${theme.muted("Docs:")} ${formatDocsLink("/cli/config", "docs.symi.ai/cli/config")}\n`).option("--section <section>", "Configure wizard sections (repeatable). Use with no subcommand.", (value, previous) => [...previous, value], []).action(async (opts) => {
209
- const { configureCommandFromSectionsArg } = await import("./configure-CAuW3YmR.js").then((n) => n.t);
209
+ const { configureCommandFromSectionsArg } = await import("./configure-BDxyPzBl.js").then((n) => n.t);
210
210
  await configureCommandFromSectionsArg(opts.section, defaultRuntime);
211
211
  });
212
212
  cmd.command("get").description("Get a config value by dot path").argument("<path>", "Config path (dot or bracket notation)").option("--json", "Output JSON", false).action(async (path, opts) => {
@@ -201,7 +201,7 @@ async function runConfigUnset(opts) {
201
201
  }
202
202
  function registerConfigCli(program) {
203
203
  const cmd = program.command("config").description("Non-interactive config helpers (get/set/unset). Run without subcommand for the setup wizard.").addHelpText("after", () => `\n${theme.muted("Docs:")} ${formatDocsLink("/cli/config", "docs.symi.ai/cli/config")}\n`).option("--section <section>", "Configure wizard sections (repeatable). Use with no subcommand.", (value, previous) => [...previous, value], []).action(async (opts) => {
204
- const { configureCommandFromSectionsArg } = await import("./configure-BYd07Mo5.js").then((n) => n.t);
204
+ const { configureCommandFromSectionsArg } = await import("./configure-U2yrALDt.js").then((n) => n.t);
205
205
  await configureCommandFromSectionsArg(opts.section, defaultRuntime);
206
206
  });
207
207
  cmd.command("get").description("Get a config value by dot path").argument("<path>", "Config path (dot or bracket notation)").option("--json", "Output JSON", false).action(async (path, opts) => {
@@ -16,7 +16,7 @@ import { t as createClackPrompter } from "./clack-prompter-DMuVyYP2.js";
16
16
  import { r as setupChannels, t as noteChannelStatus } from "./onboard-channels-CUUTFx1F.js";
17
17
  import { a as gatewayInstallErrorHint, i as buildGatewayInstallPlan, n as GATEWAY_DAEMON_RUNTIME_OPTIONS, t as DEFAULT_GATEWAY_DAEMON_RUNTIME } from "./daemon-runtime-BT1zC2PU.js";
18
18
  import { t as resolveGatewayService } from "./service-osK70kTZ.js";
19
- import { r as healthCommand } from "./health-Bx8UUqFA.js";
19
+ import { r as healthCommand } from "./health-Bj8mUXDd.js";
20
20
  import { t as ensureControlUiAssetsBuilt } from "./control-ui-assets-B7moDVHX.js";
21
21
  import { n as logConfigUpdated } from "./logging-KpicI3yD.js";
22
22
  import { n as promptAuthChoiceGrouped } from "./auth-choice-prompt-Cn6U3t8O.js";
@@ -14,7 +14,7 @@ import { t as createClackPrompter } from "./clack-prompter-B1aVoXd5.js";
14
14
  import { r as setupChannels, t as noteChannelStatus } from "./onboard-channels-HyGv2y5c.js";
15
15
  import { a as gatewayInstallErrorHint, i as buildGatewayInstallPlan, n as GATEWAY_DAEMON_RUNTIME_OPTIONS, t as DEFAULT_GATEWAY_DAEMON_RUNTIME } from "./daemon-runtime-BV78EN62.js";
16
16
  import { t as resolveGatewayService } from "./service-Cm9j9WzQ.js";
17
- import { r as healthCommand } from "./health-C7HtwYDj.js";
17
+ import { r as healthCommand } from "./health-D9pKXesa.js";
18
18
  import { t as ensureControlUiAssetsBuilt } from "./control-ui-assets-BseSWee1.js";
19
19
  import { n as logConfigUpdated } from "./logging-BGewRZy0.js";
20
20
  import { n as promptAuthChoiceGrouped } from "./auth-choice-prompt-DVcYPG2v.js";
@@ -5,7 +5,7 @@ import { c as getActivePluginRegistry, v as createInternalHookEvent, y as trigge
5
5
  import { t as createSubsystemLogger } from "./subsystem-CZixfwU8.js";
6
6
  import { a as isSilentReplyText, n as SILENT_REPLY_TOKEN } from "./tokens-Cn6drXx2.js";
7
7
  import { r as normalizeChannelId, t as getChannelPlugin } from "./plugins-71oIavrF.js";
8
- import { B as resolveMirroredTranscriptText, i as isMessagingToolDuplicate, z as appendAssistantMessageToSessionTranscript } from "./pi-embedded-helpers-BET359cH.js";
8
+ import { B as resolveMirroredTranscriptText, i as isMessagingToolDuplicate, z as appendAssistantMessageToSessionTranscript } from "./pi-embedded-helpers-D8YgtMdl.js";
9
9
  import { d as getChannelDock } from "./thinking-W85Rb32m.js";
10
10
  import { c as resolveChunkMode, f as parseFenceSpans, i as chunkMarkdownTextWithMode, l as resolveTextChunkLimit, n as chunkByParagraph } from "./chunk-DTMTDXwE.js";
11
11
  import { n as resolveMarkdownTableMode } from "./markdown-tables-DawaaZEe.js";
@@ -1,7 +1,7 @@
1
1
  import { t as resolveSymiPackageRoot } from "./symi-root-CrGJbkzf.js";
2
2
  import { r as resolveCliName } from "./command-format-COaS-S7B.js";
3
3
  import { t as note } from "./note-DQ9BvHF2.js";
4
- import { a as resolveCompletionCachePath, i as isCompletionInstalled, o as resolveShellFromEnv, r as installCompletion, s as usesSlowDynamicCompletion, t as completionCacheExists } from "./completion-cli-BX_yaiom.js";
4
+ import { a as resolveCompletionCachePath, i as isCompletionInstalled, o as resolveShellFromEnv, r as installCompletion, s as usesSlowDynamicCompletion, t as completionCacheExists } from "./completion-cli-BgneZQ7D.js";
5
5
  import path from "node:path";
6
6
  import { spawnSync } from "node:child_process";
7
7
 
@@ -1,7 +1,7 @@
1
1
  import { r as resolveCliName } from "./command-format-BtYOfWxC.js";
2
2
  import { t as resolveSymiPackageRoot } from "./symi-root-BNuQ4lAT.js";
3
3
  import { t as note } from "./note-DDecZomM.js";
4
- import { a as resolveCompletionCachePath, i as isCompletionInstalled, o as resolveShellFromEnv, r as installCompletion, s as usesSlowDynamicCompletion, t as completionCacheExists } from "./completion-cli-g-Vdnude.js";
4
+ import { a as resolveCompletionCachePath, i as isCompletionInstalled, o as resolveShellFromEnv, r as installCompletion, s as usesSlowDynamicCompletion, t as completionCacheExists } from "./completion-cli-CG24rSh8.js";
5
5
  import { spawnSync } from "node:child_process";
6
6
  import path from "node:path";
7
7
 
package/dist/entry.js CHANGED
@@ -2500,7 +2500,7 @@ if (!ensureExperimentalWarningSuppressed()) {
2500
2500
  applyCliProfileEnv({ profile: parsed.profile });
2501
2501
  process$1.argv = parsed.argv;
2502
2502
  }
2503
- import("./run-main-DfxDXt2d.js").then(({ runCli }) => runCli(process$1.argv)).catch((error) => {
2503
+ import("./run-main-D-OIb2fr.js").then(({ runCli }) => runCli(process$1.argv)).catch((error) => {
2504
2504
  console.error("[symi] Failed to start CLI:", error instanceof Error ? error.stack ?? error.message : error);
2505
2505
  process$1.exitCode = 1;
2506
2506
  });
@@ -7,13 +7,13 @@ import { a as resolveAgentIdentity } from "./reply-prefix-K_J_nfgx.js";
7
7
  import "./github-copilot-token-BbsJ0Qbo.js";
8
8
  import "./env-CQ_DQOwT.js";
9
9
  import "./tokens-Cn6drXx2.js";
10
- import { D as resolveAgentTimeoutMs, p as runEmbeddedPiAgent } from "./pi-embedded-BaNpG0Aq.js";
10
+ import { D as resolveAgentTimeoutMs, p as runEmbeddedPiAgent } from "./pi-embedded-BIATvD3R.js";
11
11
  import "./plugins-71oIavrF.js";
12
12
  import "./accounts-DDEyGwby.js";
13
13
  import "./bindings-DYVakimr.js";
14
14
  import "./send-BuJyyJe7.js";
15
15
  import "./send-D8AIYNR_.js";
16
- import "./deliver-B36OzmeP.js";
16
+ import "./deliver-DrC7tG6s.js";
17
17
  import "./diagnostic-D0xmLpej.js";
18
18
  import "./diagnostic-session-state-C1vRJs5w.js";
19
19
  import "./accounts-8zZqL37v.js";
@@ -21,10 +21,10 @@ import "./send-C0K_2AUP.js";
21
21
  import "./image-ops-ByaQt43P.js";
22
22
  import "./pi-model-discovery-j5tVLINv.js";
23
23
  import "./message-channel-BQINJQIT.js";
24
- import { G as saveSessionStore, H as loadSessionStore } from "./pi-embedded-helpers-BET359cH.js";
24
+ import { G as saveSessionStore, H as loadSessionStore } from "./pi-embedded-helpers-D8YgtMdl.js";
25
25
  import "./config-BAVNLbja.js";
26
26
  import "./manifest-registry-DWdYdchb.js";
27
- import "./chrome-BUT--ob3.js";
27
+ import "./chrome-B14NNyfm.js";
28
28
  import "./skills-XEbTRNYL.js";
29
29
  import "./redact-1NGYV_8p.js";
30
30
  import "./errors-CPfngF0S.js";
@@ -34,7 +34,7 @@ import "./thinking-W85Rb32m.js";
34
34
  import "./accounts-DImOt9jX.js";
35
35
  import { n as resolveSessionFilePath, s as resolveStorePath } from "./paths-DkMamAQ-.js";
36
36
  import "./tool-images-ChC2CXaN.js";
37
- import "./image-BHhzdmbq.js";
37
+ import "./image-CKeN0xJL.js";
38
38
  import "./manager-B0BFUVEs.js";
39
39
  import "./gemini-auth-DVcG-42i.js";
40
40
  import "./sqlite-BNh23mUR.js";
@@ -47,7 +47,7 @@ import "./ir-F0moAwIl.js";
47
47
  import "./render-B1VqYyvo.js";
48
48
  import "./commands-registry-D9ZzWaEz.js";
49
49
  import "./skill-commands-CkqZdod4.js";
50
- import "./runner-BVgCl6yZ.js";
50
+ import "./runner-COpebDew.js";
51
51
  import "./fetch-DtLn7YU3.js";
52
52
  import "./channel-activity-D9q-fIPB.js";
53
53
  import "./tables-COnZ169v.js";
@@ -131,12 +131,12 @@ import { n as resolveWideAreaDiscoveryDomain, r as writeWideAreaGatewayZone } fr
131
131
  import { i as toOptionString, n as extractGatewayMiskeys, r as maybeExplainGatewayServiceStop, t as describeUnknownError } from "./shared-BtG9rny3.js";
132
132
  import { c as probeGateway, s as resolveNodeCommandAllowlist } from "./audit-DgAM_dWL.js";
133
133
  import { t as discoverGatewayBeacons } from "./bonjour-discovery-CA_XIzr_.js";
134
- import { i as pickGatewaySelfPresence } from "./status-Ut-dfDT0.js";
135
- import { a as styleHealthChannelLine, l as startHeartbeatRunner, n as getHealthSnapshot, s as runHeartbeatOnce, t as formatHealthChannelLines } from "./health-C7HtwYDj.js";
134
+ import { i as pickGatewaySelfPresence } from "./status-Cg3Vn5FV.js";
135
+ import { a as styleHealthChannelLine, l as startHeartbeatRunner, n as getHealthSnapshot, s as runHeartbeatOnce, t as formatHealthChannelLines } from "./health-D9pKXesa.js";
136
136
  import { a as resolveControlUiRootSync, i as resolveControlUiRootOverrideSync, t as ensureControlUiAssetsBuilt } from "./control-ui-assets-BseSWee1.js";
137
137
  import { a as resolveNpmChannelTag, c as DEFAULT_PACKAGE_CHANNEL, m as normalizeUpdateChannel, n as compareSemverStrings, t as checkUpdateStatus } from "./update-check-ZdimP1aU.js";
138
- import { t as runOnboardingWizard } from "./onboarding-B4qg0ZYp.js";
139
- import { C as startGatewayConfigReloader, S as resolveCronRunLogPath, _ as MAX_PAYLOAD_BYTES, a as loadFavoritesSet, b as abortChatRunById, c as resolveAssistantIdentity, d as formatError, f as loadVoiceWakeConfig, g as MAX_BUFFERED_BYTES, h as HEALTH_REFRESH_INTERVAL_MS, i as safeParseJson, l as listSystemPresence, m as DEDUPE_TTL_MS, n as handleGatewayRequest, o as reconcileFavorites, p as DEDUPE_MAX, r as broadcastPresenceSnapshot, s as DEFAULT_ASSISTANT_IDENTITY, t as coreGatewayHandlers, u as upsertPresence, v as TICK_INTERVAL_MS, x as appendCronRunLog, y as getHandshakeTimeoutMs } from "./server-methods-OJbQNjOJ.js";
138
+ import { t as runOnboardingWizard } from "./onboarding-BHnEBXBG.js";
139
+ import { C as startGatewayConfigReloader, S as resolveCronRunLogPath, _ as MAX_PAYLOAD_BYTES, a as loadFavoritesSet, b as abortChatRunById, c as resolveAssistantIdentity, d as formatError, f as loadVoiceWakeConfig, g as MAX_BUFFERED_BYTES, h as HEALTH_REFRESH_INTERVAL_MS, i as safeParseJson, l as listSystemPresence, m as DEDUPE_TTL_MS, n as handleGatewayRequest, o as reconcileFavorites, p as DEDUPE_MAX, r as broadcastPresenceSnapshot, s as DEFAULT_ASSISTANT_IDENTITY, t as coreGatewayHandlers, u as upsertPresence, v as TICK_INTERVAL_MS, x as appendCronRunLog, y as getHandshakeTimeoutMs } from "./server-methods-Dph_r18S.js";
140
140
  import { d as shouldLogWs, f as summarizeAgentEventForWsLog, l as formatForLog, p as setGatewayWsLogStyle, u as logWs } from "./push-apns-CL2MBhWP.js";
141
141
  import { T as resolveGmailHookRuntimeConfig, _ as buildGogWatchServeArgs, i as ensureTailscaleEndpoint, v as buildGogWatchStartArgs } from "./gmail-setup-utils-CzWeiE-Y.js";
142
142
  import "./agents.config-DIjsIDbS.js";
@@ -11954,7 +11954,7 @@ async function startGatewayServer(port = 18789, opts = {}) {
11954
11954
  });
11955
11955
  let glassUiBridgeCleanup = null;
11956
11956
  if (!minimalTestGateway) {
11957
- const { createGlassUiBridge } = await import("./glass-ui-ws-Cm-WtdFI.js");
11957
+ const { createGlassUiBridge } = await import("./glass-ui-ws-Bgpyl16w.js");
11958
11958
  glassUiBridgeCleanup = createGlassUiBridge({
11959
11959
  wss: glassUiWss,
11960
11960
  context: gatewayRequestContext,
@@ -136,12 +136,12 @@ import { n as resolveWideAreaDiscoveryDomain, r as writeWideAreaGatewayZone } fr
136
136
  import { i as toOptionString, n as extractGatewayMiskeys, r as maybeExplainGatewayServiceStop, t as describeUnknownError } from "./shared-DnmJ0ABB.js";
137
137
  import { c as probeGateway, s as resolveNodeCommandAllowlist } from "./audit-DVUHZrf4.js";
138
138
  import { t as discoverGatewayBeacons } from "./bonjour-discovery-DUQ6tE92.js";
139
- import { r as pickGatewaySelfPresence } from "./status-RlJA2XzQ.js";
140
- import { c as startHeartbeatRunner, i as styleHealthChannelLine, n as getHealthSnapshot, o as runHeartbeatOnce, t as formatHealthChannelLines } from "./health-Bx8UUqFA.js";
139
+ import { r as pickGatewaySelfPresence } from "./status-Bbss-JjB.js";
140
+ import { c as startHeartbeatRunner, i as styleHealthChannelLine, n as getHealthSnapshot, o as runHeartbeatOnce, t as formatHealthChannelLines } from "./health-Bj8mUXDd.js";
141
141
  import { a as resolveControlUiRootSync, i as resolveControlUiRootOverrideSync, t as ensureControlUiAssetsBuilt } from "./control-ui-assets-B7moDVHX.js";
142
142
  import { a as resolveNpmChannelTag, c as DEFAULT_PACKAGE_CHANNEL, m as normalizeUpdateChannel, n as compareSemverStrings, t as checkUpdateStatus } from "./update-check-7EzEjSzb.js";
143
- import { t as runOnboardingWizard } from "./onboarding-C89rTOOy.js";
144
- import { C as startGatewayConfigReloader, S as resolveCronRunLogPath, _ as MAX_PAYLOAD_BYTES, a as loadFavoritesSet, b as abortChatRunById, c as resolveAssistantIdentity, d as formatError, f as loadVoiceWakeConfig, g as MAX_BUFFERED_BYTES, h as HEALTH_REFRESH_INTERVAL_MS, i as safeParseJson, l as listSystemPresence, m as DEDUPE_TTL_MS, n as handleGatewayRequest, o as reconcileFavorites, p as DEDUPE_MAX, r as broadcastPresenceSnapshot, s as DEFAULT_ASSISTANT_IDENTITY, t as coreGatewayHandlers, u as upsertPresence, v as TICK_INTERVAL_MS, x as appendCronRunLog, y as getHandshakeTimeoutMs } from "./server-methods-BcBroG6v.js";
143
+ import { t as runOnboardingWizard } from "./onboarding-CchD1d-n.js";
144
+ import { C as startGatewayConfigReloader, S as resolveCronRunLogPath, _ as MAX_PAYLOAD_BYTES, a as loadFavoritesSet, b as abortChatRunById, c as resolveAssistantIdentity, d as formatError, f as loadVoiceWakeConfig, g as MAX_BUFFERED_BYTES, h as HEALTH_REFRESH_INTERVAL_MS, i as safeParseJson, l as listSystemPresence, m as DEDUPE_TTL_MS, n as handleGatewayRequest, o as reconcileFavorites, p as DEDUPE_MAX, r as broadcastPresenceSnapshot, s as DEFAULT_ASSISTANT_IDENTITY, t as coreGatewayHandlers, u as upsertPresence, v as TICK_INTERVAL_MS, x as appendCronRunLog, y as getHandshakeTimeoutMs } from "./server-methods-b55BoGQD.js";
145
145
  import { d as shouldLogWs, f as summarizeAgentEventForWsLog, l as formatForLog, p as setGatewayWsLogStyle, u as logWs } from "./push-apns-DUWtWoB-.js";
146
146
  import { T as resolveGmailHookRuntimeConfig, _ as buildGogWatchServeArgs, i as ensureTailscaleEndpoint, v as buildGogWatchStartArgs } from "./gmail-setup-utils-Dq6vwkWW.js";
147
147
  import "./agents.config-D0ih9tP3.js";
@@ -11958,7 +11958,7 @@ async function startGatewayServer(port = 18789, opts = {}) {
11958
11958
  });
11959
11959
  let glassUiBridgeCleanup = null;
11960
11960
  if (!minimalTestGateway) {
11961
- const { createGlassUiBridge } = await import("./glass-ui-ws-BzBtCYP7.js");
11961
+ const { createGlassUiBridge } = await import("./glass-ui-ws-aKGCf5hN.js");
11962
11962
  glassUiBridgeCleanup = createGlassUiBridge({
11963
11963
  wss: glassUiWss,
11964
11964
  context: gatewayRequestContext,
@@ -109,11 +109,11 @@ import "./service-Cm9j9WzQ.js";
109
109
  import "./diagnostics-CS1ov_hH.js";
110
110
  import "./table-D01d2GuY.js";
111
111
  import "./audit-DgAM_dWL.js";
112
- import "./status-Ut-dfDT0.js";
113
- import "./health-C7HtwYDj.js";
112
+ import "./status-Cg3Vn5FV.js";
113
+ import "./health-D9pKXesa.js";
114
114
  import "./control-ui-assets-BseSWee1.js";
115
115
  import "./update-check-ZdimP1aU.js";
116
- import { n as handleGatewayRequest } from "./server-methods-OJbQNjOJ.js";
116
+ import { n as handleGatewayRequest } from "./server-methods-Dph_r18S.js";
117
117
  import "./push-apns-CL2MBhWP.js";
118
118
  import "./agents.config-DIjsIDbS.js";
119
119
  import "./dm-policy-shared-DF2uLfXk.js";
@@ -114,11 +114,11 @@ import "./service-osK70kTZ.js";
114
114
  import "./diagnostics-BRwihzJG.js";
115
115
  import "./table-BKlH0YlA.js";
116
116
  import "./audit-DVUHZrf4.js";
117
- import "./status-RlJA2XzQ.js";
118
- import "./health-Bx8UUqFA.js";
117
+ import "./status-Bbss-JjB.js";
118
+ import "./health-Bj8mUXDd.js";
119
119
  import "./control-ui-assets-B7moDVHX.js";
120
120
  import "./update-check-7EzEjSzb.js";
121
- import { n as handleGatewayRequest } from "./server-methods-BcBroG6v.js";
121
+ import { n as handleGatewayRequest } from "./server-methods-b55BoGQD.js";
122
122
  import "./push-apns-DUWtWoB-.js";
123
123
  import "./agents.config-D0ih9tP3.js";
124
124
  import "./dm-policy-shared-DwFEXR-I.js";
@@ -272,6 +272,33 @@ function resolveHeartbeatSession(cfg, agentId, heartbeat, forcedSessionKey) {
272
272
  entry: mainEntry
273
273
  };
274
274
  }
275
+ /**
276
+ * Resolve the session key the agent loop runs against during a Symipulse tick.
277
+ *
278
+ * This is deliberately split from the "anchor" session key returned by
279
+ * resolveHeartbeatSession(). The anchor is the user's main session — it carries
280
+ * delivery-target tracking (target: "last"), dedupe state (lastHeartbeatText),
281
+ * and channel context. The **runtime** session is where the agent's own
282
+ * transcript lives during the pulse.
283
+ *
284
+ * Running the pulse against an ephemeral `agent:<id>:symipulse` session prevents
285
+ * the symighost-style runaway-loop failure mode: every tick re-prefilling a
286
+ * growing user-conversation transcript against a heavyweight backend. With this
287
+ * split, the pulse transcript stays pulse-sized; the user's main session is
288
+ * never touched by the pulse loop.
289
+ *
290
+ * Two opt-outs keep legacy semantics intact:
291
+ * - `opts.sessionKey` forced by the caller (wake events)
292
+ * - `heartbeat.session` in config
293
+ * Both cause the pulse to run against the anchor key, preserving any deployment
294
+ * that deliberately wires the pulse into a specific session.
295
+ */
296
+ function resolveSymipulseRuntimeSessionKey(params) {
297
+ if (params.forcedSessionKey?.trim()) return params.anchorSessionKey;
298
+ if (params.heartbeat?.session?.trim()) return params.anchorSessionKey;
299
+ if ((params.cfg.session?.scope ?? "per-sender") === "global") return "symipulse";
300
+ return `agent:${normalizeAgentId(params.agentId)}:symipulse`;
301
+ }
275
302
  function resolveHeartbeatReasoningPayloads(replyResult) {
276
303
  return (Array.isArray(replyResult) ? replyResult : replyResult ? [replyResult] : []).filter((payload) => {
277
304
  return (typeof payload.text === "string" ? payload.text : "").trimStart().startsWith("Reasoning:");
@@ -431,9 +458,16 @@ async function runHeartbeatOnce(opts) {
431
458
  reason: preflight.skipReason
432
459
  };
433
460
  }
434
- const { entry, sessionKey, storePath } = preflight.session;
461
+ const { entry, sessionKey, storePath, store } = preflight.session;
435
462
  const { isCronEventReason, pendingEventEntries } = preflight;
436
- const previousUpdatedAt = entry?.updatedAt;
463
+ const runtimeSessionKey = resolveSymipulseRuntimeSessionKey({
464
+ cfg,
465
+ agentId,
466
+ anchorSessionKey: sessionKey,
467
+ heartbeat,
468
+ forcedSessionKey: opts.sessionKey
469
+ });
470
+ const previousRuntimeUpdatedAt = store[runtimeSessionKey]?.updatedAt;
437
471
  const delivery = resolveHeartbeatDeliveryTarget({
438
472
  cfg,
439
473
  entry,
@@ -476,7 +510,7 @@ async function runHeartbeatOnce(opts) {
476
510
  From: sender,
477
511
  To: sender,
478
512
  Provider: hasExecCompletion ? "exec-event" : hasCronEvents ? "cron-event" : "heartbeat",
479
- SessionKey: sessionKey
513
+ SessionKey: runtimeSessionKey
480
514
  };
481
515
  if (!visibility.showAlerts && !visibility.showOk && !visibility.useIndicator) {
482
516
  emitHeartbeatEvent({
@@ -518,7 +552,7 @@ async function runHeartbeatOnce(opts) {
518
552
  try {
519
553
  const transcriptState = await captureTranscriptState({
520
554
  storePath,
521
- sessionKey,
555
+ sessionKey: runtimeSessionKey,
522
556
  agentId
523
557
  });
524
558
  const heartbeatModelOverride = heartbeat?.model?.trim() || void 0;
@@ -536,8 +570,8 @@ async function runHeartbeatOnce(opts) {
536
570
  if (!replyPayload || !replyPayload.text && !replyPayload.mediaUrl && !replyPayload.mediaUrls?.length) {
537
571
  await restoreHeartbeatUpdatedAt({
538
572
  storePath,
539
- sessionKey,
540
- updatedAt: previousUpdatedAt
573
+ sessionKey: runtimeSessionKey,
574
+ updatedAt: previousRuntimeUpdatedAt
541
575
  });
542
576
  await pruneHeartbeatTranscript(transcriptState);
543
577
  const okSent = await maybeSendHeartbeatOk();
@@ -565,8 +599,8 @@ async function runHeartbeatOnce(opts) {
565
599
  if (shouldSkipMain && reasoningPayloads.length === 0) {
566
600
  await restoreHeartbeatUpdatedAt({
567
601
  storePath,
568
- sessionKey,
569
- updatedAt: previousUpdatedAt
602
+ sessionKey: runtimeSessionKey,
603
+ updatedAt: previousRuntimeUpdatedAt
570
604
  });
571
605
  await pruneHeartbeatTranscript(transcriptState);
572
606
  const okSent = await maybeSendHeartbeatOk();
@@ -590,8 +624,8 @@ async function runHeartbeatOnce(opts) {
590
624
  if (!shouldSkipMain && !mediaUrls.length && Boolean(prevHeartbeatText.trim()) && normalized.text.trim() === prevHeartbeatText.trim() && typeof prevHeartbeatAt === "number" && startedAt - prevHeartbeatAt < 1440 * 60 * 1e3) {
591
625
  await restoreHeartbeatUpdatedAt({
592
626
  storePath,
593
- sessionKey,
594
- updatedAt: previousUpdatedAt
627
+ sessionKey: runtimeSessionKey,
628
+ updatedAt: previousRuntimeUpdatedAt
595
629
  });
596
630
  await pruneHeartbeatTranscript(transcriptState);
597
631
  emitHeartbeatEvent({
@@ -626,8 +660,8 @@ async function runHeartbeatOnce(opts) {
626
660
  if (!visibility.showAlerts) {
627
661
  await restoreHeartbeatUpdatedAt({
628
662
  storePath,
629
- sessionKey,
630
- updatedAt: previousUpdatedAt
663
+ sessionKey: runtimeSessionKey,
664
+ updatedAt: previousRuntimeUpdatedAt
631
665
  });
632
666
  emitHeartbeatEvent({
633
667
  status: "skipped",
@@ -271,6 +271,33 @@ function resolveHeartbeatSession(cfg, agentId, heartbeat, forcedSessionKey) {
271
271
  entry: mainEntry
272
272
  };
273
273
  }
274
+ /**
275
+ * Resolve the session key the agent loop runs against during a Symipulse tick.
276
+ *
277
+ * This is deliberately split from the "anchor" session key returned by
278
+ * resolveHeartbeatSession(). The anchor is the user's main session — it carries
279
+ * delivery-target tracking (target: "last"), dedupe state (lastHeartbeatText),
280
+ * and channel context. The **runtime** session is where the agent's own
281
+ * transcript lives during the pulse.
282
+ *
283
+ * Running the pulse against an ephemeral `agent:<id>:symipulse` session prevents
284
+ * the symighost-style runaway-loop failure mode: every tick re-prefilling a
285
+ * growing user-conversation transcript against a heavyweight backend. With this
286
+ * split, the pulse transcript stays pulse-sized; the user's main session is
287
+ * never touched by the pulse loop.
288
+ *
289
+ * Two opt-outs keep legacy semantics intact:
290
+ * - `opts.sessionKey` forced by the caller (wake events)
291
+ * - `heartbeat.session` in config
292
+ * Both cause the pulse to run against the anchor key, preserving any deployment
293
+ * that deliberately wires the pulse into a specific session.
294
+ */
295
+ function resolveSymipulseRuntimeSessionKey(params) {
296
+ if (params.forcedSessionKey?.trim()) return params.anchorSessionKey;
297
+ if (params.heartbeat?.session?.trim()) return params.anchorSessionKey;
298
+ if ((params.cfg.session?.scope ?? "per-sender") === "global") return "symipulse";
299
+ return `agent:${normalizeAgentId(params.agentId)}:symipulse`;
300
+ }
274
301
  function resolveHeartbeatReasoningPayloads(replyResult) {
275
302
  return (Array.isArray(replyResult) ? replyResult : replyResult ? [replyResult] : []).filter((payload) => {
276
303
  return (typeof payload.text === "string" ? payload.text : "").trimStart().startsWith("Reasoning:");
@@ -430,9 +457,16 @@ async function runHeartbeatOnce(opts) {
430
457
  reason: preflight.skipReason
431
458
  };
432
459
  }
433
- const { entry, sessionKey, storePath } = preflight.session;
460
+ const { entry, sessionKey, storePath, store } = preflight.session;
434
461
  const { isCronEventReason, pendingEventEntries } = preflight;
435
- const previousUpdatedAt = entry?.updatedAt;
462
+ const runtimeSessionKey = resolveSymipulseRuntimeSessionKey({
463
+ cfg,
464
+ agentId,
465
+ anchorSessionKey: sessionKey,
466
+ heartbeat,
467
+ forcedSessionKey: opts.sessionKey
468
+ });
469
+ const previousRuntimeUpdatedAt = store[runtimeSessionKey]?.updatedAt;
436
470
  const delivery = resolveHeartbeatDeliveryTarget({
437
471
  cfg,
438
472
  entry,
@@ -475,7 +509,7 @@ async function runHeartbeatOnce(opts) {
475
509
  From: sender,
476
510
  To: sender,
477
511
  Provider: hasExecCompletion ? "exec-event" : hasCronEvents ? "cron-event" : "heartbeat",
478
- SessionKey: sessionKey
512
+ SessionKey: runtimeSessionKey
479
513
  };
480
514
  if (!visibility.showAlerts && !visibility.showOk && !visibility.useIndicator) {
481
515
  emitHeartbeatEvent({
@@ -517,7 +551,7 @@ async function runHeartbeatOnce(opts) {
517
551
  try {
518
552
  const transcriptState = await captureTranscriptState({
519
553
  storePath,
520
- sessionKey,
554
+ sessionKey: runtimeSessionKey,
521
555
  agentId
522
556
  });
523
557
  const heartbeatModelOverride = heartbeat?.model?.trim() || void 0;
@@ -535,8 +569,8 @@ async function runHeartbeatOnce(opts) {
535
569
  if (!replyPayload || !replyPayload.text && !replyPayload.mediaUrl && !replyPayload.mediaUrls?.length) {
536
570
  await restoreHeartbeatUpdatedAt({
537
571
  storePath,
538
- sessionKey,
539
- updatedAt: previousUpdatedAt
572
+ sessionKey: runtimeSessionKey,
573
+ updatedAt: previousRuntimeUpdatedAt
540
574
  });
541
575
  await pruneHeartbeatTranscript(transcriptState);
542
576
  const okSent = await maybeSendHeartbeatOk();
@@ -564,8 +598,8 @@ async function runHeartbeatOnce(opts) {
564
598
  if (shouldSkipMain && reasoningPayloads.length === 0) {
565
599
  await restoreHeartbeatUpdatedAt({
566
600
  storePath,
567
- sessionKey,
568
- updatedAt: previousUpdatedAt
601
+ sessionKey: runtimeSessionKey,
602
+ updatedAt: previousRuntimeUpdatedAt
569
603
  });
570
604
  await pruneHeartbeatTranscript(transcriptState);
571
605
  const okSent = await maybeSendHeartbeatOk();
@@ -589,8 +623,8 @@ async function runHeartbeatOnce(opts) {
589
623
  if (!shouldSkipMain && !mediaUrls.length && Boolean(prevHeartbeatText.trim()) && normalized.text.trim() === prevHeartbeatText.trim() && typeof prevHeartbeatAt === "number" && startedAt - prevHeartbeatAt < 1440 * 60 * 1e3) {
590
624
  await restoreHeartbeatUpdatedAt({
591
625
  storePath,
592
- sessionKey,
593
- updatedAt: previousUpdatedAt
626
+ sessionKey: runtimeSessionKey,
627
+ updatedAt: previousRuntimeUpdatedAt
594
628
  });
595
629
  await pruneHeartbeatTranscript(transcriptState);
596
630
  emitHeartbeatEvent({
@@ -625,8 +659,8 @@ async function runHeartbeatOnce(opts) {
625
659
  if (!visibility.showAlerts) {
626
660
  await restoreHeartbeatUpdatedAt({
627
661
  storePath,
628
- sessionKey,
629
- updatedAt: previousUpdatedAt
662
+ sessionKey: runtimeSessionKey,
663
+ updatedAt: previousRuntimeUpdatedAt
630
664
  });
631
665
  emitHeartbeatEvent({
632
666
  status: "skipped",