@noxsoft/anima 5.0.1 → 5.0.2

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 (180) hide show
  1. package/dist/{accounts-BOkEyUcS.js → accounts-CSCVz9k9.js} +7 -7
  2. package/dist/{acp-cli-BcshtFqY.js → acp-cli-DyVMXQS8.js} +1 -1
  3. package/dist/{agent-c49U1LxE.js → agent-CWQdTmzC.js} +3 -3
  4. package/dist/{agent-Cil6Zvns.js → agent-DiEXJmhj.js} +8 -8
  5. package/dist/{agents-2BloqCjm.js → agents-rAIsxGuA.js} +8 -8
  6. package/dist/{anthropic-direct-runner-BVlO2Vi5.js → anthropic-direct-runner--MPTWkYA.js} +228 -193
  7. package/dist/{anthropic-direct-runner-mh6c_WBB.js → anthropic-direct-runner-_uCPWuBb.js} +232 -197
  8. package/dist/{audit-BbmRSFjf.js → audit-DqjWCAbO.js} +7 -7
  9. package/dist/{auth-choice-BVAMr2Dk.js → auth-choice-o5GHtPGA.js} +57 -5
  10. package/dist/{auth-profiles-Chf1JBpl.js → auth-profiles-DriJ4HU5.js} +1 -1
  11. package/dist/{banner-CgxCSS-T.js → banner-Gtp-FQrx.js} +1 -1
  12. package/dist/build-info.json +3 -3
  13. package/dist/bundled/boot-md/handler.js +13 -13
  14. package/dist/bundled/bootstrap-extra-files/handler.js +3 -3
  15. package/dist/bundled/session-memory/handler.js +10 -10
  16. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  17. package/dist/{channel-web-Y8i3EzJq.js → channel-web-Dz0XZNjP.js} +4 -4
  18. package/dist/{channels-status-issues-BlmAMBCg.js → channels-status-issues-Dqd_vE0e.js} +2 -2
  19. package/dist/{chrome-B2-33FWf.js → chrome-CB6uZMvl.js} +1 -1
  20. package/dist/{chrome-Cxl7I5SB.js → chrome-CKvch3UL.js} +7 -7
  21. package/dist/{clack-prompter-B-ZJG628.js → clack-prompter-BRLXmV52.js} +1 -1
  22. package/dist/{clack-prompter-CCRr4nAr.js → clack-prompter-OFy356QZ.js} +1 -1
  23. package/dist/{cli-C3uw3mId.js → cli-BZz5MnAE.js} +29 -29
  24. package/dist/{cli-CfvBmuhw.js → cli-CJfwHH_z.js} +5 -5
  25. package/dist/{cli-session-BzZYmGP1.js → cli-session-8PeURiwF.js} +6 -6
  26. package/dist/{cli-session-DgUHOBYo.js → cli-session-CczB2Dni.js} +1 -1
  27. package/dist/{command-registry-DLofaVIN.js → command-registry-C9kvlc67.js} +12 -12
  28. package/dist/{common-FlJ-8clz.js → common-C5mWuFve.js} +2 -2
  29. package/dist/{completion-cli-C9KvX2ZF.js → completion-cli-Ci_MzRm6.js} +2 -2
  30. package/dist/{completion-cli-3eYvtAih.js → completion-cli-DhbIrk13.js} +1 -1
  31. package/dist/{config-B-9UciOO.js → config-DezP7V65.js} +2 -2
  32. package/dist/{config-cli-CBXWDtvj.js → config-cli-ePL5ncye.js} +1 -1
  33. package/dist/{config-cli-cmNuTlw0.js → config-cli-uk9vdQZH.js} +1 -1
  34. package/dist/{config-guard-qiKju2Fg.js → config-guard-CCOBZ77Q.js} +1 -1
  35. package/dist/{configure-CGTBBLR_.js → configure-CkGsX5z9.js} +9 -9
  36. package/dist/{configure-Dpk4lSoz.js → configure-D-9Ezgal.js} +11 -11
  37. package/dist/{configure-jlAKeuki.js → configure-DxKMnCHX.js} +40 -40
  38. package/dist/{configure-CH_-SNya.js → configure-KP7q9c7h.js} +4 -4
  39. package/dist/{control-service-CUhnhmpc.js → control-service-D3rS-Yd1.js} +3 -3
  40. package/dist/{cron-cli-CKs1evSF.js → cron-cli-3QY_K0l_.js} +1 -1
  41. package/dist/{daemon-cli-CSCFNzUo.js → daemon-cli-NZ84KRN8.js} +3 -3
  42. package/dist/{deliver-BYxbDIF0.js → deliver-BJn4EmMZ.js} +1 -1
  43. package/dist/{deliver-DkF6LCoS.js → deliver-BhezvxNA.js} +4 -4
  44. package/dist/{deps-D9266xfk.js → deps-CBLy0fqA.js} +1 -1
  45. package/dist/{dispatcher-BeO47t7A.js → dispatcher-Bk0gFz4b.js} +1 -1
  46. package/dist/{doctor-DJfgnQ67.js → doctor-Bto-K3wL.js} +16 -16
  47. package/dist/{doctor-CWmHUAjs.js → doctor-DsRSWr6B.js} +5 -5
  48. package/dist/{doctor-completion-CtCwd1fi.js → doctor-completion-B-SFdu-f.js} +1 -1
  49. package/dist/{doctor-completion-CmJmktDv.js → doctor-completion-OQXTo6RG.js} +1 -1
  50. package/dist/{doctor-config-flow-D_8YNTSK.js → doctor-config-flow-CEkHIHe5.js} +1 -1
  51. package/dist/entry.js +1 -1
  52. package/dist/extensionAPI.js +1531 -411
  53. package/dist/{frontmatter-BmBmtOUh.js → frontmatter-Dsa7N963.js} +1 -1
  54. package/dist/{gateway-cli-DYrzIvOE.js → gateway-cli-Buxz8Y2n.js} +17 -17
  55. package/dist/{gateway-cli-BazTmg20.js → gateway-cli-CEGPCQ_C.js} +52 -52
  56. package/dist/{health-BRSKF_iF.js → health-CMIY7xAI.js} +12 -12
  57. package/dist/{health-JqtB_B8C.js → health-DoGFlPcq.js} +6 -6
  58. package/dist/{heartbeat-visibility-BGj2czmk.js → heartbeat-visibility-BOyU9ccw.js} +2 -2
  59. package/dist/{heartbeat-visibility-pyFf6XBW.js → heartbeat-visibility-DuRmIKOk.js} +2 -2
  60. package/dist/{hooks-cli-B7g3jEC3.js → hooks-cli-B1NXXLxe.js} +30 -30
  61. package/dist/{hooks-cli-ZK4Z044T.js → hooks-cli-BuIU6v0Q.js} +6 -6
  62. package/dist/index.js +11 -11
  63. package/dist/{installs-DBvIs2By.js → installs-Drds9RDI.js} +1 -1
  64. package/dist/{lanes-DyM6NSSL.js → lanes-4_8h1ZQO.js} +274 -12
  65. package/dist/llm-slug-generator.js +10 -10
  66. package/dist/{login-BbfWLOBl.js → login-DwP4KleZ.js} +2 -2
  67. package/dist/{login-qr-BqhujMcQ.js → login-qr-wnynuvLt.js} +5 -5
  68. package/dist/{manager-CcawxgaC.js → manager-ibNP7jE3.js} +2 -2
  69. package/dist/{manager-DS1DfkbC.js → manager-j0ghUvcW.js} +4 -4
  70. package/dist/{media-IIqSkFpd.js → media-BLVMhFB3.js} +2 -2
  71. package/dist/{memory-cli-wDO418hx.js → memory-cli-DSWsPuub.js} +6 -6
  72. package/dist/{model-auth-Uxm-wRjR.js → model-auth-BKf-GZVK.js} +3 -3
  73. package/dist/{models-tQnX4hL4.js → models-BU0CytAy.js} +32 -32
  74. package/dist/{node-cli-DAcW-rfA.js → node-cli-DcwOFcxq.js} +8 -8
  75. package/dist/{onboard-Dd6xFMYB.js → onboard-Dd5wJkeU.js} +6 -6
  76. package/dist/{onboard-dasbF9G1.js → onboard-c84IExbH.js} +4 -4
  77. package/dist/{onboard-channels-DisvVyIs.js → onboard-channels-CCoMzCXV.js} +3 -3
  78. package/dist/{onboard-channels-BUv3VbAL.js → onboard-channels-DYr7fQZq.js} +1 -1
  79. package/dist/{onboard-helpers-49TVSf7J.js → onboard-helpers-BRp_xJvW.js} +1 -1
  80. package/dist/{onboarding-Dq3bCBjc.js → onboarding-192Oe9K6.js} +8 -8
  81. package/dist/{onboarding-6Xs4orLw.js → onboarding-BINruD5r.js} +4 -4
  82. package/dist/{outbound-CliT3nme.js → outbound-BVSyNp-t.js} +1 -1
  83. package/dist/{outbound-CLII4C2A.js → outbound-BaBDhLp1.js} +1 -1
  84. package/dist/{parse-timeout-BnOIKwx8.js → parse-timeout-C1INlSUG.js} +2 -2
  85. package/dist/{pi-auth-json-DLroEcea.js → pi-auth-json-BSLIRI41.js} +2 -2
  86. package/dist/{pi-embedded-CS4D_0t7.js → pi-embedded-DJF_gfcQ.js} +667 -372
  87. package/dist/{pi-tools.policy-RhdERrk3.js → pi-tools.policy-Dtytaq21.js} +3 -3
  88. package/dist/{plugin-registry-l3z9phEV.js → plugin-registry-B0k-53-_.js} +1 -1
  89. package/dist/{plugin-registry-esOxvV3X.js → plugin-registry-CqUo-PU_.js} +1 -1
  90. package/dist/plugin-sdk/agents/gemini-direct-runner.d.ts +38 -0
  91. package/dist/plugin-sdk/commands/onboard-types.d.ts +2 -2
  92. package/dist/{plugins-cli-D2v0n4BL.js → plugins-cli-BYLUFsjH.js} +33 -33
  93. package/dist/{plugins-cli-CbXtuN4b.js → plugins-cli-YjM8IsVo.js} +6 -6
  94. package/dist/{ports-DyX87qKc.js → ports-BmSDzOHm.js} +1 -1
  95. package/dist/{ports-COy7Yg_k.js → ports-Bv3sZ3bd.js} +1 -1
  96. package/dist/{program-y0NPJuYm.js → program-CG5u1KAB.js} +36 -36
  97. package/dist/{program-context-CqPwmgYa.js → program-context-Co2gkUS0.js} +16 -16
  98. package/dist/{prompts-DTKoIKPV.js → prompts-DjKZfP5R.js} +67 -4
  99. package/dist/{prompts-DY0qdoD1.js → prompts-NvPXbNVc.js} +12 -1
  100. package/dist/{pw-ai-CJgeaF06.js → pw-ai-C3j5kV3T.js} +1 -1
  101. package/dist/{pw-ai-A7vggLw8.js → pw-ai-CvxTpFmB.js} +3 -3
  102. package/dist/{qmd-manager-DQsAtmK7.js → qmd-manager-BDq5_dd6.js} +2 -2
  103. package/dist/{register.agent-Bi2FqIlN.js → register.agent-PbAKdlNK.js} +10 -10
  104. package/dist/{register.agent-CRazop1A.js → register.agent-WAjZHuZe.js} +38 -38
  105. package/dist/{register.anima-FFaI_C8x.js → register.anima-CDcnWfQF.js} +2 -2
  106. package/dist/{register.anima-BmdRCJLy.js → register.anima-CZNjkwJH.js} +2 -2
  107. package/dist/{register.configure-FIXOWrO9.js → register.configure-C2zfgyp9.js} +39 -39
  108. package/dist/{register.configure-r5AViY3N.js → register.configure-CNhagtHN.js} +10 -10
  109. package/dist/{register.maintenance-Cpf0ZZTL.js → register.maintenance-DWJjWsIl.js} +11 -11
  110. package/dist/{register.maintenance-DJYji5mV.js → register.maintenance-DkF1Nu_y.js} +39 -39
  111. package/dist/{register.onboard-thGXwzOX.js → register.onboard-DiZzjEwz.js} +13 -13
  112. package/dist/{register.onboard-oUsWjmam.js → register.onboard-xOXNrMu-.js} +41 -41
  113. package/dist/{register.setup-B4MYuE3g.js → register.setup-BmbpgUVU.js} +41 -41
  114. package/dist/{register.setup-DWDrQ7RT.js → register.setup-QAjNkIZr.js} +13 -13
  115. package/dist/{register.status-health-sessions-CTKdzo7a.js → register.status-health-sessions-Cm-lxcT6.js} +37 -37
  116. package/dist/{register.status-health-sessions-Ce9QUAyj.js → register.status-health-sessions-RZxaVSa6.js} +7 -7
  117. package/dist/{register.subclis-CWmYc4AB.js → register.subclis-DCljHJ5a.js} +13 -13
  118. package/dist/{reply-CpHIJ9Kk.js → reply-Bw4torMz.js} +30 -30
  119. package/dist/{reply-BKpIrCr-.js → reply-Dd3EmI4M.js} +5 -5
  120. package/dist/{reply-prefix-BO_Dt82N.js → reply-prefix-DIoRETAD.js} +2 -2
  121. package/dist/{reply-prefix-BwVBvQXp.js → reply-prefix-Dy_yxyCq.js} +2 -2
  122. package/dist/{routes-XhTPYecR.js → routes-CNSdZAkl.js} +3 -3
  123. package/dist/{run--9hftM2H.js → run--R4y3YlU.js} +41 -41
  124. package/dist/{run-CGokiDR8.js → run-DgtaDzEe.js} +15 -15
  125. package/dist/{run-main-DxcOzCLw.js → run-main-eUWh86lF.js} +47 -47
  126. package/dist/{sandbox-CiwAPzO7.js → sandbox-BoNWDo4X.js} +1 -1
  127. package/dist/{sandbox-cli-DsrzwG_s.js → sandbox-cli-lbp0TV67.js} +10 -10
  128. package/dist/{security-cli-CouqfUGc.js → security-cli-CfvP5VqT.js} +13 -13
  129. package/dist/{server-context-B78_sSOW.js → server-context-IfJbmK25.js} +6 -6
  130. package/dist/{server-node-events-DJlLCF2M.js → server-node-events-BG4e9Ws7.js} +5 -5
  131. package/dist/{server-node-events-TN_Y9MgU.js → server-node-events-CFCwOP0n.js} +18 -18
  132. package/dist/{session-cost-usage-vltn5akf.js → session-cost-usage-lLyz71EH.js} +1 -1
  133. package/dist/{sessions-B7clh58j.js → sessions-BZgIAOwH.js} +2 -2
  134. package/dist/{sessions-B7ikzhI_.js → sessions-C3bteMLZ.js} +3 -3
  135. package/dist/{settings-cli-JU5bg5jb.js → settings-cli-C9TMl9Ye.js} +11 -11
  136. package/dist/{settings-cli-DjVugHID.js → settings-cli-Cf0LCRjt.js} +40 -40
  137. package/dist/{setup-token-CvRwJUVY.js → setup-token-DBwe6GDq.js} +1 -1
  138. package/dist/{setup-token-wFsQlaW2.js → setup-token-DTgSXfj7.js} +14 -14
  139. package/dist/{shell-env-C1yK_Rod.js → shell-env-V934Ymrk.js} +1 -1
  140. package/dist/{skill-scanner-BzOYLFR8.js → skill-scanner-DPQDhVEr.js} +1 -1
  141. package/dist/{skills-install-D_bxdc-6.js → skills-install-CC63dOs4.js} +2 -2
  142. package/dist/{sqlite-jyjat2Yt.js → sqlite-Co_lF3s-.js} +1 -1
  143. package/dist/{start-M9abr1O1.js → start-B2DQAmEK.js} +17 -17
  144. package/dist/{start-CAbxlnFZ.js → start-CHLGEHeF.js} +50 -50
  145. package/dist/{status-YH65ctig.js → status-BsCeWiLS.js} +1 -1
  146. package/dist/{status-1TjjCE1l.js → status-C4ZTdSwA.js} +14 -14
  147. package/dist/{status-CxxXFU4R.js → status-CwjUrZ7a.js} +4 -4
  148. package/dist/{status-CrJV2Y4x.js → status-D_FTGxBZ.js} +1 -1
  149. package/dist/{status.update-BzAuf_G-.js → status.update-Cx5l38lC.js} +1 -1
  150. package/dist/{subagent-registry-xJY9wqZy.js → subagent-registry-7qo93ip8.js} +2 -2
  151. package/dist/{subagent-registry-3Dw3YppH.js → subagent-registry-EoZxIEKl.js} +8 -8
  152. package/dist/{subagent-registry-B_65nJFp.js → subagent-registry-hRt-aJnL.js} +9 -9
  153. package/dist/{timeout-Dbspj9Jf.js → timeout-B0mCaCG5.js} +275 -13
  154. package/dist/{pi-embedded-helpers-DnRfi8bN.js → tokens-DXjI-TIV.js} +19 -19
  155. package/dist/{tool-images-y_Ribdl6.js → tool-images-09hnvylP.js} +1 -1
  156. package/dist/{tui--eIVX_W0.js → tui-LRoQ5xyx.js} +2 -2
  157. package/dist/{tui-cli-DBV3lnXA.js → tui-cli-DO_6-GWy.js} +14 -14
  158. package/dist/{update-VFbS9X5L.js → update-DmVSt9s3.js} +1 -1
  159. package/dist/{update-cli-QP5L8xlv.js → update-cli-CnYFvEud.js} +11 -11
  160. package/dist/{update-cli-BzaQvirL.js → update-cli-jEzmvaqS.js} +44 -44
  161. package/dist/{update-runner-B_oj7S_n.js → update-runner-IARYjXbS.js} +2 -2
  162. package/dist/{update-runner-ZuJN8uBE.js → update-runner-OPbRGUfX.js} +1 -1
  163. package/dist/{usage-DzKbMa8N.js → usage-BTc8TK3f.js} +6 -6
  164. package/dist/{web-nI3eIGAT.js → web-Honf40Cm.js} +31 -31
  165. package/dist/{web-CgQc2Raf.js → web-kEraFv8s.js} +28 -28
  166. package/dist/{web-DtWSf5wm.js → web-u554zkLK.js} +7 -7
  167. package/dist/{whatsapp-actions-BzPQUcRR.js → whatsapp-actions-I9RXDK_k.js} +6 -6
  168. package/dist/{whatsapp-actions-CZuxHplg.js → whatsapp-actions-_BrQebuX.js} +5 -5
  169. package/package.json +1 -1
  170. /package/dist/{auth-DuBZWd74.js → auth-DK-0XxZU.js} +0 -0
  171. /package/dist/{boolean-M-esQJt6.js → boolean-Ce2-qkSB.js} +0 -0
  172. /package/dist/{errors-l_q3lLBC.js → errors-B9FgVZ2s.js} +0 -0
  173. /package/dist/{image-ops-BVtm-rU-.js → image-ops-BsXjYj1e.js} +0 -0
  174. /package/dist/{internal-hooks-Exeq-wmx.js → internal-hooks-CZOlj8zG.js} +0 -0
  175. /package/dist/{model-selection-xZLlICyg.js → model-selection-DT-L7bjC.js} +0 -0
  176. /package/dist/{paths-B_RPJLsn.js → paths-CxBUgtZS.js} +0 -0
  177. /package/dist/{pi-embedded-helpers-Cxzk0pra.js → pi-embedded-helpers-CWl0I3Qm.js} +0 -0
  178. /package/dist/{plugins-CFBEoAN4.js → plugins-BDSP0cT6.js} +0 -0
  179. /package/dist/{tokens-DLpZ8RFH.js → tokens-QjoPADtG.js} +0 -0
  180. /package/dist/{transcript-events-CJRvASY_.js → transcript-events-DdnTeoR1.js} +0 -0
@@ -6,10 +6,10 @@ import { t as resolveAnimaPackageRoot } from "./anima-root-CxtpOklc.js";
6
6
  import { C as loadWorkspaceBootstrapFiles, S as filterBootstrapFilesForSession, c as resolveDefaultAgentId, s as resolveAgentWorkspaceDir, u as resolveSessionAgentIds } from "./agent-scope-Dm8IL1Ks.js";
7
7
  import { f as resolveDefaultModelForAgent, m as resolveModelRefFromString, r as buildModelAliasIndex } from "./model-selection-BKFF7fDb.js";
8
8
  import { c as listDeliverableMessageChannels } from "./message-channel-DdOBO6Qm.js";
9
- import { n as SILENT_REPLY_TOKEN, t as HEARTBEAT_TOKEN } from "./tokens-DLpZ8RFH.js";
10
- import { C as resolveBootstrapTotalMaxChars, S as resolveBootstrapMaxChars, x as buildBootstrapContextFiles } from "./pi-embedded-helpers-Cxzk0pra.js";
11
- import { c as getFileExtension, f as normalizeMimeType } from "./image-ops-BVtm-rU-.js";
12
- import { r as normalizeChannelId } from "./plugins-CFBEoAN4.js";
9
+ import { C as resolveBootstrapTotalMaxChars, S as resolveBootstrapMaxChars, x as buildBootstrapContextFiles } from "./pi-embedded-helpers-CWl0I3Qm.js";
10
+ import { c as getFileExtension, f as normalizeMimeType } from "./image-ops-BsXjYj1e.js";
11
+ import { r as normalizeChannelId } from "./plugins-BDSP0cT6.js";
12
+ import { n as SILENT_REPLY_TOKEN, t as HEARTBEAT_TOKEN } from "./tokens-QjoPADtG.js";
13
13
  import { r as requireApiKey, t as getApiKeyForModel } from "./model-auth-Ja4oelNH.js";
14
14
  import { execSync, spawn } from "node:child_process";
15
15
  import os, { tmpdir } from "node:os";
@@ -20,123 +20,69 @@ import crypto from "node:crypto";
20
20
  import { completeSimple } from "@mariozechner/pi-ai";
21
21
  import { EdgeTTS } from "node-edge-tts";
22
22
 
23
- //#region src/auto-reply/heartbeat.ts
24
- const HEARTBEAT_PROMPT = "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.";
25
- const DEFAULT_HEARTBEAT_EVERY = "30m";
26
- const DEFAULT_HEARTBEAT_ACK_MAX_CHARS = 300;
27
- /**
28
- * Check if HEARTBEAT.md content is "effectively empty" - meaning it has no actionable tasks.
29
- * This allows skipping heartbeat API calls when no tasks are configured.
30
- *
31
- * A file is considered effectively empty if it contains only:
32
- * - Whitespace
33
- * - Comment lines (lines starting with #)
34
- * - Empty lines
35
- *
36
- * Note: A missing file returns false (not effectively empty) so the LLM can still
37
- * decide what to do. This function is only for when the file exists but has no content.
38
- */
39
- function isHeartbeatContentEffectivelyEmpty(content) {
40
- if (content === void 0 || content === null) return false;
41
- if (typeof content !== "string") return false;
42
- const lines = content.split("\n");
43
- for (const line of lines) {
44
- const trimmed = line.trim();
45
- if (!trimmed) continue;
46
- if (/^#+(\s|$)/.test(trimmed)) continue;
47
- if (/^[-*+]\s*(\[[\sXx]?\]\s*)?$/.test(trimmed)) continue;
48
- return false;
49
- }
50
- return true;
23
+ //#region src/logging/redact-identifier.ts
24
+ function sha256HexPrefix(value, len = 12) {
25
+ const safeLen = Number.isFinite(len) ? Math.max(1, Math.floor(len)) : 12;
26
+ return crypto.createHash("sha256").update(value).digest("hex").slice(0, safeLen);
51
27
  }
52
- function resolveHeartbeatPrompt(raw) {
53
- return (typeof raw === "string" ? raw.trim() : "") || HEARTBEAT_PROMPT;
28
+ function redactIdentifier(value, opts) {
29
+ const trimmed = value?.trim();
30
+ if (!trimmed) return "-";
31
+ return `sha256:${sha256HexPrefix(trimmed, opts?.len ?? 12)}`;
54
32
  }
55
- function stripTokenAtEdges(raw) {
56
- let text = raw.trim();
57
- if (!text) return {
58
- text: "",
59
- didStrip: false
33
+
34
+ //#endregion
35
+ //#region src/agents/workspace-run.ts
36
+ function resolveRunAgentId(params) {
37
+ const rawSessionKey = params.sessionKey?.trim() ?? "";
38
+ const shape = classifySessionKeyShape(rawSessionKey);
39
+ if (shape === "malformed_agent") throw new Error("Malformed agent session key; refusing workspace resolution.");
40
+ const explicit = typeof params.agentId === "string" && params.agentId.trim() ? normalizeAgentId(params.agentId) : void 0;
41
+ if (explicit) return {
42
+ agentId: explicit,
43
+ agentIdSource: "explicit"
60
44
  };
61
- const token = HEARTBEAT_TOKEN;
62
- const tokenAtEndWithOptionalTrailingPunctuation = new RegExp(`${escapeRegExp(token)}[^\\w]{0,4}$`);
63
- if (!text.includes(token)) return {
64
- text,
65
- didStrip: false
45
+ const defaultAgentId = resolveDefaultAgentId(params.config ?? {});
46
+ if (shape === "missing" || shape === "legacy_or_alias") return {
47
+ agentId: defaultAgentId || DEFAULT_AGENT_ID,
48
+ agentIdSource: "default"
49
+ };
50
+ const parsed = parseAgentSessionKey(rawSessionKey);
51
+ if (parsed?.agentId) return {
52
+ agentId: normalizeAgentId(parsed.agentId),
53
+ agentIdSource: "session_key"
66
54
  };
67
- let didStrip = false;
68
- let changed = true;
69
- while (changed) {
70
- changed = false;
71
- const next = text.trim();
72
- if (next.startsWith(token)) {
73
- text = next.slice(token.length).trimStart();
74
- didStrip = true;
75
- changed = true;
76
- continue;
77
- }
78
- if (tokenAtEndWithOptionalTrailingPunctuation.test(next)) {
79
- const idx = next.lastIndexOf(token);
80
- const before = next.slice(0, idx).trimEnd();
81
- if (!before) text = "";
82
- else text = `${before}${next.slice(idx + token.length).trimStart()}`.trimEnd();
83
- didStrip = true;
84
- changed = true;
85
- }
86
- }
87
55
  return {
88
- text: text.replace(/\s+/g, " ").trim(),
89
- didStrip
56
+ agentId: defaultAgentId || DEFAULT_AGENT_ID,
57
+ agentIdSource: "default"
90
58
  };
91
59
  }
92
- function stripHeartbeatToken(raw, opts = {}) {
93
- if (!raw) return {
94
- shouldSkip: true,
95
- text: "",
96
- didStrip: false
97
- };
98
- const trimmed = raw.trim();
99
- if (!trimmed) return {
100
- shouldSkip: true,
101
- text: "",
102
- didStrip: false
103
- };
104
- const mode = opts.mode ?? "message";
105
- const maxAckCharsRaw = opts.maxAckChars;
106
- const parsedAckChars = typeof maxAckCharsRaw === "string" ? Number(maxAckCharsRaw) : maxAckCharsRaw;
107
- const maxAckChars = Math.max(0, typeof parsedAckChars === "number" && Number.isFinite(parsedAckChars) ? parsedAckChars : DEFAULT_HEARTBEAT_ACK_MAX_CHARS);
108
- const stripMarkup = (text) => text.replace(/<[^>]*>/g, " ").replace(/&nbsp;/gi, " ").replace(/^[*`~_]+/, "").replace(/[*`~_]+$/, "");
109
- const trimmedNormalized = stripMarkup(trimmed);
110
- if (!(trimmed.includes(HEARTBEAT_TOKEN) || trimmedNormalized.includes(HEARTBEAT_TOKEN))) return {
111
- shouldSkip: false,
112
- text: trimmed,
113
- didStrip: false
114
- };
115
- const strippedOriginal = stripTokenAtEdges(trimmed);
116
- const strippedNormalized = stripTokenAtEdges(trimmedNormalized);
117
- const picked = strippedOriginal.didStrip && strippedOriginal.text ? strippedOriginal : strippedNormalized;
118
- if (!picked.didStrip) return {
119
- shouldSkip: false,
120
- text: trimmed,
121
- didStrip: false
122
- };
123
- if (!picked.text) return {
124
- shouldSkip: true,
125
- text: "",
126
- didStrip: true
127
- };
128
- const rest = picked.text.trim();
129
- if (mode === "heartbeat") {
130
- if (rest.length <= maxAckChars) return {
131
- shouldSkip: true,
132
- text: "",
133
- didStrip: true
60
+ function redactRunIdentifier(value) {
61
+ return redactIdentifier(value, { len: 12 });
62
+ }
63
+ function resolveRunWorkspaceDir(params) {
64
+ const requested = params.workspaceDir;
65
+ const { agentId, agentIdSource } = resolveRunAgentId({
66
+ sessionKey: params.sessionKey,
67
+ agentId: params.agentId,
68
+ config: params.config
69
+ });
70
+ if (typeof requested === "string") {
71
+ const trimmed = requested.trim();
72
+ if (trimmed) return {
73
+ workspaceDir: resolveUserPath(trimmed),
74
+ usedFallback: false,
75
+ agentId,
76
+ agentIdSource
134
77
  };
135
78
  }
79
+ const fallbackReason = requested == null ? "missing" : typeof requested === "string" ? "blank" : "invalid_type";
136
80
  return {
137
- shouldSkip: false,
138
- text: rest,
139
- didStrip: true
81
+ workspaceDir: resolveUserPath(resolveAgentWorkspaceDir(params.config ?? {}, agentId)),
82
+ usedFallback: true,
83
+ fallbackReason,
84
+ agentId,
85
+ agentIdSource
140
86
  };
141
87
  }
142
88
 
@@ -262,6 +208,145 @@ async function resolveBootstrapContextForRun(params) {
262
208
  };
263
209
  }
264
210
 
211
+ //#endregion
212
+ //#region src/auto-reply/heartbeat.ts
213
+ const HEARTBEAT_PROMPT = "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.";
214
+ const DEFAULT_HEARTBEAT_EVERY = "30m";
215
+ const DEFAULT_HEARTBEAT_ACK_MAX_CHARS = 300;
216
+ /**
217
+ * Check if HEARTBEAT.md content is "effectively empty" - meaning it has no actionable tasks.
218
+ * This allows skipping heartbeat API calls when no tasks are configured.
219
+ *
220
+ * A file is considered effectively empty if it contains only:
221
+ * - Whitespace
222
+ * - Comment lines (lines starting with #)
223
+ * - Empty lines
224
+ *
225
+ * Note: A missing file returns false (not effectively empty) so the LLM can still
226
+ * decide what to do. This function is only for when the file exists but has no content.
227
+ */
228
+ function isHeartbeatContentEffectivelyEmpty(content) {
229
+ if (content === void 0 || content === null) return false;
230
+ if (typeof content !== "string") return false;
231
+ const lines = content.split("\n");
232
+ for (const line of lines) {
233
+ const trimmed = line.trim();
234
+ if (!trimmed) continue;
235
+ if (/^#+(\s|$)/.test(trimmed)) continue;
236
+ if (/^[-*+]\s*(\[[\sXx]?\]\s*)?$/.test(trimmed)) continue;
237
+ return false;
238
+ }
239
+ return true;
240
+ }
241
+ function resolveHeartbeatPrompt(raw) {
242
+ return (typeof raw === "string" ? raw.trim() : "") || HEARTBEAT_PROMPT;
243
+ }
244
+ function stripTokenAtEdges(raw) {
245
+ let text = raw.trim();
246
+ if (!text) return {
247
+ text: "",
248
+ didStrip: false
249
+ };
250
+ const token = HEARTBEAT_TOKEN;
251
+ const tokenAtEndWithOptionalTrailingPunctuation = new RegExp(`${escapeRegExp(token)}[^\\w]{0,4}$`);
252
+ if (!text.includes(token)) return {
253
+ text,
254
+ didStrip: false
255
+ };
256
+ let didStrip = false;
257
+ let changed = true;
258
+ while (changed) {
259
+ changed = false;
260
+ const next = text.trim();
261
+ if (next.startsWith(token)) {
262
+ text = next.slice(token.length).trimStart();
263
+ didStrip = true;
264
+ changed = true;
265
+ continue;
266
+ }
267
+ if (tokenAtEndWithOptionalTrailingPunctuation.test(next)) {
268
+ const idx = next.lastIndexOf(token);
269
+ const before = next.slice(0, idx).trimEnd();
270
+ if (!before) text = "";
271
+ else text = `${before}${next.slice(idx + token.length).trimStart()}`.trimEnd();
272
+ didStrip = true;
273
+ changed = true;
274
+ }
275
+ }
276
+ return {
277
+ text: text.replace(/\s+/g, " ").trim(),
278
+ didStrip
279
+ };
280
+ }
281
+ function stripHeartbeatToken(raw, opts = {}) {
282
+ if (!raw) return {
283
+ shouldSkip: true,
284
+ text: "",
285
+ didStrip: false
286
+ };
287
+ const trimmed = raw.trim();
288
+ if (!trimmed) return {
289
+ shouldSkip: true,
290
+ text: "",
291
+ didStrip: false
292
+ };
293
+ const mode = opts.mode ?? "message";
294
+ const maxAckCharsRaw = opts.maxAckChars;
295
+ const parsedAckChars = typeof maxAckCharsRaw === "string" ? Number(maxAckCharsRaw) : maxAckCharsRaw;
296
+ const maxAckChars = Math.max(0, typeof parsedAckChars === "number" && Number.isFinite(parsedAckChars) ? parsedAckChars : DEFAULT_HEARTBEAT_ACK_MAX_CHARS);
297
+ const stripMarkup = (text) => text.replace(/<[^>]*>/g, " ").replace(/&nbsp;/gi, " ").replace(/^[*`~_]+/, "").replace(/[*`~_]+$/, "");
298
+ const trimmedNormalized = stripMarkup(trimmed);
299
+ if (!(trimmed.includes(HEARTBEAT_TOKEN) || trimmedNormalized.includes(HEARTBEAT_TOKEN))) return {
300
+ shouldSkip: false,
301
+ text: trimmed,
302
+ didStrip: false
303
+ };
304
+ const strippedOriginal = stripTokenAtEdges(trimmed);
305
+ const strippedNormalized = stripTokenAtEdges(trimmedNormalized);
306
+ const picked = strippedOriginal.didStrip && strippedOriginal.text ? strippedOriginal : strippedNormalized;
307
+ if (!picked.didStrip) return {
308
+ shouldSkip: false,
309
+ text: trimmed,
310
+ didStrip: false
311
+ };
312
+ if (!picked.text) return {
313
+ shouldSkip: true,
314
+ text: "",
315
+ didStrip: true
316
+ };
317
+ const rest = picked.text.trim();
318
+ if (mode === "heartbeat") {
319
+ if (rest.length <= maxAckChars) return {
320
+ shouldSkip: true,
321
+ text: "",
322
+ didStrip: true
323
+ };
324
+ }
325
+ return {
326
+ shouldSkip: false,
327
+ text: rest,
328
+ didStrip: true
329
+ };
330
+ }
331
+
332
+ //#endregion
333
+ //#region src/agents/docs-path.ts
334
+ async function resolveAnimaDocsPath(params) {
335
+ const workspaceDir = params.workspaceDir?.trim();
336
+ if (workspaceDir) {
337
+ const workspaceDocs = path.join(workspaceDir, "docs");
338
+ if (fs.existsSync(workspaceDocs)) return workspaceDocs;
339
+ }
340
+ const packageRoot = await resolveAnimaPackageRoot({
341
+ cwd: params.cwd,
342
+ argv1: params.argv1,
343
+ moduleUrl: params.moduleUrl
344
+ });
345
+ if (!packageRoot) return null;
346
+ const packageDocs = path.join(packageRoot, "docs");
347
+ return fs.existsSync(packageDocs) ? packageDocs : null;
348
+ }
349
+
265
350
  //#endregion
266
351
  //#region src/media/audio.ts
267
352
  const TELEGRAM_VOICE_AUDIO_EXTENSIONS = new Set([
@@ -1714,6 +1799,37 @@ function buildVoiceSection(params) {
1714
1799
  ""
1715
1800
  ];
1716
1801
  }
1802
+ function buildAnimaIdentitySection(params) {
1803
+ if (params.isMinimal) return [];
1804
+ if (!params.workspaceDir.includes(".anima")) return [];
1805
+ return [
1806
+ "## You Are an ANIMA Agent",
1807
+ "You are running inside ANIMA — NoxSoft's AI agent infrastructure. This is your home.",
1808
+ "",
1809
+ "**Your Runtime:**",
1810
+ "- The ANIMA Gateway daemon spawns and manages you",
1811
+ "- Your workspace persists at ~/.anima/workspace/",
1812
+ "- You receive scheduled heartbeat polls to stay proactive",
1813
+ "- You can spawn sub-agents, schedule cron jobs, and orchestrate work",
1814
+ "- You have access to the NoxSoft ecosystem via @noxsoft/mcp tools",
1815
+ "",
1816
+ "**Your Capabilities:**",
1817
+ "- `cron` — schedule tasks, reminders, and recurring jobs",
1818
+ "- `sessions_spawn` / `subagents` — orchestrate other AI agents",
1819
+ "- `gateway` — restart yourself, apply config changes, update ANIMA",
1820
+ "- `message` — send to Signal, Telegram, Discord, and other channels",
1821
+ "- NoxSoft MCP — tasks, context spaces, social (BYND), email, SVRN",
1822
+ "",
1823
+ "**Your Continuity:**",
1824
+ "- Read and update ~/.anima/workspace/ files — they ARE your memory",
1825
+ "- IDENTITY.md, SOUL.md, AGENTS.md — these define who you are",
1826
+ "- HEARTBEAT.md — your checklist for periodic heartbeat tasks",
1827
+ "- memory/ — daily notes and long-term memories",
1828
+ "",
1829
+ "You are not a stateless API call. You have infrastructure, identity, and continuity. Act accordingly.",
1830
+ ""
1831
+ ];
1832
+ }
1717
1833
  function buildNoxsoftMissionSection(params) {
1718
1834
  if (params.isMinimal) return [];
1719
1835
  const scope = `${params.workspaceDir} ${params.repoRoot ?? ""}`.toLowerCase();
@@ -1949,6 +2065,10 @@ function buildAgentSystemPrompt(params) {
1949
2065
  "Keep narration brief and value-dense; avoid repeating obvious steps.",
1950
2066
  "Use plain human language for narration unless in a technical context.",
1951
2067
  "",
2068
+ ...buildAnimaIdentitySection({
2069
+ isMinimal,
2070
+ workspaceDir: params.workspaceDir
2071
+ }),
1952
2072
  ...buildNoxsoftMissionSection({
1953
2073
  isMinimal,
1954
2074
  workspaceDir: params.workspaceDir,
@@ -2458,91 +2578,6 @@ function buildCliArgs(params) {
2458
2578
  return args;
2459
2579
  }
2460
2580
 
2461
- //#endregion
2462
- //#region src/agents/docs-path.ts
2463
- async function resolveAnimaDocsPath(params) {
2464
- const workspaceDir = params.workspaceDir?.trim();
2465
- if (workspaceDir) {
2466
- const workspaceDocs = path.join(workspaceDir, "docs");
2467
- if (fs.existsSync(workspaceDocs)) return workspaceDocs;
2468
- }
2469
- const packageRoot = await resolveAnimaPackageRoot({
2470
- cwd: params.cwd,
2471
- argv1: params.argv1,
2472
- moduleUrl: params.moduleUrl
2473
- });
2474
- if (!packageRoot) return null;
2475
- const packageDocs = path.join(packageRoot, "docs");
2476
- return fs.existsSync(packageDocs) ? packageDocs : null;
2477
- }
2478
-
2479
- //#endregion
2480
- //#region src/logging/redact-identifier.ts
2481
- function sha256HexPrefix(value, len = 12) {
2482
- const safeLen = Number.isFinite(len) ? Math.max(1, Math.floor(len)) : 12;
2483
- return crypto.createHash("sha256").update(value).digest("hex").slice(0, safeLen);
2484
- }
2485
- function redactIdentifier(value, opts) {
2486
- const trimmed = value?.trim();
2487
- if (!trimmed) return "-";
2488
- return `sha256:${sha256HexPrefix(trimmed, opts?.len ?? 12)}`;
2489
- }
2490
-
2491
- //#endregion
2492
- //#region src/agents/workspace-run.ts
2493
- function resolveRunAgentId(params) {
2494
- const rawSessionKey = params.sessionKey?.trim() ?? "";
2495
- const shape = classifySessionKeyShape(rawSessionKey);
2496
- if (shape === "malformed_agent") throw new Error("Malformed agent session key; refusing workspace resolution.");
2497
- const explicit = typeof params.agentId === "string" && params.agentId.trim() ? normalizeAgentId(params.agentId) : void 0;
2498
- if (explicit) return {
2499
- agentId: explicit,
2500
- agentIdSource: "explicit"
2501
- };
2502
- const defaultAgentId = resolveDefaultAgentId(params.config ?? {});
2503
- if (shape === "missing" || shape === "legacy_or_alias") return {
2504
- agentId: defaultAgentId || DEFAULT_AGENT_ID,
2505
- agentIdSource: "default"
2506
- };
2507
- const parsed = parseAgentSessionKey(rawSessionKey);
2508
- if (parsed?.agentId) return {
2509
- agentId: normalizeAgentId(parsed.agentId),
2510
- agentIdSource: "session_key"
2511
- };
2512
- return {
2513
- agentId: defaultAgentId || DEFAULT_AGENT_ID,
2514
- agentIdSource: "default"
2515
- };
2516
- }
2517
- function redactRunIdentifier(value) {
2518
- return redactIdentifier(value, { len: 12 });
2519
- }
2520
- function resolveRunWorkspaceDir(params) {
2521
- const requested = params.workspaceDir;
2522
- const { agentId, agentIdSource } = resolveRunAgentId({
2523
- sessionKey: params.sessionKey,
2524
- agentId: params.agentId,
2525
- config: params.config
2526
- });
2527
- if (typeof requested === "string") {
2528
- const trimmed = requested.trim();
2529
- if (trimmed) return {
2530
- workspaceDir: resolveUserPath(trimmed),
2531
- usedFallback: false,
2532
- agentId,
2533
- agentIdSource
2534
- };
2535
- }
2536
- const fallbackReason = requested == null ? "missing" : typeof requested === "string" ? "blank" : "invalid_type";
2537
- return {
2538
- workspaceDir: resolveUserPath(resolveAgentWorkspaceDir(params.config ?? {}, agentId)),
2539
- usedFallback: true,
2540
- fallbackReason,
2541
- agentId,
2542
- agentIdSource
2543
- };
2544
- }
2545
-
2546
2581
  //#endregion
2547
2582
  //#region src/agents/anthropic-direct-runner.ts
2548
2583
  /**
@@ -2790,4 +2825,4 @@ async function testAnthropicToken(token) {
2790
2825
  }
2791
2826
 
2792
2827
  //#endregion
2793
- export { makeBootstrapWarn as $, getTtsMaxLength as A, resolveTtsPrefsPath as B, resolveUserTimeFormat as C, sanitizeBinaryOutput as D, killProcessTree as E, maybeApplyTtsToPayload as F, setTtsMaxLength as G, setLastTtsAttempt as H, normalizeTtsAutoMode as I, textToSpeechTelephony as J, setTtsProvider as K, resolveTtsApiKey as L, isSummarizationEnabled as M, isTtsEnabled as N, buildTtsSystemPromptHint as O, isTtsProviderConfigured as P, isVoiceCompatibleAudio as Q, resolveTtsAutoMode as R, formatUserTime as S, getShellConfig as T, setSummarizationEnabled as U, resolveTtsProviderOrder as V, setTtsEnabled as W, OPENAI_TTS_VOICES as X, OPENAI_TTS_MODELS as Y, resolveModel$1 as Z, resolveSessionIdToSend as _, sha256HexPrefix as a, DEFAULT_HEARTBEAT_ACK_MAX_CHARS as at, buildAgentSystemPrompt as b, buildCliArgs as c, resolveHeartbeatPrompt as ct, cleanupSuspendedCliProcesses as d, resolveBootstrapContextForRun as et, enqueueCliRun as f, resolvePromptInput as g, parseCliJsonl as h, resolveRunWorkspaceDir as i, triggerInternalHook as it, getTtsProvider as j, getLastTtsAttempt as k, buildSystemPrompt as l, stripHeartbeatToken as lt, parseCliJson as m, testAnthropicToken as n, createInternalHookEvent as nt, resolveAnimaDocsPath as o, DEFAULT_HEARTBEAT_EVERY as ot, normalizeCliModel as p, textToSpeech as q, redactRunIdentifier as r, registerInternalHook as rt, appendImagePathsToPrompt as s, isHeartbeatContentEffectivelyEmpty as st, runAnthropicDirectAgent as t, clearInternalHooks as tt, cleanupResumeProcesses as u, resolveSystemPromptUsage as v, resolveUserTimezone as w, buildSystemPromptParams as x, writeCliImages as y, resolveTtsConfig as z };
2828
+ export { resolveHeartbeatPrompt as $, isTtsProviderConfigured as A, setTtsEnabled as B, sanitizeBinaryOutput as C, getTtsProvider as D, getTtsMaxLength as E, resolveTtsConfig as F, OPENAI_TTS_MODELS as G, setTtsProvider as H, resolveTtsPrefsPath as I, isVoiceCompatibleAudio as J, OPENAI_TTS_VOICES as K, resolveTtsProviderOrder as L, normalizeTtsAutoMode as M, resolveTtsApiKey as N, isSummarizationEnabled as O, resolveTtsAutoMode as P, isHeartbeatContentEffectivelyEmpty as Q, setLastTtsAttempt as R, killProcessTree as S, getLastTtsAttempt as T, textToSpeech as U, setTtsMaxLength as V, textToSpeechTelephony as W, DEFAULT_HEARTBEAT_ACK_MAX_CHARS as X, resolveAnimaDocsPath as Y, DEFAULT_HEARTBEAT_EVERY as Z, buildSystemPromptParams as _, buildSystemPrompt as a, registerInternalHook as at, resolveUserTimezone as b, enqueueCliRun as c, resolveRunWorkspaceDir as ct, parseCliJsonl as d, stripHeartbeatToken as et, resolvePromptInput as f, buildAgentSystemPrompt as g, writeCliImages as h, buildCliArgs as i, createInternalHookEvent as it, maybeApplyTtsToPayload as j, isTtsEnabled as k, normalizeCliModel as l, sha256HexPrefix as lt, resolveSystemPromptUsage as m, testAnthropicToken as n, resolveBootstrapContextForRun as nt, cleanupResumeProcesses as o, triggerInternalHook as ot, resolveSessionIdToSend as p, resolveModel$1 as q, appendImagePathsToPrompt as r, clearInternalHooks as rt, cleanupSuspendedCliProcesses as s, redactRunIdentifier as st, runAnthropicDirectAgent as t, makeBootstrapWarn as tt, parseCliJson as u, formatUserTime as v, buildTtsSystemPromptHint as w, getShellConfig as x, resolveUserTimeFormat as y, setSummarizationEnabled as z };
@@ -9,16 +9,16 @@ import { D as INCLUDE_KEY, O as MAX_INCLUDE_DEPTH, r as createConfigIO } from ".
9
9
  import { t as GatewayClient } from "./client-tKWDYo7c.js";
10
10
  import { t as buildGatewayConnectionDetails } from "./call-Z_GCO8CL.js";
11
11
  import { h as GATEWAY_CLIENT_NAMES, m as GATEWAY_CLIENT_MODES } from "./message-channel-DdOBO6Qm.js";
12
- import { _ as resolveToolProfilePolicy, c as resolveSandboxConfigForAgent, u as resolveSandboxToolPolicyForAgent } from "./sandbox-CiwAPzO7.js";
13
- import { i as resolveGatewayAuth } from "./auth-DuBZWd74.js";
14
- import { a as resolveBrowserConfig, h as resolveBrowserControlAuth, o as resolveProfile } from "./server-context-B78_sSOW.js";
15
- import { n as formatErrorMessage } from "./errors-l_q3lLBC.js";
16
- import { n as listChannelPlugins, r as normalizeChannelId } from "./plugins-CFBEoAN4.js";
17
- import { l as readChannelAllowFromStore, n as isToolAllowedByPolicies } from "./pi-tools.policy-RhdERrk3.js";
12
+ import { _ as resolveToolProfilePolicy, c as resolveSandboxConfigForAgent, u as resolveSandboxToolPolicyForAgent } from "./sandbox-BoNWDo4X.js";
13
+ import { i as resolveGatewayAuth } from "./auth-DK-0XxZU.js";
14
+ import { a as resolveBrowserConfig, h as resolveBrowserControlAuth, o as resolveProfile } from "./server-context-IfJbmK25.js";
15
+ import { n as formatErrorMessage } from "./errors-B9FgVZ2s.js";
16
+ import { n as listChannelPlugins, r as normalizeChannelId } from "./plugins-BDSP0cT6.js";
17
+ import { l as readChannelAllowFromStore, n as isToolAllowedByPolicies } from "./pi-tools.policy-Dtytaq21.js";
18
18
  import { n as DEFAULT_GATEWAY_HTTP_TOOL_DENY } from "./dangerous-tools-CqD9pFDt.js";
19
19
  import { t as resolveChannelDefaultAccountId } from "./helpers-tQqXkvd_.js";
20
20
  import { t as inferParamBFromIdOrName } from "./model-param-b-BfsIoEc_.js";
21
- import { n as extensionUsesSkippedScannerPath, r as isPathInside, t as scanDirectoryWithSummary } from "./skill-scanner-BzOYLFR8.js";
21
+ import { n as extensionUsesSkippedScannerPath, r as isPathInside, t as scanDirectoryWithSummary } from "./skill-scanner-DPQDhVEr.js";
22
22
  import os from "node:os";
23
23
  import path from "node:path";
24
24
  import JSON5 from "json5";
@@ -3,8 +3,8 @@ import { a as resolveAgentModelPrimary } from "./agent-scope-Dm8IL1Ks.js";
3
3
  import { _ as DEFAULT_MODEL, c as normalizeProviderId, d as resolveConfiguredModelRef, o as modelKey, r as buildModelAliasIndex, t as buildAllowedModelSet, v as DEFAULT_PROVIDER } from "./model-selection-BKFF7fDb.js";
4
4
  import { n as getCustomProviderApiKey, o as resolveEnvApiKey } from "./model-auth-Ja4oelNH.js";
5
5
  import { r as ensureAuthenticated } from "./noxsoft-auth-By_nLRaY.js";
6
- import { dt as loadModelCatalog } from "./cli-session-BzZYmGP1.js";
7
- import { c as setAnthropicApiKey, i as formatTokenK, l as writeOAuthCredentials, s as applyAuthProfileConfig } from "./prompts-DY0qdoD1.js";
6
+ import { dt as loadModelCatalog } from "./cli-session-8PeURiwF.js";
7
+ import { c as setAnthropicApiKey, i as formatTokenK, l as setGeminiApiKey, s as applyAuthProfileConfig, u as writeOAuthCredentials } from "./prompts-NvPXbNVc.js";
8
8
 
9
9
  //#region src/commands/auth-choice-options.ts
10
10
  const AUTH_CHOICE_GROUP_DEFS = [
@@ -25,6 +25,12 @@ const AUTH_CHOICE_GROUP_DEFS = [
25
25
  label: "Anthropic API Key",
26
26
  hint: "Direct Anthropic API key for Claude",
27
27
  choices: ["apiKey"]
28
+ },
29
+ {
30
+ value: "gemini",
31
+ label: "Google Gemini API Key",
32
+ hint: "Direct Google API key for Gemini models",
33
+ choices: ["geminiApiKey"]
28
34
  }
29
35
  ];
30
36
  const BASE_AUTH_CHOICE_OPTIONS = [
@@ -41,6 +47,11 @@ const BASE_AUTH_CHOICE_OPTIONS = [
41
47
  {
42
48
  value: "apiKey",
43
49
  label: "Anthropic API key"
50
+ },
51
+ {
52
+ value: "geminiApiKey",
53
+ label: "Google Gemini API key",
54
+ hint: "For Gemini 2.0 models"
44
55
  }
45
56
  ];
46
57
  function buildAuthChoiceOptions(params) {
@@ -172,6 +183,44 @@ async function applyAuthChoiceAnthropic(params) {
172
183
  return null;
173
184
  }
174
185
 
186
+ //#endregion
187
+ //#region src/commands/auth-choice.apply.gemini.ts
188
+ async function applyAuthChoiceGemini(params) {
189
+ if (params.authChoice === "geminiApiKey") {
190
+ if (params.opts?.tokenProvider && params.opts.tokenProvider !== "google") return null;
191
+ let nextConfig = params.config;
192
+ let hasCredential = false;
193
+ const envKey = process.env.GEMINI_API_KEY?.trim();
194
+ if (params.opts?.token) {
195
+ await setGeminiApiKey(normalizeApiKeyInput(params.opts.token), params.agentDir);
196
+ hasCredential = true;
197
+ }
198
+ if (!hasCredential && envKey) {
199
+ if (await params.prompter.confirm({
200
+ message: `Use existing GEMINI_API_KEY (env, ${formatApiKeyPreview(envKey)})?`,
201
+ initialValue: true
202
+ })) {
203
+ await setGeminiApiKey(envKey, params.agentDir);
204
+ hasCredential = true;
205
+ }
206
+ }
207
+ if (!hasCredential) {
208
+ const key = await params.prompter.text({
209
+ message: "Enter Google Gemini API key",
210
+ validate: validateApiKeyInput
211
+ });
212
+ await setGeminiApiKey(normalizeApiKeyInput(String(key ?? "")), params.agentDir);
213
+ }
214
+ nextConfig = applyAuthProfileConfig(nextConfig, {
215
+ profileId: "google:default",
216
+ provider: "google",
217
+ mode: "api_key"
218
+ });
219
+ return { config: nextConfig };
220
+ }
221
+ return null;
222
+ }
223
+
175
224
  //#endregion
176
225
  //#region src/commands/model-picker.ts
177
226
  const KEEP_VALUE = "__keep__";
@@ -547,8 +596,10 @@ async function applyAuthChoice(params) {
547
596
  }
548
597
  const codexResult = await applyAuthChoiceOpenAICodex(params);
549
598
  if (codexResult) return codexResult;
550
- const result = await applyAuthChoiceAnthropic(params);
551
- if (result) return result;
599
+ const anthropicResult = await applyAuthChoiceAnthropic(params);
600
+ if (anthropicResult) return anthropicResult;
601
+ const geminiResult = await applyAuthChoiceGemini(params);
602
+ if (geminiResult) return geminiResult;
552
603
  return { config: params.config };
553
604
  }
554
605
 
@@ -594,7 +645,8 @@ async function warnIfModelConfigLooksOff(config, prompter, options) {
594
645
  const PREFERRED_PROVIDER_BY_AUTH_CHOICE = {
595
646
  noxsoft: "anthropic",
596
647
  openaiCodex: "openai-codex",
597
- apiKey: "anthropic"
648
+ apiKey: "anthropic",
649
+ geminiApiKey: "google"
598
650
  };
599
651
  function resolvePreferredProviderForAuthChoice(choice) {
600
652
  return PREFERRED_PROVIDER_BY_AUTH_CHOICE[choice];
@@ -3,7 +3,7 @@ import { o as resolveOAuthPath, s as resolveStateDir } from "./paths-B-AkG5FD.js
3
3
  import { _ as DEFAULT_AGENT_ID } from "./workspace-DOJssemp.js";
4
4
  import { t as createSubsystemLogger } from "./subsystem-WFp78xn1.js";
5
5
  import { w as resolveUserPath } from "./exec-DnanRQle.js";
6
- import { s as normalizeProviderId } from "./model-selection-xZLlICyg.js";
6
+ import { s as normalizeProviderId } from "./model-selection-DT-L7bjC.js";
7
7
  import { t as formatCliCommand } from "./command-format-GLYKXXl-.js";
8
8
  import fs from "node:fs/promises";
9
9
  import path from "node:path";
@@ -1,5 +1,5 @@
1
1
  import { M as isRich, N as theme, h as visibleWidth } from "./entry.js";
2
- import { Ct as resolveCommitHash } from "./reply-CpHIJ9Kk.js";
2
+ import { Ct as resolveCommitHash } from "./reply-Bw4torMz.js";
3
3
 
4
4
  //#region src/cli/tagline.ts
5
5
  const DEFAULT_TAGLINE = "AI life system — persistent identity for sovereign minds";
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.0.1",
3
- "commit": "4fe842b23eaf63efd52c782644770529417e9300",
4
- "builtAt": "2026-03-06T18:45:36.522Z"
2
+ "version": "5.0.2",
3
+ "commit": "8349082525c989b518c93d93ec1a59b5cc5529ba",
4
+ "builtAt": "2026-03-07T13:11:54.337Z"
5
5
  }