@symerian/symi 2.6.42 → 2.7.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.
Files changed (204) hide show
  1. package/dist/{acp-cli-CrEIx-c7.js → acp-cli-B2f0qBiM.js} +2 -2
  2. package/dist/{acp-cli-BLUeUUA5.js → acp-cli-D-9rzaOI.js} +2 -2
  3. package/dist/{agents-DDRDszOI.js → agents-Z8ruJPz2.js} +5 -5
  4. package/dist/{agents.config-BEVb1Pyx.js → agents.config-B9BZoM2m.js} +1 -1
  5. package/dist/{agents.config-BKCY6F2A.js → agents.config-C951ocyh.js} +1 -1
  6. package/dist/{audio-preflight-DD18zIZd.js → audio-preflight-HILy3i0m.js} +4 -4
  7. package/dist/{audit-DB9YkTVX.js → audit-BgdM9XZl.js} +2 -2
  8. package/dist/{audit-BjI_Yyr5.js → audit-xSagQWH8.js} +2 -2
  9. package/dist/{auth-choice-D2xXwBeN.js → auth-choice-BmYi6pBy.js} +2 -2
  10. package/dist/{auth-choice-BbzReh6k.js → auth-choice-D_VfXxhG.js} +2 -2
  11. package/dist/{banner-DqqRwplt.js → banner-Bucr6qZ5.js} +1 -1
  12. package/dist/{browser-cli-kDUw45Y0.js → browser-cli-Bc_JVdTj.js} +3 -3
  13. package/dist/{browser-cli-Ctn9do4z.js → browser-cli-Dr0yx7-7.js} +3 -3
  14. package/dist/build-info.json +3 -3
  15. package/dist/bundled/boot-md/handler.js +1 -1
  16. package/dist/bundled/session-memory/handler.js +1 -1
  17. package/dist/{call-DwpGquzW.js → call-CX0cs106.js} +1 -1
  18. package/dist/{call-DKi-hnaF.js → call-DeCQ2DhS.js} +1 -1
  19. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  20. package/dist/{channel-options-DQcpDVCx.js → channel-options-BMDryXHq.js} +1 -1
  21. package/dist/{channel-options-DcazVJQf.js → channel-options-z8-WeZyO.js} +1 -1
  22. package/dist/{channel-web-u5yMYO4j.js → channel-web-D_YxZAHT.js} +1 -1
  23. package/dist/{channels-cli-C3iJE8eg.js → channels-cli-397NgC51.js} +7 -7
  24. package/dist/{channels-cli-Bog4Kn3X.js → channels-cli-CV7_JUru.js} +7 -7
  25. package/dist/{chrome-BxwUEWrH.js → chrome-CiOKaTN-.js} +7 -7
  26. package/dist/cli/daemon-cli.js +1 -1
  27. package/dist/{cli-eBtEEHLK.js → cli-4XU7pNlM.js} +4 -4
  28. package/dist/{cli-QybdZdE7.js → cli-Dq95udFO.js} +4 -4
  29. package/dist/{client-jI1oE0_k.js → client-B8xmq-Pw.js} +13 -1
  30. package/dist/{client-T3qcxXru.js → client-qUlxXXVJ.js} +13 -1
  31. package/dist/{command-registry-BWnZSpbL.js → command-registry-Cx9T7GYx.js} +10 -10
  32. package/dist/{completion-cli-BhJFXaVU.js → completion-cli-WlSuySPZ.js} +1 -1
  33. package/dist/{completion-cli-CUKm7Hb6.js → completion-cli-cyVjlhls.js} +2 -2
  34. package/dist/{config-cli-B796xZBe.js → config-cli-CMymzmrI.js} +1 -1
  35. package/dist/{config-cli-CjnQyv45.js → config-cli-EdmbBExA.js} +1 -1
  36. package/dist/{configure-D3wIQ0yI.js → configure-DRMAIBBf.js} +6 -6
  37. package/dist/{configure-DUqT7Dyn.js → configure-DkFujfiY.js} +6 -6
  38. package/dist/control-ui/css/style.css +165 -0
  39. package/dist/control-ui/js/app.js +39 -0
  40. package/dist/control-ui/js/gateway.js +2 -0
  41. package/dist/control-ui/js/history.js +220 -85
  42. package/dist/control-ui/js/settings.js +71 -8
  43. package/dist/{cron-cli-DCpsXkrw.js → cron-cli-BHxfvWeT.js} +3 -3
  44. package/dist/{cron-cli-QCTdVZuP.js → cron-cli-DacyI1Pw.js} +3 -3
  45. package/dist/{daemon-cli-DSDcmWOi.js → daemon-cli-BLhFbih0.js} +2 -2
  46. package/dist/{daemon-cli-DhJYEAoL.js → daemon-cli-BxKtiouf.js} +2 -2
  47. package/dist/daemon-cli.js +12 -0
  48. package/dist/{deliver-DtuY4Wgl.js → deliver-D6IcPfbt.js} +1 -1
  49. package/dist/{devices-cli-BNG-fvdl.js → devices-cli-1kiO08aL.js} +2 -2
  50. package/dist/{devices-cli-x3jIP4Ih.js → devices-cli-B8Q8AzbX.js} +2 -2
  51. package/dist/{doctor-completion-DBE1IVKj.js → doctor-completion-BDzhB9pE.js} +1 -1
  52. package/dist/{doctor-completion-D3oUNFQM.js → doctor-completion-CfeROjIz.js} +1 -1
  53. package/dist/entry.js +1 -1
  54. package/dist/{exec-approvals-cli-CmndFjEA.js → exec-approvals-cli-BRx2oxs5.js} +4 -4
  55. package/dist/{exec-approvals-cli-BSgxsdMt.js → exec-approvals-cli-Cj6Z-vxL.js} +4 -4
  56. package/dist/extensionAPI.js +6 -6
  57. package/dist/{gateway-cli-BguO9yV4.js → gateway-cli-C-G0QrTd.js} +185 -81
  58. package/dist/{gateway-cli-Dc1RT_b9.js → gateway-cli-Cpn7JyAw.js} +185 -81
  59. package/dist/{gateway-rpc-BMdVa3QV.js → gateway-rpc-BWTK7g8B.js} +1 -1
  60. package/dist/{gateway-rpc-5fREQe9Q.js → gateway-rpc-WM-HXUbl.js} +1 -1
  61. package/dist/{glass-ui-ws-DoIZyE9O.js → glass-ui-ws-BI81Lh6Z.js} +32 -13
  62. package/dist/{glass-ui-ws-D0UYleBF.js → glass-ui-ws-jAbqZVc9.js} +32 -13
  63. package/dist/{health-D3w4YMlC.js → health-B1nih5LD.js} +2 -2
  64. package/dist/{health-cVvZdeDu.js → health-CsTxt66a.js} +2 -2
  65. package/dist/{hooks-cli-te5hzOAB.js → hooks-cli-BhxMFkKe.js} +5 -5
  66. package/dist/{hooks-cli-DZIbjfOA.js → hooks-cli-CIlvtt2M.js} +5 -5
  67. package/dist/{image-lp19FlzF.js → image-D7Fl08gG.js} +1 -1
  68. package/dist/index.js +9 -9
  69. package/dist/llm-slug-generator.js +1 -1
  70. package/dist/{logs-cli-DtlrLf7u.js → logs-cli-BZV7dq_U.js} +3 -3
  71. package/dist/{logs-cli-CfGj-dOg.js → logs-cli-DyCcDkRs.js} +3 -3
  72. package/dist/{models-BCfPhQ4m.js → models-DhMe2rzL.js} +3 -3
  73. package/dist/{models-cli-BFAtjNIF.js → models-cli-DKM5sCQM.js} +5 -5
  74. package/dist/{models-cli-Cj2CwbPw.js → models-cli-Dewg24W2.js} +6 -6
  75. package/dist/{node-cli-DnfDOh1d.js → node-cli-4eMRkmrw.js} +1 -1
  76. package/dist/{node-cli-eHn9-YfJ.js → node-cli-Dfs0UmnJ.js} +1 -1
  77. package/dist/{nodes-cli-Ct4M7JOe.js → nodes-cli-BKb61OjH.js} +3 -3
  78. package/dist/{nodes-cli-Ci3oxw8k.js → nodes-cli-DxfP9DIz.js} +3 -3
  79. package/dist/{onboard-BMq8qc1m.js → onboard-Dw_nX2RD.js} +3 -3
  80. package/dist/{onboard-channels-B5wgcffj.js → onboard-channels-8ynJSZL6.js} +1 -1
  81. package/dist/{onboard-channels-CiOun4k1.js → onboard-channels-ChxtmhFY.js} +1 -1
  82. package/dist/{onboard-helpers-DFvWPFhU.js → onboard-helpers-CueJ7O_B.js} +1 -1
  83. package/dist/{onboard-helpers-BBtPmJEe.js → onboard-helpers-PpGrZIGw.js} +1 -1
  84. package/dist/{onboard-remote-BURDxwoE.js → onboard-remote-Cd9kIiSG.js} +1 -1
  85. package/dist/{onboard-remote-D-B4EiOE.js → onboard-remote-DCdpB2HH.js} +1 -1
  86. package/dist/{onboard-skills-BDCzVjxb.js → onboard-skills-CC2CV5Er.js} +1 -1
  87. package/dist/{onboard-skills-CbzgBT1W.js → onboard-skills-DRICcBwa.js} +1 -1
  88. package/dist/{onboard-VcdBF5TB.js → onboard-yrgbC1mu.js} +3 -3
  89. package/dist/{onboarding-Dp7p6zKa.js → onboarding-BJcYsOFw.js} +7 -7
  90. package/dist/{onboarding-CGNpTyg2.js → onboarding-e-RSXpUi.js} +7 -7
  91. package/dist/{onboarding.finalize-B6DOu8vp.js → onboarding.finalize-CKNdiZEZ.js} +9 -9
  92. package/dist/{onboarding.finalize-CrsE5P43.js → onboarding.finalize-DenYTWUu.js} +10 -10
  93. package/dist/{onboarding.gateway-config-DKwJ5bWd.js → onboarding.gateway-config-DTWQ-Bqq.js} +3 -3
  94. package/dist/{onboarding.gateway-config-B9zGPfCl.js → onboarding.gateway-config-Dj68bVBt.js} +3 -3
  95. package/dist/{pi-embedded-DQe8vBwU.js → pi-embedded-BzS693I1.js} +72 -21
  96. package/dist/{pi-embedded-helpers-Dij3O6ox.js → pi-embedded-helpers-DXAoe1Bx.js} +4 -4
  97. package/dist/{plugin-registry-BzIbwU3K.js → plugin-registry-Bzz7mUyl.js} +1 -1
  98. package/dist/{plugin-registry-D3TUplW8.js → plugin-registry-SUa2FFIj.js} +1 -1
  99. package/dist/plugin-sdk/{channel-web-B6m8UOCl.js → channel-web-DRabhx1e.js} +1 -1
  100. package/dist/plugin-sdk/gateway/protocol/index.d.ts +13 -2
  101. package/dist/plugin-sdk/gateway/protocol/schema/sessions.d.ts +11 -0
  102. package/dist/plugin-sdk/gateway/protocol/schema/types.d.ts +4 -1
  103. package/dist/plugin-sdk/index.js +2 -2
  104. package/dist/plugin-sdk/{reply-CGoJQT_s.js → reply-Cw3shPk2.js} +58 -7
  105. package/dist/plugin-sdk/{web-CJjSOTnI.js → web-CH43nBP0.js} +2 -2
  106. package/dist/{plugins-cli-BD1Jb2Ml.js → plugins-cli-DwtoU3xk.js} +5 -5
  107. package/dist/{plugins-cli-DFyRjAtJ.js → plugins-cli-qG50__1A.js} +5 -5
  108. package/dist/{program-context-45vPEw2G.js → program-context-CZwy-bh6.js} +29 -29
  109. package/dist/{program-qGm2M9PG.js → program-mZOVTSdQ.js} +10 -10
  110. package/dist/{prompt-select-styled-DRIS9jSv.js → prompt-select-styled-BZnuv8jI.js} +6 -6
  111. package/dist/{prompt-select-styled-DRraJGwA.js → prompt-select-styled-CtNg5KGU.js} +6 -6
  112. package/dist/{provider-auth-helpers-BNOWsjW5.js → provider-auth-helpers-CEYCb2mJ.js} +1 -1
  113. package/dist/{provider-auth-helpers-BREVjR7R.js → provider-auth-helpers-D60nbSLq.js} +1 -1
  114. package/dist/{push-apns-CYC70eKy.js → push-apns-B5txhDVi.js} +1 -1
  115. package/dist/{push-apns-CObVeJLC.js → push-apns-CoG1P_P0.js} +1 -1
  116. package/dist/{pw-ai-BO5cSmwD.js → pw-ai-CANiWpMA.js} +1 -1
  117. package/dist/{register.agent-DzzY8jON.js → register.agent-BY_Df_Me.js} +9 -9
  118. package/dist/{register.agent-DRrHvYcz.js → register.agent-CopGIf9e.js} +8 -8
  119. package/dist/{register.configure-DlXkwkNR.js → register.configure-Bu_XKu7Z.js} +11 -11
  120. package/dist/{register.configure-BxtTIFTa.js → register.configure-CoYQhQBT.js} +11 -11
  121. package/dist/{register.maintenance-LEf8Q_5p.js → register.maintenance-BtqQ3hDN.js} +11 -11
  122. package/dist/{register.maintenance-CXLXouZV.js → register.maintenance-VqCqhB7y.js} +10 -10
  123. package/dist/{register.message-DsPa-xHV.js → register.message-DZCCEK01.js} +5 -5
  124. package/dist/{register.message-C4ifV9vG.js → register.message-dd1xYBZT.js} +5 -5
  125. package/dist/{register.onboard-CrY4PxLP.js → register.onboard-B6EL1d-C.js} +7 -7
  126. package/dist/{register.onboard-DLRPa_4B.js → register.onboard-lzwHKufI.js} +7 -7
  127. package/dist/{register.setup-fBG_dJfi.js → register.setup-BJsr5_qp.js} +7 -7
  128. package/dist/{register.setup-By37g1vN.js → register.setup-D_b_HW5D.js} +7 -7
  129. package/dist/{register.status-health-sessions-DG7KGnD0.js → register.status-health-sessions-Dvj4mlom.js} +7 -7
  130. package/dist/{register.status-health-sessions-Ckw86-gn.js → register.status-health-sessions-jeiqtgl7.js} +7 -7
  131. package/dist/{register.subclis-C_xKLugM.js → register.subclis-DdPRkz29.js} +20 -20
  132. package/dist/{reply-DyjXROKp.js → reply-XaXqDK9F.js} +49 -10
  133. package/dist/{rpc-Co5PQ3IJ.js → rpc-N1nf_c1A.js} +1 -1
  134. package/dist/{rpc-D0FiEinj.js → rpc-QHo-8pCM.js} +1 -1
  135. package/dist/{run-main-Cg3ecTbO.js → run-main-MhL-xG3_.js} +17 -17
  136. package/dist/{runner-Ct0suQrd.js → runner-BS9gGL5i.js} +1 -1
  137. package/dist/{security-cli-D5BWzqEJ.js → security-cli-B-4J6enu.js} +3 -3
  138. package/dist/{security-cli-CG1uSlRK.js → security-cli-CSMUEGPK.js} +3 -3
  139. package/dist/{server-methods-CWcLut3F.js → server-methods-0ksPFnev.js} +471 -88
  140. package/dist/{server-methods-CW8eFTGD.js → server-methods-Bu1RjLe6.js} +471 -88
  141. package/dist/{server-node-events-C2h9OPo7.js → server-node-events-DCbzFyQF.js} +5 -5
  142. package/dist/{server-node-events-CDB0u8PP.js → server-node-events-DZAN3hWE.js} +5 -5
  143. package/dist/{status-B2Qt-5kL.js → status-CiHkFbIh.js} +1 -1
  144. package/dist/{status-ZPW5EACm.js → status-DOTlXdcN.js} +5 -5
  145. package/dist/{status-CMx3GAax.js → status-IWqSLXLR.js} +1 -1
  146. package/dist/{status-DfPfMVNZ.js → status-qkmUAeWo.js} +5 -5
  147. package/dist/{subagent-registry-DQHg3jUV.js → subagent-registry-DCoU9xIE.js} +49 -10
  148. package/dist/{system-cli-DFZNGx0i.js → system-cli-DY7ov1OT.js} +3 -3
  149. package/dist/{system-cli-Z7uzO8qd.js → system-cli-LFURKpwS.js} +3 -3
  150. package/dist/{tui-DjPsMdL6.js → tui-BH7JwqvB.js} +2 -2
  151. package/dist/{tui-DrATGNms.js → tui-C_5HG495.js} +2 -2
  152. package/dist/{tui-cli-D19-MCXt.js → tui-cli-B65PKZMj.js} +3 -3
  153. package/dist/{tui-cli-pWD_NrUR.js → tui-cli-CJnfmuxq.js} +3 -3
  154. package/dist/{unified-runner-DvOFqcrw.js → unified-runner-CApgXtVC.js} +58 -7
  155. package/dist/{update-cli-Df9rh_aN.js → update-cli-Bi6iMCXr.js} +11 -11
  156. package/dist/{update-cli-DBasZeVl.js → update-cli-BjQ3o9gQ.js} +12 -12
  157. package/dist/{update-runner-DVa6cMqp.js → update-runner-BhVsdpxm.js} +1 -1
  158. package/dist/{update-runner-BRKFzAwV.js → update-runner-FhW6n-Nv.js} +1 -1
  159. package/dist/{web-Dd05xbUr.js → web-ConlA_Ch.js} +4 -4
  160. package/dist/{web-Cw3bFAiP.js → web-CthDLVSz.js} +1 -1
  161. package/dist/{web-CGh5tw__.js → web-Db_-ahjX.js} +6 -6
  162. package/dist/{web-KiuDkd0x.js → web-Dpb_tv_j.js} +5 -5
  163. package/extensions/bluebubbles/package.json +1 -1
  164. package/extensions/copilot-proxy/package.json +1 -1
  165. package/extensions/diagnostics-otel/package.json +1 -1
  166. package/extensions/discord/package.json +1 -1
  167. package/extensions/feishu/package.json +1 -1
  168. package/extensions/google-antigravity-auth/package.json +1 -1
  169. package/extensions/google-gemini-cli-auth/package.json +1 -1
  170. package/extensions/googlechat/package.json +1 -1
  171. package/extensions/imessage/package.json +1 -1
  172. package/extensions/irc/package.json +1 -1
  173. package/extensions/learning-loop/package.json +1 -1
  174. package/extensions/line/package.json +1 -1
  175. package/extensions/llm-task/package.json +1 -1
  176. package/extensions/matrix/CHANGELOG.md +12 -0
  177. package/extensions/matrix/package.json +1 -1
  178. package/extensions/mattermost/package.json +1 -1
  179. package/extensions/memory-core/package.json +1 -1
  180. package/extensions/memory-lancedb/package.json +1 -1
  181. package/extensions/minimax-portal-auth/package.json +1 -1
  182. package/extensions/msteams/CHANGELOG.md +12 -0
  183. package/extensions/msteams/package.json +1 -1
  184. package/extensions/nextcloud-talk/package.json +1 -1
  185. package/extensions/nostr/CHANGELOG.md +12 -0
  186. package/extensions/nostr/package.json +1 -1
  187. package/extensions/open-prose/package.json +1 -1
  188. package/extensions/outlook/package.json +1 -1
  189. package/extensions/pipeline/package.json +1 -1
  190. package/extensions/signal/package.json +1 -1
  191. package/extensions/slack/package.json +1 -1
  192. package/extensions/telegram/package.json +1 -1
  193. package/extensions/tlon/package.json +1 -1
  194. package/extensions/twitch/CHANGELOG.md +12 -0
  195. package/extensions/twitch/package.json +1 -1
  196. package/extensions/voice-call/CHANGELOG.md +12 -0
  197. package/extensions/voice-call/package.json +1 -1
  198. package/extensions/whatsapp/package.json +1 -1
  199. package/extensions/zalo/CHANGELOG.md +12 -0
  200. package/extensions/zalo/package.json +1 -1
  201. package/extensions/zalouser/CHANGELOG.md +12 -0
  202. package/extensions/zalouser/package.json +1 -1
  203. package/package.json +1 -1
  204. package/skills/long-task/scripts/detach-task.sh +91 -14
@@ -6,13 +6,13 @@ import { C as ensureAgentWorkspace, S as DEFAULT_USER_FILENAME, T as isWorkspace
6
6
  import { i as loadWorkspaceSkillEntries } from "./skills-hAdgFdrv.js";
7
7
  import { t as buildWorkspaceSkillStatus } from "./skills-status-DKXJ-tbi.js";
8
8
  import { H as VERSION, N as applyMergePatch, P as applyLegacyMigrations, S as sensitive, U as resolveRuntimeServiceVersion, a as parseConfigJson5, c as resolveConfigSnapshotHash, d as SymiSchema, i as loadConfig, l as writeConfigFile, o as readConfigFileSnapshot, s as readConfigFileSnapshotForWrite, u as validateConfigObjectWithPlugins } from "./config-BNTB6qj8.js";
9
- import { $ as validateNodePairRejectParams, A as validateCronStatusParams, B as validateExecApprovalsGetParams, Bt as rejectDevicePairing, C as validateConfigSetParams, Ct as validateWakeParams, D as validateCronRemoveParams, Dt as validateWizardNextParams, E as validateCronListParams, Et as validateWizardCancelParams, F as validateDevicePairRemoveParams, G as validateModelsListParams, Gt as summarizeDeviceTokens, H as validateExecApprovalsNodeSetParams, I as validateDeviceTokenRevokeParams, It as approveDevicePairing, J as validateNodeInvokeParams, K as validateNodeDescribeParams, L as validateDeviceTokenRotateParams, M as validateDevicePairApproveParams, Mt as errorShape, N as validateDevicePairListParams, O as validateCronRunParams, Ot as validateWizardStartParams, P as validateDevicePairRejectParams, Pt as parseSessionLabel, Q as validateNodePairListParams, S as validateConfigSchemaParams, St as validateUpdateRunParams, T as validateCronAddParams, Tt as validateWebLoginWaitParams, U as validateExecApprovalsSetParams, Ut as revokeDeviceToken, V as validateExecApprovalsNodeGetParams, Vt as removePairedDevice, W as validateLogsTailParams, Wt as rotateDeviceToken, X as validateNodeListParams, Y as validateNodeInvokeResultParams, Z as validateNodePairApproveParams, _ as validateChatInjectParams, _t as validateSkillsInstallParams, a as validateAgentWaitParams, b as validateConfigGetParams, bt as validateTalkConfigParams, c as validateAgentsFilesGetParams, ct as validateSessionsDeleteParams, d as validateAgentsListParams, dt as validateSessionsPreviewParams, et as validateNodePairRequestParams, f as validateAgentsUpdateParams, ft as validateSessionsResetParams, g as validateChatHistoryParams, gt as validateSkillsBinsParams, h as validateChatAbortParams, ht as validateSessionsUsageParams, i as validateAgentParams, it as validatePushTestParams, j as validateCronUpdateParams, jt as ErrorCodes, k as validateCronRunsParams, kt as validateWizardStatusParams, l as validateAgentsFilesListParams, lt as validateSessionsListParams, m as validateChannelsStatusParams, mt as validateSessionsRestoreParams, n as formatValidationErrors, nt as validateNodeRenameParams, o as validateAgentsCreateParams, ot as validateSendParams, p as validateChannelsLogoutParams, pt as validateSessionsResolveParams, q as validateNodeEventParams, r as validateAgentIdentityParams, rt as validatePollParams, s as validateAgentsDeleteParams, st as validateSessionsCompactParams, tt as validateNodePairVerifyParams, u as validateAgentsFilesSetParams, ut as validateSessionsPatchParams, v as validateChatSendParams, vt as validateSkillsStatusParams, wt as validateWebLoginStartParams, x as validateConfigPatchParams, xt as validateTalkModeParams, y as validateConfigApplyParams, yt as validateSkillsUpdateParams, zt as listDevicePairing } from "./client-T3qcxXru.js";
10
- import { l as authorizeOperatorScopesForMethod, s as ADMIN_SCOPE$2, u as isNodeRoleMethod } from "./call-DKi-hnaF.js";
9
+ import { $ as validateNodePairRejectParams, A as validateCronStatusParams, At as validateWizardNextParams, B as validateExecApprovalsGetParams, C as validateConfigSetParams, Ct as validateTalkConfigParams, D as validateCronRemoveParams, Dt as validateWebLoginStartParams, E as validateCronListParams, Et as validateWakeParams, F as validateDevicePairRemoveParams, Ft as errorShape, G as validateModelsListParams, H as validateExecApprovalsNodeSetParams, Ht as listDevicePairing, I as validateDeviceTokenRevokeParams, J as validateNodeInvokeParams, Jt as summarizeDeviceTokens, K as validateNodeDescribeParams, Kt as revokeDeviceToken, L as validateDeviceTokenRotateParams, Lt as parseSessionLabel, M as validateDevicePairApproveParams, Mt as validateWizardStatusParams, N as validateDevicePairListParams, O as validateCronRunParams, Ot as validateWebLoginWaitParams, P as validateDevicePairRejectParams, Pt as ErrorCodes, Q as validateNodePairListParams, S as validateConfigSchemaParams, St as validateSkillsUpdateParams, T as validateCronAddParams, Tt as validateUpdateRunParams, U as validateExecApprovalsSetParams, Ut as rejectDevicePairing, V as validateExecApprovalsNodeGetParams, W as validateLogsTailParams, Wt as removePairedDevice, X as validateNodeListParams, Y as validateNodeInvokeResultParams, Z as validateNodePairApproveParams, _ as validateChatInjectParams, _t as validateSessionsRestoreParams, a as validateAgentWaitParams, b as validateConfigGetParams, bt as validateSkillsInstallParams, c as validateAgentsFilesGetParams, ct as validateSessionsCompactParams, d as validateAgentsListParams, dt as validateSessionsFavoriteFileParams, et as validateNodePairRequestParams, f as validateAgentsUpdateParams, ft as validateSessionsListParams, g as validateChatHistoryParams, gt as validateSessionsResolveParams, h as validateChatAbortParams, ht as validateSessionsResetParams, i as validateAgentParams, it as validatePushTestParams, j as validateCronUpdateParams, jt as validateWizardStartParams, k as validateCronRunsParams, kt as validateWizardCancelParams, l as validateAgentsFilesListParams, lt as validateSessionsDeleteFileParams, m as validateChannelsStatusParams, mt as validateSessionsPreviewParams, n as formatValidationErrors, nt as validateNodeRenameParams, o as validateAgentsCreateParams, ot as validateSendParams, p as validateChannelsLogoutParams, pt as validateSessionsPatchParams, q as validateNodeEventParams, qt as rotateDeviceToken, r as validateAgentIdentityParams, rt as validatePollParams, s as validateAgentsDeleteParams, st as validateSessionsAdoptFileParams, tt as validateNodePairVerifyParams, u as validateAgentsFilesSetParams, ut as validateSessionsDeleteParams, v as validateChatSendParams, vt as validateSessionsUsageParams, wt as validateTalkModeParams, x as validateConfigPatchParams, xt as validateSkillsStatusParams, y as validateConfigApplyParams, yt as validateSkillsBinsParams, zt as approveDevicePairing } from "./client-qUlxXXVJ.js";
10
+ import { l as authorizeOperatorScopesForMethod, s as ADMIN_SCOPE$2, u as isNodeRoleMethod } from "./call-DeCQ2DhS.js";
11
11
  import { f as GATEWAY_CLIENT_CAPS, g as hasGatewayClientCap, i as isGatewayMessageChannel, l as normalizeMessageChannel, n as isDeliverableMessageChannel, t as INTERNAL_MESSAGE_CHANNEL } from "./message-channel-C9dERklz.js";
12
12
  import { c as writeJsonAtomic, o as createAsyncLock, s as readJsonFile } from "./pairing-token-Byh6drgn.js";
13
13
  import { s as pickPrimaryLanIPv4 } from "./net-DZ5Ayk-W.js";
14
14
  import { i as normalizeInputProvenance } from "./input-provenance-D0lNkCf6.js";
15
- import { $n as resolveTtsAutoMode, B as dispatchInboundMessage, C as resolveAgentDeliveryPlan, Cn as enqueueSystemEvent, Cr as onAgentEvent, D as createOutboundSendDeps, Dt as normalizeCronJobPatch, Et as normalizeCronJobCreate, G as BARE_SESSION_RESET_PROMPT, Gn as stopSubagentsForRequester, Gt as persistBrowserProxyFiles, In as resolveAgentTimeoutMs, Jn as resolveUserTimezone, Qn as resolveTtsApiKey, Sn as parseVerboseOverride, V as createReplyDispatcher, Vn as formatZonedTimestamp, Wn as isAbortTrigger, Wt as applyBrowserProxyPaths, Xn as isTtsEnabled, Y as abortEmbeddedPiRun, Yn as getTtsProvider, Z as waitForEmbeddedPiRunEnd, Zn as isTtsProviderConfigured, Zt as scheduleGatewaySigusr1Restart, a as listSubagentRunsForRequester, ar as textToSpeech, bn as applyModelOverrideToSessionEntry, c as clearSessionQueues, ct as resolveOutboundSessionRoute, dt as resolveOutboundTarget, en as unbindThreadBindingsBySessionKey, er as resolveTtsConfig, hn as resolveSendPolicy, i as listDescendantRunsForRequester, ir as setTtsProvider, m as loadSymiPlugins, mn as normalizeSendPolicy, nr as resolveTtsProviderOrder, or as OPENAI_TTS_MODELS, rn as loadProviderUsageSummary, rr as setTtsEnabled, sr as OPENAI_TTS_VOICES, st as ensureOutboundSessionEntry, tn as normalizeGroupActivation, tr as resolveTtsPrefsPath, w as resolveAgentOutboundTarget, wn as isSystemEventContextChanged, wr as registerAgentRunContext, wt as writeRestartSentinel, x as agentCommand, xn as applyVerboseOverride, yt as formatDoctorNonInteractiveHint } from "./subagent-registry-DQHg3jUV.js";
15
+ import { $n as resolveTtsAutoMode, B as dispatchInboundMessage, C as resolveAgentDeliveryPlan, Cn as enqueueSystemEvent, Cr as onAgentEvent, D as createOutboundSendDeps, Dt as normalizeCronJobPatch, Et as normalizeCronJobCreate, G as BARE_SESSION_RESET_PROMPT, Gn as stopSubagentsForRequester, Gt as persistBrowserProxyFiles, In as resolveAgentTimeoutMs, Jn as resolveUserTimezone, Qn as resolveTtsApiKey, Sn as parseVerboseOverride, V as createReplyDispatcher, Vn as formatZonedTimestamp, Wn as isAbortTrigger, Wt as applyBrowserProxyPaths, Xn as isTtsEnabled, Y as abortEmbeddedPiRun, Yn as getTtsProvider, Z as waitForEmbeddedPiRunEnd, Zn as isTtsProviderConfigured, Zt as scheduleGatewaySigusr1Restart, a as listSubagentRunsForRequester, ar as textToSpeech, bn as applyModelOverrideToSessionEntry, c as clearSessionQueues, ct as resolveOutboundSessionRoute, dt as resolveOutboundTarget, en as unbindThreadBindingsBySessionKey, er as resolveTtsConfig, hn as resolveSendPolicy, i as listDescendantRunsForRequester, ir as setTtsProvider, m as loadSymiPlugins, mn as normalizeSendPolicy, nr as resolveTtsProviderOrder, or as OPENAI_TTS_MODELS, rn as loadProviderUsageSummary, rr as setTtsEnabled, sr as OPENAI_TTS_VOICES, st as ensureOutboundSessionEntry, tn as normalizeGroupActivation, tr as resolveTtsPrefsPath, w as resolveAgentOutboundTarget, wn as isSystemEventContextChanged, wr as registerAgentRunContext, wt as writeRestartSentinel, x as agentCommand, xn as applyVerboseOverride, yt as formatDoctorNonInteractiveHint } from "./subagent-registry-DCoU9xIE.js";
16
16
  import { F as resolveMainSessionKey, I as resolveMainSessionKeyFromConfig, J as normalizeSessionDeliveryFields, N as resolveAgentMainSessionKey, P as resolveExplicitAgentSessionKey, R as snapshotSessionOrigin, S as stripEnvelopeFromMessages, _ as capArrayByJsonBytes, d as updateSessionStore, g as archiveSessionTranscripts, h as archiveFileOnDisk, o as loadSessionStore, t as extractDeliveryInfo, v as readSessionMessages, x as resolveSessionTranscriptCandidates, y as readSessionPreviewItemsFromTranscript } from "./sessions-Cfa6JEB3.js";
17
17
  import { n as listChannelPlugins, r as normalizeChannelId, t as getChannelPlugin } from "./plugins-CwSlLxM8.js";
18
18
  import { n as createBrowserRouteDispatcher } from "./with-timeout-Cgi3TwWN.js";
@@ -30,21 +30,21 @@ import { t as getChannelActivity } from "./channel-activity-myOnmDZi.js";
30
30
  import { n as normalizePollInput } from "./polls-DXeUmcgz.js";
31
31
  import { n as createBrowserControlContext, r as startBrowserControlServiceFromConfig } from "./control-service-rbSHSlcd.js";
32
32
  import { i as parseAbsoluteTimeMs } from "./stagger-CQar2eKe.js";
33
- import { w as resolveAssistantAvatarUrl } from "./onboard-helpers-BBtPmJEe.js";
33
+ import { w as resolveAssistantAvatarUrl } from "./onboard-helpers-PpGrZIGw.js";
34
34
  import { r as getLastHeartbeatEvent } from "./heartbeat-visibility-B8TDjqpW.js";
35
35
  import { t as buildChannelUiCatalog } from "./catalog-DLQFKucJ.js";
36
36
  import { t as WizardCancelledError } from "./prompts-m1IJwIAx.js";
37
37
  import { t as resolveChannelDefaultAccountId } from "./helpers-cLP5YLeQ.js";
38
38
  import { t as buildChannelAccountSnapshot } from "./status-BUedPCLb.js";
39
- import { o as isNodeCommandAllowed, s as resolveNodeCommandAllowlist } from "./audit-BjI_Yyr5.js";
40
- import { r as getStatusSummary } from "./status-DfPfMVNZ.js";
41
- import { c as setHeartbeatsEnabled } from "./health-cVvZdeDu.js";
39
+ import { o as isNodeCommandAllowed, s as resolveNodeCommandAllowlist } from "./audit-xSagQWH8.js";
40
+ import { r as getStatusSummary } from "./status-qkmUAeWo.js";
41
+ import { c as setHeartbeatsEnabled } from "./health-CsTxt66a.js";
42
42
  import { m as normalizeUpdateChannel } from "./update-check-ZdimP1aU.js";
43
- import { a as sendApnsAlert, c as parseMessageWithAttachments, i as resolveApnsAuthConfigFromEnv, l as formatForLog, n as normalizeApnsEnvironment, o as sendApnsBackgroundWake, s as normalizeRpcAttachmentsToChatAttachments, t as loadApnsRegistration } from "./push-apns-CYC70eKy.js";
44
- import { a as pruneAgentConfig, i as loadAgentIdentity, r as findAgentEntryIndex, t as applyAgentConfig } from "./agents.config-BKCY6F2A.js";
43
+ import { a as sendApnsAlert, c as parseMessageWithAttachments, i as resolveApnsAuthConfigFromEnv, l as formatForLog, n as normalizeApnsEnvironment, o as sendApnsBackgroundWake, s as normalizeRpcAttachmentsToChatAttachments, t as loadApnsRegistration } from "./push-apns-B5txhDVi.js";
44
+ import { a as pruneAgentConfig, i as loadAgentIdentity, r as findAgentEntryIndex, t as applyAgentConfig } from "./agents.config-C951ocyh.js";
45
45
  import { t as resolveSystemRunCommand } from "./system-run-command-ByVa3txU.js";
46
46
  import { t as installSkill } from "./skills-install-1ZdwGTnh.js";
47
- import { t as runGatewayUpdate } from "./update-runner-DVa6cMqp.js";
47
+ import { t as runGatewayUpdate } from "./update-runner-BhVsdpxm.js";
48
48
  import { spawnSync } from "node:child_process";
49
49
  import * as os$1 from "node:os";
50
50
  import os from "node:os";
@@ -1176,6 +1176,144 @@ function timestampOptsFromConfig(cfg) {
1176
1176
  return { timezone: resolveUserTimezone(cfg.agents?.defaults?.userTimezone) };
1177
1177
  }
1178
1178
 
1179
+ //#endregion
1180
+ //#region src/config/sessions/favorites.ts
1181
+ /**
1182
+ * Session favourites sidecar.
1183
+ *
1184
+ * Stores a set of "favourited" session files at
1185
+ * `<sessionsDir>/favorites.json`. Keyed by **filename** (basename), not
1186
+ * sessionId, because archived files (`.reset.<ts>` / `.deleted.<ts>`) can
1187
+ * share a UUID with an active `<uuid>.jsonl`. Filename is the unique
1188
+ * reference that survives restore/adopt/rename operations — we explicitly
1189
+ * rename the entry in the sidecar when the underlying file is renamed.
1190
+ *
1191
+ * Writes go through a tmp-file + rename cycle to preserve the old contents
1192
+ * if a write fails mid-flight. Reads are synchronous and cheap (the file
1193
+ * is small); no in-memory cache is maintained because the list endpoint
1194
+ * re-reads on every HTTP request anyway.
1195
+ *
1196
+ * @module
1197
+ */
1198
+ const FAVORITES_FILE_NAME = "favorites.json";
1199
+ const EMPTY_FILE = {
1200
+ version: 1,
1201
+ files: []
1202
+ };
1203
+ function resolveFavoritesPath(agentId) {
1204
+ return path.join(resolveSessionTranscriptsDirForAgent(agentId), FAVORITES_FILE_NAME);
1205
+ }
1206
+ function readFavoritesFile(favPath) {
1207
+ if (!fs.existsSync(favPath)) return { ...EMPTY_FILE };
1208
+ try {
1209
+ const raw = fs.readFileSync(favPath, "utf-8");
1210
+ const parsed = JSON.parse(raw);
1211
+ return {
1212
+ version: 1,
1213
+ files: Array.isArray(parsed?.files) ? parsed.files.filter((f) => typeof f === "string" && f.length > 0) : []
1214
+ };
1215
+ } catch {
1216
+ return { ...EMPTY_FILE };
1217
+ }
1218
+ }
1219
+ function writeFavoritesFileAtomic(favPath, file) {
1220
+ fs.mkdirSync(path.dirname(favPath), { recursive: true });
1221
+ const tmp = `${favPath}.${process.pid}.${randomUUID()}.tmp`;
1222
+ try {
1223
+ fs.writeFileSync(tmp, JSON.stringify(file, null, 2), {
1224
+ mode: 384,
1225
+ encoding: "utf-8"
1226
+ });
1227
+ fs.renameSync(tmp, favPath);
1228
+ } catch (err) {
1229
+ try {
1230
+ fs.rmSync(tmp, { force: true });
1231
+ } catch {}
1232
+ throw err;
1233
+ }
1234
+ }
1235
+ /**
1236
+ * Load the set of favourited filenames for an agent. Returns an empty set if
1237
+ * the sidecar file is missing or corrupt. Never throws.
1238
+ */
1239
+ function loadFavoritesSet(agentId) {
1240
+ try {
1241
+ const file = readFavoritesFile(resolveFavoritesPath(agentId));
1242
+ return new Set(file.files);
1243
+ } catch {
1244
+ return /* @__PURE__ */ new Set();
1245
+ }
1246
+ }
1247
+ /**
1248
+ * Set the favourited flag for a file. If `favorited` is true and the file is
1249
+ * already present, or false and already absent, this is a no-op. Returns the
1250
+ * new favourited state (so callers can echo it back in an RPC response).
1251
+ */
1252
+ function setFavorite(file, favorited, agentId) {
1253
+ const favPath = resolveFavoritesPath(agentId);
1254
+ const current = readFavoritesFile(favPath);
1255
+ const set = new Set(current.files);
1256
+ const had = set.has(file);
1257
+ if (favorited && !had) set.add(file);
1258
+ else if (!favorited && had) set.delete(file);
1259
+ else return favorited;
1260
+ writeFavoritesFileAtomic(favPath, {
1261
+ version: 1,
1262
+ files: [...set].toSorted()
1263
+ });
1264
+ return favorited;
1265
+ }
1266
+ /**
1267
+ * Rename a favourites entry. Called by adoptFile/restore when a file on disk
1268
+ * is renamed (e.g. `<uuid>.jsonl.reset.<ts>` → `<uuid>.jsonl`). If `oldFile`
1269
+ * wasn't favourited, this is a no-op. If both `oldFile` and `newFile` are
1270
+ * favourited (unlikely but possible), the `oldFile` entry is simply dropped.
1271
+ */
1272
+ function renameFavoriteEntry(oldFile, newFile, agentId) {
1273
+ const favPath = resolveFavoritesPath(agentId);
1274
+ const current = readFavoritesFile(favPath);
1275
+ const set = new Set(current.files);
1276
+ if (!set.has(oldFile)) return;
1277
+ set.delete(oldFile);
1278
+ set.add(newFile);
1279
+ writeFavoritesFileAtomic(favPath, {
1280
+ version: 1,
1281
+ files: [...set].toSorted()
1282
+ });
1283
+ }
1284
+ /**
1285
+ * Drop an entry from the sidecar regardless of current state. Used when a
1286
+ * file is permanently deleted so we don't keep a stale favourite pointing at
1287
+ * something that no longer exists. No-op if absent.
1288
+ */
1289
+ function dropFavoriteEntry(file, agentId) {
1290
+ const favPath = resolveFavoritesPath(agentId);
1291
+ const current = readFavoritesFile(favPath);
1292
+ if (!current.files.includes(file)) return;
1293
+ writeFavoritesFileAtomic(favPath, {
1294
+ version: 1,
1295
+ files: current.files.filter((f) => f !== file).toSorted()
1296
+ });
1297
+ }
1298
+ /**
1299
+ * Reconcile the sidecar against an authoritative set of filenames that still
1300
+ * exist on disk. Drops any favourites whose files are missing. Safe to call
1301
+ * on every list operation — the write only happens when something changes.
1302
+ * Returns the reconciled set.
1303
+ */
1304
+ function reconcileFavorites(existingFiles, agentId) {
1305
+ const existingSet = new Set(existingFiles);
1306
+ const favPath = resolveFavoritesPath(agentId);
1307
+ const current = readFavoritesFile(favPath);
1308
+ const keep = current.files.filter((f) => existingSet.has(f));
1309
+ if (keep.length === current.files.length) return new Set(current.files);
1310
+ writeFavoritesFileAtomic(favPath, {
1311
+ version: 1,
1312
+ files: keep.toSorted()
1313
+ });
1314
+ return new Set(keep);
1315
+ }
1316
+
1179
1317
  //#endregion
1180
1318
  //#region src/gateway/sessions-patch.ts
1181
1319
  function invalid(message) {
@@ -1609,6 +1747,237 @@ async function emitSessionUnboundLifecycleEvent(params) {
1609
1747
  outcome: params.reason === "session-reset" ? "reset" : "deleted"
1610
1748
  }, { childSessionKey: params.targetSessionKey });
1611
1749
  }
1750
+ /**
1751
+ * Per-session in-flight lock shared by `sessions.restore` and
1752
+ * `sessions.adoptFile`. Prevents two concurrent adoption calls for the same
1753
+ * session key from corrupting each other (e.g. one archives the active
1754
+ * transcript while the other is mid-rename). Keyed by canonical session key.
1755
+ */
1756
+ const restoreInFlight = /* @__PURE__ */ new Set();
1757
+ /**
1758
+ * Classify a target file basename into the adoption mode we need to take.
1759
+ * - `archived`: a `.reset.<ts>` / `.deleted.<ts>` transcript that must be
1760
+ * renamed back to `<sessionId>.jsonl`.
1761
+ * - `active`: a plain `<sessionId>.jsonl` that may already be owned by
1762
+ * another session key in the registry; we adopt it by dropping the other
1763
+ * key's entry (if any) and pointing ours at it. No filesystem rename.
1764
+ */
1765
+ function classifyTargetFile(basename) {
1766
+ if (/\.jsonl\.reset\./.test(basename)) return {
1767
+ kind: "archived",
1768
+ reason: "reset"
1769
+ };
1770
+ if (/\.jsonl\.deleted\./.test(basename)) return {
1771
+ kind: "archived",
1772
+ reason: "deleted"
1773
+ };
1774
+ if (/^[A-Za-z0-9][\w.-]*\.jsonl$/.test(basename)) return { kind: "active" };
1775
+ return null;
1776
+ }
1777
+ async function performAdoptFile(params) {
1778
+ const { key } = params;
1779
+ const targetBasename = path.basename(params.targetFile);
1780
+ if (targetBasename !== params.targetFile || targetBasename.includes("..") || targetBasename.length === 0) return {
1781
+ ok: false,
1782
+ errorCode: "INVALID_REQUEST",
1783
+ errorMessage: "Invalid target file name."
1784
+ };
1785
+ const classification = classifyTargetFile(targetBasename);
1786
+ if (!classification) return {
1787
+ ok: false,
1788
+ errorCode: "INVALID_REQUEST",
1789
+ errorMessage: "Target file is not a recognised session transcript."
1790
+ };
1791
+ const { cfg, target, storePath } = resolveGatewaySessionTargetFromKey(key);
1792
+ const sessionsDir = path.dirname(storePath);
1793
+ const targetPath = path.join(sessionsDir, targetBasename);
1794
+ if (!fs.existsSync(targetPath)) return {
1795
+ ok: false,
1796
+ errorCode: "INVALID_REQUEST",
1797
+ errorMessage: `Target file not found: ${targetBasename}`
1798
+ };
1799
+ let restoredSessionId;
1800
+ try {
1801
+ const firstLine = fs.readFileSync(targetPath, "utf8").split("\n")[0] ?? "";
1802
+ const header = JSON.parse(firstLine);
1803
+ if (!header.id || header.type !== "session") throw new Error("invalid session header");
1804
+ restoredSessionId = header.id;
1805
+ } catch {
1806
+ return {
1807
+ ok: false,
1808
+ errorCode: "INVALID_REQUEST",
1809
+ errorMessage: "Target file is not a valid session transcript."
1810
+ };
1811
+ }
1812
+ const lockKey = target.canonicalKey ?? key;
1813
+ if (restoreInFlight.has(lockKey)) return {
1814
+ ok: false,
1815
+ errorCode: "UNAVAILABLE",
1816
+ errorMessage: `Adopt already in progress for session ${lockKey}; try again in a moment.`
1817
+ };
1818
+ restoreInFlight.add(lockKey);
1819
+ const rollback = [];
1820
+ try {
1821
+ const { entry: currentEntry } = loadSessionEntry(key);
1822
+ const cleanupError = await ensureSessionRuntimeCleanup({
1823
+ cfg,
1824
+ key,
1825
+ target,
1826
+ sessionId: currentEntry?.sessionId
1827
+ });
1828
+ if (cleanupError) return {
1829
+ ok: false,
1830
+ errorCode: "UNAVAILABLE",
1831
+ errorMessage: cleanupError.message ?? "runtime cleanup failed"
1832
+ };
1833
+ if (currentEntry?.sessionId === restoredSessionId && classification.kind === "active") return {
1834
+ ok: true,
1835
+ sessionId: restoredSessionId,
1836
+ canonicalKey: target.canonicalKey,
1837
+ entry: currentEntry,
1838
+ restoredFileName: targetBasename,
1839
+ droppedSourceKeys: []
1840
+ };
1841
+ const archivedPaths = archiveSessionTranscriptsForSession({
1842
+ sessionId: currentEntry?.sessionId,
1843
+ storePath,
1844
+ sessionFile: currentEntry?.sessionFile,
1845
+ agentId: target.agentId,
1846
+ reason: "reset"
1847
+ });
1848
+ for (const archived of archivedPaths) {
1849
+ const archivedBasename = path.basename(archived);
1850
+ const originalBasename = archivedBasename.replace(/\.reset\.[^/]+$/, "");
1851
+ rollback.push({
1852
+ desc: `un-archive ${archivedBasename}`,
1853
+ fn: () => {
1854
+ renameArchivedBackToOriginal(archived, "reset");
1855
+ if (originalBasename && originalBasename !== archivedBasename) renameFavoriteEntry(archivedBasename, originalBasename, target.agentId);
1856
+ }
1857
+ });
1858
+ if (originalBasename && originalBasename !== archivedBasename) renameFavoriteEntry(originalBasename, archivedBasename, target.agentId);
1859
+ }
1860
+ const restoredFileName = `${restoredSessionId}.jsonl`;
1861
+ const restoredPath = path.join(sessionsDir, restoredFileName);
1862
+ if (classification.kind === "archived" && targetPath !== restoredPath) {
1863
+ fs.renameSync(targetPath, restoredPath);
1864
+ rollback.push({
1865
+ desc: `re-archive ${restoredPath} to ${targetPath}`,
1866
+ fn: () => {
1867
+ try {
1868
+ fs.renameSync(restoredPath, targetPath);
1869
+ } catch (err) {
1870
+ console.warn(`[sessions.adoptFile] rollback: rename ${restoredPath} → ${targetPath} failed: ${String(err)}`);
1871
+ }
1872
+ renameFavoriteEntry(restoredFileName, targetBasename, target.agentId);
1873
+ }
1874
+ });
1875
+ renameFavoriteEntry(targetBasename, restoredFileName, target.agentId);
1876
+ }
1877
+ const droppedSourceKeys = [];
1878
+ let droppedSourceEntries = [];
1879
+ const next = await updateSessionStore(storePath, (store) => {
1880
+ const { primaryKey } = migrateAndPruneSessionStoreKey({
1881
+ cfg,
1882
+ key,
1883
+ store
1884
+ });
1885
+ if (classification.kind === "active") for (const [otherKey, otherEntry] of Object.entries(store)) {
1886
+ if (otherKey === primaryKey) continue;
1887
+ if (otherEntry?.sessionId === restoredSessionId) {
1888
+ droppedSourceEntries.push({
1889
+ key: otherKey,
1890
+ entry: otherEntry
1891
+ });
1892
+ droppedSourceKeys.push(otherKey);
1893
+ delete store[otherKey];
1894
+ }
1895
+ }
1896
+ const existingEntry = store[primaryKey];
1897
+ const nextEntry = {
1898
+ sessionId: restoredSessionId,
1899
+ sessionFile: restoredPath,
1900
+ updatedAt: Date.now(),
1901
+ systemSent: false,
1902
+ abortedLastRun: false,
1903
+ thinkingLevel: existingEntry?.thinkingLevel,
1904
+ verboseLevel: existingEntry?.verboseLevel,
1905
+ reasoningLevel: existingEntry?.reasoningLevel,
1906
+ responseUsage: existingEntry?.responseUsage,
1907
+ model: existingEntry?.model,
1908
+ contextTokens: existingEntry?.contextTokens,
1909
+ sendPolicy: existingEntry?.sendPolicy,
1910
+ label: existingEntry?.label,
1911
+ origin: snapshotSessionOrigin(existingEntry),
1912
+ lastChannel: existingEntry?.lastChannel,
1913
+ lastTo: existingEntry?.lastTo,
1914
+ skillsSnapshot: existingEntry?.skillsSnapshot,
1915
+ inputTokens: 0,
1916
+ outputTokens: 0,
1917
+ totalTokens: 0,
1918
+ totalTokensFresh: true
1919
+ };
1920
+ store[primaryKey] = nextEntry;
1921
+ return nextEntry;
1922
+ });
1923
+ if (droppedSourceEntries.length > 0) {
1924
+ const restoreEntries = droppedSourceEntries.slice();
1925
+ rollback.push({
1926
+ desc: `restore ${restoreEntries.length} source registry entry/entries`,
1927
+ fn: () => {
1928
+ updateSessionStore(storePath, (store) => {
1929
+ for (const { key: k, entry: e } of restoreEntries) store[k] = e;
1930
+ }).catch((err) => {
1931
+ console.warn(`[sessions.adoptFile] rollback: could not restore source entries: ${String(err)}`);
1932
+ });
1933
+ }
1934
+ });
1935
+ }
1936
+ rollback.length = 0;
1937
+ return {
1938
+ ok: true,
1939
+ sessionId: restoredSessionId,
1940
+ canonicalKey: target.canonicalKey,
1941
+ entry: next,
1942
+ restoredFileName,
1943
+ droppedSourceKeys
1944
+ };
1945
+ } catch (err) {
1946
+ console.warn(`[sessions.adoptFile] failed for ${lockKey}; running ${rollback.length} rollback step(s): ${String(err)}`);
1947
+ for (let i = rollback.length - 1; i >= 0; i--) {
1948
+ const step = rollback[i];
1949
+ if (step) step.fn();
1950
+ }
1951
+ return {
1952
+ ok: false,
1953
+ errorCode: "UNAVAILABLE",
1954
+ errorMessage: `Adopt failed: ${err instanceof Error ? err.message : String(err)}`
1955
+ };
1956
+ } finally {
1957
+ restoreInFlight.delete(lockKey);
1958
+ }
1959
+ }
1960
+ /**
1961
+ * Best-effort inverse of `archiveFileOnDisk(file, "reset")` — renames
1962
+ * `<file>.reset.<timestamp>` back to `<file>`. Used by the sessions.restore
1963
+ * rollback path when a later step fails after the current transcript was
1964
+ * archived. Swallows all errors and logs; the goal is to recover as much
1965
+ * state as possible, not to guarantee success.
1966
+ */
1967
+ function renameArchivedBackToOriginal(archivedPath, reason) {
1968
+ const marker = `.${reason}.`;
1969
+ const idx = archivedPath.lastIndexOf(marker);
1970
+ if (idx <= 0) {
1971
+ console.warn(`[sessions.restore] cannot parse archived path for rollback: ${archivedPath}`);
1972
+ return;
1973
+ }
1974
+ const originalPath = archivedPath.slice(0, idx);
1975
+ try {
1976
+ fs.renameSync(archivedPath, originalPath);
1977
+ } catch (err) {
1978
+ console.warn(`[sessions.restore] rollback failed: could not rename ${archivedPath} back to ${originalPath}: ${String(err)}`);
1979
+ }
1980
+ }
1612
1981
  async function ensureSessionRuntimeCleanup(params) {
1613
1982
  const queueKeys = new Set(params.target.storeKeys);
1614
1983
  queueKeys.add(params.target.canonicalKey);
@@ -1835,92 +2204,106 @@ const sessionsHandlers = {
1835
2204
  const p = params;
1836
2205
  const key = requireSessionKey(p.key, respond);
1837
2206
  if (!key) return;
1838
- const targetBasename = path.basename(p.targetFile);
1839
- if (targetBasename !== p.targetFile || targetBasename.includes("..")) {
1840
- respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "Invalid target file name."));
1841
- return;
1842
- }
1843
- const { cfg, target, storePath } = resolveGatewaySessionTargetFromKey(key);
1844
- const sessionsDir = path.dirname(storePath);
1845
- const targetPath = path.join(sessionsDir, targetBasename);
1846
- if (!fs.existsSync(targetPath)) {
1847
- respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, `Target file not found: ${targetBasename}`));
1848
- return;
1849
- }
1850
- let restoredSessionId;
1851
- try {
1852
- const firstLine = fs.readFileSync(targetPath, "utf8").split("\n")[0];
1853
- const header = JSON.parse(firstLine);
1854
- if (!header.id || header.type !== "session") throw new Error("invalid session header");
1855
- restoredSessionId = header.id;
1856
- } catch {
1857
- respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "Target file is not a valid session transcript."));
2207
+ const outcome = await performAdoptFile({
2208
+ key,
2209
+ targetFile: p.targetFile
2210
+ });
2211
+ if (!outcome.ok) {
2212
+ respond(false, void 0, errorShape(ErrorCodes[outcome.errorCode], outcome.errorMessage));
1858
2213
  return;
1859
2214
  }
1860
- const { entry } = loadSessionEntry(key);
1861
- const sessionId = entry?.sessionId;
1862
- const cleanupError = await ensureSessionRuntimeCleanup({
1863
- cfg,
2215
+ respond(true, {
2216
+ ok: true,
2217
+ key: outcome.canonicalKey,
2218
+ sessionId: outcome.sessionId,
2219
+ entry: outcome.entry
2220
+ }, void 0);
2221
+ },
2222
+ "sessions.adoptFile": async ({ params, respond }) => {
2223
+ if (!assertValidParams(params, validateSessionsAdoptFileParams, "sessions.adoptFile", respond)) return;
2224
+ const p = params;
2225
+ const key = requireSessionKey(p.key, respond);
2226
+ if (!key) return;
2227
+ const outcome = await performAdoptFile({
1864
2228
  key,
1865
- target,
1866
- sessionId
2229
+ targetFile: p.targetFile
1867
2230
  });
1868
- if (cleanupError) {
1869
- respond(false, void 0, cleanupError);
2231
+ if (!outcome.ok) {
2232
+ respond(false, void 0, errorShape(ErrorCodes[outcome.errorCode], outcome.errorMessage));
1870
2233
  return;
1871
2234
  }
1872
- const oldSessionId = entry?.sessionId;
1873
- const oldSessionFile = entry?.sessionFile;
1874
- archiveSessionTranscriptsForSession({
1875
- sessionId: oldSessionId,
1876
- storePath,
1877
- sessionFile: oldSessionFile,
1878
- agentId: target.agentId,
1879
- reason: "reset"
1880
- });
1881
- const restoredFileName = `${restoredSessionId}.jsonl`;
1882
- const restoredPath = path.join(sessionsDir, restoredFileName);
1883
- if (targetPath !== restoredPath) fs.renameSync(targetPath, restoredPath);
1884
- const next = await updateSessionStore(storePath, (store) => {
1885
- const { primaryKey } = migrateAndPruneSessionStoreKey({
1886
- cfg,
1887
- key,
1888
- store
1889
- });
1890
- const existingEntry = store[primaryKey];
1891
- const nextEntry = {
1892
- sessionId: restoredSessionId,
1893
- sessionFile: restoredPath,
1894
- updatedAt: Date.now(),
1895
- systemSent: false,
1896
- abortedLastRun: false,
1897
- thinkingLevel: existingEntry?.thinkingLevel,
1898
- verboseLevel: existingEntry?.verboseLevel,
1899
- reasoningLevel: existingEntry?.reasoningLevel,
1900
- responseUsage: existingEntry?.responseUsage,
1901
- model: existingEntry?.model,
1902
- contextTokens: existingEntry?.contextTokens,
1903
- sendPolicy: existingEntry?.sendPolicy,
1904
- label: existingEntry?.label,
1905
- origin: snapshotSessionOrigin(existingEntry),
1906
- lastChannel: existingEntry?.lastChannel,
1907
- lastTo: existingEntry?.lastTo,
1908
- skillsSnapshot: existingEntry?.skillsSnapshot,
1909
- inputTokens: 0,
1910
- outputTokens: 0,
1911
- totalTokens: 0,
1912
- totalTokensFresh: true
1913
- };
1914
- store[primaryKey] = nextEntry;
1915
- return nextEntry;
1916
- });
1917
2235
  respond(true, {
1918
2236
  ok: true,
1919
- key: target.canonicalKey,
1920
- sessionId: restoredSessionId,
1921
- entry: next
2237
+ key: outcome.canonicalKey,
2238
+ sessionId: outcome.sessionId,
2239
+ entry: outcome.entry,
2240
+ file: outcome.restoredFileName,
2241
+ droppedSourceKeys: outcome.droppedSourceKeys
1922
2242
  }, void 0);
1923
2243
  },
2244
+ "sessions.favoriteFile": ({ params, respond }) => {
2245
+ if (!assertValidParams(params, validateSessionsFavoriteFileParams, "sessions.favoriteFile", respond)) return;
2246
+ const p = params;
2247
+ const file = path.basename(p.file);
2248
+ if (file !== p.file || file.includes("..") || file.length === 0) {
2249
+ respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "Invalid file name."));
2250
+ return;
2251
+ }
2252
+ const agentId = resolveDefaultAgentId(loadConfig());
2253
+ const sessionsDir = resolveSessionTranscriptsDirForAgent(agentId);
2254
+ const abs = path.join(sessionsDir, file);
2255
+ if (!fs.existsSync(abs)) {
2256
+ respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, `Session file not found: ${file}`));
2257
+ return;
2258
+ }
2259
+ try {
2260
+ respond(true, {
2261
+ ok: true,
2262
+ file,
2263
+ favorited: setFavorite(file, p.favorited, agentId)
2264
+ }, void 0);
2265
+ } catch (err) {
2266
+ respond(false, void 0, errorShape(ErrorCodes.UNAVAILABLE, `Favorite write failed: ${err instanceof Error ? err.message : String(err)}`));
2267
+ }
2268
+ },
2269
+ "sessions.deleteFile": async ({ params, respond }) => {
2270
+ if (!assertValidParams(params, validateSessionsDeleteFileParams, "sessions.deleteFile", respond)) return;
2271
+ const p = params;
2272
+ const file = path.basename(p.file);
2273
+ if (file !== p.file || file.includes("..") || file.length === 0) {
2274
+ respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "Invalid file name."));
2275
+ return;
2276
+ }
2277
+ const cfg = loadConfig();
2278
+ const agentId = resolveDefaultAgentId(cfg);
2279
+ const sessionsDir = resolveSessionTranscriptsDirForAgent(agentId);
2280
+ const abs = path.join(sessionsDir, file);
2281
+ if (!fs.existsSync(abs)) {
2282
+ respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, `Session file not found: ${file}`));
2283
+ return;
2284
+ }
2285
+ const { store } = loadCombinedSessionStoreForGateway(cfg);
2286
+ if (classifyTargetFile(file)?.kind === "active") {
2287
+ const sessionId = file.match(/^(.+)\.jsonl$/)?.[1];
2288
+ if (sessionId) {
2289
+ const referrer = Object.entries(store).find(([, entry]) => entry?.sessionId === sessionId)?.[0];
2290
+ if (referrer) {
2291
+ respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, `File is still bound to session key ${referrer}; use sessions.delete on that key to archive it first.`));
2292
+ return;
2293
+ }
2294
+ }
2295
+ }
2296
+ try {
2297
+ fs.unlinkSync(abs);
2298
+ dropFavoriteEntry(file, agentId);
2299
+ respond(true, {
2300
+ ok: true,
2301
+ file
2302
+ }, void 0);
2303
+ } catch (err) {
2304
+ respond(false, void 0, errorShape(ErrorCodes.UNAVAILABLE, `Delete failed: ${err instanceof Error ? err.message : String(err)}`));
2305
+ }
2306
+ },
1924
2307
  "sessions.delete": async ({ params, respond, client, isWebchatConnect }) => {
1925
2308
  if (!assertValidParams(params, validateSessionsDeleteParams, "sessions.delete", respond)) return;
1926
2309
  const p = params;
@@ -6942,7 +7325,7 @@ const nodeHandlers = {
6942
7325
  const p = params;
6943
7326
  const payloadJSON = typeof p.payloadJSON === "string" ? p.payloadJSON : p.payload !== void 0 ? JSON.stringify(p.payload) : null;
6944
7327
  await respondUnavailableOnThrow(respond, async () => {
6945
- const { handleNodeEvent } = await import("./server-node-events-C2h9OPo7.js");
7328
+ const { handleNodeEvent } = await import("./server-node-events-DCbzFyQF.js");
6946
7329
  const nodeId = client?.connect?.device?.id ?? client?.connect?.client?.id ?? "node";
6947
7330
  await handleNodeEvent({
6948
7331
  deps: context.deps,
@@ -9007,4 +9390,4 @@ async function handleGatewayRequest(opts) {
9007
9390
  }
9008
9391
 
9009
9392
  //#endregion
9010
- export { getHandshakeTimeoutMs as _, DEFAULT_ASSISTANT_IDENTITY as a, resolveCronRunLogPath as b, upsertPresence as c, DEDUPE_MAX as d, DEDUPE_TTL_MS as f, TICK_INTERVAL_MS as g, MAX_PAYLOAD_BYTES as h, safeParseJson as i, formatError as l, MAX_BUFFERED_BYTES as m, handleGatewayRequest as n, resolveAssistantIdentity as o, HEALTH_REFRESH_INTERVAL_MS as p, broadcastPresenceSnapshot as r, listSystemPresence as s, coreGatewayHandlers as t, loadVoiceWakeConfig as u, abortChatRunById as v, startGatewayConfigReloader as x, appendCronRunLog as y };
9393
+ export { startGatewayConfigReloader as C, resolveCronRunLogPath as S, MAX_PAYLOAD_BYTES as _, loadFavoritesSet as a, abortChatRunById as b, resolveAssistantIdentity as c, formatError as d, loadVoiceWakeConfig as f, MAX_BUFFERED_BYTES as g, HEALTH_REFRESH_INTERVAL_MS as h, safeParseJson as i, listSystemPresence as l, DEDUPE_TTL_MS as m, handleGatewayRequest as n, reconcileFavorites as o, DEDUPE_MAX as p, broadcastPresenceSnapshot as r, DEFAULT_ASSISTANT_IDENTITY as s, coreGatewayHandlers as t, upsertPresence as u, TICK_INTERVAL_MS as v, appendCronRunLog as x, getHandshakeTimeoutMs as y };