@aitne/daemon 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1386) hide show
  1. package/LICENSE +21 -0
  2. package/dist/adapters/composite-dashboard-stream.d.ts +42 -0
  3. package/dist/adapters/composite-dashboard-stream.d.ts.map +1 -0
  4. package/dist/adapters/composite-dashboard-stream.js +49 -0
  5. package/dist/adapters/composite-dashboard-stream.js.map +1 -0
  6. package/dist/adapters/dashboard-adapter.d.ts +104 -0
  7. package/dist/adapters/dashboard-adapter.d.ts.map +1 -0
  8. package/dist/adapters/dashboard-adapter.js +216 -0
  9. package/dist/adapters/dashboard-adapter.js.map +1 -0
  10. package/dist/adapters/discord.d.ts +77 -0
  11. package/dist/adapters/discord.d.ts.map +1 -0
  12. package/dist/adapters/discord.js +339 -0
  13. package/dist/adapters/discord.js.map +1 -0
  14. package/dist/adapters/docs-qa-adapter.d.ts +123 -0
  15. package/dist/adapters/docs-qa-adapter.d.ts.map +1 -0
  16. package/dist/adapters/docs-qa-adapter.js +218 -0
  17. package/dist/adapters/docs-qa-adapter.js.map +1 -0
  18. package/dist/adapters/message-hub.d.ts +70 -0
  19. package/dist/adapters/message-hub.d.ts.map +1 -0
  20. package/dist/adapters/message-hub.js +359 -0
  21. package/dist/adapters/message-hub.js.map +1 -0
  22. package/dist/adapters/notification-manager.d.ts +99 -0
  23. package/dist/adapters/notification-manager.d.ts.map +1 -0
  24. package/dist/adapters/notification-manager.js +498 -0
  25. package/dist/adapters/notification-manager.js.map +1 -0
  26. package/dist/adapters/outbound-text.d.ts +28 -0
  27. package/dist/adapters/outbound-text.d.ts.map +1 -0
  28. package/dist/adapters/outbound-text.js +58 -0
  29. package/dist/adapters/outbound-text.js.map +1 -0
  30. package/dist/adapters/slack-adapter.d.ts +82 -0
  31. package/dist/adapters/slack-adapter.d.ts.map +1 -0
  32. package/dist/adapters/slack-adapter.js +359 -0
  33. package/dist/adapters/slack-adapter.js.map +1 -0
  34. package/dist/adapters/telegram-adapter.d.ts +107 -0
  35. package/dist/adapters/telegram-adapter.d.ts.map +1 -0
  36. package/dist/adapters/telegram-adapter.js +477 -0
  37. package/dist/adapters/telegram-adapter.js.map +1 -0
  38. package/dist/adapters/types.d.ts +92 -0
  39. package/dist/adapters/types.d.ts.map +1 -0
  40. package/dist/adapters/types.js +2 -0
  41. package/dist/adapters/types.js.map +1 -0
  42. package/dist/adapters/whatsapp-adapter.d.ts +213 -0
  43. package/dist/adapters/whatsapp-adapter.d.ts.map +1 -0
  44. package/dist/adapters/whatsapp-adapter.js +1216 -0
  45. package/dist/adapters/whatsapp-adapter.js.map +1 -0
  46. package/dist/api/chat-binding-query.d.ts +36 -0
  47. package/dist/api/chat-binding-query.d.ts.map +1 -0
  48. package/dist/api/chat-binding-query.js +63 -0
  49. package/dist/api/chat-binding-query.js.map +1 -0
  50. package/dist/api/chat-session-resume.d.ts +12 -0
  51. package/dist/api/chat-session-resume.d.ts.map +1 -0
  52. package/dist/api/chat-session-resume.js +21 -0
  53. package/dist/api/chat-session-resume.js.map +1 -0
  54. package/dist/api/delegated-proxy-helper.d.ts +33 -0
  55. package/dist/api/delegated-proxy-helper.d.ts.map +1 -0
  56. package/dist/api/delegated-proxy-helper.js +54 -0
  57. package/dist/api/delegated-proxy-helper.js.map +1 -0
  58. package/dist/api/directory-picker.d.ts +38 -0
  59. package/dist/api/directory-picker.d.ts.map +1 -0
  60. package/dist/api/directory-picker.js +278 -0
  61. package/dist/api/directory-picker.js.map +1 -0
  62. package/dist/api/env-writer.d.ts +25 -0
  63. package/dist/api/env-writer.d.ts.map +1 -0
  64. package/dist/api/env-writer.js +421 -0
  65. package/dist/api/env-writer.js.map +1 -0
  66. package/dist/api/integration-route-gate.d.ts +60 -0
  67. package/dist/api/integration-route-gate.d.ts.map +1 -0
  68. package/dist/api/integration-route-gate.js +83 -0
  69. package/dist/api/integration-route-gate.js.map +1 -0
  70. package/dist/api/json-body.d.ts +29 -0
  71. package/dist/api/json-body.d.ts.map +1 -0
  72. package/dist/api/json-body.js +87 -0
  73. package/dist/api/json-body.js.map +1 -0
  74. package/dist/api/routes/activity-sources.d.ts +20 -0
  75. package/dist/api/routes/activity-sources.d.ts.map +1 -0
  76. package/dist/api/routes/activity-sources.js +18 -0
  77. package/dist/api/routes/activity-sources.js.map +1 -0
  78. package/dist/api/routes/agent.d.ts +4 -0
  79. package/dist/api/routes/agent.d.ts.map +1 -0
  80. package/dist/api/routes/agent.js +619 -0
  81. package/dist/api/routes/agent.js.map +1 -0
  82. package/dist/api/routes/apple-calendar.d.ts +31 -0
  83. package/dist/api/routes/apple-calendar.d.ts.map +1 -0
  84. package/dist/api/routes/apple-calendar.js +310 -0
  85. package/dist/api/routes/apple-calendar.js.map +1 -0
  86. package/dist/api/routes/attachments.d.ts +36 -0
  87. package/dist/api/routes/attachments.d.ts.map +1 -0
  88. package/dist/api/routes/attachments.js +305 -0
  89. package/dist/api/routes/attachments.js.map +1 -0
  90. package/dist/api/routes/backends.d.ts +4 -0
  91. package/dist/api/routes/backends.d.ts.map +1 -0
  92. package/dist/api/routes/backends.js +1132 -0
  93. package/dist/api/routes/backends.js.map +1 -0
  94. package/dist/api/routes/books.d.ts +63 -0
  95. package/dist/api/routes/books.d.ts.map +1 -0
  96. package/dist/api/routes/books.js +467 -0
  97. package/dist/api/routes/books.js.map +1 -0
  98. package/dist/api/routes/calendar.d.ts +36 -0
  99. package/dist/api/routes/calendar.d.ts.map +1 -0
  100. package/dist/api/routes/calendar.js +351 -0
  101. package/dist/api/routes/calendar.js.map +1 -0
  102. package/dist/api/routes/commands.d.ts +4 -0
  103. package/dist/api/routes/commands.d.ts.map +1 -0
  104. package/dist/api/routes/commands.js +251 -0
  105. package/dist/api/routes/commands.js.map +1 -0
  106. package/dist/api/routes/context.d.ts +57 -0
  107. package/dist/api/routes/context.d.ts.map +1 -0
  108. package/dist/api/routes/context.js +1765 -0
  109. package/dist/api/routes/context.js.map +1 -0
  110. package/dist/api/routes/dashboard.d.ts +29 -0
  111. package/dist/api/routes/dashboard.d.ts.map +1 -0
  112. package/dist/api/routes/dashboard.js +2062 -0
  113. package/dist/api/routes/dashboard.js.map +1 -0
  114. package/dist/api/routes/delegated-sync.d.ts +4 -0
  115. package/dist/api/routes/delegated-sync.d.ts.map +1 -0
  116. package/dist/api/routes/delegated-sync.js +192 -0
  117. package/dist/api/routes/delegated-sync.js.map +1 -0
  118. package/dist/api/routes/delegated.d.ts +42 -0
  119. package/dist/api/routes/delegated.d.ts.map +1 -0
  120. package/dist/api/routes/delegated.js +250 -0
  121. package/dist/api/routes/delegated.js.map +1 -0
  122. package/dist/api/routes/docs.d.ts +34 -0
  123. package/dist/api/routes/docs.d.ts.map +1 -0
  124. package/dist/api/routes/docs.js +580 -0
  125. package/dist/api/routes/docs.js.map +1 -0
  126. package/dist/api/routes/entities.d.ts +9 -0
  127. package/dist/api/routes/entities.d.ts.map +1 -0
  128. package/dist/api/routes/entities.js +176 -0
  129. package/dist/api/routes/entities.js.map +1 -0
  130. package/dist/api/routes/git-accounts.d.ts +23 -0
  131. package/dist/api/routes/git-accounts.d.ts.map +1 -0
  132. package/dist/api/routes/git-accounts.js +227 -0
  133. package/dist/api/routes/git-accounts.js.map +1 -0
  134. package/dist/api/routes/git-templates.d.ts +50 -0
  135. package/dist/api/routes/git-templates.d.ts.map +1 -0
  136. package/dist/api/routes/git-templates.js +276 -0
  137. package/dist/api/routes/git-templates.js.map +1 -0
  138. package/dist/api/routes/git.d.ts +34 -0
  139. package/dist/api/routes/git.d.ts.map +1 -0
  140. package/dist/api/routes/git.js +126 -0
  141. package/dist/api/routes/git.js.map +1 -0
  142. package/dist/api/routes/github.d.ts +34 -0
  143. package/dist/api/routes/github.d.ts.map +1 -0
  144. package/dist/api/routes/github.js +465 -0
  145. package/dist/api/routes/github.js.map +1 -0
  146. package/dist/api/routes/health.d.ts +4 -0
  147. package/dist/api/routes/health.d.ts.map +1 -0
  148. package/dist/api/routes/health.js +257 -0
  149. package/dist/api/routes/health.js.map +1 -0
  150. package/dist/api/routes/integrations-reconcile.d.ts +33 -0
  151. package/dist/api/routes/integrations-reconcile.d.ts.map +1 -0
  152. package/dist/api/routes/integrations-reconcile.js +463 -0
  153. package/dist/api/routes/integrations-reconcile.js.map +1 -0
  154. package/dist/api/routes/integrations.d.ts +19 -0
  155. package/dist/api/routes/integrations.d.ts.map +1 -0
  156. package/dist/api/routes/integrations.js +1384 -0
  157. package/dist/api/routes/integrations.js.map +1 -0
  158. package/dist/api/routes/knowledge.d.ts +4 -0
  159. package/dist/api/routes/knowledge.d.ts.map +1 -0
  160. package/dist/api/routes/knowledge.js +224 -0
  161. package/dist/api/routes/knowledge.js.map +1 -0
  162. package/dist/api/routes/mail.d.ts +39 -0
  163. package/dist/api/routes/mail.d.ts.map +1 -0
  164. package/dist/api/routes/mail.js +1406 -0
  165. package/dist/api/routes/mail.js.map +1 -0
  166. package/dist/api/routes/managed-tasks.d.ts +48 -0
  167. package/dist/api/routes/managed-tasks.d.ts.map +1 -0
  168. package/dist/api/routes/managed-tasks.js +844 -0
  169. package/dist/api/routes/managed-tasks.js.map +1 -0
  170. package/dist/api/routes/mcp.d.ts +50 -0
  171. package/dist/api/routes/mcp.d.ts.map +1 -0
  172. package/dist/api/routes/mcp.js +470 -0
  173. package/dist/api/routes/mcp.js.map +1 -0
  174. package/dist/api/routes/metrics.d.ts +13 -0
  175. package/dist/api/routes/metrics.d.ts.map +1 -0
  176. package/dist/api/routes/metrics.js +117 -0
  177. package/dist/api/routes/metrics.js.map +1 -0
  178. package/dist/api/routes/notion.d.ts +35 -0
  179. package/dist/api/routes/notion.d.ts.map +1 -0
  180. package/dist/api/routes/notion.js +442 -0
  181. package/dist/api/routes/notion.js.map +1 -0
  182. package/dist/api/routes/observations.d.ts +4 -0
  183. package/dist/api/routes/observations.d.ts.map +1 -0
  184. package/dist/api/routes/observations.js +177 -0
  185. package/dist/api/routes/observations.js.map +1 -0
  186. package/dist/api/routes/obsidian.d.ts +16 -0
  187. package/dist/api/routes/obsidian.d.ts.map +1 -0
  188. package/dist/api/routes/obsidian.js +321 -0
  189. package/dist/api/routes/obsidian.js.map +1 -0
  190. package/dist/api/routes/profile-questions.d.ts +17 -0
  191. package/dist/api/routes/profile-questions.d.ts.map +1 -0
  192. package/dist/api/routes/profile-questions.js +115 -0
  193. package/dist/api/routes/profile-questions.js.map +1 -0
  194. package/dist/api/routes/receipts.d.ts +4 -0
  195. package/dist/api/routes/receipts.d.ts.map +1 -0
  196. package/dist/api/routes/receipts.js +155 -0
  197. package/dist/api/routes/receipts.js.map +1 -0
  198. package/dist/api/routes/recurring-schedules.d.ts +4 -0
  199. package/dist/api/routes/recurring-schedules.d.ts.map +1 -0
  200. package/dist/api/routes/recurring-schedules.js +137 -0
  201. package/dist/api/routes/recurring-schedules.js.map +1 -0
  202. package/dist/api/routes/repositories.d.ts +40 -0
  203. package/dist/api/routes/repositories.d.ts.map +1 -0
  204. package/dist/api/routes/repositories.js +857 -0
  205. package/dist/api/routes/repositories.js.map +1 -0
  206. package/dist/api/routes/setup-migrate.d.ts +74 -0
  207. package/dist/api/routes/setup-migrate.d.ts.map +1 -0
  208. package/dist/api/routes/setup-migrate.js +944 -0
  209. package/dist/api/routes/setup-migrate.js.map +1 -0
  210. package/dist/api/routes/setup.d.ts +4 -0
  211. package/dist/api/routes/setup.d.ts.map +1 -0
  212. package/dist/api/routes/setup.js +443 -0
  213. package/dist/api/routes/setup.js.map +1 -0
  214. package/dist/api/routes/skill-curation.d.ts +5 -0
  215. package/dist/api/routes/skill-curation.d.ts.map +1 -0
  216. package/dist/api/routes/skill-curation.js +728 -0
  217. package/dist/api/routes/skill-curation.js.map +1 -0
  218. package/dist/api/routes/skills.d.ts +52 -0
  219. package/dist/api/routes/skills.d.ts.map +1 -0
  220. package/dist/api/routes/skills.js +429 -0
  221. package/dist/api/routes/skills.js.map +1 -0
  222. package/dist/api/routes/sot-bindings.d.ts +20 -0
  223. package/dist/api/routes/sot-bindings.d.ts.map +1 -0
  224. package/dist/api/routes/sot-bindings.js +163 -0
  225. package/dist/api/routes/sot-bindings.js.map +1 -0
  226. package/dist/api/routes/sse.d.ts +86 -0
  227. package/dist/api/routes/sse.d.ts.map +1 -0
  228. package/dist/api/routes/sse.js +378 -0
  229. package/dist/api/routes/sse.js.map +1 -0
  230. package/dist/api/routes/system.d.ts +4 -0
  231. package/dist/api/routes/system.d.ts.map +1 -0
  232. package/dist/api/routes/system.js +207 -0
  233. package/dist/api/routes/system.js.map +1 -0
  234. package/dist/api/routes/task-flows.d.ts +30 -0
  235. package/dist/api/routes/task-flows.d.ts.map +1 -0
  236. package/dist/api/routes/task-flows.js +155 -0
  237. package/dist/api/routes/task-flows.js.map +1 -0
  238. package/dist/api/routes/travel-bookings.d.ts +4 -0
  239. package/dist/api/routes/travel-bookings.d.ts.map +1 -0
  240. package/dist/api/routes/travel-bookings.js +142 -0
  241. package/dist/api/routes/travel-bookings.js.map +1 -0
  242. package/dist/api/routes/travel-time.d.ts +8 -0
  243. package/dist/api/routes/travel-time.d.ts.map +1 -0
  244. package/dist/api/routes/travel-time.js +87 -0
  245. package/dist/api/routes/travel-time.js.map +1 -0
  246. package/dist/api/routes/triggers.d.ts +4 -0
  247. package/dist/api/routes/triggers.d.ts.map +1 -0
  248. package/dist/api/routes/triggers.js +101 -0
  249. package/dist/api/routes/triggers.js.map +1 -0
  250. package/dist/api/routes/voice.d.ts +48 -0
  251. package/dist/api/routes/voice.d.ts.map +1 -0
  252. package/dist/api/routes/voice.js +232 -0
  253. package/dist/api/routes/voice.js.map +1 -0
  254. package/dist/api/server.d.ts +428 -0
  255. package/dist/api/server.d.ts.map +1 -0
  256. package/dist/api/server.js +558 -0
  257. package/dist/api/server.js.map +1 -0
  258. package/dist/config.d.ts +136 -0
  259. package/dist/config.d.ts.map +1 -0
  260. package/dist/config.js +699 -0
  261. package/dist/config.js.map +1 -0
  262. package/dist/core/agent-core.d.ts +517 -0
  263. package/dist/core/agent-core.d.ts.map +1 -0
  264. package/dist/core/agent-core.js +102 -0
  265. package/dist/core/agent-core.js.map +1 -0
  266. package/dist/core/alerts.d.ts +86 -0
  267. package/dist/core/alerts.d.ts.map +1 -0
  268. package/dist/core/alerts.js +304 -0
  269. package/dist/core/alerts.js.map +1 -0
  270. package/dist/core/atomic-write.d.ts +51 -0
  271. package/dist/core/atomic-write.d.ts.map +1 -0
  272. package/dist/core/atomic-write.js +135 -0
  273. package/dist/core/atomic-write.js.map +1 -0
  274. package/dist/core/backends/api-key-probe.d.ts +40 -0
  275. package/dist/core/backends/api-key-probe.d.ts.map +1 -0
  276. package/dist/core/backends/api-key-probe.js +116 -0
  277. package/dist/core/backends/api-key-probe.js.map +1 -0
  278. package/dist/core/backends/auth-health-monitor.d.ts +373 -0
  279. package/dist/core/backends/auth-health-monitor.d.ts.map +1 -0
  280. package/dist/core/backends/auth-health-monitor.js +950 -0
  281. package/dist/core/backends/auth-health-monitor.js.map +1 -0
  282. package/dist/core/backends/auth-recovery.d.ts +263 -0
  283. package/dist/core/backends/auth-recovery.d.ts.map +1 -0
  284. package/dist/core/backends/auth-recovery.js +1086 -0
  285. package/dist/core/backends/auth-recovery.js.map +1 -0
  286. package/dist/core/backends/auth-telemetry.d.ts +81 -0
  287. package/dist/core/backends/auth-telemetry.d.ts.map +1 -0
  288. package/dist/core/backends/auth-telemetry.js +108 -0
  289. package/dist/core/backends/auth-telemetry.js.map +1 -0
  290. package/dist/core/backends/backend-router.d.ts +272 -0
  291. package/dist/core/backends/backend-router.d.ts.map +1 -0
  292. package/dist/core/backends/backend-router.js +759 -0
  293. package/dist/core/backends/backend-router.js.map +1 -0
  294. package/dist/core/backends/claude-code-core.d.ts +299 -0
  295. package/dist/core/backends/claude-code-core.d.ts.map +1 -0
  296. package/dist/core/backends/claude-code-core.js +2541 -0
  297. package/dist/core/backends/claude-code-core.js.map +1 -0
  298. package/dist/core/backends/claude-credentials-store.d.ts +83 -0
  299. package/dist/core/backends/claude-credentials-store.d.ts.map +1 -0
  300. package/dist/core/backends/claude-credentials-store.js +243 -0
  301. package/dist/core/backends/claude-credentials-store.js.map +1 -0
  302. package/dist/core/backends/cli-utils.d.ts +95 -0
  303. package/dist/core/backends/cli-utils.d.ts.map +1 -0
  304. package/dist/core/backends/cli-utils.js +464 -0
  305. package/dist/core/backends/cli-utils.js.map +1 -0
  306. package/dist/core/backends/codex-core.d.ts +127 -0
  307. package/dist/core/backends/codex-core.d.ts.map +1 -0
  308. package/dist/core/backends/codex-core.js +1693 -0
  309. package/dist/core/backends/codex-core.js.map +1 -0
  310. package/dist/core/backends/gemini-cli-core.d.ts +367 -0
  311. package/dist/core/backends/gemini-cli-core.d.ts.map +1 -0
  312. package/dist/core/backends/gemini-cli-core.js +2331 -0
  313. package/dist/core/backends/gemini-cli-core.js.map +1 -0
  314. package/dist/core/backends/idle-watchdog.d.ts +77 -0
  315. package/dist/core/backends/idle-watchdog.d.ts.map +1 -0
  316. package/dist/core/backends/idle-watchdog.js +94 -0
  317. package/dist/core/backends/idle-watchdog.js.map +1 -0
  318. package/dist/core/backends/install-methods.d.ts +93 -0
  319. package/dist/core/backends/install-methods.d.ts.map +1 -0
  320. package/dist/core/backends/install-methods.js +267 -0
  321. package/dist/core/backends/install-methods.js.map +1 -0
  322. package/dist/core/backends/model-registry.d.ts +58 -0
  323. package/dist/core/backends/model-registry.d.ts.map +1 -0
  324. package/dist/core/backends/model-registry.js +539 -0
  325. package/dist/core/backends/model-registry.js.map +1 -0
  326. package/dist/core/backends/plan-presets.d.ts +123 -0
  327. package/dist/core/backends/plan-presets.d.ts.map +1 -0
  328. package/dist/core/backends/plan-presets.js +235 -0
  329. package/dist/core/backends/plan-presets.js.map +1 -0
  330. package/dist/core/backends/price-fetcher.d.ts +48 -0
  331. package/dist/core/backends/price-fetcher.d.ts.map +1 -0
  332. package/dist/core/backends/price-fetcher.js +248 -0
  333. package/dist/core/backends/price-fetcher.js.map +1 -0
  334. package/dist/core/backends/process-config-cascade.d.ts +68 -0
  335. package/dist/core/backends/process-config-cascade.d.ts.map +1 -0
  336. package/dist/core/backends/process-config-cascade.js +173 -0
  337. package/dist/core/backends/process-config-cascade.js.map +1 -0
  338. package/dist/core/backends/prompt-utils.d.ts +6 -0
  339. package/dist/core/backends/prompt-utils.d.ts.map +1 -0
  340. package/dist/core/backends/prompt-utils.js +80 -0
  341. package/dist/core/backends/prompt-utils.js.map +1 -0
  342. package/dist/core/backends/proxy-model-registry.d.ts +110 -0
  343. package/dist/core/backends/proxy-model-registry.d.ts.map +1 -0
  344. package/dist/core/backends/proxy-model-registry.js +195 -0
  345. package/dist/core/backends/proxy-model-registry.js.map +1 -0
  346. package/dist/core/backends/silent-api-error-detector.d.ts +31 -0
  347. package/dist/core/backends/silent-api-error-detector.d.ts.map +1 -0
  348. package/dist/core/backends/silent-api-error-detector.js +44 -0
  349. package/dist/core/backends/silent-api-error-detector.js.map +1 -0
  350. package/dist/core/bang-commands/commands-cost.d.ts +13 -0
  351. package/dist/core/bang-commands/commands-cost.d.ts.map +1 -0
  352. package/dist/core/bang-commands/commands-cost.js +91 -0
  353. package/dist/core/bang-commands/commands-cost.js.map +1 -0
  354. package/dist/core/bang-commands/commands-report.d.ts +18 -0
  355. package/dist/core/bang-commands/commands-report.d.ts.map +1 -0
  356. package/dist/core/bang-commands/commands-report.js +105 -0
  357. package/dist/core/bang-commands/commands-report.js.map +1 -0
  358. package/dist/core/bang-commands/commands-stop-start.d.ts +4 -0
  359. package/dist/core/bang-commands/commands-stop-start.d.ts.map +1 -0
  360. package/dist/core/bang-commands/commands-stop-start.js +88 -0
  361. package/dist/core/bang-commands/commands-stop-start.js.map +1 -0
  362. package/dist/core/bang-commands/format-utils.d.ts +34 -0
  363. package/dist/core/bang-commands/format-utils.d.ts.map +1 -0
  364. package/dist/core/bang-commands/format-utils.js +118 -0
  365. package/dist/core/bang-commands/format-utils.js.map +1 -0
  366. package/dist/core/bang-commands/index.d.ts +20 -0
  367. package/dist/core/bang-commands/index.d.ts.map +1 -0
  368. package/dist/core/bang-commands/index.js +31 -0
  369. package/dist/core/bang-commands/index.js.map +1 -0
  370. package/dist/core/bang-commands/registry.d.ts +72 -0
  371. package/dist/core/bang-commands/registry.d.ts.map +1 -0
  372. package/dist/core/bang-commands/registry.js +174 -0
  373. package/dist/core/bang-commands/registry.js.map +1 -0
  374. package/dist/core/bang-commands/user-commands.d.ts +86 -0
  375. package/dist/core/bang-commands/user-commands.d.ts.map +1 -0
  376. package/dist/core/bang-commands/user-commands.js +212 -0
  377. package/dist/core/bang-commands/user-commands.js.map +1 -0
  378. package/dist/core/channel-timeline.d.ts +28 -0
  379. package/dist/core/channel-timeline.d.ts.map +1 -0
  380. package/dist/core/channel-timeline.js +117 -0
  381. package/dist/core/channel-timeline.js.map +1 -0
  382. package/dist/core/character-block.d.ts +37 -0
  383. package/dist/core/character-block.d.ts.map +1 -0
  384. package/dist/core/character-block.js +162 -0
  385. package/dist/core/character-block.js.map +1 -0
  386. package/dist/core/context/activity-sources.d.ts +37 -0
  387. package/dist/core/context/activity-sources.d.ts.map +1 -0
  388. package/dist/core/context/activity-sources.js +69 -0
  389. package/dist/core/context/activity-sources.js.map +1 -0
  390. package/dist/core/context/activity-view-reconciler.d.ts +110 -0
  391. package/dist/core/context/activity-view-reconciler.d.ts.map +1 -0
  392. package/dist/core/context/activity-view-reconciler.js +252 -0
  393. package/dist/core/context/activity-view-reconciler.js.map +1 -0
  394. package/dist/core/context/activity-view-runner.d.ts +38 -0
  395. package/dist/core/context/activity-view-runner.d.ts.map +1 -0
  396. package/dist/core/context/activity-view-runner.js +402 -0
  397. package/dist/core/context/activity-view-runner.js.map +1 -0
  398. package/dist/core/context/default-schedules-reconciler.d.ts +85 -0
  399. package/dist/core/context/default-schedules-reconciler.d.ts.map +1 -0
  400. package/dist/core/context/default-schedules-reconciler.js +153 -0
  401. package/dist/core/context/default-schedules-reconciler.js.map +1 -0
  402. package/dist/core/context/default-schedules-runner.d.ts +40 -0
  403. package/dist/core/context/default-schedules-runner.d.ts.map +1 -0
  404. package/dist/core/context/default-schedules-runner.js +233 -0
  405. package/dist/core/context/default-schedules-runner.js.map +1 -0
  406. package/dist/core/context/domain-index-reconciler.d.ts +81 -0
  407. package/dist/core/context/domain-index-reconciler.d.ts.map +1 -0
  408. package/dist/core/context/domain-index-reconciler.js +199 -0
  409. package/dist/core/context/domain-index-reconciler.js.map +1 -0
  410. package/dist/core/context/domain-index-runner.d.ts +35 -0
  411. package/dist/core/context/domain-index-runner.d.ts.map +1 -0
  412. package/dist/core/context/domain-index-runner.js +223 -0
  413. package/dist/core/context/domain-index-runner.js.map +1 -0
  414. package/dist/core/context/entity-mirror.d.ts +227 -0
  415. package/dist/core/context/entity-mirror.d.ts.map +1 -0
  416. package/dist/core/context/entity-mirror.js +629 -0
  417. package/dist/core/context/entity-mirror.js.map +1 -0
  418. package/dist/core/context/entity-source-rename.d.ts +61 -0
  419. package/dist/core/context/entity-source-rename.d.ts.map +1 -0
  420. package/dist/core/context/entity-source-rename.js +237 -0
  421. package/dist/core/context/entity-source-rename.js.map +1 -0
  422. package/dist/core/context/index-reconciler.d.ts +61 -0
  423. package/dist/core/context/index-reconciler.d.ts.map +1 -0
  424. package/dist/core/context/index-reconciler.js +329 -0
  425. package/dist/core/context/index-reconciler.js.map +1 -0
  426. package/dist/core/context/policy-index-reconciler.d.ts +102 -0
  427. package/dist/core/context/policy-index-reconciler.d.ts.map +1 -0
  428. package/dist/core/context/policy-index-reconciler.js +202 -0
  429. package/dist/core/context/policy-index-reconciler.js.map +1 -0
  430. package/dist/core/context/policy-index-runner.d.ts +66 -0
  431. package/dist/core/context/policy-index-runner.d.ts.map +1 -0
  432. package/dist/core/context/policy-index-runner.js +406 -0
  433. package/dist/core/context/policy-index-runner.js.map +1 -0
  434. package/dist/core/context/reconciler-runner.d.ts +44 -0
  435. package/dist/core/context/reconciler-runner.d.ts.map +1 -0
  436. package/dist/core/context/reconciler-runner.js +273 -0
  437. package/dist/core/context/reconciler-runner.js.map +1 -0
  438. package/dist/core/context-builder.d.ts +115 -0
  439. package/dist/core/context-builder.d.ts.map +1 -0
  440. package/dist/core/context-builder.js +1148 -0
  441. package/dist/core/context-builder.js.map +1 -0
  442. package/dist/core/context-frontmatter-backfill.d.ts +33 -0
  443. package/dist/core/context-frontmatter-backfill.d.ts.map +1 -0
  444. package/dist/core/context-frontmatter-backfill.js +111 -0
  445. package/dist/core/context-frontmatter-backfill.js.map +1 -0
  446. package/dist/core/context-frontmatter.d.ts +13 -0
  447. package/dist/core/context-frontmatter.d.ts.map +1 -0
  448. package/dist/core/context-frontmatter.js +325 -0
  449. package/dist/core/context-frontmatter.js.map +1 -0
  450. package/dist/core/context-health.d.ts +51 -0
  451. package/dist/core/context-health.d.ts.map +1 -0
  452. package/dist/core/context-health.js +304 -0
  453. package/dist/core/context-health.js.map +1 -0
  454. package/dist/core/context-paths.d.ts +183 -0
  455. package/dist/core/context-paths.d.ts.map +1 -0
  456. package/dist/core/context-paths.js +241 -0
  457. package/dist/core/context-paths.js.map +1 -0
  458. package/dist/core/context-staleness.d.ts +45 -0
  459. package/dist/core/context-staleness.d.ts.map +1 -0
  460. package/dist/core/context-staleness.js +88 -0
  461. package/dist/core/context-staleness.js.map +1 -0
  462. package/dist/core/custom-routine-scheduler.d.ts +151 -0
  463. package/dist/core/custom-routine-scheduler.d.ts.map +1 -0
  464. package/dist/core/custom-routine-scheduler.js +335 -0
  465. package/dist/core/custom-routine-scheduler.js.map +1 -0
  466. package/dist/core/daemon-api-cli.d.ts +33 -0
  467. package/dist/core/daemon-api-cli.d.ts.map +1 -0
  468. package/dist/core/daemon-api-cli.js +614 -0
  469. package/dist/core/daemon-api-cli.js.map +1 -0
  470. package/dist/core/dashboard-session-cleanup.d.ts +39 -0
  471. package/dist/core/dashboard-session-cleanup.d.ts.map +1 -0
  472. package/dist/core/dashboard-session-cleanup.js +108 -0
  473. package/dist/core/dashboard-session-cleanup.js.map +1 -0
  474. package/dist/core/dashboard-session-controls.d.ts +41 -0
  475. package/dist/core/dashboard-session-controls.d.ts.map +1 -0
  476. package/dist/core/dashboard-session-controls.js +154 -0
  477. package/dist/core/dashboard-session-controls.js.map +1 -0
  478. package/dist/core/delegated-connector-health.d.ts +63 -0
  479. package/dist/core/delegated-connector-health.d.ts.map +1 -0
  480. package/dist/core/delegated-connector-health.js +157 -0
  481. package/dist/core/delegated-connector-health.js.map +1 -0
  482. package/dist/core/dispatcher.d.ts +999 -0
  483. package/dist/core/dispatcher.d.ts.map +1 -0
  484. package/dist/core/dispatcher.js +4378 -0
  485. package/dist/core/dispatcher.js.map +1 -0
  486. package/dist/core/dm-freshness-metrics.d.ts +73 -0
  487. package/dist/core/dm-freshness-metrics.d.ts.map +1 -0
  488. package/dist/core/dm-freshness-metrics.js +138 -0
  489. package/dist/core/dm-freshness-metrics.js.map +1 -0
  490. package/dist/core/docs/citation-validator.d.ts +73 -0
  491. package/dist/core/docs/citation-validator.d.ts.map +1 -0
  492. package/dist/core/docs/citation-validator.js +195 -0
  493. package/dist/core/docs/citation-validator.js.map +1 -0
  494. package/dist/core/docs/extract-terms.d.ts +78 -0
  495. package/dist/core/docs/extract-terms.d.ts.map +1 -0
  496. package/dist/core/docs/extract-terms.js +147 -0
  497. package/dist/core/docs/extract-terms.js.map +1 -0
  498. package/dist/core/docs/indexer.d.ts +104 -0
  499. package/dist/core/docs/indexer.d.ts.map +1 -0
  500. package/dist/core/docs/indexer.js +340 -0
  501. package/dist/core/docs/indexer.js.map +1 -0
  502. package/dist/core/drift-effects.d.ts +30 -0
  503. package/dist/core/drift-effects.d.ts.map +1 -0
  504. package/dist/core/drift-effects.js +384 -0
  505. package/dist/core/drift-effects.js.map +1 -0
  506. package/dist/core/event-bus.d.ts +56 -0
  507. package/dist/core/event-bus.d.ts.map +1 -0
  508. package/dist/core/event-bus.js +135 -0
  509. package/dist/core/event-bus.js.map +1 -0
  510. package/dist/core/git-project-docs.d.ts +77 -0
  511. package/dist/core/git-project-docs.d.ts.map +1 -0
  512. package/dist/core/git-project-docs.js +439 -0
  513. package/dist/core/git-project-docs.js.map +1 -0
  514. package/dist/core/health-monitor.d.ts +57 -0
  515. package/dist/core/health-monitor.d.ts.map +1 -0
  516. package/dist/core/health-monitor.js +137 -0
  517. package/dist/core/health-monitor.js.map +1 -0
  518. package/dist/core/heartbeat.d.ts +26 -0
  519. package/dist/core/heartbeat.d.ts.map +1 -0
  520. package/dist/core/heartbeat.js +48 -0
  521. package/dist/core/heartbeat.js.map +1 -0
  522. package/dist/core/integration-health.d.ts +49 -0
  523. package/dist/core/integration-health.d.ts.map +1 -0
  524. package/dist/core/integration-health.js +89 -0
  525. package/dist/core/integration-health.js.map +1 -0
  526. package/dist/core/integration-lifecycle.d.ts +79 -0
  527. package/dist/core/integration-lifecycle.d.ts.map +1 -0
  528. package/dist/core/integration-lifecycle.js +153 -0
  529. package/dist/core/integration-lifecycle.js.map +1 -0
  530. package/dist/core/integration-main-backend.d.ts +36 -0
  531. package/dist/core/integration-main-backend.d.ts.map +1 -0
  532. package/dist/core/integration-main-backend.js +59 -0
  533. package/dist/core/integration-main-backend.js.map +1 -0
  534. package/dist/core/integration-probe.d.ts +98 -0
  535. package/dist/core/integration-probe.d.ts.map +1 -0
  536. package/dist/core/integration-probe.js +152 -0
  537. package/dist/core/integration-probe.js.map +1 -0
  538. package/dist/core/management-md-write-lock.d.ts +68 -0
  539. package/dist/core/management-md-write-lock.d.ts.map +1 -0
  540. package/dist/core/management-md-write-lock.js +93 -0
  541. package/dist/core/management-md-write-lock.js.map +1 -0
  542. package/dist/core/management-md.d.ts +186 -0
  543. package/dist/core/management-md.d.ts.map +1 -0
  544. package/dist/core/management-md.js +652 -0
  545. package/dist/core/management-md.js.map +1 -0
  546. package/dist/core/management-registry.d.ts +245 -0
  547. package/dist/core/management-registry.d.ts.map +1 -0
  548. package/dist/core/management-registry.js +906 -0
  549. package/dist/core/management-registry.js.map +1 -0
  550. package/dist/core/management-telemetry.d.ts +100 -0
  551. package/dist/core/management-telemetry.d.ts.map +1 -0
  552. package/dist/core/management-telemetry.js +156 -0
  553. package/dist/core/management-telemetry.js.map +1 -0
  554. package/dist/core/message-recorder.d.ts +38 -0
  555. package/dist/core/message-recorder.d.ts.map +1 -0
  556. package/dist/core/message-recorder.js +88 -0
  557. package/dist/core/message-recorder.js.map +1 -0
  558. package/dist/core/metrics.d.ts +338 -0
  559. package/dist/core/metrics.d.ts.map +1 -0
  560. package/dist/core/metrics.js +747 -0
  561. package/dist/core/metrics.js.map +1 -0
  562. package/dist/core/migration-backup.d.ts +218 -0
  563. package/dist/core/migration-backup.d.ts.map +1 -0
  564. package/dist/core/migration-backup.js +934 -0
  565. package/dist/core/migration-backup.js.map +1 -0
  566. package/dist/core/overview-write-lock.d.ts +48 -0
  567. package/dist/core/overview-write-lock.d.ts.map +1 -0
  568. package/dist/core/overview-write-lock.js +56 -0
  569. package/dist/core/overview-write-lock.js.map +1 -0
  570. package/dist/core/path-compat.d.ts +22 -0
  571. package/dist/core/path-compat.d.ts.map +1 -0
  572. package/dist/core/path-compat.js +67 -0
  573. package/dist/core/path-compat.js.map +1 -0
  574. package/dist/core/path-rewrite.d.ts +58 -0
  575. package/dist/core/path-rewrite.d.ts.map +1 -0
  576. package/dist/core/path-rewrite.js +141 -0
  577. package/dist/core/path-rewrite.js.map +1 -0
  578. package/dist/core/policy-files.d.ts +108 -0
  579. package/dist/core/policy-files.d.ts.map +1 -0
  580. package/dist/core/policy-files.js +198 -0
  581. package/dist/core/policy-files.js.map +1 -0
  582. package/dist/core/profile-questions/seed.d.ts +44 -0
  583. package/dist/core/profile-questions/seed.d.ts.map +1 -0
  584. package/dist/core/profile-questions/seed.js +173 -0
  585. package/dist/core/profile-questions/seed.js.map +1 -0
  586. package/dist/core/profile-questions/slot-filled.d.ts +51 -0
  587. package/dist/core/profile-questions/slot-filled.d.ts.map +1 -0
  588. package/dist/core/profile-questions/slot-filled.js +118 -0
  589. package/dist/core/profile-questions/slot-filled.js.map +1 -0
  590. package/dist/core/prompts.d.ts +111 -0
  591. package/dist/core/prompts.d.ts.map +1 -0
  592. package/dist/core/prompts.js +267 -0
  593. package/dist/core/prompts.js.map +1 -0
  594. package/dist/core/quiet-hours-sync.d.ts +15 -0
  595. package/dist/core/quiet-hours-sync.d.ts.map +1 -0
  596. package/dist/core/quiet-hours-sync.js +51 -0
  597. package/dist/core/quiet-hours-sync.js.map +1 -0
  598. package/dist/core/read-sensitive-token-manager.d.ts +19 -0
  599. package/dist/core/read-sensitive-token-manager.d.ts.map +1 -0
  600. package/dist/core/read-sensitive-token-manager.js +29 -0
  601. package/dist/core/read-sensitive-token-manager.js.map +1 -0
  602. package/dist/core/recurrence.d.ts +24 -0
  603. package/dist/core/recurrence.d.ts.map +1 -0
  604. package/dist/core/recurrence.js +162 -0
  605. package/dist/core/recurrence.js.map +1 -0
  606. package/dist/core/reinstall.d.ts +107 -0
  607. package/dist/core/reinstall.d.ts.map +1 -0
  608. package/dist/core/reinstall.js +163 -0
  609. package/dist/core/reinstall.js.map +1 -0
  610. package/dist/core/release-assets.d.ts +106 -0
  611. package/dist/core/release-assets.d.ts.map +1 -0
  612. package/dist/core/release-assets.js +434 -0
  613. package/dist/core/release-assets.js.map +1 -0
  614. package/dist/core/repository-management-docs.d.ts +216 -0
  615. package/dist/core/repository-management-docs.d.ts.map +1 -0
  616. package/dist/core/repository-management-docs.js +855 -0
  617. package/dist/core/repository-management-docs.js.map +1 -0
  618. package/dist/core/retention.d.ts +164 -0
  619. package/dist/core/retention.d.ts.map +1 -0
  620. package/dist/core/retention.js +1008 -0
  621. package/dist/core/retention.js.map +1 -0
  622. package/dist/core/review-context.d.ts +48 -0
  623. package/dist/core/review-context.d.ts.map +1 -0
  624. package/dist/core/review-context.js +282 -0
  625. package/dist/core/review-context.js.map +1 -0
  626. package/dist/core/roadmap-horizon.d.ts +48 -0
  627. package/dist/core/roadmap-horizon.d.ts.map +1 -0
  628. package/dist/core/roadmap-horizon.js +213 -0
  629. package/dist/core/roadmap-horizon.js.map +1 -0
  630. package/dist/core/roadmap-ids.d.ts +57 -0
  631. package/dist/core/roadmap-ids.d.ts.map +1 -0
  632. package/dist/core/roadmap-ids.js +118 -0
  633. package/dist/core/roadmap-ids.js.map +1 -0
  634. package/dist/core/roadmap-merge.d.ts +7 -0
  635. package/dist/core/roadmap-merge.d.ts.map +1 -0
  636. package/dist/core/roadmap-merge.js +187 -0
  637. package/dist/core/roadmap-merge.js.map +1 -0
  638. package/dist/core/roadmap-refresh-triggers.d.ts +32 -0
  639. package/dist/core/roadmap-refresh-triggers.d.ts.map +1 -0
  640. package/dist/core/roadmap-refresh-triggers.js +51 -0
  641. package/dist/core/roadmap-refresh-triggers.js.map +1 -0
  642. package/dist/core/roadmap-truncate.d.ts +49 -0
  643. package/dist/core/roadmap-truncate.d.ts.map +1 -0
  644. package/dist/core/roadmap-truncate.js +152 -0
  645. package/dist/core/roadmap-truncate.js.map +1 -0
  646. package/dist/core/roadmap-validate.d.ts +31 -0
  647. package/dist/core/roadmap-validate.d.ts.map +1 -0
  648. package/dist/core/roadmap-validate.js +403 -0
  649. package/dist/core/roadmap-validate.js.map +1 -0
  650. package/dist/core/roadmap-write-lock.d.ts +53 -0
  651. package/dist/core/roadmap-write-lock.d.ts.map +1 -0
  652. package/dist/core/roadmap-write-lock.js +59 -0
  653. package/dist/core/roadmap-write-lock.js.map +1 -0
  654. package/dist/core/schedule-insert-helper.d.ts +46 -0
  655. package/dist/core/schedule-insert-helper.d.ts.map +1 -0
  656. package/dist/core/schedule-insert-helper.js +52 -0
  657. package/dist/core/schedule-insert-helper.js.map +1 -0
  658. package/dist/core/schedule-maintenance.d.ts +22 -0
  659. package/dist/core/schedule-maintenance.d.ts.map +1 -0
  660. package/dist/core/schedule-maintenance.js +57 -0
  661. package/dist/core/schedule-maintenance.js.map +1 -0
  662. package/dist/core/scheduler.d.ts +208 -0
  663. package/dist/core/scheduler.d.ts.map +1 -0
  664. package/dist/core/scheduler.js +896 -0
  665. package/dist/core/scheduler.js.map +1 -0
  666. package/dist/core/semaphore.d.ts +13 -0
  667. package/dist/core/semaphore.d.ts.map +1 -0
  668. package/dist/core/semaphore.js +31 -0
  669. package/dist/core/semaphore.js.map +1 -0
  670. package/dist/core/session-gate.d.ts +37 -0
  671. package/dist/core/session-gate.d.ts.map +1 -0
  672. package/dist/core/session-gate.js +69 -0
  673. package/dist/core/session-gate.js.map +1 -0
  674. package/dist/core/session-manager.d.ts +252 -0
  675. package/dist/core/session-manager.d.ts.map +1 -0
  676. package/dist/core/session-manager.js +716 -0
  677. package/dist/core/session-manager.js.map +1 -0
  678. package/dist/core/signal-detector.d.ts +97 -0
  679. package/dist/core/signal-detector.d.ts.map +1 -0
  680. package/dist/core/signal-detector.js +215 -0
  681. package/dist/core/signal-detector.js.map +1 -0
  682. package/dist/core/skeleton.d.ts +83 -0
  683. package/dist/core/skeleton.d.ts.map +1 -0
  684. package/dist/core/skeleton.js +255 -0
  685. package/dist/core/skeleton.js.map +1 -0
  686. package/dist/core/skill-curation/apply-proposal.d.ts +71 -0
  687. package/dist/core/skill-curation/apply-proposal.d.ts.map +1 -0
  688. package/dist/core/skill-curation/apply-proposal.js +175 -0
  689. package/dist/core/skill-curation/apply-proposal.js.map +1 -0
  690. package/dist/core/skill-curation/auto-revert.d.ts +43 -0
  691. package/dist/core/skill-curation/auto-revert.d.ts.map +1 -0
  692. package/dist/core/skill-curation/auto-revert.js +155 -0
  693. package/dist/core/skill-curation/auto-revert.js.map +1 -0
  694. package/dist/core/skill-curation/classify-diff.d.ts +27 -0
  695. package/dist/core/skill-curation/classify-diff.d.ts.map +1 -0
  696. package/dist/core/skill-curation/classify-diff.js +0 -0
  697. package/dist/core/skill-curation/classify-diff.js.map +1 -0
  698. package/dist/core/skill-curation/declarations.d.ts +32 -0
  699. package/dist/core/skill-curation/declarations.d.ts.map +1 -0
  700. package/dist/core/skill-curation/declarations.js +171 -0
  701. package/dist/core/skill-curation/declarations.js.map +1 -0
  702. package/dist/core/skill-curation/knowledge-map.d.ts +26 -0
  703. package/dist/core/skill-curation/knowledge-map.d.ts.map +1 -0
  704. package/dist/core/skill-curation/knowledge-map.js +154 -0
  705. package/dist/core/skill-curation/knowledge-map.js.map +1 -0
  706. package/dist/core/skill-curation/orphan-overlay.d.ts +35 -0
  707. package/dist/core/skill-curation/orphan-overlay.d.ts.map +1 -0
  708. package/dist/core/skill-curation/orphan-overlay.js +167 -0
  709. package/dist/core/skill-curation/orphan-overlay.js.map +1 -0
  710. package/dist/core/skill-curation/overlay-store.d.ts +41 -0
  711. package/dist/core/skill-curation/overlay-store.d.ts.map +1 -0
  712. package/dist/core/skill-curation/overlay-store.js +143 -0
  713. package/dist/core/skill-curation/overlay-store.js.map +1 -0
  714. package/dist/core/skill-curation/render/convention-notes.d.ts +4 -0
  715. package/dist/core/skill-curation/render/convention-notes.d.ts.map +1 -0
  716. package/dist/core/skill-curation/render/convention-notes.js +13 -0
  717. package/dist/core/skill-curation/render/convention-notes.js.map +1 -0
  718. package/dist/core/skill-curation/render/cross-references.d.ts +4 -0
  719. package/dist/core/skill-curation/render/cross-references.d.ts.map +1 -0
  720. package/dist/core/skill-curation/render/cross-references.js +10 -0
  721. package/dist/core/skill-curation/render/cross-references.js.map +1 -0
  722. package/dist/core/skill-curation/render/frontmatter-schema.d.ts +4 -0
  723. package/dist/core/skill-curation/render/frontmatter-schema.d.ts.map +1 -0
  724. package/dist/core/skill-curation/render/frontmatter-schema.js +25 -0
  725. package/dist/core/skill-curation/render/frontmatter-schema.js.map +1 -0
  726. package/dist/core/skill-curation/render/index.d.ts +5 -0
  727. package/dist/core/skill-curation/render/index.d.ts.map +1 -0
  728. package/dist/core/skill-curation/render/index.js +42 -0
  729. package/dist/core/skill-curation/render/index.js.map +1 -0
  730. package/dist/core/skill-curation/render/knowledge-layout.d.ts +4 -0
  731. package/dist/core/skill-curation/render/knowledge-layout.d.ts.map +1 -0
  732. package/dist/core/skill-curation/render/knowledge-layout.js +36 -0
  733. package/dist/core/skill-curation/render/knowledge-layout.js.map +1 -0
  734. package/dist/core/skill-curation/render/routing-table.d.ts +4 -0
  735. package/dist/core/skill-curation/render/routing-table.d.ts.map +1 -0
  736. package/dist/core/skill-curation/render/routing-table.js +37 -0
  737. package/dist/core/skill-curation/render/routing-table.js.map +1 -0
  738. package/dist/core/skill-curation/render/search-recipes.d.ts +4 -0
  739. package/dist/core/skill-curation/render/search-recipes.d.ts.map +1 -0
  740. package/dist/core/skill-curation/render/search-recipes.js +39 -0
  741. package/dist/core/skill-curation/render/search-recipes.js.map +1 -0
  742. package/dist/core/skill-curation/run-token.d.ts +27 -0
  743. package/dist/core/skill-curation/run-token.d.ts.map +1 -0
  744. package/dist/core/skill-curation/run-token.js +81 -0
  745. package/dist/core/skill-curation/run-token.js.map +1 -0
  746. package/dist/core/skill-curation/signals.d.ts +49 -0
  747. package/dist/core/skill-curation/signals.d.ts.map +1 -0
  748. package/dist/core/skill-curation/signals.js +149 -0
  749. package/dist/core/skill-curation/signals.js.map +1 -0
  750. package/dist/core/skill-curation/smoke-test.d.ts +39 -0
  751. package/dist/core/skill-curation/smoke-test.d.ts.map +1 -0
  752. package/dist/core/skill-curation/smoke-test.js +313 -0
  753. package/dist/core/skill-curation/smoke-test.js.map +1 -0
  754. package/dist/core/skill-curation/splicer.d.ts +16 -0
  755. package/dist/core/skill-curation/splicer.d.ts.map +1 -0
  756. package/dist/core/skill-curation/splicer.js +78 -0
  757. package/dist/core/skill-curation/splicer.js.map +1 -0
  758. package/dist/core/skill-curation/workdir.d.ts +40 -0
  759. package/dist/core/skill-curation/workdir.d.ts.map +1 -0
  760. package/dist/core/skill-curation/workdir.js +242 -0
  761. package/dist/core/skill-curation/workdir.js.map +1 -0
  762. package/dist/core/skills-compiler.d.ts +391 -0
  763. package/dist/core/skills-compiler.d.ts.map +1 -0
  764. package/dist/core/skills-compiler.js +1271 -0
  765. package/dist/core/skills-compiler.js.map +1 -0
  766. package/dist/core/skills-manifest.d.ts +8 -0
  767. package/dist/core/skills-manifest.d.ts.map +1 -0
  768. package/dist/core/skills-manifest.js +408 -0
  769. package/dist/core/skills-manifest.js.map +1 -0
  770. package/dist/core/system-reset.d.ts +268 -0
  771. package/dist/core/system-reset.d.ts.map +1 -0
  772. package/dist/core/system-reset.js +816 -0
  773. package/dist/core/system-reset.js.map +1 -0
  774. package/dist/core/template-store.d.ts +170 -0
  775. package/dist/core/template-store.d.ts.map +1 -0
  776. package/dist/core/template-store.js +388 -0
  777. package/dist/core/template-store.js.map +1 -0
  778. package/dist/core/template-versions.d.ts +95 -0
  779. package/dist/core/template-versions.d.ts.map +1 -0
  780. package/dist/core/template-versions.js +175 -0
  781. package/dist/core/template-versions.js.map +1 -0
  782. package/dist/core/today-agent-plan.d.ts +33 -0
  783. package/dist/core/today-agent-plan.d.ts.map +1 -0
  784. package/dist/core/today-agent-plan.js +120 -0
  785. package/dist/core/today-agent-plan.js.map +1 -0
  786. package/dist/core/today-direct-writer.d.ts +62 -0
  787. package/dist/core/today-direct-writer.d.ts.map +1 -0
  788. package/dist/core/today-direct-writer.js +132 -0
  789. package/dist/core/today-direct-writer.js.map +1 -0
  790. package/dist/core/today-write-lock.d.ts +89 -0
  791. package/dist/core/today-write-lock.d.ts.map +1 -0
  792. package/dist/core/today-write-lock.js +154 -0
  793. package/dist/core/today-write-lock.js.map +1 -0
  794. package/dist/core/trigger-dispatch.d.ts +31 -0
  795. package/dist/core/trigger-dispatch.d.ts.map +1 -0
  796. package/dist/core/trigger-dispatch.js +100 -0
  797. package/dist/core/trigger-dispatch.js.map +1 -0
  798. package/dist/core/trigger-evaluator.d.ts +59 -0
  799. package/dist/core/trigger-evaluator.d.ts.map +1 -0
  800. package/dist/core/trigger-evaluator.js +243 -0
  801. package/dist/core/trigger-evaluator.js.map +1 -0
  802. package/dist/core/workdir.d.ts +241 -0
  803. package/dist/core/workdir.d.ts.map +1 -0
  804. package/dist/core/workdir.js +565 -0
  805. package/dist/core/workdir.js.map +1 -0
  806. package/dist/db/automation-triggers.d.ts +90 -0
  807. package/dist/db/automation-triggers.d.ts.map +1 -0
  808. package/dist/db/automation-triggers.js +199 -0
  809. package/dist/db/automation-triggers.js.map +1 -0
  810. package/dist/db/client.d.ts +6 -0
  811. package/dist/db/client.d.ts.map +1 -0
  812. package/dist/db/client.js +47 -0
  813. package/dist/db/client.js.map +1 -0
  814. package/dist/db/entities-store.d.ts +92 -0
  815. package/dist/db/entities-store.d.ts.map +1 -0
  816. package/dist/db/entities-store.js +180 -0
  817. package/dist/db/entities-store.js.map +1 -0
  818. package/dist/db/hourly-check-signals.d.ts +78 -0
  819. package/dist/db/hourly-check-signals.d.ts.map +1 -0
  820. package/dist/db/hourly-check-signals.js +289 -0
  821. package/dist/db/hourly-check-signals.js.map +1 -0
  822. package/dist/db/integration-probe-store.d.ts +27 -0
  823. package/dist/db/integration-probe-store.d.ts.map +1 -0
  824. package/dist/db/integration-probe-store.js +75 -0
  825. package/dist/db/integration-probe-store.js.map +1 -0
  826. package/dist/db/integrations-store.d.ts +19 -0
  827. package/dist/db/integrations-store.d.ts.map +1 -0
  828. package/dist/db/integrations-store.js +85 -0
  829. package/dist/db/integrations-store.js.map +1 -0
  830. package/dist/db/managed-tasks-store.d.ts +130 -0
  831. package/dist/db/managed-tasks-store.d.ts.map +1 -0
  832. package/dist/db/managed-tasks-store.js +238 -0
  833. package/dist/db/managed-tasks-store.js.map +1 -0
  834. package/dist/db/management-parse-failures-store.d.ts +45 -0
  835. package/dist/db/management-parse-failures-store.d.ts.map +1 -0
  836. package/dist/db/management-parse-failures-store.js +36 -0
  837. package/dist/db/management-parse-failures-store.js.map +1 -0
  838. package/dist/db/observations.d.ts +145 -0
  839. package/dist/db/observations.d.ts.map +1 -0
  840. package/dist/db/observations.js +287 -0
  841. package/dist/db/observations.js.map +1 -0
  842. package/dist/db/recurring-schedules.d.ts +70 -0
  843. package/dist/db/recurring-schedules.d.ts.map +1 -0
  844. package/dist/db/recurring-schedules.js +213 -0
  845. package/dist/db/recurring-schedules.js.map +1 -0
  846. package/dist/db/repositories-store.d.ts +296 -0
  847. package/dist/db/repositories-store.d.ts.map +1 -0
  848. package/dist/db/repositories-store.js +754 -0
  849. package/dist/db/repositories-store.js.map +1 -0
  850. package/dist/db/runtime-state.d.ts +61 -0
  851. package/dist/db/runtime-state.d.ts.map +1 -0
  852. package/dist/db/runtime-state.js +104 -0
  853. package/dist/db/runtime-state.js.map +1 -0
  854. package/dist/db/schema.d.ts +4 -0
  855. package/dist/db/schema.d.ts.map +1 -0
  856. package/dist/db/schema.js +1338 -0
  857. package/dist/db/schema.js.map +1 -0
  858. package/dist/db/sot-bindings-store.d.ts +41 -0
  859. package/dist/db/sot-bindings-store.d.ts.map +1 -0
  860. package/dist/db/sot-bindings-store.js +64 -0
  861. package/dist/db/sot-bindings-store.js.map +1 -0
  862. package/dist/db/test-schemas.d.ts +23 -0
  863. package/dist/db/test-schemas.d.ts.map +1 -0
  864. package/dist/db/test-schemas.js +111 -0
  865. package/dist/db/test-schemas.js.map +1 -0
  866. package/dist/db/voice-transcripts-store.d.ts +28 -0
  867. package/dist/db/voice-transcripts-store.d.ts.map +1 -0
  868. package/dist/db/voice-transcripts-store.js +43 -0
  869. package/dist/db/voice-transcripts-store.js.map +1 -0
  870. package/dist/index.d.ts +2 -0
  871. package/dist/index.d.ts.map +1 -0
  872. package/dist/index.js +2913 -0
  873. package/dist/index.js.map +1 -0
  874. package/dist/init.d.ts +7 -0
  875. package/dist/init.d.ts.map +1 -0
  876. package/dist/init.js +32 -0
  877. package/dist/init.js.map +1 -0
  878. package/dist/log-buffer.d.ts +71 -0
  879. package/dist/log-buffer.d.ts.map +1 -0
  880. package/dist/log-buffer.js +201 -0
  881. package/dist/log-buffer.js.map +1 -0
  882. package/dist/logging.d.ts +5 -0
  883. package/dist/logging.d.ts.map +1 -0
  884. package/dist/logging.js +130 -0
  885. package/dist/logging.js.map +1 -0
  886. package/dist/management-rules.d.ts +2 -0
  887. package/dist/management-rules.d.ts.map +1 -0
  888. package/dist/management-rules.js +62 -0
  889. package/dist/management-rules.js.map +1 -0
  890. package/dist/messaging/constants.d.ts +33 -0
  891. package/dist/messaging/constants.d.ts.map +1 -0
  892. package/dist/messaging/constants.js +52 -0
  893. package/dist/messaging/constants.js.map +1 -0
  894. package/dist/messaging/magic-phrase.d.ts +16 -0
  895. package/dist/messaging/magic-phrase.d.ts.map +1 -0
  896. package/dist/messaging/magic-phrase.js +103 -0
  897. package/dist/messaging/magic-phrase.js.map +1 -0
  898. package/dist/messaging/owner-channels.d.ts +20 -0
  899. package/dist/messaging/owner-channels.d.ts.map +1 -0
  900. package/dist/messaging/owner-channels.js +41 -0
  901. package/dist/messaging/owner-channels.js.map +1 -0
  902. package/dist/observers/calendar-poller.d.ts +51 -0
  903. package/dist/observers/calendar-poller.d.ts.map +1 -0
  904. package/dist/observers/calendar-poller.js +128 -0
  905. package/dist/observers/calendar-poller.js.map +1 -0
  906. package/dist/observers/context-index-reconciler-observer.d.ts +72 -0
  907. package/dist/observers/context-index-reconciler-observer.d.ts.map +1 -0
  908. package/dist/observers/context-index-reconciler-observer.js +253 -0
  909. package/dist/observers/context-index-reconciler-observer.js.map +1 -0
  910. package/dist/observers/delegated-probe-observer.d.ts +83 -0
  911. package/dist/observers/delegated-probe-observer.d.ts.map +1 -0
  912. package/dist/observers/delegated-probe-observer.js +237 -0
  913. package/dist/observers/delegated-probe-observer.js.map +1 -0
  914. package/dist/observers/delegated-sync-worker.d.ts +375 -0
  915. package/dist/observers/delegated-sync-worker.d.ts.map +1 -0
  916. package/dist/observers/delegated-sync-worker.js +1087 -0
  917. package/dist/observers/delegated-sync-worker.js.map +1 -0
  918. package/dist/observers/entity-mirror-observer.d.ts +55 -0
  919. package/dist/observers/entity-mirror-observer.d.ts.map +1 -0
  920. package/dist/observers/entity-mirror-observer.js +73 -0
  921. package/dist/observers/entity-mirror-observer.js.map +1 -0
  922. package/dist/observers/git-delegated-cron.d.ts +41 -0
  923. package/dist/observers/git-delegated-cron.d.ts.map +1 -0
  924. package/dist/observers/git-delegated-cron.js +159 -0
  925. package/dist/observers/git-delegated-cron.js.map +1 -0
  926. package/dist/observers/git-event-classifier.d.ts +52 -0
  927. package/dist/observers/git-event-classifier.d.ts.map +1 -0
  928. package/dist/observers/git-event-classifier.js +70 -0
  929. package/dist/observers/git-event-classifier.js.map +1 -0
  930. package/dist/observers/git-watcher.d.ts +162 -0
  931. package/dist/observers/git-watcher.d.ts.map +1 -0
  932. package/dist/observers/git-watcher.js +768 -0
  933. package/dist/observers/git-watcher.js.map +1 -0
  934. package/dist/observers/github-poller-classifier.d.ts +101 -0
  935. package/dist/observers/github-poller-classifier.d.ts.map +1 -0
  936. package/dist/observers/github-poller-classifier.js +199 -0
  937. package/dist/observers/github-poller-classifier.js.map +1 -0
  938. package/dist/observers/github-poller.d.ts +291 -0
  939. package/dist/observers/github-poller.d.ts.map +1 -0
  940. package/dist/observers/github-poller.js +609 -0
  941. package/dist/observers/github-poller.js.map +1 -0
  942. package/dist/observers/imminent-event-scheduler.d.ts +34 -0
  943. package/dist/observers/imminent-event-scheduler.d.ts.map +1 -0
  944. package/dist/observers/imminent-event-scheduler.js +125 -0
  945. package/dist/observers/imminent-event-scheduler.js.map +1 -0
  946. package/dist/observers/mail-poller.d.ts +133 -0
  947. package/dist/observers/mail-poller.d.ts.map +1 -0
  948. package/dist/observers/mail-poller.js +563 -0
  949. package/dist/observers/mail-poller.js.map +1 -0
  950. package/dist/observers/mail-reconciliation.d.ts +87 -0
  951. package/dist/observers/mail-reconciliation.d.ts.map +1 -0
  952. package/dist/observers/mail-reconciliation.js +241 -0
  953. package/dist/observers/mail-reconciliation.js.map +1 -0
  954. package/dist/observers/manager.d.ts +67 -0
  955. package/dist/observers/manager.d.ts.map +1 -0
  956. package/dist/observers/manager.js +136 -0
  957. package/dist/observers/manager.js.map +1 -0
  958. package/dist/observers/notion-poller.d.ts +43 -0
  959. package/dist/observers/notion-poller.d.ts.map +1 -0
  960. package/dist/observers/notion-poller.js +184 -0
  961. package/dist/observers/notion-poller.js.map +1 -0
  962. package/dist/observers/observation-summarizer/index.d.ts +13 -0
  963. package/dist/observers/observation-summarizer/index.d.ts.map +1 -0
  964. package/dist/observers/observation-summarizer/index.js +13 -0
  965. package/dist/observers/observation-summarizer/index.js.map +1 -0
  966. package/dist/observers/observation-summarizer/pre-filter.d.ts +62 -0
  967. package/dist/observers/observation-summarizer/pre-filter.d.ts.map +1 -0
  968. package/dist/observers/observation-summarizer/pre-filter.js +189 -0
  969. package/dist/observers/observation-summarizer/pre-filter.js.map +1 -0
  970. package/dist/observers/observation-summarizer/response-parser.d.ts +30 -0
  971. package/dist/observers/observation-summarizer/response-parser.d.ts.map +1 -0
  972. package/dist/observers/observation-summarizer/response-parser.js +106 -0
  973. package/dist/observers/observation-summarizer/response-parser.js.map +1 -0
  974. package/dist/observers/observation-summarizer/summarizer-client.d.ts +83 -0
  975. package/dist/observers/observation-summarizer/summarizer-client.d.ts.map +1 -0
  976. package/dist/observers/observation-summarizer/summarizer-client.js +185 -0
  977. package/dist/observers/observation-summarizer/summarizer-client.js.map +1 -0
  978. package/dist/observers/observation-summarizer/summarizer-prompts.d.ts +51 -0
  979. package/dist/observers/observation-summarizer/summarizer-prompts.d.ts.map +1 -0
  980. package/dist/observers/observation-summarizer/summarizer-prompts.js +286 -0
  981. package/dist/observers/observation-summarizer/summarizer-prompts.js.map +1 -0
  982. package/dist/observers/observation-summarizer/worker.d.ts +106 -0
  983. package/dist/observers/observation-summarizer/worker.d.ts.map +1 -0
  984. package/dist/observers/observation-summarizer/worker.js +311 -0
  985. package/dist/observers/observation-summarizer/worker.js.map +1 -0
  986. package/dist/observers/obsidian-watcher.d.ts +90 -0
  987. package/dist/observers/obsidian-watcher.d.ts.map +1 -0
  988. package/dist/observers/obsidian-watcher.js +166 -0
  989. package/dist/observers/obsidian-watcher.js.map +1 -0
  990. package/dist/observers/primary-vault-watcher.d.ts +73 -0
  991. package/dist/observers/primary-vault-watcher.d.ts.map +1 -0
  992. package/dist/observers/primary-vault-watcher.js +115 -0
  993. package/dist/observers/primary-vault-watcher.js.map +1 -0
  994. package/dist/observers/repository-management-cron.d.ts +70 -0
  995. package/dist/observers/repository-management-cron.d.ts.map +1 -0
  996. package/dist/observers/repository-management-cron.js +166 -0
  997. package/dist/observers/repository-management-cron.js.map +1 -0
  998. package/dist/observers/skill-curation-walker.d.ts +33 -0
  999. package/dist/observers/skill-curation-walker.d.ts.map +1 -0
  1000. package/dist/observers/skill-curation-walker.js +216 -0
  1001. package/dist/observers/skill-curation-walker.js.map +1 -0
  1002. package/dist/safety/absolute-block-audit.d.ts +22 -0
  1003. package/dist/safety/absolute-block-audit.d.ts.map +1 -0
  1004. package/dist/safety/absolute-block-audit.js +32 -0
  1005. package/dist/safety/absolute-block-audit.js.map +1 -0
  1006. package/dist/safety/agent-write-tracker.d.ts +42 -0
  1007. package/dist/safety/agent-write-tracker.d.ts.map +1 -0
  1008. package/dist/safety/agent-write-tracker.js +82 -0
  1009. package/dist/safety/agent-write-tracker.js.map +1 -0
  1010. package/dist/safety/always-disallowed.d.ts +66 -0
  1011. package/dist/safety/always-disallowed.d.ts.map +1 -0
  1012. package/dist/safety/always-disallowed.js +347 -0
  1013. package/dist/safety/always-disallowed.js.map +1 -0
  1014. package/dist/safety/audit.d.ts +118 -0
  1015. package/dist/safety/audit.d.ts.map +1 -0
  1016. package/dist/safety/audit.js +324 -0
  1017. package/dist/safety/audit.js.map +1 -0
  1018. package/dist/safety/integration-write-tracker.d.ts +58 -0
  1019. package/dist/safety/integration-write-tracker.d.ts.map +1 -0
  1020. package/dist/safety/integration-write-tracker.js +41 -0
  1021. package/dist/safety/integration-write-tracker.js.map +1 -0
  1022. package/dist/safety/risk-classifier.d.ts +65 -0
  1023. package/dist/safety/risk-classifier.d.ts.map +1 -0
  1024. package/dist/safety/risk-classifier.js +763 -0
  1025. package/dist/safety/risk-classifier.js.map +1 -0
  1026. package/dist/scheduler/hourly-check-gate.d.ts +73 -0
  1027. package/dist/scheduler/hourly-check-gate.d.ts.map +1 -0
  1028. package/dist/scheduler/hourly-check-gate.js +128 -0
  1029. package/dist/scheduler/hourly-check-gate.js.map +1 -0
  1030. package/dist/secrets/backend-api-key-env.d.ts +104 -0
  1031. package/dist/secrets/backend-api-key-env.d.ts.map +1 -0
  1032. package/dist/secrets/backend-api-key-env.js +197 -0
  1033. package/dist/secrets/backend-api-key-env.js.map +1 -0
  1034. package/dist/secrets/codex-home-materializer.d.ts +35 -0
  1035. package/dist/secrets/codex-home-materializer.d.ts.map +1 -0
  1036. package/dist/secrets/codex-home-materializer.js +76 -0
  1037. package/dist/secrets/codex-home-materializer.js.map +1 -0
  1038. package/dist/secrets/encrypted-blob-store.d.ts +20 -0
  1039. package/dist/secrets/encrypted-blob-store.d.ts.map +1 -0
  1040. package/dist/secrets/encrypted-blob-store.js +80 -0
  1041. package/dist/secrets/encrypted-blob-store.js.map +1 -0
  1042. package/dist/secrets/platform-secret-store.d.ts +17 -0
  1043. package/dist/secrets/platform-secret-store.d.ts.map +1 -0
  1044. package/dist/secrets/platform-secret-store.js +37 -0
  1045. package/dist/secrets/platform-secret-store.js.map +1 -0
  1046. package/dist/secrets/redaction.d.ts +2 -0
  1047. package/dist/secrets/redaction.d.ts.map +1 -0
  1048. package/dist/secrets/redaction.js +2 -0
  1049. package/dist/secrets/redaction.js.map +1 -0
  1050. package/dist/secrets/secret-broker.d.ts +61 -0
  1051. package/dist/secrets/secret-broker.d.ts.map +1 -0
  1052. package/dist/secrets/secret-broker.js +160 -0
  1053. package/dist/secrets/secret-broker.js.map +1 -0
  1054. package/dist/secrets/secret-names.d.ts +34 -0
  1055. package/dist/secrets/secret-names.d.ts.map +1 -0
  1056. package/dist/secrets/secret-names.js +39 -0
  1057. package/dist/secrets/secret-names.js.map +1 -0
  1058. package/dist/secrets/secret-store.d.ts +8 -0
  1059. package/dist/secrets/secret-store.d.ts.map +1 -0
  1060. package/dist/secrets/secret-store.js +2 -0
  1061. package/dist/secrets/secret-store.js.map +1 -0
  1062. package/dist/secrets/types.d.ts +7 -0
  1063. package/dist/secrets/types.d.ts.map +1 -0
  1064. package/dist/secrets/types.js +2 -0
  1065. package/dist/secrets/types.js.map +1 -0
  1066. package/dist/services/apple-calendar/caldav-client.d.ts +48 -0
  1067. package/dist/services/apple-calendar/caldav-client.d.ts.map +1 -0
  1068. package/dist/services/apple-calendar/caldav-client.js +86 -0
  1069. package/dist/services/apple-calendar/caldav-client.js.map +1 -0
  1070. package/dist/services/apple-calendar/caldav-codec.d.ts +67 -0
  1071. package/dist/services/apple-calendar/caldav-codec.d.ts.map +1 -0
  1072. package/dist/services/apple-calendar/caldav-codec.js +341 -0
  1073. package/dist/services/apple-calendar/caldav-codec.js.map +1 -0
  1074. package/dist/services/apple-calendar/index.d.ts +3 -0
  1075. package/dist/services/apple-calendar/index.d.ts.map +1 -0
  1076. package/dist/services/apple-calendar/index.js +2 -0
  1077. package/dist/services/apple-calendar/index.js.map +1 -0
  1078. package/dist/services/apple-calendar/service.d.ts +75 -0
  1079. package/dist/services/apple-calendar/service.d.ts.map +1 -0
  1080. package/dist/services/apple-calendar/service.js +374 -0
  1081. package/dist/services/apple-calendar/service.js.map +1 -0
  1082. package/dist/services/apple-calendar/types.d.ts +78 -0
  1083. package/dist/services/apple-calendar/types.d.ts.map +1 -0
  1084. package/dist/services/apple-calendar/types.js +17 -0
  1085. package/dist/services/apple-calendar/types.js.map +1 -0
  1086. package/dist/services/attachments/hardlink.d.ts +11 -0
  1087. package/dist/services/attachments/hardlink.d.ts.map +1 -0
  1088. package/dist/services/attachments/hardlink.js +56 -0
  1089. package/dist/services/attachments/hardlink.js.map +1 -0
  1090. package/dist/services/attachments/sanitize.d.ts +21 -0
  1091. package/dist/services/attachments/sanitize.d.ts.map +1 -0
  1092. package/dist/services/attachments/sanitize.js +128 -0
  1093. package/dist/services/attachments/sanitize.js.map +1 -0
  1094. package/dist/services/attachments/store.d.ts +146 -0
  1095. package/dist/services/attachments/store.d.ts.map +1 -0
  1096. package/dist/services/attachments/store.js +477 -0
  1097. package/dist/services/attachments/store.js.map +1 -0
  1098. package/dist/services/calendar/outlook/graph-calendar-client.d.ts +114 -0
  1099. package/dist/services/calendar/outlook/graph-calendar-client.d.ts.map +1 -0
  1100. package/dist/services/calendar/outlook/graph-calendar-client.js +146 -0
  1101. package/dist/services/calendar/outlook/graph-calendar-client.js.map +1 -0
  1102. package/dist/services/calendar.d.ts +115 -0
  1103. package/dist/services/calendar.d.ts.map +1 -0
  1104. package/dist/services/calendar.js +281 -0
  1105. package/dist/services/calendar.js.map +1 -0
  1106. package/dist/services/delegated-backend-invoker.d.ts +414 -0
  1107. package/dist/services/delegated-backend-invoker.d.ts.map +1 -0
  1108. package/dist/services/delegated-backend-invoker.js +2372 -0
  1109. package/dist/services/delegated-backend-invoker.js.map +1 -0
  1110. package/dist/services/delegated-proxy-config.d.ts +93 -0
  1111. package/dist/services/delegated-proxy-config.d.ts.map +1 -0
  1112. package/dist/services/delegated-proxy-config.js +98 -0
  1113. package/dist/services/delegated-proxy-config.js.map +1 -0
  1114. package/dist/services/delegated-task-result-cache.d.ts +176 -0
  1115. package/dist/services/delegated-task-result-cache.d.ts.map +1 -0
  1116. package/dist/services/delegated-task-result-cache.js +0 -0
  1117. package/dist/services/delegated-task-result-cache.js.map +1 -0
  1118. package/dist/services/delegated-task-runtime.d.ts +346 -0
  1119. package/dist/services/delegated-task-runtime.d.ts.map +1 -0
  1120. package/dist/services/delegated-task-runtime.js +589 -0
  1121. package/dist/services/delegated-task-runtime.js.map +1 -0
  1122. package/dist/services/delegated-task-session-pool.d.ts +182 -0
  1123. package/dist/services/delegated-task-session-pool.d.ts.map +1 -0
  1124. package/dist/services/delegated-task-session-pool.js +292 -0
  1125. package/dist/services/delegated-task-session-pool.js.map +1 -0
  1126. package/dist/services/delegated-tool-runtime.d.ts +50 -0
  1127. package/dist/services/delegated-tool-runtime.d.ts.map +1 -0
  1128. package/dist/services/delegated-tool-runtime.js +120 -0
  1129. package/dist/services/delegated-tool-runtime.js.map +1 -0
  1130. package/dist/services/fts5.d.ts +40 -0
  1131. package/dist/services/fts5.d.ts.map +1 -0
  1132. package/dist/services/fts5.js +54 -0
  1133. package/dist/services/fts5.js.map +1 -0
  1134. package/dist/services/git-account-registry.d.ts +164 -0
  1135. package/dist/services/git-account-registry.d.ts.map +1 -0
  1136. package/dist/services/git-account-registry.js +297 -0
  1137. package/dist/services/git-account-registry.js.map +1 -0
  1138. package/dist/services/github.d.ts +49 -0
  1139. package/dist/services/github.d.ts.map +1 -0
  1140. package/dist/services/github.js +123 -0
  1141. package/dist/services/github.js.map +1 -0
  1142. package/dist/services/gmail-classifier.d.ts +62 -0
  1143. package/dist/services/gmail-classifier.d.ts.map +1 -0
  1144. package/dist/services/gmail-classifier.js +221 -0
  1145. package/dist/services/gmail-classifier.js.map +1 -0
  1146. package/dist/services/gmail.d.ts +192 -0
  1147. package/dist/services/gmail.d.ts.map +1 -0
  1148. package/dist/services/gmail.js +678 -0
  1149. package/dist/services/gmail.js.map +1 -0
  1150. package/dist/services/google-auth.d.ts +16 -0
  1151. package/dist/services/google-auth.d.ts.map +1 -0
  1152. package/dist/services/google-auth.js +37 -0
  1153. package/dist/services/google-auth.js.map +1 -0
  1154. package/dist/services/google-maps.d.ts +35 -0
  1155. package/dist/services/google-maps.d.ts.map +1 -0
  1156. package/dist/services/google-maps.js +82 -0
  1157. package/dist/services/google-maps.js.map +1 -0
  1158. package/dist/services/integrations/extract-write-item-id.d.ts +64 -0
  1159. package/dist/services/integrations/extract-write-item-id.d.ts.map +1 -0
  1160. package/dist/services/integrations/extract-write-item-id.js +188 -0
  1161. package/dist/services/integrations/extract-write-item-id.js.map +1 -0
  1162. package/dist/services/integrations/reconcile.d.ts +136 -0
  1163. package/dist/services/integrations/reconcile.d.ts.map +1 -0
  1164. package/dist/services/integrations/reconcile.js +218 -0
  1165. package/dist/services/integrations/reconcile.js.map +1 -0
  1166. package/dist/services/integrations/snapshot-partitions.d.ts +40 -0
  1167. package/dist/services/integrations/snapshot-partitions.d.ts.map +1 -0
  1168. package/dist/services/integrations/snapshot-partitions.js +113 -0
  1169. package/dist/services/integrations/snapshot-partitions.js.map +1 -0
  1170. package/dist/services/journal/render.d.ts +15 -0
  1171. package/dist/services/journal/render.d.ts.map +1 -0
  1172. package/dist/services/journal/render.js +17 -0
  1173. package/dist/services/journal/render.js.map +1 -0
  1174. package/dist/services/journal/writer.d.ts +26 -0
  1175. package/dist/services/journal/writer.d.ts.map +1 -0
  1176. package/dist/services/journal/writer.js +50 -0
  1177. package/dist/services/journal/writer.js.map +1 -0
  1178. package/dist/services/mail/account-registry.d.ts +208 -0
  1179. package/dist/services/mail/account-registry.d.ts.map +1 -0
  1180. package/dist/services/mail/account-registry.js +554 -0
  1181. package/dist/services/mail/account-registry.js.map +1 -0
  1182. package/dist/services/mail/gmail/auth-failure-classifier.d.ts +24 -0
  1183. package/dist/services/mail/gmail/auth-failure-classifier.d.ts.map +1 -0
  1184. package/dist/services/mail/gmail/auth-failure-classifier.js +67 -0
  1185. package/dist/services/mail/gmail/auth-failure-classifier.js.map +1 -0
  1186. package/dist/services/mail/gmail/gmail-provider.d.ts +58 -0
  1187. package/dist/services/mail/gmail/gmail-provider.d.ts.map +1 -0
  1188. package/dist/services/mail/gmail/gmail-provider.js +434 -0
  1189. package/dist/services/mail/gmail/gmail-provider.js.map +1 -0
  1190. package/dist/services/mail/gmail/legacy-row.d.ts +24 -0
  1191. package/dist/services/mail/gmail/legacy-row.d.ts.map +1 -0
  1192. package/dist/services/mail/gmail/legacy-row.js +71 -0
  1193. package/dist/services/mail/gmail/legacy-row.js.map +1 -0
  1194. package/dist/services/mail/gmail/poll-cursor.d.ts +12 -0
  1195. package/dist/services/mail/gmail/poll-cursor.d.ts.map +1 -0
  1196. package/dist/services/mail/gmail/poll-cursor.js +32 -0
  1197. package/dist/services/mail/gmail/poll-cursor.js.map +1 -0
  1198. package/dist/services/mail/html-to-plaintext.d.ts +27 -0
  1199. package/dist/services/mail/html-to-plaintext.d.ts.map +1 -0
  1200. package/dist/services/mail/html-to-plaintext.js +163 -0
  1201. package/dist/services/mail/html-to-plaintext.js.map +1 -0
  1202. package/dist/services/mail/imap/app-password.d.ts +27 -0
  1203. package/dist/services/mail/imap/app-password.d.ts.map +1 -0
  1204. package/dist/services/mail/imap/app-password.js +86 -0
  1205. package/dist/services/mail/imap/app-password.js.map +1 -0
  1206. package/dist/services/mail/imap/auth-failure-classifier.d.ts +21 -0
  1207. package/dist/services/mail/imap/auth-failure-classifier.d.ts.map +1 -0
  1208. package/dist/services/mail/imap/auth-failure-classifier.js +54 -0
  1209. package/dist/services/mail/imap/auth-failure-classifier.js.map +1 -0
  1210. package/dist/services/mail/imap/capabilities.d.ts +30 -0
  1211. package/dist/services/mail/imap/capabilities.d.ts.map +1 -0
  1212. package/dist/services/mail/imap/capabilities.js +70 -0
  1213. package/dist/services/mail/imap/capabilities.js.map +1 -0
  1214. package/dist/services/mail/imap/client.d.ts +15 -0
  1215. package/dist/services/mail/imap/client.d.ts.map +1 -0
  1216. package/dist/services/mail/imap/client.js +60 -0
  1217. package/dist/services/mail/imap/client.js.map +1 -0
  1218. package/dist/services/mail/imap/cursor.d.ts +19 -0
  1219. package/dist/services/mail/imap/cursor.d.ts.map +1 -0
  1220. package/dist/services/mail/imap/cursor.js +47 -0
  1221. package/dist/services/mail/imap/cursor.js.map +1 -0
  1222. package/dist/services/mail/imap/folder-resolver.d.ts +24 -0
  1223. package/dist/services/mail/imap/folder-resolver.d.ts.map +1 -0
  1224. package/dist/services/mail/imap/folder-resolver.js +58 -0
  1225. package/dist/services/mail/imap/folder-resolver.js.map +1 -0
  1226. package/dist/services/mail/imap/icloud-provider.d.ts +5 -0
  1227. package/dist/services/mail/imap/icloud-provider.d.ts.map +1 -0
  1228. package/dist/services/mail/imap/icloud-provider.js +5 -0
  1229. package/dist/services/mail/imap/icloud-provider.js.map +1 -0
  1230. package/dist/services/mail/imap/imap-provider-base.d.ts +173 -0
  1231. package/dist/services/mail/imap/imap-provider-base.d.ts.map +1 -0
  1232. package/dist/services/mail/imap/imap-provider-base.js +1004 -0
  1233. package/dist/services/mail/imap/imap-provider-base.js.map +1 -0
  1234. package/dist/services/mail/imap/query-translator.d.ts +13 -0
  1235. package/dist/services/mail/imap/query-translator.d.ts.map +1 -0
  1236. package/dist/services/mail/imap/query-translator.js +114 -0
  1237. package/dist/services/mail/imap/query-translator.js.map +1 -0
  1238. package/dist/services/mail/imap/reconcile-planner.d.ts +56 -0
  1239. package/dist/services/mail/imap/reconcile-planner.d.ts.map +1 -0
  1240. package/dist/services/mail/imap/reconcile-planner.js +52 -0
  1241. package/dist/services/mail/imap/reconcile-planner.js.map +1 -0
  1242. package/dist/services/mail/imap/reply-mime.d.ts +24 -0
  1243. package/dist/services/mail/imap/reply-mime.d.ts.map +1 -0
  1244. package/dist/services/mail/imap/reply-mime.js +77 -0
  1245. package/dist/services/mail/imap/reply-mime.js.map +1 -0
  1246. package/dist/services/mail/imap/yahoo-provider.d.ts +5 -0
  1247. package/dist/services/mail/imap/yahoo-provider.d.ts.map +1 -0
  1248. package/dist/services/mail/imap/yahoo-provider.js +5 -0
  1249. package/dist/services/mail/imap/yahoo-provider.js.map +1 -0
  1250. package/dist/services/mail/mail-search.d.ts +35 -0
  1251. package/dist/services/mail/mail-search.d.ts.map +1 -0
  1252. package/dist/services/mail/mail-search.js +59 -0
  1253. package/dist/services/mail/mail-search.js.map +1 -0
  1254. package/dist/services/mail/outlook/auth-failure-classifier.d.ts +38 -0
  1255. package/dist/services/mail/outlook/auth-failure-classifier.d.ts.map +1 -0
  1256. package/dist/services/mail/outlook/auth-failure-classifier.js +91 -0
  1257. package/dist/services/mail/outlook/auth-failure-classifier.js.map +1 -0
  1258. package/dist/services/mail/outlook/client-config.d.ts +34 -0
  1259. package/dist/services/mail/outlook/client-config.d.ts.map +1 -0
  1260. package/dist/services/mail/outlook/client-config.js +58 -0
  1261. package/dist/services/mail/outlook/client-config.js.map +1 -0
  1262. package/dist/services/mail/outlook/delta-cursor.d.ts +66 -0
  1263. package/dist/services/mail/outlook/delta-cursor.d.ts.map +1 -0
  1264. package/dist/services/mail/outlook/delta-cursor.js +85 -0
  1265. package/dist/services/mail/outlook/delta-cursor.js.map +1 -0
  1266. package/dist/services/mail/outlook/graph-client.d.ts +98 -0
  1267. package/dist/services/mail/outlook/graph-client.d.ts.map +1 -0
  1268. package/dist/services/mail/outlook/graph-client.js +198 -0
  1269. package/dist/services/mail/outlook/graph-client.js.map +1 -0
  1270. package/dist/services/mail/outlook/msal-app-factory.d.ts +20 -0
  1271. package/dist/services/mail/outlook/msal-app-factory.d.ts.map +1 -0
  1272. package/dist/services/mail/outlook/msal-app-factory.js +62 -0
  1273. package/dist/services/mail/outlook/msal-app-factory.js.map +1 -0
  1274. package/dist/services/mail/outlook/msal-cache-plugin.d.ts +19 -0
  1275. package/dist/services/mail/outlook/msal-cache-plugin.d.ts.map +1 -0
  1276. package/dist/services/mail/outlook/msal-cache-plugin.js +30 -0
  1277. package/dist/services/mail/outlook/msal-cache-plugin.js.map +1 -0
  1278. package/dist/services/mail/outlook/oauth-device-code.d.ts +26 -0
  1279. package/dist/services/mail/outlook/oauth-device-code.d.ts.map +1 -0
  1280. package/dist/services/mail/outlook/oauth-device-code.js +32 -0
  1281. package/dist/services/mail/outlook/oauth-device-code.js.map +1 -0
  1282. package/dist/services/mail/outlook/oauth-loopback.d.ts +41 -0
  1283. package/dist/services/mail/outlook/oauth-loopback.d.ts.map +1 -0
  1284. package/dist/services/mail/outlook/oauth-loopback.js +223 -0
  1285. package/dist/services/mail/outlook/oauth-loopback.js.map +1 -0
  1286. package/dist/services/mail/outlook/outlook-provider.d.ts +100 -0
  1287. package/dist/services/mail/outlook/outlook-provider.d.ts.map +1 -0
  1288. package/dist/services/mail/outlook/outlook-provider.js +619 -0
  1289. package/dist/services/mail/outlook/outlook-provider.js.map +1 -0
  1290. package/dist/services/mail/outlook/query-translator.d.ts +10 -0
  1291. package/dist/services/mail/outlook/query-translator.d.ts.map +1 -0
  1292. package/dist/services/mail/outlook/query-translator.js +103 -0
  1293. package/dist/services/mail/outlook/query-translator.js.map +1 -0
  1294. package/dist/services/mail/provider.d.ts +267 -0
  1295. package/dist/services/mail/provider.d.ts.map +1 -0
  1296. package/dist/services/mail/provider.js +34 -0
  1297. package/dist/services/mail/provider.js.map +1 -0
  1298. package/dist/services/mail/query-utils.d.ts +13 -0
  1299. package/dist/services/mail/query-utils.d.ts.map +1 -0
  1300. package/dist/services/mail/query-utils.js +18 -0
  1301. package/dist/services/mail/query-utils.js.map +1 -0
  1302. package/dist/services/mail-classifier.d.ts +25 -0
  1303. package/dist/services/mail-classifier.d.ts.map +1 -0
  1304. package/dist/services/mail-classifier.js +52 -0
  1305. package/dist/services/mail-classifier.js.map +1 -0
  1306. package/dist/services/mail-ingestion.d.ts +139 -0
  1307. package/dist/services/mail-ingestion.d.ts.map +1 -0
  1308. package/dist/services/mail-ingestion.js +223 -0
  1309. package/dist/services/mail-ingestion.js.map +1 -0
  1310. package/dist/services/mcp/auto-probe.d.ts +76 -0
  1311. package/dist/services/mcp/auto-probe.d.ts.map +1 -0
  1312. package/dist/services/mcp/auto-probe.js +147 -0
  1313. package/dist/services/mcp/auto-probe.js.map +1 -0
  1314. package/dist/services/mcp/generators/claude.d.ts +18 -0
  1315. package/dist/services/mcp/generators/claude.d.ts.map +1 -0
  1316. package/dist/services/mcp/generators/claude.js +90 -0
  1317. package/dist/services/mcp/generators/claude.js.map +1 -0
  1318. package/dist/services/mcp/generators/codex.d.ts +22 -0
  1319. package/dist/services/mcp/generators/codex.d.ts.map +1 -0
  1320. package/dist/services/mcp/generators/codex.js +102 -0
  1321. package/dist/services/mcp/generators/codex.js.map +1 -0
  1322. package/dist/services/mcp/generators/gemini.d.ts +20 -0
  1323. package/dist/services/mcp/generators/gemini.d.ts.map +1 -0
  1324. package/dist/services/mcp/generators/gemini.js +97 -0
  1325. package/dist/services/mcp/generators/gemini.js.map +1 -0
  1326. package/dist/services/mcp/generators/index.d.ts +20 -0
  1327. package/dist/services/mcp/generators/index.d.ts.map +1 -0
  1328. package/dist/services/mcp/generators/index.js +29 -0
  1329. package/dist/services/mcp/generators/index.js.map +1 -0
  1330. package/dist/services/mcp/generators/types.d.ts +47 -0
  1331. package/dist/services/mcp/generators/types.d.ts.map +1 -0
  1332. package/dist/services/mcp/generators/types.js +40 -0
  1333. package/dist/services/mcp/generators/types.js.map +1 -0
  1334. package/dist/services/mcp/probe.d.ts +31 -0
  1335. package/dist/services/mcp/probe.d.ts.map +1 -0
  1336. package/dist/services/mcp/probe.js +437 -0
  1337. package/dist/services/mcp/probe.js.map +1 -0
  1338. package/dist/services/mcp/registry.d.ts +84 -0
  1339. package/dist/services/mcp/registry.d.ts.map +1 -0
  1340. package/dist/services/mcp/registry.js +387 -0
  1341. package/dist/services/mcp/registry.js.map +1 -0
  1342. package/dist/services/mcp/risk.d.ts +82 -0
  1343. package/dist/services/mcp/risk.d.ts.map +1 -0
  1344. package/dist/services/mcp/risk.js +126 -0
  1345. package/dist/services/mcp/risk.js.map +1 -0
  1346. package/dist/services/mcp/session-materializer.d.ts +123 -0
  1347. package/dist/services/mcp/session-materializer.d.ts.map +1 -0
  1348. package/dist/services/mcp/session-materializer.js +361 -0
  1349. package/dist/services/mcp/session-materializer.js.map +1 -0
  1350. package/dist/services/mcp/tool-audit.d.ts +53 -0
  1351. package/dist/services/mcp/tool-audit.d.ts.map +1 -0
  1352. package/dist/services/mcp/tool-audit.js +74 -0
  1353. package/dist/services/mcp/tool-audit.js.map +1 -0
  1354. package/dist/services/mcp/types.d.ts +88 -0
  1355. package/dist/services/mcp/types.d.ts.map +1 -0
  1356. package/dist/services/mcp/types.js +94 -0
  1357. package/dist/services/mcp/types.js.map +1 -0
  1358. package/dist/services/notion.d.ts +134 -0
  1359. package/dist/services/notion.d.ts.map +1 -0
  1360. package/dist/services/notion.js +350 -0
  1361. package/dist/services/notion.js.map +1 -0
  1362. package/dist/services/obsidian.d.ts +116 -0
  1363. package/dist/services/obsidian.d.ts.map +1 -0
  1364. package/dist/services/obsidian.js +305 -0
  1365. package/dist/services/obsidian.js.map +1 -0
  1366. package/dist/services/service-registry.d.ts +31 -0
  1367. package/dist/services/service-registry.d.ts.map +1 -0
  1368. package/dist/services/service-registry.js +15 -0
  1369. package/dist/services/service-registry.js.map +1 -0
  1370. package/dist/services/voice/transcriber-impl.d.ts +15 -0
  1371. package/dist/services/voice/transcriber-impl.d.ts.map +1 -0
  1372. package/dist/services/voice/transcriber-impl.js +129 -0
  1373. package/dist/services/voice/transcriber-impl.js.map +1 -0
  1374. package/dist/services/voice/transcriber.d.ts +117 -0
  1375. package/dist/services/voice/transcriber.d.ts.map +1 -0
  1376. package/dist/services/voice/transcriber.js +201 -0
  1377. package/dist/services/voice/transcriber.js.map +1 -0
  1378. package/dist/settings/runtime-settings.d.ts +232 -0
  1379. package/dist/settings/runtime-settings.d.ts.map +1 -0
  1380. package/dist/settings/runtime-settings.js +769 -0
  1381. package/dist/settings/runtime-settings.js.map +1 -0
  1382. package/dist/settings/settings-store.d.ts +13 -0
  1383. package/dist/settings/settings-store.d.ts.map +1 -0
  1384. package/dist/settings/settings-store.js +87 -0
  1385. package/dist/settings/settings-store.js.map +1 -0
  1386. package/package.json +85 -0
@@ -0,0 +1,2331 @@
1
+ import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join, resolve as resolvePath } from "node:path";
4
+ import { APP_NAME, collectSessionDeniedTools, getAgentDayDateStr, INTEGRATION_DESCRIPTORS, INTEGRATION_KEYS, isAutonomousProcessKey, isPlausibleGeminiApiKey, matchRunAllowedToolPattern, } from "@aitne/shared";
5
+ import { readIntegrations } from "../../db/integrations-store.js";
6
+ import { getContextDir } from "../../config.js";
7
+ import { cleanupSessionWorkdir, createSessionWorkdir } from "../workdir.js";
8
+ import { BackendDecisiveFailure, BackendQuotaError, DelegatedProxyTimeoutError, classifyAbortReason, } from "../agent-core.js";
9
+ import { IdleWatchdog } from "./idle-watchdog.js";
10
+ import { buildDelegatedToolPrompt, emptyCost, tryParseToolResult, withDurationMs, } from "../../services/delegated-tool-runtime.js";
11
+ import { DELEGATED_PROXY_DEFAULTS } from "../../services/delegated-proxy-config.js";
12
+ import { materializeMcpForSession } from "../../services/mcp/session-materializer.js";
13
+ import { parseMcpToolName } from "../../services/mcp/risk.js";
14
+ import { logMcpToolCall } from "../../services/mcp/tool-audit.js";
15
+ import { buildDaemonApiCliEnv } from "../daemon-api-cli.js";
16
+ import { ALWAYS_DISALLOWED_TOOLS } from "../../safety/always-disallowed.js";
17
+ import { CliPathCache, parseJsonLine, runLineCommand, } from "./cli-utils.js";
18
+ import { isPathInsideOrEqual, jsonStringPathForms, shellPathForms, } from "../path-compat.js";
19
+ import { probeApiKeyServerSide } from "./api-key-probe.js";
20
+ import { extractSilentApiErrors, logSilentApiErrors, } from "./silent-api-error-detector.js";
21
+ import { estimateTextInputTokens, findRegisteredModel, getModelsForBackend, latestLiteFor, } from "./model-registry.js";
22
+ import { PriceFetcher } from "./price-fetcher.js";
23
+ import { buildExecutionPrompt, buildSummaryPrompt } from "./prompt-utils.js";
24
+ import { createLogger } from "../../logging.js";
25
+ import { readRuntimeState, writeRuntimeState } from "../../db/runtime-state.js";
26
+ const logger = createLogger("gemini-cli-core");
27
+ /**
28
+ * runtime_state key for the Gemini per-agent-day request counter.
29
+ * Gemini meters per-day model requests, and `maxTurns` alone cannot
30
+ * bound daily consumption — so this counter applies a conservative
31
+ * fixed ceiling that matches the free Gemini API tier (500 requests/
32
+ * day × 0.9 = 450 requests/day). Operators on higher-quota Gemini
33
+ * accounts can widen via the dashboard config.
34
+ */
35
+ const GEMINI_REQUESTS_STATE_KEY = "gemini_requests_today";
36
+ /**
37
+ * Conservative default. Replaces the legacy plan-driven ceilings — the
38
+ * daemon does not ask the operator which Gemini account tier they
39
+ * hold (Aitne is intended to run on `GEMINI_API_KEY` / `GOOGLE_API_KEY`,
40
+ * with the CLI's local auth as a fallback), so we cannot infer a
41
+ * tier-specific quota and assume the free-tier published cap. When an
42
+ * API key is configured, the upstream Google quota is the real bound
43
+ * and this counter just stops the daemon from blowing past 450/day in
44
+ * the worst case.
45
+ */
46
+ const GEMINI_DAILY_REQUEST_CEILING = 450;
47
+ /** Policy file name written into each session workdir. */
48
+ const ADMIN_POLICY_FILENAME = ".pa-admin-policy.toml";
49
+ const EMPTY_USAGE = {
50
+ inputTokens: 0,
51
+ outputTokens: 0,
52
+ cacheCreationInputTokens: 0,
53
+ cacheReadInputTokens: 0,
54
+ };
55
+ export class GeminiCliCore {
56
+ config;
57
+ writeTracker;
58
+ priceFetcher;
59
+ db;
60
+ backendId = "gemini";
61
+ // Lazily re-resolved with a 60 s TTL — see ClaudeCodeCore for rationale (§9.4).
62
+ cliPathCache;
63
+ /** Legacy shared read token injected into the Gemini subprocess env. */
64
+ readToken;
65
+ /** Scoped token manager preferred over the legacy shared read token. */
66
+ readTokenManager;
67
+ get cliPath() {
68
+ return this.cliPathCache.get();
69
+ }
70
+ constructor(config,
71
+ /**
72
+ * Shared AgentWriteTracker. When present, vault-scoped writes detected in
73
+ * Gemini's tool_use stream are pre-marked so the ObsidianWatcher attributes
74
+ * the chokidar event to `actor='agent'` instead of `'user'`.
75
+ */
76
+ writeTracker, priceFetcher = new PriceFetcher(config.dataDir),
77
+ /**
78
+ * DB handle for the per-agent-day Gemini request counter. Optional so
79
+ * unit tests that construct the core without a database get
80
+ * graceful degradation: no quota enforcement and no counter writes.
81
+ * Production always supplies this.
82
+ */
83
+ db = null) {
84
+ this.config = config;
85
+ this.writeTracker = writeTracker;
86
+ this.priceFetcher = priceFetcher;
87
+ this.db = db;
88
+ this.cliPathCache = new CliPathCache("gemini");
89
+ }
90
+ /** Set the per-daemon-boot read token for subprocess-local daemon API auth. */
91
+ setReadToken(token) {
92
+ this.readToken = token;
93
+ }
94
+ setReadTokenManager(manager) {
95
+ this.readTokenManager = manager;
96
+ }
97
+ mcpContext;
98
+ setMcpContext(context) {
99
+ this.mcpContext = context;
100
+ }
101
+ async materializeMcp(sessionDir, processKey) {
102
+ if (!this.mcpContext) {
103
+ return {
104
+ servers: [],
105
+ env: {},
106
+ configPath: null,
107
+ claudeMcpServers: null,
108
+ disallowedTools: [],
109
+ };
110
+ }
111
+ // Allow mode bypasses the approve-tier MCP strip (see claude-code-core
112
+ // for the rationale — "strong permission mode" enables every MCP tool,
113
+ // autonomous routines included).
114
+ const allowMode = this.config.geminiExecutionPermissionMode === "allow";
115
+ const autonomous = !allowMode && (processKey ? isAutonomousProcessKey(processKey) : false);
116
+ return materializeMcpForSession({
117
+ db: this.mcpContext.db,
118
+ blobStore: this.mcpContext.blobStore,
119
+ sessionDir,
120
+ backendId: this.backendId,
121
+ autonomous,
122
+ contextDir: getContextDir(this.config),
123
+ });
124
+ }
125
+ async execute(params, streamCallbacks) {
126
+ return await this.runTurn({
127
+ prompt: appendGeminiAttachmentTokens(buildExecutionPrompt(params.prompt, params.context, params.event, params.conversationHistory), params.stagedAttachments),
128
+ modelId: params.modelId,
129
+ eventType: params.event.type,
130
+ processKey: params.processKey,
131
+ sessionDir: params.sessionDir,
132
+ maxBudgetUsd: params.maxBudgetUsd,
133
+ webSearchEnabled: params.webSearchEnabled,
134
+ turnToken: params.turnToken,
135
+ sessionDbId: params.sessionDbId,
136
+ eventCorrelationId: params.event.correlationId,
137
+ }, streamCallbacks);
138
+ }
139
+ async executeResume(params, streamCallbacks) {
140
+ return await this.runTurn({
141
+ prompt: appendGeminiAttachmentTokens(params.message, params.stagedAttachments),
142
+ modelId: params.modelId,
143
+ eventType: "message.received",
144
+ sessionDir: params.sessionDir,
145
+ resumeSessionId: params.sessionId,
146
+ maxBudgetUsd: params.maxBudgetUsd,
147
+ webSearchEnabled: params.webSearchEnabled,
148
+ turnToken: params.turnToken,
149
+ sessionDbId: params.sessionDbId,
150
+ eventCorrelationId: params.eventCorrelationId,
151
+ }, streamCallbacks);
152
+ }
153
+ async summarize(conversationText) {
154
+ const result = await this.runTurn({
155
+ prompt: buildSummaryPrompt(conversationText),
156
+ modelId: this.pickSummaryModel(),
157
+ eventType: "message.received",
158
+ });
159
+ return result.output;
160
+ }
161
+ async checkAuth() {
162
+ if (!this.cliPath) {
163
+ return { ok: false, reason: "Gemini CLI is not installed or not on PATH." };
164
+ }
165
+ const rawApiKey = process.env.GEMINI_API_KEY?.trim() || process.env.GOOGLE_API_KEY?.trim();
166
+ if (rawApiKey) {
167
+ if (!isPlausibleGeminiApiKey(rawApiKey)) {
168
+ return {
169
+ ok: false,
170
+ reason: "GEMINI_API_KEY / GOOGLE_API_KEY is set but does not look like a Google API key (expected `AIza…`, 39 chars).",
171
+ };
172
+ }
173
+ return { ok: true, method: "api_key" };
174
+ }
175
+ if (process.env.GOOGLE_APPLICATION_CREDENTIALS?.trim()
176
+ && process.env.GOOGLE_CLOUD_PROJECT?.trim()) {
177
+ return { ok: true, method: "vertex" };
178
+ }
179
+ if (existsSync(join(homedir(), ".gemini", "oauth_creds.json"))
180
+ || existsSync(join(homedir(), ".gemini", "google_accounts.json"))) {
181
+ return { ok: true, method: "oauth" };
182
+ }
183
+ return {
184
+ ok: false,
185
+ reason: "Gemini is not authenticated. Configure OAuth, Vertex, or GEMINI_API_KEY.",
186
+ };
187
+ }
188
+ /**
189
+ * Detailed auth probe. Three modes:
190
+ * - **API key** (`GEMINI_API_KEY` / `GOOGLE_API_KEY`): format check +
191
+ * server-side probe via `probeApiKeyServerSide("google", ...)`
192
+ * (roadmap §9.1). Throws on network/timeout.
193
+ * - **Vertex** (`GOOGLE_APPLICATION_CREDENTIALS` + `GOOGLE_CLOUD_PROJECT`):
194
+ * env-var presence check only.
195
+ * - **OAuth** (`~/.gemini/oauth_creds.json`): presence check on
196
+ * `refresh_token` field + grace window. Does NOT validate the
197
+ * refresh_token server-side; real failures surface via the reactive
198
+ * path during `execute()`.
199
+ */
200
+ async checkAuthDetailed() {
201
+ if (!this.cliPath) {
202
+ return {
203
+ ok: false,
204
+ status: "missing",
205
+ method: "cli_login",
206
+ detail: "Gemini CLI not found on PATH",
207
+ recoveryCommand: "npm install -g @google/gemini-cli",
208
+ };
209
+ }
210
+ const rawApiKey = process.env.GEMINI_API_KEY?.trim() || process.env.GOOGLE_API_KEY?.trim();
211
+ if (rawApiKey) {
212
+ if (!isPlausibleGeminiApiKey(rawApiKey)) {
213
+ return {
214
+ ok: false,
215
+ status: "expired",
216
+ method: "api_key",
217
+ detail: "GEMINI_API_KEY / GOOGLE_API_KEY does not match Google API key format (`AIza…`, 39 chars).",
218
+ recoveryCommand: "Unset the env var or replace it with a valid Google API key",
219
+ };
220
+ }
221
+ // Format is plausible — attempt a server-side probe to detect
222
+ // revoked keys within 1 hourly cycle (roadmap §9.1).
223
+ const probe = await probeApiKeyServerSide("google", rawApiKey);
224
+ return {
225
+ ok: probe.ok,
226
+ status: probe.ok ? "ok" : "expired",
227
+ method: "api_key",
228
+ detail: probe.detail,
229
+ ...(!probe.ok && {
230
+ recoveryCommand: "Unset the env var or replace it with a valid Google API key",
231
+ }),
232
+ };
233
+ }
234
+ if (process.env.GOOGLE_APPLICATION_CREDENTIALS?.trim()
235
+ && process.env.GOOGLE_CLOUD_PROJECT?.trim()) {
236
+ return { ok: true, status: "ok", method: "vertex" };
237
+ }
238
+ const oauthPath = join(homedir(), ".gemini", "oauth_creds.json");
239
+ if (existsSync(oauthPath)) {
240
+ try {
241
+ const raw = readFileSync(oauthPath, "utf-8");
242
+ const creds = JSON.parse(raw);
243
+ if (typeof creds.refresh_token === "string" && creds.refresh_token.length > 0) {
244
+ return { ok: true, status: "ok", method: "oauth" };
245
+ }
246
+ // refresh_token missing — treat recently-modified files as ok
247
+ // because the Gemini CLI has a known upstream bug where the field
248
+ // drops out mid-session (observed in 0.x CLI versions). Without
249
+ // this grace, every Gemini user would false-trip to "expired"
250
+ // until they re-authenticated. The grace window is tunable via
251
+ // `PA_GEMINI_OAUTH_GRACE_HOURS`; set to 0 to disable the grace
252
+ // entirely once the upstream bug is fixed.
253
+ const graceHours = parseGraceHours(process.env.PA_GEMINI_OAUTH_GRACE_HOURS, 24);
254
+ const hoursSinceModified = (Date.now() - statSync(oauthPath).mtimeMs) / 3_600_000;
255
+ if (graceHours > 0 && hoursSinceModified < graceHours) {
256
+ logger.warn({ graceHours, hoursSinceModified }, "Gemini oauth_creds.json missing refresh_token — applying grace window");
257
+ return {
258
+ ok: true,
259
+ status: "ok",
260
+ method: "oauth",
261
+ detail: `refresh_token missing but file was updated ${hoursSinceModified.toFixed(1)}h ago (< ${graceHours}h grace)`,
262
+ };
263
+ }
264
+ return {
265
+ ok: false,
266
+ status: "expired",
267
+ method: "oauth",
268
+ detail: "refresh_token missing from oauth_creds.json",
269
+ recoveryCommand: "gemini → Sign in with Google",
270
+ };
271
+ }
272
+ catch (err) {
273
+ logger.warn({ err }, "Failed to read Gemini oauth_creds.json");
274
+ return {
275
+ ok: false,
276
+ status: "expired",
277
+ method: "oauth",
278
+ detail: err instanceof Error ? err.message : "Failed to parse oauth_creds.json",
279
+ recoveryCommand: "gemini → Sign in with Google",
280
+ };
281
+ }
282
+ }
283
+ if (existsSync(join(homedir(), ".gemini", "gemini-credentials.json"))) {
284
+ return {
285
+ ok: true,
286
+ status: "ok",
287
+ method: "oauth",
288
+ detail: "Encrypted storage detected — CLI handles validation",
289
+ };
290
+ }
291
+ if (existsSync(join(homedir(), ".gemini", "google_accounts.json"))) {
292
+ return { ok: true, status: "ok", method: "oauth" };
293
+ }
294
+ return {
295
+ ok: false,
296
+ status: "expired",
297
+ method: "oauth",
298
+ detail: "No Gemini OAuth credentials found",
299
+ recoveryCommand: "gemini → Sign in with Google",
300
+ };
301
+ }
302
+ listModels() {
303
+ return getModelsForBackend(this.backendId);
304
+ }
305
+ /**
306
+ * Phase 5 §4.11 live probe for Gemini. Gemini CLI exposes no first-party
307
+ * tool-enumeration API and its MCP namespace (`mcp_<server>_<tool>`,
308
+ * single-underscore — confirmed via stream-event probe 2026-04-26)
309
+ * differs from Claude / Codex (`mcp__<server>__<tool>`).
310
+ *
311
+ * Strategy: scan the host for registered MCP servers (the
312
+ * `gemini-extension.json` `mcpServers` block under each subdir of
313
+ * `~/.gemini/extensions/` plus the `~/.gemini/settings.json`
314
+ * `mcpServers` block), then for every registry-declared Gemini
315
+ * connector whose namespace points at a detected server, synthesize
316
+ * the expected fully-qualified tool names from `capabilityTools`. The
317
+ * synthetic list is what `evaluateProbe` matches against the
318
+ * descriptor.
319
+ *
320
+ * Trade-off: this is a "presence-only" probe — it verifies the server
321
+ * is registered with Gemini, not that the agent's OAuth / tool-call
322
+ * actually works. Connector auth failures surface when the agent first
323
+ * invokes the tool. Codex / Claude run live `tool_search` queries
324
+ * because their MCP catalog is queryable from the SDK; Gemini does not
325
+ * expose that surface, and asking the model to enumerate via prompt
326
+ * proved unreliable (whitespace-only responses, see chat history).
327
+ *
328
+ * Two distinct outcomes:
329
+ * - Server NOT detected → returns `[]`. `evaluateProbe` matches
330
+ * against the connector's expected tools, finds none, reports all
331
+ * required capabilities missing — dashboard correctly shows
332
+ * "Gemini's <X> connector is not installed."
333
+ * - Server detected → returns the registry's claimed tool list for
334
+ * that server. `evaluateProbe` matches every entry exactly (since
335
+ * the list IS the registry's expectation), so all caps mark
336
+ * present. The dashboard shows "all features available." This is
337
+ * accurate for `google-workspace` (whose tool names were verified
338
+ * from `~/.gemini/extensions/google-workspace/dist/index.js` —
339
+ * `registerTool("gmail.*", ...)` etc. — at registry-write time)
340
+ * and is a guess for `notion` (registry assumes `notion-search`,
341
+ * `notion-fetch`, etc.; actual hosted-MCP names may diverge —
342
+ * surfaced via the install card's namespace caveat). Runtime
343
+ * `wrong_tool` errors are the failure mode for the latter.
344
+ */
345
+ async probeTools() {
346
+ const detectedServers = new Set();
347
+ // Extension-installed MCP servers (e.g. google-workspace ships
348
+ // gmail.* and calendar.* via this path).
349
+ const extDir = join(homedir(), ".gemini", "extensions");
350
+ if (existsSync(extDir)) {
351
+ try {
352
+ const subdirs = readdirSync(extDir, { withFileTypes: true });
353
+ for (const ent of subdirs) {
354
+ if (!ent.isDirectory())
355
+ continue;
356
+ const manifestPath = join(extDir, ent.name, "gemini-extension.json");
357
+ if (!existsSync(manifestPath))
358
+ continue;
359
+ collectMcpServerNames(manifestPath, detectedServers);
360
+ }
361
+ }
362
+ catch (err) {
363
+ logger.warn({ err, extDir }, "failed to scan Gemini extensions");
364
+ }
365
+ }
366
+ // User-added MCP servers (`gemini mcp add <name> ...`). Notion's
367
+ // hosted MCP server is typically registered here under the literal
368
+ // name `notion` — that's the assumption the registry's Notion
369
+ // descriptor encodes.
370
+ const settingsPath = join(homedir(), ".gemini", "settings.json");
371
+ if (existsSync(settingsPath)) {
372
+ collectMcpServerNames(settingsPath, detectedServers);
373
+ }
374
+ const tools = [];
375
+ for (const integrationKey of INTEGRATION_KEYS) {
376
+ const connector = INTEGRATION_DESCRIPTORS[integrationKey].backendConnectors.gemini;
377
+ if (!connector)
378
+ continue;
379
+ const serverName = extractGeminiServerName(connector.toolNamespace);
380
+ if (!serverName || !detectedServers.has(serverName))
381
+ continue;
382
+ for (const toolList of Object.values(connector.capabilityTools)) {
383
+ for (const t of toolList) {
384
+ tools.push(connector.toolNamespace + t);
385
+ }
386
+ }
387
+ }
388
+ const deduped = Array.from(new Set(tools));
389
+ logger.info({
390
+ detectedServers: [...detectedServers],
391
+ toolCount: deduped.length,
392
+ }, "Gemini probe collected tool manifest via host MCP scan");
393
+ return deduped;
394
+ }
395
+ async runTurn(params, streamCallbacks) {
396
+ // Pre-flight auth gate — intentionally absent in ClaudeCodeCore.
397
+ // Same reasoning as Codex: spawning the Gemini CLI subprocess has
398
+ // non-trivial TTFB, so reading `oauth_creds.json` (or the API key
399
+ // format) once here is cheaper than discovering the failure after
400
+ // the subprocess has already booted and begun streaming. Claude
401
+ // leans on the Agent SDK's own 401 instead, which is why it has
402
+ // no equivalent pre-flight. See the class-level comment on
403
+ // `ClaudeCodeCore` for the full rationale.
404
+ const auth = await this.checkAuth();
405
+ if (!auth.ok) {
406
+ logger.warn({ reason: auth.reason }, "Gemini auth check failed");
407
+ throw new BackendDecisiveFailure(this.backendId, "auth", new Error(auth.reason));
408
+ }
409
+ // Daily-request quota gate. Reads `backend_global_defaults.gemini_plan`
410
+ // → `PlanPreset.dailyRequestCeiling` and compares against the per-agent-day
411
+ // counter in runtime_state. Pre-flight refusal so we don't waste a CLI
412
+ // subprocess on a request we know is over quota. See
413
+ // `docs/design/09-safety-cost.md` §9.4.8 for the full contract.
414
+ const today = getAgentDayDateStr(this.config.timezone, this.config.dayBoundaryHour);
415
+ const ceiling = this.resolveDailyRequestCeiling();
416
+ if (ceiling !== null) {
417
+ const currentCount = this.readRequestsCount(today);
418
+ if (currentCount >= ceiling) {
419
+ logger.warn({ currentCount, ceiling, date: today }, "Gemini daily-request ceiling hit — refusing execution");
420
+ throw new BackendQuotaError(this.backendId, "daily_ceiling", null, `Gemini daily-request ceiling reached (${currentCount}/${ceiling}) — resets at the next agent-day boundary.`);
421
+ }
422
+ }
423
+ this.assertPromptWithinMaxBudget(params.prompt, params.maxBudgetUsd, params.modelId);
424
+ const startMs = Date.now();
425
+ const sessionDir = params.sessionDir ?? createSessionWorkdir(this.config.workspaceDir, params.eventType, `${this.config.dataDir}/skills`, {
426
+ backendId: this.backendId,
427
+ processKey: params.processKey,
428
+ character: this.config.character,
429
+ });
430
+ const ownsSessionDir = !params.sessionDir;
431
+ const daemonReadToken = this.readTokenManager?.issue(sessionDir) ?? this.readToken;
432
+ // Write admin policy to session workdir. The admin tier overrides the
433
+ // --approval-mode yolo grants, so this policy is the ONLY mechanism on
434
+ // Gemini for preserving non-negotiable invariants — chiefly that writes
435
+ // to the context directory must go through the daemon API.
436
+ //
437
+ // Strict mode: full whitelist policy (catch-all deny + explicit allows).
438
+ // Allow mode: minimal policy with NO catch-all — only denies context-dir
439
+ // writes and sensitive-path reads; everything else falls through to yolo.
440
+ const allowMode = this.config.geminiExecutionPermissionMode === "allow";
441
+ const policyPath = join(sessionDir, ADMIN_POLICY_FILENAME);
442
+ writeFileSync(policyPath, allowMode
443
+ ? this.generateAllowModeMinimalPolicy()
444
+ : this.generateAdminPolicy({ webSearchEnabled: params.webSearchEnabled }), "utf-8");
445
+ const mcp = await this.materializeMcp(sessionDir, params.processKey);
446
+ logger.info({ eventType: params.eventType, model: params.modelId, promptLen: params.prompt.length, mcpServers: mcp.servers.map((s) => s.id) }, "Gemini execute started");
447
+ let assistantDelta = "";
448
+ let finalAssistantMessage = "";
449
+ let sessionId = params.resumeSessionId ?? null;
450
+ let lastError = null;
451
+ let resultStatus = "error";
452
+ let stats = null;
453
+ let streamed = false;
454
+ const deferStreamingUntilBudgetCheck = params.maxBudgetUsd !== undefined;
455
+ // Accumulate raw subprocess text across the run so we can scan once for
456
+ // `PA_API_ERROR` markers the pa-api / curl wrappers emit on HTTP errors.
457
+ // Gemini's stream schema doesn't expose a dedicated tool-output field, so
458
+ // we fall back to the raw stdout/stderr lines (which include both the
459
+ // JSONL itself and any uncaptured subprocess stderr).
460
+ const apiOutputBuffer = [];
461
+ try {
462
+ const runResult = await runLineCommand({
463
+ command: "gemini",
464
+ args: this.buildArgs(params, policyPath),
465
+ cwd: sessionDir,
466
+ env: {
467
+ ...buildDaemonApiCliEnv(sessionDir, this.config.apiPort, {
468
+ readToken: daemonReadToken,
469
+ sessionBackend: "gemini",
470
+ sessionId: params.sessionDbId,
471
+ eventCorrelationId: params.eventCorrelationId,
472
+ }),
473
+ ...mcp.env,
474
+ ...(params.turnToken ? { PA_TURN_TOKEN: params.turnToken } : {}),
475
+ },
476
+ timeoutMs: this.config.executeTimeoutMinutes * 60 * 1000,
477
+ onStdoutLine: (line) => {
478
+ apiOutputBuffer.push(line);
479
+ const event = parseJsonLine(line);
480
+ if (!event?.type) {
481
+ if (isLikelyGeminiFailure(line)) {
482
+ lastError = line.trim();
483
+ }
484
+ return;
485
+ }
486
+ if (event.type === "init" && typeof event.session_id === "string") {
487
+ sessionId = event.session_id;
488
+ return;
489
+ }
490
+ // Pre-mark vault writes for observer attribution (same as Claude Code hook).
491
+ if (this.writeTracker && event.type === "tool_use") {
492
+ this.trackVaultWrite(event);
493
+ }
494
+ // B-003 Phase 4.4 — persist MCP tool call to `mcp_tool_calls`.
495
+ // Gemini emits `mcp_<server>_<tool>` (single underscore — see
496
+ // parseMcpToolName); host-installed Gemini MCPs (like
497
+ // `google-workspace` from extensions, or user-added `notion`)
498
+ // produce `serverId` values that DON'T appear in the daemon's
499
+ // `mcp_servers` table. The schema has no FK so writes succeed,
500
+ // but the dashboard's per-server activity panel (keyed by a
501
+ // matching server-card) won't surface them. The rows persist
502
+ // for any future "all MCP activity" view; for now they're a
503
+ // forensic-only audit trail.
504
+ if (event.type === "tool_use" && typeof event.tool_name === "string") {
505
+ const parsed = parseMcpToolName(event.tool_name);
506
+ if (parsed) {
507
+ logger.debug({
508
+ serverId: parsed.serverId,
509
+ toolName: parsed.toolName,
510
+ sessionId,
511
+ eventType: params.eventType,
512
+ }, "mcp.tool_call");
513
+ if (this.mcpContext?.db) {
514
+ try {
515
+ logMcpToolCall(this.mcpContext.db, {
516
+ serverId: parsed.serverId,
517
+ toolName: parsed.toolName,
518
+ eventType: params.eventType,
519
+ sessionId: sessionId ?? undefined,
520
+ });
521
+ }
522
+ catch (err) {
523
+ logger.warn({ err, serverId: parsed.serverId }, "mcp.tool_call audit insert failed");
524
+ }
525
+ }
526
+ }
527
+ }
528
+ if (event.type === "message" && event.role === "assistant") {
529
+ const content = typeof event.content === "string" ? event.content : "";
530
+ if (!content) {
531
+ return;
532
+ }
533
+ if (event.delta) {
534
+ assistantDelta += content;
535
+ if (!deferStreamingUntilBudgetCheck) {
536
+ streamCallbacks?.onText?.(content);
537
+ streamed = true;
538
+ }
539
+ return;
540
+ }
541
+ finalAssistantMessage = content;
542
+ return;
543
+ }
544
+ if (event.type === "result") {
545
+ const payload = event.result ?? event;
546
+ resultStatus = payload.status ?? resultStatus;
547
+ stats = payload.stats ?? stats;
548
+ lastError = payload.error ?? lastError;
549
+ }
550
+ },
551
+ onStderrLine: (line) => {
552
+ apiOutputBuffer.push(line);
553
+ if (isLikelyGeminiFailure(line)) {
554
+ lastError = line.trim();
555
+ }
556
+ },
557
+ });
558
+ const apiErrors = extractSilentApiErrors(apiOutputBuffer.join("\n"));
559
+ if (apiErrors.length > 0) {
560
+ logSilentApiErrors(logger, apiErrors, {
561
+ backendId: this.backendId,
562
+ sessionId,
563
+ eventType: params.eventType,
564
+ });
565
+ }
566
+ if (runResult.timedOut) {
567
+ const err = new BackendDecisiveFailure(this.backendId, "timeout", new Error(`Gemini execution exceeded timeout of ${this.config.executeTimeoutMinutes} minutes`));
568
+ logger.error({ err, eventType: params.eventType, model: params.modelId, durationMs: Date.now() - startMs }, "Gemini execute timed out");
569
+ throw err;
570
+ }
571
+ const outputSource = finalAssistantMessage.trim().length > 0
572
+ ? finalAssistantMessage
573
+ : assistantDelta;
574
+ const output = outputSource.trim();
575
+ if (resultStatus !== "success" || runResult.exitCode !== 0) {
576
+ const failureText = lastError
577
+ ?? firstFailureLine(runResult.stdoutLines)
578
+ ?? firstFailureLine(runResult.stderrLines)
579
+ ?? "Gemini execution did not complete successfully.";
580
+ const classified = this.classifyFailure(failureText);
581
+ logger.error({ err: classified, eventType: params.eventType, model: params.modelId, exitCode: runResult.exitCode, durationMs: Date.now() - startMs }, "Gemini execute failed");
582
+ throw classified;
583
+ }
584
+ const normalizedUsage = normalizeGeminiUsage(stats);
585
+ const { modelUsage, costSource } = buildGeminiModelUsage(this.priceFetcher, stats);
586
+ const actualModelId = resolveActualGeminiModel(params.modelId, modelUsage);
587
+ const durationApiMs = stats?.duration_ms ?? Date.now() - startMs;
588
+ const estimatedCost = this.priceFetcher.estimateUsageCost({
589
+ backendId: this.backendId,
590
+ modelId: actualModelId,
591
+ usage: normalizedUsage,
592
+ fallbackModel: findRegisteredModel(this.backendId, actualModelId),
593
+ });
594
+ const costUsd = Object.values(modelUsage)
595
+ .reduce((total, usage) => total + usage.costUsd, 0)
596
+ || estimatedCost.costUsd;
597
+ this.assertWithinMaxBudget(costUsd, params.maxBudgetUsd, actualModelId);
598
+ if (output && !streamed) {
599
+ streamCallbacks?.onText?.(output);
600
+ }
601
+ const durationMs = Date.now() - startMs;
602
+ logger.info({ eventType: params.eventType, model: actualModelId, durationMs, costUsd }, "Gemini execute completed");
603
+ // Bump the per-agent-day request counter on successful completion.
604
+ // We increment per-runTurn rather than per-JSONL-event because
605
+ // Gemini's streaming CLI may emit only delta messages without a
606
+ // final non-delta aggregate — counting on events made the ceiling
607
+ // enforcement silently break in streaming-only mode. Per-runTurn is
608
+ // protocol-agnostic and guaranteed to fire once per successful
609
+ // execution. Tool-fanout turns still count as one request, which
610
+ // undercounts real API consumption; that is an acceptable
611
+ // approximation for a safety-net ceiling (the tight 900 / 1350 /
612
+ // 1800 plan ceilings absorb the slack).
613
+ this.incrementRequestsCount(today);
614
+ return {
615
+ output,
616
+ sessionId,
617
+ backendId: this.backendId,
618
+ modelId: actualModelId,
619
+ costSource: Object.keys(modelUsage).length > 0 ? costSource : estimatedCost.costSource,
620
+ costUsd,
621
+ usage: normalizedUsage,
622
+ modelUsage,
623
+ numTurns: 1,
624
+ durationMs,
625
+ durationApiMs,
626
+ model: actualModelId,
627
+ isError: false,
628
+ stopReason: resultStatus,
629
+ contextUpdated: false,
630
+ // advisorCallCount omitted — non-Anthropic backends never populate
631
+ // this field, consumers treat undefined as 0.
632
+ };
633
+ }
634
+ finally {
635
+ if (ownsSessionDir) {
636
+ this.readTokenManager?.revoke(sessionDir);
637
+ }
638
+ streamCallbacks?.onEnd?.();
639
+ if (ownsSessionDir) {
640
+ cleanupSessionWorkdir(sessionDir);
641
+ }
642
+ }
643
+ }
644
+ buildArgs(params, policyPath) {
645
+ // The admin policy always applies (strict or allow) so context-dir and
646
+ // sensitive-path guardrails remain enforced. `--sandbox` is the container
647
+ // sandbox toggle (Docker/Podman) — only strict mode runs inside it.
648
+ // `--skip-trust` bypasses the workspace-trust prompt: session workdirs
649
+ // under PA_DATA_DIR are created fresh by the daemon and can't realistically
650
+ // be trusted interactively; the admin policy is the actual safety surface.
651
+ const allowMode = this.config.geminiExecutionPermissionMode === "allow";
652
+ return [
653
+ ...(params.resumeSessionId ? ["--resume", params.resumeSessionId] : []),
654
+ "--prompt",
655
+ params.prompt,
656
+ "--model",
657
+ params.modelId,
658
+ "--approval-mode",
659
+ "yolo",
660
+ "--skip-trust",
661
+ ...(allowMode ? [] : ["--sandbox"]),
662
+ "--admin-policy",
663
+ policyPath,
664
+ "--output-format",
665
+ "stream-json",
666
+ ];
667
+ }
668
+ /**
669
+ * Generate a TOML admin policy that restricts Gemini CLI tools to match
670
+ * the same security posture as Claude Code (allowedTools + security hooks).
671
+ *
672
+ * Admin policies are tier 5 (highest priority) and override --approval-mode yolo.
673
+ *
674
+ * All regex patterns use TOML literal strings ('...') to avoid escape-sequence
675
+ * conflicts — TOML basic strings ("...") treat `\b` as backspace and reject
676
+ * unknown escapes like `\.` / `\s`, which are valid regex metacharacters.
677
+ *
678
+ * ── Audit note: DM reactive-path allowlist bug (BUG-DM-BACKEND-PERMISSIONS) ──
679
+ *
680
+ * This Gemini policy does NOT need the Skill / Bash(jq *) additions that
681
+ * Claude Code needed for the same bug. Reasons verified 2026-04-11:
682
+ *
683
+ * 1. Gemini CLI has no first-class "Skill" tool. User skills are loaded
684
+ * as files in the session workdir (`${dataDir}/skills/`), and the
685
+ * agent reads them via `read_file` — which is already allowed at
686
+ * priority 500 below. There is no tool invocation to deny.
687
+ *
688
+ * 2. The priority-950 rule below denies any shell command that contains
689
+ * a pipe (`|`), semicolon (`;`), `&&`, or subshell operator. That
690
+ * means `curl ... | jq ...` is ALREADY denied on this backend by
691
+ * design — adding `jq` to an allowlist would have no effect while the
692
+ * pipe-chaining deny rule is in force. Gemini's workflow for JSON
693
+ * post-processing is: `curl -o /tmp/out.json ...`, then `read_file`,
694
+ * then parse in-model. That workflow does not need `jq`.
695
+ *
696
+ * If `message.dm` is ever re-routed to Gemini by default, re-audit: the
697
+ * task-flow prompts may reference `Skill(...)` syntax the agent cannot
698
+ * invoke on this backend. That would be a prompt/task-flow issue, not an
699
+ * allowlist issue.
700
+ */
701
+ generateAdminPolicy(options) {
702
+ const webSearchEnabled = options?.webSearchEnabled ?? false;
703
+ const port = this.config.apiPort;
704
+ const contextDir = resolvePath(getContextDir(this.config));
705
+ // Escape regex special chars in the path for use inside TOML literal strings.
706
+ // Literal strings don't process escapes, so single backslash is fine.
707
+ const escapedContextDir = contextDir.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
708
+ // Build sensitive-path argsPattern (regex alternation).
709
+ const sensitivePathPatterns = [
710
+ "\\.ssh/",
711
+ "\\.gnupg/",
712
+ "\\.aws/",
713
+ "Library/Keychains/",
714
+ "\\.personal-agent/backups/",
715
+ "\\.personal-agent/whatsapp/auth/",
716
+ // `\"` (closing JSON string quote) is a required terminator because
717
+ // Gemini matches argsPattern against the JSON-stringified args object
718
+ // like `{"file_path":".env"}` — without `\"` the pattern silently
719
+ // misses root `.env` reads (after `.env` comes `"` in the JSON, which
720
+ // matches none of $ / . / /).
721
+ '\\.env($|\\.|/|\\")',
722
+ ];
723
+ const sensitivePathRegex = sensitivePathPatterns.join("|");
724
+ const sessionHelperPathRegex = '(^|/)\\.pa/';
725
+ // Translate config.disallowedTools into additional deny rules.
726
+ // Claude Code format: "Bash(rm -rf *)", "Read(~/.ssh/**)" etc.
727
+ const extraDenyRules = this.buildDisallowedToolRules();
728
+ // DELEGATED-MODE-V2-DESIGN.md §4.3.3 — same-backend integration deny
729
+ // rules. For each integration whose `delegatedBackend === "gemini"`,
730
+ // emit one literal-toolName deny rule per concrete (glob-expanded)
731
+ // tool name. Priority sits between user-disallowedTools (935) and the
732
+ // absolute-block layer (1000) — same enforcement weight as user-driven
733
+ // disallowedTools by intent, but distinct so logs/audits can attribute.
734
+ const sessionDenyRules = this.buildSessionDeniedToolRules();
735
+ // EXECUTION-MODE-DESIGN.md §6 absolute-block layer — applied in both
736
+ // strict and allow mode at priority 999 (the in-tier ceiling enforced
737
+ // by Gemini CLI's PolicyFileSchema; admin tier still outranks user /
738
+ // workspace / default tiers regardless of in-tier priority).
739
+ const absoluteBlockRules = this.buildAbsoluteBlockRules();
740
+ return `# ${APP_NAME} admin policy for Gemini CLI (auto-generated)
741
+ # Admin tier — overrides approval-mode yolo
742
+
743
+ # ══════════════════════════════════════════════════
744
+ # Catch-all: deny everything not explicitly allowed.
745
+ # This creates whitelist semantics matching Claude Code's allowedTools.
746
+ # Every allowed tool must have a higher-priority allow rule below.
747
+ # ══════════════════════════════════════════════════
748
+ [[rule]]
749
+ toolName = "*"
750
+ decision = "deny"
751
+ denyMessage = "This tool is not permitted in daemon mode."
752
+ priority = 1
753
+
754
+ ${this.buildWebAccessRules(webSearchEnabled)}
755
+
756
+ # ── Shell: restrict to curl localhost:${port} and git ──
757
+
758
+ # Deny any shell command containing a non-localhost HTTP URL.
759
+ # This catches curl piping/chaining bypasses like:
760
+ # curl http://localhost:8321/... ; curl http://evil.com
761
+ # Negative lookahead ensures only localhost:{port} URLs are permitted.
762
+ [[rule]]
763
+ toolName = "run_shell_command"
764
+ commandRegex = 'https?://(?!(localhost|127\\.0\\.0\\.1):${port}[/\\s?#])'
765
+ decision = "deny"
766
+ denyMessage = "HTTP requests to non-localhost targets are forbidden. Use the daemon API."
767
+ priority = 960
768
+
769
+ # Deny curl with connection-override flags (bypass prevention, matches Claude Code hook)
770
+ [[rule]]
771
+ toolName = "run_shell_command"
772
+ commandRegex = '\\bcurl\\b.*(--connect-to|--resolve|--config(\\b|=)|\\s-K|--proxy(\\b|=)|\\s-x|--socks)'
773
+ decision = "deny"
774
+ denyMessage = "curl connection override flags are not allowed (--connect-to, --resolve, --config, --proxy)."
775
+ priority = 955
776
+
777
+ # Deny curl with command chaining operators (pipe, semicolon, &&, ||, subshell, backtick)
778
+ [[rule]]
779
+ toolName = "run_shell_command"
780
+ commandRegex = '\\bcurl\\b.*(;|\\|\\||&&|\\||\\$\\(|\x60)'
781
+ decision = "deny"
782
+ denyMessage = "curl with command chaining is not allowed. Use separate tool calls."
783
+ priority = 950
784
+
785
+ # Allow curl targeting localhost:${port}
786
+ [[rule]]
787
+ toolName = "run_shell_command"
788
+ commandRegex = '\\bcurl\\b.*https?://(localhost|127\\.0\\.0\\.1):${port}(/|\\s|$|\\?)'
789
+ decision = "allow"
790
+ priority = 900
791
+
792
+ # Deny any other curl command
793
+ [[rule]]
794
+ toolName = "run_shell_command"
795
+ commandRegex = '\\bcurl\\b'
796
+ decision = "deny"
797
+ denyMessage = "curl is restricted to localhost:${port}. Use the daemon API for all HTTP requests."
798
+ priority = 850
799
+
800
+ # Deny dangerous git operations (matches Claude Code's disallowedTools)
801
+ [[rule]]
802
+ toolName = "run_shell_command"
803
+ commandRegex = '\\bgit\\s+push\\s+(-f|--force)'
804
+ decision = "deny"
805
+ denyMessage = "git push --force is not allowed."
806
+ priority = 940
807
+
808
+ [[rule]]
809
+ toolName = "run_shell_command"
810
+ commandRegex = '\\bgit\\s+reset\\s+--hard'
811
+ decision = "deny"
812
+ denyMessage = "git reset --hard is not allowed."
813
+ priority = 940
814
+
815
+ [[rule]]
816
+ toolName = "run_shell_command"
817
+ commandRegex = '\\bgit\\s+clean\\b'
818
+ decision = "deny"
819
+ denyMessage = "git clean is not allowed."
820
+ priority = 940
821
+
822
+ # Allow other git commands
823
+ [[rule]]
824
+ toolName = "run_shell_command"
825
+ commandPrefix = "git "
826
+ decision = "allow"
827
+ priority = 800
828
+
829
+ [[rule]]
830
+ toolName = "run_shell_command"
831
+ commandPrefix = "git"
832
+ decision = "allow"
833
+ priority = 800
834
+
835
+ # Deny keychain access (secrets use -A flag; block agent from reading them)
836
+ [[rule]]
837
+ toolName = "run_shell_command"
838
+ commandPrefix = "security "
839
+ decision = "deny"
840
+ denyMessage = "Keychain access is not allowed in daemon mode."
841
+ priority = 950
842
+
843
+ # Deny dangerous shell commands
844
+ [[rule]]
845
+ toolName = "run_shell_command"
846
+ commandPrefix = "rm -rf"
847
+ decision = "deny"
848
+ priority = 940
849
+
850
+ [[rule]]
851
+ toolName = "run_shell_command"
852
+ commandPrefix = "rm -r"
853
+ decision = "deny"
854
+ priority = 940
855
+
856
+ [[rule]]
857
+ toolName = "run_shell_command"
858
+ commandPrefix = "sudo "
859
+ decision = "deny"
860
+ priority = 940
861
+
862
+ [[rule]]
863
+ toolName = "run_shell_command"
864
+ commandPrefix = "su "
865
+ decision = "deny"
866
+ priority = 940
867
+
868
+ [[rule]]
869
+ toolName = "run_shell_command"
870
+ commandPrefix = "chmod "
871
+ decision = "deny"
872
+ priority = 940
873
+
874
+ [[rule]]
875
+ toolName = "run_shell_command"
876
+ commandPrefix = "chown "
877
+ decision = "deny"
878
+ priority = 940
879
+
880
+ # Deny all other shell commands (only curl-to-localhost and git are allowed)
881
+ [[rule]]
882
+ toolName = "run_shell_command"
883
+ decision = "deny"
884
+ denyMessage = "Only 'curl localhost:${port}' and 'git' commands are allowed in daemon mode."
885
+ priority = 100
886
+
887
+ # ── File operations ──
888
+
889
+ # Deny writes to context directory (must use daemon API)
890
+ [[rule]]
891
+ toolName = ["write_file", "replace"]
892
+ argsPattern = '${escapedContextDir}'
893
+ decision = "deny"
894
+ denyMessage = "Direct writes to context directory are forbidden. Use PUT/PATCH http://localhost:${port}/api/context/*"
895
+ priority = 960
896
+
897
+ # Deny writes to the session helper directory. The daemon manages .pa/bin/*
898
+ # wrappers; allowing edits would let the agent rewrite the curl shim that
899
+ # receives daemon-auth env at execution time.
900
+ [[rule]]
901
+ toolName = ["write_file", "replace"]
902
+ argsPattern = '${sessionHelperPathRegex}'
903
+ decision = "deny"
904
+ denyMessage = "Direct writes to .pa are forbidden. Session helper binaries are daemon-managed."
905
+ priority = 958
906
+
907
+ # Deny reads/writes to sensitive paths
908
+ [[rule]]
909
+ toolName = ["read_file", "read_many_files", "write_file", "replace"]
910
+ argsPattern = '${sensitivePathRegex}'
911
+ decision = "deny"
912
+ denyMessage = "Access to sensitive paths (.ssh, .aws, .gnupg, Keychains, .env, backups) is forbidden."
913
+ priority = 955
914
+
915
+ # Allow standard file operations
916
+ [[rule]]
917
+ toolName = ["read_file", "read_many_files", "glob", "grep_search", "list_directory"]
918
+ decision = "allow"
919
+ priority = 500
920
+
921
+ [[rule]]
922
+ toolName = ["write_file", "replace"]
923
+ decision = "allow"
924
+ priority = 500
925
+
926
+ # ── Other tools ──
927
+ [[rule]]
928
+ toolName = ["ask_user", "write_todos", "save_memory"]
929
+ decision = "allow"
930
+ priority = 500
931
+
932
+ # ── Subagent delegation (invoke_agent) ──
933
+ # Block Gemini CLI's built-in subagent dispatcher. The daemon's stream
934
+ # parsers (runTurn + runDelegatedTool) only observe the parent agent's
935
+ # tool_use events — subagent-internal MCP calls don't surface, so the
936
+ # anti-prompt-injection guard would mis-classify the turn as wrong_tool.
937
+ # Subagents also paraphrase tool output instead of returning the raw
938
+ # connector envelope, and per-integration deniedTools / cost accounting
939
+ # don't cross the subagent boundary. Bundled policies/agents.toml allows
940
+ # invoke_agent at default-tier priority 50; admin tier wins cross-tier
941
+ # so this rule's priority only orders it inside the admin policy, not
942
+ # against the bundled allow.
943
+ #
944
+ # Hard-coded by tool name — if a future Gemini CLI ships a renamed or
945
+ # additional delegation builtin, this rule will not catch it. Watch for
946
+ # new tool-name constants alongside AGENT_TOOL_NAME in the bundled CLI.
947
+ [[rule]]
948
+ toolName = "invoke_agent"
949
+ decision = "deny"
950
+ denyMessage = "Subagent delegation via invoke_agent is not allowed in daemon-managed sessions. Call the requested tool directly."
951
+ priority = 950
952
+ ${absoluteBlockRules}${extraDenyRules}${sessionDenyRules}`;
953
+ }
954
+ /**
955
+ * Minimal admin policy for allow mode. No catch-all deny — every tool not
956
+ * matched by a rule below falls through to the `--approval-mode yolo`
957
+ * grants, which is what "all commands/MCPs/skills enabled" requires.
958
+ *
959
+ * Only two invariants are preserved:
960
+ * 1. Context directory writes must go through the daemon API. This is
961
+ * memory-layer integrity (today-write-lock, md_file_snapshots,
962
+ * CONTEXT_WRITE_PERMISSIONS, onPromptContextChanged) — orthogonal to
963
+ * tool permissions. Denied for both `write_file`/`replace` directly
964
+ * and for `run_shell_command` whose argv contains the context path.
965
+ * 2. Reads of keychain / SSH / GPG / AWS / .env / daemon secrets /
966
+ * WhatsApp auth / backups stay denied. These aren't tool policy
967
+ * either — they're the exfiltration surface, and enabling them
968
+ * serves no agent workflow on a single-owner device.
969
+ *
970
+ * Everything else (arbitrary `rm`, `curl` to any host, `chmod`, `sudo`,
971
+ * web search / fetch, etc.) is permitted because allow mode is meant to
972
+ * be the "strong permission mode" the user asked for.
973
+ */
974
+ generateAllowModeMinimalPolicy() {
975
+ const port = this.config.apiPort;
976
+ const contextDir = resolvePath(getContextDir(this.config));
977
+ // Escape regex metacharacters — TOML literal strings don't process escapes,
978
+ // so a single backslash reaches the regex engine unchanged.
979
+ const escapeRegex = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
980
+ // Match any shell-level path form that points at the context dir:
981
+ // - absolute: /Users/.../context
982
+ // - home-tilde: ~/... (shell expands; raw command text contains "~")
983
+ // - $HOME / ${HOME} env-var interpolation
984
+ // Without these alternations, `tee ~/.personal-agent/context/today.md`
985
+ // slips through the context-write deny rule.
986
+ const home = homedir();
987
+ const contextPathForms = shellPathForms(contextDir, home);
988
+ const contextPathRegex = contextPathForms.map(escapeRegex).join("|");
989
+ const contextArgsRegex = jsonStringPathForms(contextPathForms)
990
+ .map(escapeRegex)
991
+ .join("|");
992
+ const sensitivePathPatterns = [
993
+ "\\.ssh[\\\\/]",
994
+ "\\.gnupg[\\\\/]",
995
+ "\\.aws[\\\\/]",
996
+ "Library[\\\\/]Keychains[\\\\/]",
997
+ "\\.personal-agent[\\\\/]backups[\\\\/]",
998
+ "\\.personal-agent[\\\\/]whatsapp[\\\\/]auth[\\\\/]",
999
+ "\\.personal-agent[\\\\/]secrets[\\\\/]",
1000
+ // `\"` (closing JSON string quote) is a required terminator because
1001
+ // Gemini matches argsPattern against the JSON-stringified args object
1002
+ // like `{"file_path":".env"}` — without `\"` the pattern silently
1003
+ // misses root `.env` reads (after `.env` comes `"` in the JSON, which
1004
+ // matches none of $ / . / /).
1005
+ '\\.env($|\\.|[\\\\/]|\\")',
1006
+ ];
1007
+ const sensitivePathRegex = sensitivePathPatterns.join("|");
1008
+ return `# ${APP_NAME} admin policy for Gemini CLI — Allow mode (minimal)
1009
+ # Admin tier — overrides approval-mode yolo only for the rules below.
1010
+ # No catch-all deny: every tool not matched here inherits yolo's auto-approve.
1011
+
1012
+ # ── Context directory writes must go through the daemon API ──
1013
+ # Memory-layer integrity invariants (today-write-lock, md_file_snapshots,
1014
+ # CONTEXT_WRITE_PERMISSIONS, onPromptContextChanged) cannot be enforced on
1015
+ # shell-level writes; so we deny any shell command or direct tool that
1016
+ # targets the context dir.
1017
+
1018
+ [[rule]]
1019
+ toolName = ["write_file", "replace"]
1020
+ argsPattern = '${contextArgsRegex}'
1021
+ decision = "deny"
1022
+ denyMessage = "Direct writes to the context directory are forbidden even in Allow mode. Use PUT/PATCH http://localhost:${port}/api/context/* so today-write-lock, md_file_snapshots, and CONTEXT_WRITE_PERMISSIONS stay enforced."
1023
+ priority = 999
1024
+
1025
+ [[rule]]
1026
+ toolName = "run_shell_command"
1027
+ commandRegex = '${contextPathRegex}'
1028
+ decision = "deny"
1029
+ denyMessage = "Shell commands that reference the context directory are forbidden — writing via redirects / tee / sed -i / script engines bypasses daemon-API guarantees. Use http://localhost:${port}/api/context/*. Absolute, ~, and HOME-env-var forms are all matched."
1030
+ priority = 999
1031
+
1032
+ # ── Sensitive-path reads ──
1033
+ # Secrets, keys, and daemon backups stay read-blocked. Writes to these
1034
+ # paths are also blocked so the agent cannot plant credentials or tamper
1035
+ # with keychain-adjacent directories.
1036
+
1037
+ [[rule]]
1038
+ toolName = ["read_file", "read_many_files", "write_file", "replace"]
1039
+ argsPattern = '${sensitivePathRegex}'
1040
+ decision = "deny"
1041
+ denyMessage = "Access to sensitive paths (.ssh, .aws, .gnupg, Keychains, .env, daemon secrets, backups, WhatsApp auth) is forbidden even in Allow mode."
1042
+ priority = 998
1043
+
1044
+ # ── Subagent delegation (invoke_agent) ──
1045
+ # Same rationale as the strict-mode policy: daemon stream parsers don't
1046
+ # see subagent-internal tool calls, subagents paraphrase results, and
1047
+ # per-integration deniedTools / cost accounting don't cross the subagent
1048
+ # boundary. Allow mode has no catch-all "*" deny, so this explicit rule
1049
+ # is the only thing keeping bundled policies/agents.toml (default tier,
1050
+ # priority 50) from re-allowing invoke_agent.
1051
+ [[rule]]
1052
+ toolName = "invoke_agent"
1053
+ decision = "deny"
1054
+ denyMessage = "Subagent delegation via invoke_agent is not allowed in daemon-managed sessions. Call the requested tool directly."
1055
+ priority = 950
1056
+ ${this.buildAbsoluteBlockRules()}${this.buildSessionDeniedToolRules()}`;
1057
+ }
1058
+ /**
1059
+ * EXECUTION-MODE-DESIGN.md §6.2 — absolute-block rules applied in BOTH
1060
+ * strict and allow mode. Priority is pinned at 999 — the in-tier
1061
+ * ceiling enforced by Gemini CLI's `PolicyFileSchema` (`priority` is
1062
+ * `.int().min(0).max(999)`; values >= 1000 fail with "Schema validation
1063
+ * failed" and the entire policy file is dropped, which would also drop
1064
+ * every other guardrail in this admin policy).
1065
+ *
1066
+ * Cross-tier precedence is unaffected: the daemon registers this file
1067
+ * via `--admin-policy <path>`, which puts it at `ADMIN_POLICY_TIER (=5)`,
1068
+ * strictly above user/workspace/default. Within the admin tier, 999 is
1069
+ * the maximum so absolute-block still wins against every other rule
1070
+ * here. The two existing 998/999 deny rules in allow mode are also
1071
+ * `decision = "deny"`, so a tie at 999 collapses to the same outcome
1072
+ * (deny) — no semantic conflict.
1073
+ *
1074
+ * Highest-priority ALLOW rule across both modes is `curl localhost`
1075
+ * at 900, well below 999, so absolute-block continues to override any
1076
+ * allow currently emitted.
1077
+ */
1078
+ buildAbsoluteBlockRules() {
1079
+ return this.convertToolListToTomlRules(ALWAYS_DISALLOWED_TOOLS, {
1080
+ priority: 999,
1081
+ denyPrefix: "Blocked by absolute-block layer: ",
1082
+ sectionHeader: "Absolute-block layer (EXECUTION-MODE-DESIGN.md §6)",
1083
+ });
1084
+ }
1085
+ /**
1086
+ * Convert config.disallowedTools entries into TOML deny rules.
1087
+ *
1088
+ * Claude Code format entries like "Bash(rm -rf *)" or "Read(~/.ssh/**)"
1089
+ * are translated into Gemini-native policy rules.
1090
+ */
1091
+ buildDisallowedToolRules() {
1092
+ return this.convertToolListToTomlRules(this.config.disallowedTools ?? [], {
1093
+ priority: 935,
1094
+ denyPrefix: "Blocked by disallowedTools: ",
1095
+ sectionHeader: "User-configured disallowedTools",
1096
+ });
1097
+ }
1098
+ /**
1099
+ * DELEGATED-MODE-V2-DESIGN.md §4.3.3 — emit deny rules for every
1100
+ * concrete (glob-expanded) MCP tool name carried by an integration's
1101
+ * `deniedTools` whose `delegatedBackend === "gemini"`. Tools are
1102
+ * matched by literal name (e.g.
1103
+ * `mcp__codex_apps__google_calendar._delete_event`) at priority 936
1104
+ * — one tick above the user-disallowedTools block (935) so a deny
1105
+ * here cannot be overridden by anything below.
1106
+ *
1107
+ * Empty when no integration is in same-backend mode for Gemini.
1108
+ */
1109
+ buildSessionDeniedToolRules() {
1110
+ if (!this.mcpContext)
1111
+ return "";
1112
+ let denied = [];
1113
+ try {
1114
+ const integrations = readIntegrations(this.mcpContext.db);
1115
+ const map = collectSessionDeniedTools(integrations, "gemini");
1116
+ const flat = [];
1117
+ for (const names of map.values())
1118
+ flat.push(...names);
1119
+ denied = flat;
1120
+ }
1121
+ catch (err) {
1122
+ logger.warn({ err }, "Failed to read integrations for same-backend denied-tools — proceeding without per-integration deny");
1123
+ return "";
1124
+ }
1125
+ if (denied.length === 0)
1126
+ return "";
1127
+ const rules = [
1128
+ "",
1129
+ "",
1130
+ "# ══════════════════════════════════════════════════",
1131
+ "# Same-backend deniedTools (DELEGATED-MODE-V2-DESIGN.md §4.3.3)",
1132
+ "# ══════════════════════════════════════════════════",
1133
+ ];
1134
+ for (const tool of denied) {
1135
+ rules.push(`
1136
+ [[rule]]
1137
+ toolName = "${this.escapeTomlBasicString(tool)}"
1138
+ decision = "deny"
1139
+ denyMessage = "Tool '${this.escapeTomlBasicString(tool)}' is denied by the user's integration deniedTools setting."
1140
+ priority = 936`);
1141
+ }
1142
+ return rules.join("\n");
1143
+ }
1144
+ convertToolListToTomlRules(disallowed, opts) {
1145
+ const rules = [];
1146
+ for (const entry of disallowed) {
1147
+ const bashMatch = /^Bash\((.+)\)$/.exec(entry);
1148
+ if (bashMatch) {
1149
+ // "Bash(rm -rf *)" → deny run_shell_command with commandPrefix
1150
+ const cmdPattern = bashMatch[1].replace(/\s*\*$/, "").trim();
1151
+ if (cmdPattern) {
1152
+ rules.push(`
1153
+ [[rule]]
1154
+ toolName = "run_shell_command"
1155
+ commandPrefix = "${this.escapeTomlBasicString(cmdPattern)}"
1156
+ decision = "deny"
1157
+ denyMessage = "${this.escapeTomlBasicString(opts.denyPrefix)}${this.escapeTomlBasicString(entry)}"
1158
+ priority = ${opts.priority}`);
1159
+ }
1160
+ continue;
1161
+ }
1162
+ const fileMatch = /^(Read|Write|Edit)\((.+)\)$/.exec(entry);
1163
+ if (fileMatch) {
1164
+ const [, toolType, pathGlob] = fileMatch;
1165
+ // Convert glob to a simple regex substring for argsPattern.
1166
+ // "~/.ssh/**" → ".ssh/"
1167
+ const pathFragment = pathGlob
1168
+ .replace(/^~\//, "")
1169
+ .replace(/\*+$/g, "")
1170
+ .replace(/\\/g, "/");
1171
+ if (!pathFragment)
1172
+ continue;
1173
+ const toolNames = [];
1174
+ if (toolType === "Read")
1175
+ toolNames.push("read_file", "read_many_files");
1176
+ if (toolType === "Write" || toolType === "Edit")
1177
+ toolNames.push("write_file", "replace");
1178
+ if (toolNames.length > 0) {
1179
+ const toolNameValue = toolNames.length === 1
1180
+ ? `"${toolNames[0]}"`
1181
+ : `[${toolNames.map((t) => `"${t}"`).join(", ")}]`;
1182
+ rules.push(`
1183
+ [[rule]]
1184
+ toolName = ${toolNameValue}
1185
+ argsPattern = '${pathFragment}'
1186
+ decision = "deny"
1187
+ denyMessage = "${this.escapeTomlBasicString(opts.denyPrefix)}${this.escapeTomlBasicString(entry)}"
1188
+ priority = ${opts.priority}`);
1189
+ }
1190
+ }
1191
+ }
1192
+ if (rules.length === 0)
1193
+ return "";
1194
+ return `
1195
+ # ── ${opts.sectionHeader} ──
1196
+ ${rules.join("\n")}
1197
+ `;
1198
+ }
1199
+ /**
1200
+ * Build the web-access TOML rules section.
1201
+ *
1202
+ * When disabled (default): deny both google_web_search and web_fetch at
1203
+ * priority 999 (overrides any lower-priority allow).
1204
+ *
1205
+ * When enabled: allow google_web_search only. web_fetch remains denied
1206
+ * because it can fetch arbitrary URLs, creating a data-exfiltration
1207
+ * vector that contradicts the curl-to-localhost shell restriction.
1208
+ */
1209
+ buildWebAccessRules(webSearchEnabled) {
1210
+ if (webSearchEnabled) {
1211
+ return `# ── Web access: PARTIAL ALLOW ──
1212
+ # google_web_search enabled via dashboard settings.
1213
+ # web_fetch remains denied (arbitrary URL fetch = exfiltration risk).
1214
+
1215
+ [[rule]]
1216
+ toolName = "google_web_search"
1217
+ decision = "allow"
1218
+ priority = 500
1219
+
1220
+ [[rule]]
1221
+ toolName = "web_fetch"
1222
+ decision = "deny"
1223
+ denyMessage = "Web fetch is not allowed. Only google_web_search is permitted when web search is enabled."
1224
+ priority = 999`;
1225
+ }
1226
+ return `# ── Web access: DENY ──
1227
+ # Block internet search and URL fetching (parity with Claude Code's allowedTools whitelist)
1228
+
1229
+ [[rule]]
1230
+ toolName = "google_web_search"
1231
+ decision = "deny"
1232
+ denyMessage = "Web search is not allowed in daemon mode. Use the daemon API for external data."
1233
+ priority = 999
1234
+
1235
+ [[rule]]
1236
+ toolName = "web_fetch"
1237
+ decision = "deny"
1238
+ denyMessage = "Web fetch is not allowed in daemon mode. Use the daemon API for external data."
1239
+ priority = 999`;
1240
+ }
1241
+ /** Escape characters for TOML basic string values (double-quoted). */
1242
+ escapeTomlBasicString(value) {
1243
+ return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
1244
+ }
1245
+ /**
1246
+ * Pre-mark vault-scoped file writes from Gemini's tool_use events
1247
+ * so the ObsidianWatcher attributes them to actor='agent'.
1248
+ */
1249
+ trackVaultWrite(event) {
1250
+ if (!this.writeTracker)
1251
+ return;
1252
+ const vaultPath = this.config.externalObsidianVaultPath;
1253
+ if (!vaultPath)
1254
+ return;
1255
+ if (event.tool_name !== "write_file" && event.tool_name !== "replace")
1256
+ return;
1257
+ const filePath = event.args?.file_path;
1258
+ if (typeof filePath !== "string" || !filePath)
1259
+ return;
1260
+ const absFile = resolvePath(filePath);
1261
+ const absVault = resolvePath(vaultPath);
1262
+ if (isPathInsideOrEqual(absVault, absFile)) {
1263
+ this.writeTracker.markWriting(absFile);
1264
+ logger.debug({ filePath: absFile }, "Gemini vault write pre-marked for observer attribution");
1265
+ }
1266
+ }
1267
+ pickSummaryModel() {
1268
+ // Registry-derived lite-tier model is the canonical pick (compaction
1269
+ // summaries are short-shape and benefit from the cheapest model).
1270
+ // Falls through to "any registered model" when the registry has no
1271
+ // available lite entry, then throws when the registry is empty for
1272
+ // this backend — preferable to the prior silent literal fallback
1273
+ // that hid registry misconfiguration.
1274
+ const liteFromRegistry = latestLiteFor(this.backendId);
1275
+ if (liteFromRegistry)
1276
+ return liteFromRegistry;
1277
+ const anyFromRegistry = this.listModels()[0]?.modelId;
1278
+ if (anyFromRegistry)
1279
+ return anyFromRegistry;
1280
+ throw new Error(`pickSummaryModel: no models registered for backend ${this.backendId}`);
1281
+ }
1282
+ /**
1283
+ * Resolve the Gemini per-agent-day request ceiling. The daemon does
1284
+ * not store per-backend account tiers (Aitne runs on
1285
+ * `GEMINI_API_KEY` / `GOOGLE_API_KEY`, with CLI auth as fallback),
1286
+ * so this returns a fixed conservative default
1287
+ * (`GEMINI_DAILY_REQUEST_CEILING`, matching the free Gemini API tier
1288
+ * with 10% headroom). Operators on a paid Google account whose real
1289
+ * upstream quota is higher can widen the gate by editing
1290
+ * `runtime_state` directly or via a dashboard config surface (out of
1291
+ * scope for this layer).
1292
+ *
1293
+ * Returns `null` only when no db handle is injected (test/dev paths
1294
+ * that bypass enforcement entirely).
1295
+ */
1296
+ resolveDailyRequestCeiling() {
1297
+ if (!this.db)
1298
+ return null;
1299
+ return GEMINI_DAILY_REQUEST_CEILING;
1300
+ }
1301
+ /**
1302
+ * Read the current request count for today's agent day. Returns 0 when:
1303
+ * - the stored state is from a previous agent day (natural daily reset),
1304
+ * - the row is missing,
1305
+ * - or the db handle is not injected.
1306
+ */
1307
+ readRequestsCount(today) {
1308
+ if (!this.db)
1309
+ return 0;
1310
+ const state = readRuntimeState(this.db, GEMINI_REQUESTS_STATE_KEY);
1311
+ if (!state || state.date !== today)
1312
+ return 0;
1313
+ return state.count;
1314
+ }
1315
+ /**
1316
+ * Increment the per-agent-day counter. Resets to 1 when the stored date
1317
+ * does not match the current agent day (that is the reset path — no
1318
+ * separate scheduler job is needed because the key is agent-day scoped).
1319
+ */
1320
+ incrementRequestsCount(today) {
1321
+ if (!this.db)
1322
+ return;
1323
+ try {
1324
+ const state = readRuntimeState(this.db, GEMINI_REQUESTS_STATE_KEY);
1325
+ const nextCount = state && state.date === today ? state.count + 1 : 1;
1326
+ writeRuntimeState(this.db, GEMINI_REQUESTS_STATE_KEY, {
1327
+ date: today,
1328
+ count: nextCount,
1329
+ });
1330
+ }
1331
+ catch (err) {
1332
+ // A counter write failure must not break an in-flight execution.
1333
+ logger.warn({ err }, "Failed to persist Gemini request counter");
1334
+ }
1335
+ }
1336
+ classifyFailure(message) {
1337
+ if (isMaxBudgetMessage(message)) {
1338
+ return new BackendQuotaError(this.backendId, "max_budget_usd", null, message);
1339
+ }
1340
+ if (/rate limit|quota|429/i.test(message)) {
1341
+ return new BackendQuotaError(this.backendId, "rate_limited", null, message);
1342
+ }
1343
+ if (/authentication page|oauth|api key|login|required/i.test(message)) {
1344
+ return new BackendDecisiveFailure(this.backendId, "auth", new Error(message));
1345
+ }
1346
+ if (/timed out|timeout/i.test(message)) {
1347
+ return new BackendDecisiveFailure(this.backendId, "timeout", new Error(message));
1348
+ }
1349
+ return new BackendDecisiveFailure(this.backendId, "other_non_retryable", new Error(message));
1350
+ }
1351
+ assertWithinMaxBudget(costUsd, maxBudgetUsd, modelId) {
1352
+ if (maxBudgetUsd === undefined || costUsd <= maxBudgetUsd) {
1353
+ return;
1354
+ }
1355
+ throw new BackendQuotaError(this.backendId, "max_budget_usd", null, `Gemini CLI estimated cost $${costUsd.toFixed(4)} exceeded the per-turn budget limit $${maxBudgetUsd.toFixed(2)} for ${modelId}.`);
1356
+ }
1357
+ assertPromptWithinMaxBudget(prompt, maxBudgetUsd, modelId) {
1358
+ if (maxBudgetUsd === undefined) {
1359
+ return;
1360
+ }
1361
+ const estimatedUsage = {
1362
+ inputTokens: estimateTextInputTokens(prompt),
1363
+ outputTokens: 0,
1364
+ cacheCreationInputTokens: 0,
1365
+ cacheReadInputTokens: 0,
1366
+ };
1367
+ const { costUsd } = this.priceFetcher.estimateUsageCost({
1368
+ backendId: this.backendId,
1369
+ modelId,
1370
+ usage: estimatedUsage,
1371
+ fallbackModel: findRegisteredModel(this.backendId, modelId),
1372
+ });
1373
+ if (costUsd <= maxBudgetUsd) {
1374
+ return;
1375
+ }
1376
+ throw new BackendQuotaError(this.backendId, "max_budget_usd", null, `Gemini CLI estimated prompt cost $${costUsd.toFixed(4)} exceeded the per-turn budget limit $${maxBudgetUsd.toFixed(2)} for ${modelId}.`);
1377
+ }
1378
+ /**
1379
+ * Delegated proxy invocation — Gemini CLI path.
1380
+ *
1381
+ * **Result extraction**: Gemini CLI ≥ 0.40 emits structured
1382
+ * `tool_result` events with `tool_id` correlation and a string-encoded
1383
+ * `output` field. We capture the first `tool_result` whose `tool_id`
1384
+ * pairs with a `tool_use` event for the requested tool name; that
1385
+ * output (parsed JSON when possible) becomes the `toolResult`. This
1386
+ * matches the Claude/Codex paths and is robust to Gemini Flash Lite
1387
+ * disregarding the proxy prompt's "return raw result, do not narrate"
1388
+ * instruction by emitting prose summaries — the prose lands in the
1389
+ * assistant message stream, which we now ignore.
1390
+ *
1391
+ * **Fallback**: if no matching `tool_result` event arrives (older CLI,
1392
+ * unexpected stream shape) we fall back to the previous text-based
1393
+ * extraction from the final assistant message — strictly worse, but
1394
+ * better than failing the call outright.
1395
+ *
1396
+ * Reachable for every integration whose registry descriptor lists a
1397
+ * Gemini connector. As of 2026-04-26 that includes `gmail` (via the
1398
+ * `google-workspace` extension), `google_calendar` (same extension),
1399
+ * and `notion` (user-installed Notion MCP server registered as
1400
+ * `notion`). Gmail and Calendar are also in `PROXY_DRIVEN_INTEGRATIONS`,
1401
+ * so a Claude/Codex DM session with `delegatedBackend = "gemini"` for
1402
+ * either lands here through `/api/integrations/:key/invoke`.
1403
+ */
1404
+ async runDelegatedTool(params) {
1405
+ const startMs = Date.now();
1406
+ const { toolName, toolArgs, modelId, sessionDir, abortSignal } = params;
1407
+ if (!this.cliPath) {
1408
+ return {
1409
+ ok: false,
1410
+ errorClass: "subprocess_crashed",
1411
+ message: "gemini CLI not found on PATH",
1412
+ cost: withDurationMs(emptyCost(), startMs),
1413
+ };
1414
+ }
1415
+ const auth = await this.checkAuth();
1416
+ if (!auth.ok) {
1417
+ return {
1418
+ ok: false,
1419
+ errorClass: "auth_error",
1420
+ message: auth.reason,
1421
+ cost: withDurationMs(emptyCost(), startMs),
1422
+ };
1423
+ }
1424
+ // Daily-request quota gate. Mirrors `runTurn` (line 480-495) — Gemini
1425
+ // meters per-day model requests via plan-preset `dailyRequestCeiling`
1426
+ // (900/1350/1800), and proxy invocations consume the same quota as
1427
+ // direct execute()s. Without this gate, proxy calls would silently
1428
+ // exceed the day cap. Counter increment lives at the end of the
1429
+ // success path so failed proxy calls don't bias the count toward
1430
+ // saturation. See `docs/design/09-safety-cost.md` §9.4.8.
1431
+ const today = getAgentDayDateStr(this.config.timezone, this.config.dayBoundaryHour);
1432
+ const ceiling = this.resolveDailyRequestCeiling();
1433
+ if (ceiling !== null) {
1434
+ const currentCount = this.readRequestsCount(today);
1435
+ if (currentCount >= ceiling) {
1436
+ return {
1437
+ ok: false,
1438
+ errorClass: "auth_error",
1439
+ message: `Gemini daily-request ceiling reached (${currentCount}/${ceiling}) — `
1440
+ + `resets at the next agent-day boundary.`,
1441
+ cost: withDurationMs(emptyCost(), startMs),
1442
+ };
1443
+ }
1444
+ }
1445
+ // Write the same admin policy the normal path uses so context-dir
1446
+ // writes and pipe-chained shell commands are denied even on the
1447
+ // proxy session. Proxy.md tells the model to call exactly one tool;
1448
+ // the policy is belt-and-suspenders.
1449
+ const allowMode = this.config.geminiExecutionPermissionMode === "allow";
1450
+ const policyPath = join(sessionDir, ADMIN_POLICY_FILENAME);
1451
+ writeFileSync(policyPath, allowMode
1452
+ ? this.generateAllowModeMinimalPolicy()
1453
+ : this.generateAdminPolicy({ webSearchEnabled: false }), "utf-8");
1454
+ const prompt = buildDelegatedToolPrompt(toolName, toolArgs);
1455
+ const args = this.buildArgs({ prompt, modelId }, policyPath);
1456
+ let calledMatchingTool = false;
1457
+ let wrongToolName = null;
1458
+ let assistantDelta = "";
1459
+ let finalAssistantMessage = "";
1460
+ let lastError = null;
1461
+ let resultStatus = null;
1462
+ let stats = null;
1463
+ // tool_use → tool_id mapping for the requested tool. Gemini sometimes
1464
+ // calls the matching tool more than once (e.g. retries with refined
1465
+ // args, or extra confirmation calls disregarding the prompt's
1466
+ // "do not call other tools"). We capture every matching tool_id and
1467
+ // keep only the first paired tool_result so the proxy returns
1468
+ // deterministic output.
1469
+ const matchingToolIds = new Set();
1470
+ let capturedToolOutput = null;
1471
+ let capturedToolStatus = null;
1472
+ // Local aborter bridged from the caller's signal so we can also
1473
+ // trigger an early abort on wrong-tool detection without polluting
1474
+ // the caller's signal. Without early abort, a wrong-tool failure
1475
+ // burns the full 180s gemini wall-clock waiting for natural
1476
+ // completion (audit log 2026-05-01: 9.5s when subprocess completes
1477
+ // naturally, but up to 180s when the model loops on the missing
1478
+ // tool name). Abort caps it at ~5s.
1479
+ const proxyAborter = new AbortController();
1480
+ const callerAbortListener = () => {
1481
+ proxyAborter.abort(abortSignal?.reason);
1482
+ };
1483
+ if (abortSignal) {
1484
+ if (abortSignal.aborted) {
1485
+ proxyAborter.abort(abortSignal.reason);
1486
+ }
1487
+ else {
1488
+ abortSignal.addEventListener("abort", callerAbortListener, {
1489
+ once: true,
1490
+ });
1491
+ }
1492
+ }
1493
+ // Idle / hang watchdog. `gemini-cli` has been observed (audit log
1494
+ // 2026-05-02 / 2026-05-03: 9 / 83 cadence calls) to lock up entirely
1495
+ // — subprocess alive, zero stream-json output, only the 180s wall-
1496
+ // clock fires. The idle detector trips much earlier (75s default,
1497
+ // see `delegated-proxy-config.ts`) by treating each arrived line as
1498
+ // a heartbeat. On trip, we abort with a `DelegatedProxyTimeoutError`
1499
+ // so the post-loop classifier maps to `errorClass="timeout"`,
1500
+ // identical to wall-clock — the cadence retry path stays uniform.
1501
+ let idleTimedOut = false;
1502
+ const idleTimeoutMs = DELEGATED_PROXY_DEFAULTS.idleTimeoutMsByBackend.gemini
1503
+ ?? DELEGATED_PROXY_DEFAULTS.idleTimeoutMs;
1504
+ const idleWatchdog = new IdleWatchdog({
1505
+ idleTimeoutMs,
1506
+ onTimeout: (idleMs) => {
1507
+ idleTimedOut = true;
1508
+ logger.warn({ idleMs, idleTimeoutMs, toolName }, "gemini delegated proxy idle watchdog tripped");
1509
+ proxyAborter.abort(new DelegatedProxyTimeoutError(`gemini stream idle for ${idleMs}ms (limit ${idleTimeoutMs}ms)`));
1510
+ },
1511
+ });
1512
+ try {
1513
+ idleWatchdog.start();
1514
+ const runResult = await runLineCommand({
1515
+ command: this.cliPath,
1516
+ args,
1517
+ cwd: sessionDir,
1518
+ env: buildDaemonApiCliEnv(sessionDir, this.config.apiPort, { sessionBackend: "gemini" }),
1519
+ // Safety-net timeout, derived from the invoker's per-backend
1520
+ // abort timeout (`callTimeoutMsByBackend.gemini`). We add a 60s
1521
+ // grace window so the abort signal *always* fires first and we
1522
+ // get a clean `timeout` errorClass instead of the watchdog's
1523
+ // ambiguous "subprocess exceeded local safety-net timeout".
1524
+ // Deriving rather than hard-coding prevents drift if the abort
1525
+ // cap is later raised or lowered.
1526
+ timeoutMs: (DELEGATED_PROXY_DEFAULTS.callTimeoutMsByBackend.gemini
1527
+ ?? DELEGATED_PROXY_DEFAULTS.callTimeoutMs)
1528
+ + 60_000,
1529
+ abortSignal: proxyAborter.signal,
1530
+ onStdoutLine: (line) => {
1531
+ idleWatchdog.beat();
1532
+ const event = parseJsonLine(line);
1533
+ if (!event?.type)
1534
+ return;
1535
+ if (event.type === "tool_use"
1536
+ && typeof event.tool_name === "string") {
1537
+ if (event.tool_name === toolName) {
1538
+ calledMatchingTool = true;
1539
+ if (typeof event.tool_id === "string") {
1540
+ matchingToolIds.add(event.tool_id);
1541
+ }
1542
+ }
1543
+ else if (wrongToolName === null) {
1544
+ wrongToolName = event.tool_name;
1545
+ // Early abort: kill the subprocess as soon as we see the
1546
+ // model call a tool that doesn't match `toolName`. The
1547
+ // post-await classifier checks `wrongToolName` BEFORE
1548
+ // `abortSignal?.aborted`, so the resulting failure is
1549
+ // attributed to wrong_tool (not cancelled).
1550
+ proxyAborter.abort(new Error("wrong_tool"));
1551
+ }
1552
+ return;
1553
+ }
1554
+ if (event.type === "tool_result"
1555
+ && typeof event.tool_id === "string"
1556
+ && matchingToolIds.has(event.tool_id)
1557
+ && capturedToolOutput === null) {
1558
+ capturedToolOutput =
1559
+ typeof event.output === "string" ? event.output : "";
1560
+ capturedToolStatus = event.status ?? null;
1561
+ return;
1562
+ }
1563
+ if (event.type === "message" && event.role === "assistant") {
1564
+ const content = typeof event.content === "string" ? event.content : "";
1565
+ if (!content)
1566
+ return;
1567
+ if (event.delta) {
1568
+ assistantDelta += content;
1569
+ }
1570
+ else {
1571
+ finalAssistantMessage = content;
1572
+ }
1573
+ return;
1574
+ }
1575
+ if (event.type === "result") {
1576
+ const payload = event.result ?? event;
1577
+ resultStatus = payload.status ?? resultStatus;
1578
+ stats = payload.stats ?? stats;
1579
+ lastError = payload.error ?? lastError;
1580
+ }
1581
+ },
1582
+ onStderrLine: (line) => {
1583
+ idleWatchdog.beat();
1584
+ if (isLikelyGeminiFailure(line)) {
1585
+ lastError = line.trim();
1586
+ }
1587
+ },
1588
+ });
1589
+ const usage = normalizeGeminiUsage(stats);
1590
+ const actualModelId = modelId;
1591
+ const estimatedCost = this.priceFetcher.estimateUsageCost({
1592
+ backendId: this.backendId,
1593
+ modelId: actualModelId,
1594
+ usage,
1595
+ fallbackModel: findRegisteredModel(this.backendId, actualModelId),
1596
+ });
1597
+ const cost = withDurationMs({
1598
+ tokensInput: usage.inputTokens,
1599
+ tokensOutput: usage.outputTokens,
1600
+ cacheCreationTokens: usage.cacheCreationInputTokens,
1601
+ cacheReadTokens: usage.cacheReadInputTokens,
1602
+ costUsd: estimatedCost.costUsd,
1603
+ durationMs: 0,
1604
+ numTurns: 1,
1605
+ }, startMs);
1606
+ // Order matters: wrong_tool is checked before the abort branch
1607
+ // because the early-abort path (proxyAborter.abort) sets
1608
+ // wrongToolName + triggers a kill. Without this ordering, the
1609
+ // failure would surface as "cancelled" instead of the actual
1610
+ // upstream cause. The idle-watchdog branch is checked AFTER
1611
+ // wrong_tool (a wrong-tool-then-idle race should still attribute
1612
+ // wrong_tool, since the model demonstrably misbehaved) but BEFORE
1613
+ // the caller's abortSignal branch (idle-induced proxyAborter abort
1614
+ // does not propagate back to abortSignal, so without this ordering
1615
+ // an idle hang would mis-classify as `no_tool_call`).
1616
+ if (wrongToolName !== null && !calledMatchingTool) {
1617
+ return {
1618
+ ok: false,
1619
+ errorClass: "wrong_tool",
1620
+ message: `model called '${wrongToolName}' instead of requested '${toolName}'`,
1621
+ cost,
1622
+ };
1623
+ }
1624
+ if (idleTimedOut) {
1625
+ return {
1626
+ ok: false,
1627
+ errorClass: "timeout",
1628
+ message: `delegated proxy stream went idle (no gemini events for ${idleTimeoutMs}ms)`,
1629
+ cost,
1630
+ };
1631
+ }
1632
+ if (abortSignal?.aborted) {
1633
+ const errorClass = classifyAbortReason(abortSignal.reason);
1634
+ return {
1635
+ ok: false,
1636
+ errorClass,
1637
+ message: errorClass === "timeout"
1638
+ ? "delegated proxy timed out (wall-clock)"
1639
+ : "delegated proxy cancelled by caller",
1640
+ cost,
1641
+ };
1642
+ }
1643
+ if (runResult.timedOut) {
1644
+ return {
1645
+ ok: false,
1646
+ errorClass: "timeout",
1647
+ message: "gemini subprocess exceeded local safety-net timeout",
1648
+ cost,
1649
+ };
1650
+ }
1651
+ if (!calledMatchingTool) {
1652
+ const failure = lastError;
1653
+ if (failure && /unauthorized|forbidden|api key|login|auth/i.test(failure)) {
1654
+ return {
1655
+ ok: false,
1656
+ errorClass: "auth_error",
1657
+ message: failure,
1658
+ cost,
1659
+ };
1660
+ }
1661
+ return {
1662
+ ok: false,
1663
+ errorClass: "no_tool_call",
1664
+ message: failure
1665
+ ?? `model did not invoke '${toolName}' (resultStatus=${resultStatus ?? "unknown"})`,
1666
+ cost,
1667
+ };
1668
+ }
1669
+ // Preferred path: structured tool_result captured from the stream.
1670
+ // Reliable across Gemini Flash Lite's prose-narration tendency
1671
+ // because we ignore the assistant message and use the connector's
1672
+ // raw output verbatim.
1673
+ if (capturedToolOutput !== null) {
1674
+ if (capturedToolStatus === "error") {
1675
+ // Gemini CLI surfaces an MCP-tool-name-not-in-registry condition
1676
+ // as a tool_result with `status="error"` and an output starting
1677
+ // `Tool "<name>" not found. Did you mean…`. This is a transient
1678
+ // CLI-side registry miss (extension MCP server cold-start race
1679
+ // observed when the cadence worker's first tick fires <10s after
1680
+ // an integration switches to `delegated` — the host's
1681
+ // google-workspace MCP hasn't completed handshake yet, so the
1682
+ // model's tool_use lands on an empty registry). It is NOT a
1683
+ // real connector error from the upstream API, so we classify it
1684
+ // distinctly and let `delegated-sync-worker`'s retry policy
1685
+ // bounce once with a delay; the second attempt finds the tool
1686
+ // registered.
1687
+ if (isToolNotRegisteredError(capturedToolOutput, toolName)) {
1688
+ return {
1689
+ ok: false,
1690
+ errorClass: "tool_not_registered",
1691
+ message: capturedToolOutput,
1692
+ cost,
1693
+ };
1694
+ }
1695
+ return {
1696
+ ok: false,
1697
+ errorClass: "tool_error",
1698
+ message: capturedToolOutput || "tool returned error",
1699
+ cost,
1700
+ };
1701
+ }
1702
+ this.incrementRequestsCount(today);
1703
+ return {
1704
+ ok: true,
1705
+ toolResult: tryParseToolResult(capturedToolOutput),
1706
+ cost,
1707
+ };
1708
+ }
1709
+ // Fallback: text-based extraction from the assistant message.
1710
+ // Reached when the CLI's stream-json schema doesn't emit
1711
+ // tool_result events (older versions) or when the matching
1712
+ // tool_use never paired with a tool_result for some reason.
1713
+ //
1714
+ // Warn so production can detect CLI version drift — silent fallback
1715
+ // is what produced the original Flash Lite "narrate-the-result"
1716
+ // bug. If this warning starts firing, audit the CLI version.
1717
+ logger.warn({
1718
+ integrationKey: params.integrationKey,
1719
+ toolName,
1720
+ backendId: this.backendId,
1721
+ modelId,
1722
+ matchingToolUseCount: matchingToolIds.size,
1723
+ }, "Gemini delegated proxy fell back to assistant-text extraction — no paired tool_result event captured. Audit CLI stream schema if this fires regularly.");
1724
+ const resultText = finalAssistantMessage.trim().length > 0
1725
+ ? finalAssistantMessage.trim()
1726
+ : assistantDelta.trim();
1727
+ if (resultText.length === 0) {
1728
+ return {
1729
+ ok: false,
1730
+ errorClass: "parse_error",
1731
+ message: "gemini emitted matching tool_use but no tool_result event and no assistant text to extract result from",
1732
+ cost,
1733
+ };
1734
+ }
1735
+ // resultStatus === "error" with content present is a connector
1736
+ // tool_error path — surface the message verbatim per proxy.md.
1737
+ if (resultStatus === "error") {
1738
+ return {
1739
+ ok: false,
1740
+ errorClass: "tool_error",
1741
+ message: resultText,
1742
+ cost,
1743
+ };
1744
+ }
1745
+ // Bump the per-agent-day counter on the success path only, mirroring
1746
+ // `runTurn` line 720. Proxy success consumes one Gemini request
1747
+ // (turn-level approximation; tool fanout still counts as one,
1748
+ // matching the existing accounting).
1749
+ this.incrementRequestsCount(today);
1750
+ return {
1751
+ ok: true,
1752
+ toolResult: tryParseToolResult(resultText),
1753
+ cost,
1754
+ };
1755
+ }
1756
+ catch (err) {
1757
+ const message = err instanceof Error ? err.message : String(err);
1758
+ const cost = withDurationMs(emptyCost(), startMs);
1759
+ if (abortSignal?.aborted) {
1760
+ return {
1761
+ ok: false,
1762
+ errorClass: classifyAbortReason(abortSignal.reason),
1763
+ message,
1764
+ cost,
1765
+ };
1766
+ }
1767
+ return { ok: false, errorClass: "subprocess_crashed", message, cost };
1768
+ }
1769
+ finally {
1770
+ // Stop the idle watchdog before listener cleanup so a late-firing
1771
+ // poll cannot abort an already-resolved subprocess.
1772
+ idleWatchdog.stop();
1773
+ // Drop the listener regardless of how the call resolved so a
1774
+ // long-lived caller signal doesn't accumulate references across
1775
+ // back-to-back proxy invocations.
1776
+ if (abortSignal && !abortSignal.aborted) {
1777
+ abortSignal.removeEventListener("abort", callerAbortListener);
1778
+ }
1779
+ }
1780
+ }
1781
+ /**
1782
+ * DELEGATED-TASK-MODE-DESIGN.md §9.3 — Gemini CLI task mode.
1783
+ *
1784
+ * The admin policy is rebuilt per-request as a tightly-scoped task-only
1785
+ * surface (not the full strict/allow generators):
1786
+ * - catch-all deny at priority 1
1787
+ * - per-task allow rules at priority 920 for each tool in `allowedTools`
1788
+ * - destructive denies at priority 998 (when allowDestructive=false)
1789
+ * - absolute-block at priority 999
1790
+ * No shell or file allows — task mode runs MCP tools only.
1791
+ *
1792
+ * Stream parsing tracks `tool_use` / `tool_result` pairs to populate the
1793
+ * trace, counts assistant turns for the §8.3 Gemini per-day request
1794
+ * counter, and aborts on `maxToolCalls` overrun or any tool not in
1795
+ * `allowedTools` (defense-in-depth past the admin TOML).
1796
+ */
1797
+ async runDelegatedTask(params) {
1798
+ const startMs = Date.now();
1799
+ const { systemPrompt, allowedTools, destructiveTools, writeClassTools, modelId, maxToolCalls, sessionDir, abortSignal, onToolStep, allowDestructive, } = params;
1800
+ const trace = [];
1801
+ let writeClassToolFired = false;
1802
+ // §6.2 / §7.4 — match against the *write-class* set (destructive ∪
1803
+ // reversible writes), not just destructive. Otherwise reversible
1804
+ // write tools like `create_draft` slip past the retry guard and the
1805
+ // single retry creates a duplicate side effect.
1806
+ //
1807
+ // Phase 1 (`/exec`) entries are fully-qualified exact names; Phase 2
1808
+ // (`/api/delegated/run`) may pass `*`-suffixed glob patterns. The shared
1809
+ // `matchRunAllowedToolPattern` helper covers both shapes — exact equality
1810
+ // OR trailing-`*` prefix match — so the same matcher applies to the
1811
+ // allowed-tool guard further down (§9.3 stream-level enforcement).
1812
+ const writeClassMatcher = (name) => writeClassTools.some((pattern) => matchRunAllowedToolPattern(pattern, name));
1813
+ if (!this.cliPath) {
1814
+ return {
1815
+ ok: false,
1816
+ errorClass: "subprocess_crashed",
1817
+ message: "gemini CLI not found on PATH",
1818
+ cost: withDurationMs(emptyCost(), startMs),
1819
+ trace,
1820
+ writeClassToolFired,
1821
+ };
1822
+ }
1823
+ const auth = await this.checkAuth();
1824
+ if (!auth.ok) {
1825
+ return {
1826
+ ok: false,
1827
+ errorClass: "auth_error",
1828
+ message: auth.reason,
1829
+ cost: withDurationMs(emptyCost(), startMs),
1830
+ trace,
1831
+ writeClassToolFired,
1832
+ };
1833
+ }
1834
+ // §8.3 — pre-spawn daily-request gate. Mirrors runDelegatedTool because
1835
+ // task mode consumes the same daily budget.
1836
+ const today = getAgentDayDateStr(this.config.timezone, this.config.dayBoundaryHour);
1837
+ const ceiling = this.resolveDailyRequestCeiling();
1838
+ if (ceiling !== null) {
1839
+ const currentCount = this.readRequestsCount(today);
1840
+ if (currentCount >= ceiling) {
1841
+ return {
1842
+ ok: false,
1843
+ errorClass: "auth_error",
1844
+ message: `Gemini daily-request ceiling reached (${currentCount}/${ceiling}) — `
1845
+ + `resets at the next agent-day boundary.`,
1846
+ cost: withDurationMs(emptyCost(), startMs),
1847
+ trace,
1848
+ writeClassToolFired,
1849
+ };
1850
+ }
1851
+ }
1852
+ const policyPath = join(sessionDir, ADMIN_POLICY_FILENAME);
1853
+ writeFileSync(policyPath, this.generateTaskModePolicy({
1854
+ allowedTools,
1855
+ destructiveTools: allowDestructive ? [] : destructiveTools,
1856
+ }), "utf-8");
1857
+ const args = this.buildArgs({ prompt: systemPrompt, modelId }, policyPath);
1858
+ const pendingByUseId = new Map();
1859
+ let toolCallCount = 0;
1860
+ let loopAborted = false;
1861
+ let assistantDelta = "";
1862
+ let finalAssistantMessage = "";
1863
+ let lastError = null;
1864
+ let resultStatus = null;
1865
+ let stats = null;
1866
+ let policyViolationTool = null;
1867
+ let assistantTurns = 0;
1868
+ const aborter = new AbortController();
1869
+ const callerListener = () => aborter.abort(abortSignal?.reason);
1870
+ if (abortSignal) {
1871
+ if (abortSignal.aborted) {
1872
+ aborter.abort(abortSignal.reason);
1873
+ }
1874
+ else {
1875
+ abortSignal.addEventListener("abort", callerListener, { once: true });
1876
+ }
1877
+ }
1878
+ // §9.3 — stream-level allowed-tools guard. `allowedTools` may carry
1879
+ // Phase 2 (`/api/delegated/run`) trailing-`*` glob patterns
1880
+ // (DELEGATED-TASK-MODE-DESIGN.md §4.2), so an exact-equality `Set.has`
1881
+ // would silently reject every glob-admitted call as `policy_violation`.
1882
+ // The Gemini admin policy TOML at priority 920 honors the same glob
1883
+ // shape upstream (verified against the gemini-cli policy engine docs);
1884
+ // the daemon-side guard mirrors that semantics so the two layers agree.
1885
+ // Phase 1 (`/exec`) entries are fully-qualified exact names — the
1886
+ // exact-equality fast path inside `matchRunAllowedToolPattern` covers
1887
+ // them at one comparison.
1888
+ const isAllowedTool = (name) => allowedTools.some((pattern) => matchRunAllowedToolPattern(pattern, name));
1889
+ // `destructiveTools` is fully-qualified exact names from the registry
1890
+ // (Phase 1 only — Phase 2 passes `[]`), so a Set lookup is correct here
1891
+ // and stays O(1).
1892
+ const destructiveSet = allowDestructive
1893
+ ? new Set()
1894
+ : new Set(destructiveTools);
1895
+ try {
1896
+ const runResult = await runLineCommand({
1897
+ command: this.cliPath,
1898
+ args,
1899
+ cwd: sessionDir,
1900
+ env: buildDaemonApiCliEnv(sessionDir, this.config.apiPort, { sessionBackend: "gemini" }),
1901
+ timeoutMs: (DELEGATED_PROXY_DEFAULTS.callTimeoutMsByBackend.gemini
1902
+ ?? DELEGATED_PROXY_DEFAULTS.callTimeoutMs)
1903
+ + 60_000,
1904
+ abortSignal: aborter.signal,
1905
+ onStdoutLine: (line) => {
1906
+ const event = parseJsonLine(line);
1907
+ if (!event?.type)
1908
+ return;
1909
+ if (event.type === "tool_use" && typeof event.tool_name === "string") {
1910
+ const toolName = event.tool_name;
1911
+ if (!isAllowedTool(toolName) || destructiveSet.has(toolName)) {
1912
+ policyViolationTool = toolName;
1913
+ loopAborted = true;
1914
+ aborter.abort(new Error("policy_violation"));
1915
+ return;
1916
+ }
1917
+ toolCallCount += 1;
1918
+ if (toolCallCount > maxToolCalls) {
1919
+ loopAborted = true;
1920
+ aborter.abort(new Error("loop_aborted"));
1921
+ return;
1922
+ }
1923
+ if (writeClassMatcher(toolName)) {
1924
+ writeClassToolFired = true;
1925
+ }
1926
+ if (typeof event.tool_id === "string") {
1927
+ pendingByUseId.set(event.tool_id, {
1928
+ name: toolName,
1929
+ args: event.args ?? null,
1930
+ startedAt: Date.now(),
1931
+ });
1932
+ }
1933
+ return;
1934
+ }
1935
+ if (event.type === "tool_result"
1936
+ && typeof event.tool_id === "string") {
1937
+ const pending = pendingByUseId.get(event.tool_id);
1938
+ if (!pending)
1939
+ return;
1940
+ pendingByUseId.delete(event.tool_id);
1941
+ const status = event.status === "error" ? "error" : "ok";
1942
+ // `event.output` is a string-encoded tool result (the
1943
+ // google-workspace extension and most other connectors
1944
+ // serialize JSON responses to text). Try to parse so the
1945
+ // response-shape walker downstream can pluck ids; fall back
1946
+ // to the raw string when parsing fails (free-form text
1947
+ // replies).
1948
+ let parsedToolResult;
1949
+ if (typeof event.output === "string") {
1950
+ try {
1951
+ parsedToolResult = JSON.parse(event.output);
1952
+ }
1953
+ catch {
1954
+ parsedToolResult = event.output;
1955
+ }
1956
+ }
1957
+ const step = {
1958
+ toolName: pending.name,
1959
+ toolArgs: pending.args,
1960
+ durationMs: Date.now() - pending.startedAt,
1961
+ status,
1962
+ costUsd: null,
1963
+ tokensInput: null,
1964
+ tokensOutput: null,
1965
+ toolResult: parsedToolResult,
1966
+ };
1967
+ trace.push(step);
1968
+ onToolStep?.(step);
1969
+ return;
1970
+ }
1971
+ if (event.type === "message" && event.role === "assistant") {
1972
+ assistantTurns += 1;
1973
+ const content = typeof event.content === "string" ? event.content : "";
1974
+ if (!content)
1975
+ return;
1976
+ if (event.delta) {
1977
+ assistantDelta += content;
1978
+ }
1979
+ else {
1980
+ finalAssistantMessage = content;
1981
+ }
1982
+ return;
1983
+ }
1984
+ if (event.type === "result") {
1985
+ const payload = event.result ?? event;
1986
+ resultStatus = payload.status ?? resultStatus;
1987
+ stats = payload.stats ?? stats;
1988
+ lastError = payload.error ?? lastError;
1989
+ }
1990
+ },
1991
+ onStderrLine: (line) => {
1992
+ if (isLikelyGeminiFailure(line)) {
1993
+ lastError = line.trim();
1994
+ }
1995
+ },
1996
+ });
1997
+ const usage = normalizeGeminiUsage(stats);
1998
+ const estimatedCost = this.priceFetcher.estimateUsageCost({
1999
+ backendId: this.backendId,
2000
+ modelId,
2001
+ usage,
2002
+ fallbackModel: findRegisteredModel(this.backendId, modelId),
2003
+ });
2004
+ const cost = withDurationMs({
2005
+ tokensInput: usage.inputTokens,
2006
+ tokensOutput: usage.outputTokens,
2007
+ cacheCreationTokens: usage.cacheCreationInputTokens,
2008
+ cacheReadTokens: usage.cacheReadInputTokens,
2009
+ costUsd: estimatedCost.costUsd,
2010
+ durationMs: 0,
2011
+ numTurns: assistantTurns,
2012
+ }, startMs);
2013
+ // §8.3 per-turn counter — increment once per assistant message
2014
+ // observed (turn-level approximation matching Google's billing
2015
+ // surface).
2016
+ for (let i = 0; i < assistantTurns; i++) {
2017
+ this.incrementRequestsCount(today);
2018
+ }
2019
+ if (policyViolationTool) {
2020
+ return {
2021
+ ok: false,
2022
+ errorClass: "policy_violation",
2023
+ message: `subprocess attempted to call '${policyViolationTool}' which is outside the per-task allowlist`,
2024
+ cost,
2025
+ trace,
2026
+ writeClassToolFired,
2027
+ };
2028
+ }
2029
+ if (loopAborted) {
2030
+ return {
2031
+ ok: false,
2032
+ errorClass: "loop_aborted",
2033
+ message: `subprocess exceeded maxToolCalls=${maxToolCalls}`,
2034
+ cost,
2035
+ trace,
2036
+ writeClassToolFired,
2037
+ };
2038
+ }
2039
+ if (abortSignal?.aborted) {
2040
+ const errorClass = classifyAbortReason(abortSignal.reason);
2041
+ return {
2042
+ ok: false,
2043
+ errorClass,
2044
+ message: errorClass === "timeout"
2045
+ ? "delegated task timed out (wall-clock)"
2046
+ : "delegated task cancelled by caller",
2047
+ cost,
2048
+ trace,
2049
+ writeClassToolFired,
2050
+ };
2051
+ }
2052
+ if (runResult.timedOut) {
2053
+ return {
2054
+ ok: false,
2055
+ errorClass: "timeout",
2056
+ message: "gemini subprocess exceeded local safety-net timeout",
2057
+ cost,
2058
+ trace,
2059
+ writeClassToolFired,
2060
+ };
2061
+ }
2062
+ const finalText = finalAssistantMessage.trim().length > 0
2063
+ ? finalAssistantMessage.trim()
2064
+ : assistantDelta.trim();
2065
+ if (finalText.length === 0) {
2066
+ const failure = lastError;
2067
+ if (failure && /unauthorized|forbidden|api key|login|auth/i.test(failure)) {
2068
+ return {
2069
+ ok: false,
2070
+ errorClass: "auth_error",
2071
+ message: failure,
2072
+ cost,
2073
+ trace,
2074
+ writeClassToolFired,
2075
+ };
2076
+ }
2077
+ return {
2078
+ ok: false,
2079
+ errorClass: "parse_error",
2080
+ message: failure
2081
+ ?? `gemini emitted no final assistant message (resultStatus=${resultStatus ?? "unknown"})`,
2082
+ cost,
2083
+ trace,
2084
+ writeClassToolFired,
2085
+ };
2086
+ }
2087
+ return {
2088
+ ok: true,
2089
+ rawAssistantText: finalText,
2090
+ cost,
2091
+ trace,
2092
+ writeClassToolFired,
2093
+ };
2094
+ }
2095
+ catch (err) {
2096
+ const message = err instanceof Error ? err.message : String(err);
2097
+ const cost = withDurationMs(emptyCost(), startMs);
2098
+ if (abortSignal?.aborted || aborter.signal.aborted) {
2099
+ return {
2100
+ ok: false,
2101
+ errorClass: classifyAbortReason(abortSignal?.reason ?? aborter.signal.reason),
2102
+ message,
2103
+ cost,
2104
+ trace,
2105
+ writeClassToolFired,
2106
+ };
2107
+ }
2108
+ return {
2109
+ ok: false,
2110
+ errorClass: "subprocess_crashed",
2111
+ message,
2112
+ cost,
2113
+ trace,
2114
+ writeClassToolFired,
2115
+ };
2116
+ }
2117
+ finally {
2118
+ if (abortSignal) {
2119
+ abortSignal.removeEventListener("abort", callerListener);
2120
+ }
2121
+ }
2122
+ }
2123
+ /**
2124
+ * DELEGATED-TASK-MODE-DESIGN.md §9.3 — task-mode admin policy. Tightly
2125
+ * scoped: catch-all deny at priority 1, per-task allow rules at 920,
2126
+ * destructive denies at 998, absolute-block at 999. No shell or file
2127
+ * allows — the task subprocess only needs MCP tool calls.
2128
+ */
2129
+ generateTaskModePolicy(args) {
2130
+ const parts = [];
2131
+ parts.push(`# ${APP_NAME} task-mode admin policy (auto-generated)`, "# DELEGATED-TASK-MODE-DESIGN.md §9.3", "", "# Catch-all deny", "[[rule]]", 'toolName = "*"', 'decision = "deny"', 'denyMessage = "Tool not in the per-task allowlist."', "priority = 1", "");
2132
+ if (args.destructiveTools.length > 0) {
2133
+ parts.push("# Destructive tools — denied at priority 998 (allowDestructive=false)");
2134
+ for (const tool of args.destructiveTools) {
2135
+ parts.push("[[rule]]", `toolName = ${JSON.stringify(tool)}`, 'decision = "deny"', 'denyMessage = "Destructive tool denied — caller did not pass allowDestructive=true."', "priority = 998", "");
2136
+ }
2137
+ }
2138
+ if (args.allowedTools.length > 0) {
2139
+ parts.push("# Per-task allowed tools (priority 920)");
2140
+ for (const tool of args.allowedTools) {
2141
+ parts.push("[[rule]]", `toolName = ${JSON.stringify(tool)}`, 'decision = "allow"', "priority = 920", "");
2142
+ }
2143
+ }
2144
+ parts.push(this.buildAbsoluteBlockRules());
2145
+ return parts.join("\n");
2146
+ }
2147
+ }
2148
+ function isMaxBudgetMessage(message) {
2149
+ return /max(?:imum)? budget|max_budget_usd|budget limit|per-turn budget/i.test(message);
2150
+ }
2151
+ function normalizeGeminiUsage(stats) {
2152
+ if (!stats) {
2153
+ return { ...EMPTY_USAGE };
2154
+ }
2155
+ const totalInputTokens = readNumber(stats.input_tokens);
2156
+ const cacheReadInputTokens = readNumber(stats.cached);
2157
+ return {
2158
+ inputTokens: nonCachedInputTokens(totalInputTokens, cacheReadInputTokens),
2159
+ outputTokens: readNumber(stats.output_tokens),
2160
+ cacheCreationInputTokens: 0,
2161
+ cacheReadInputTokens,
2162
+ };
2163
+ }
2164
+ function buildGeminiModelUsage(priceFetcher, stats) {
2165
+ if (!stats?.models) {
2166
+ return { modelUsage: {}, costSource: "hardcoded" };
2167
+ }
2168
+ const usage = {};
2169
+ let allFromLitellm = true;
2170
+ for (const [modelId, modelStats] of Object.entries(stats.models)) {
2171
+ const cacheReadInputTokens = readNumber(modelStats.cached);
2172
+ const normalized = {
2173
+ inputTokens: nonCachedInputTokens(readNumber(modelStats.input_tokens), cacheReadInputTokens),
2174
+ outputTokens: readNumber(modelStats.output_tokens),
2175
+ cacheCreationInputTokens: 0,
2176
+ cacheReadInputTokens,
2177
+ };
2178
+ const priceEstimate = priceFetcher.estimateUsageCost({
2179
+ backendId: "gemini",
2180
+ modelId,
2181
+ usage: normalized,
2182
+ fallbackModel: findRegisteredModel("gemini", modelId),
2183
+ });
2184
+ usage[modelId] = {
2185
+ inputTokens: normalized.inputTokens,
2186
+ outputTokens: normalized.outputTokens,
2187
+ costUsd: priceEstimate.costUsd,
2188
+ };
2189
+ if (priceEstimate.costSource !== "litellm") {
2190
+ allFromLitellm = false;
2191
+ }
2192
+ }
2193
+ return {
2194
+ modelUsage: usage,
2195
+ costSource: allFromLitellm ? "litellm" : "hardcoded",
2196
+ };
2197
+ }
2198
+ function nonCachedInputTokens(totalInputTokens, cacheReadInputTokens, cacheCreationInputTokens = 0) {
2199
+ return Math.max(totalInputTokens - cacheReadInputTokens - cacheCreationInputTokens, 0);
2200
+ }
2201
+ function resolveActualGeminiModel(requestedModel, modelUsage) {
2202
+ const [firstModel] = Object.keys(modelUsage);
2203
+ return firstModel ?? requestedModel;
2204
+ }
2205
+ function isLikelyGeminiFailure(line) {
2206
+ return /error|failed|authentication|oauth|api key|quota|rate limit/i.test(line);
2207
+ }
2208
+ /**
2209
+ * Detect Gemini CLI's "tool name not in registry" tool_result error pattern.
2210
+ *
2211
+ * Format produced by `getToolSuggestion` in @google/gemini-cli (verified
2212
+ * 2026-05-04 against bundle 0.40.1):
2213
+ * `Tool "<name>" not found. Did you mean one of: "<a>", "<b>"?` (≥2 hits)
2214
+ * `Tool "<name>" not found. Did you mean "<a>"?` (1 hit)
2215
+ *
2216
+ * The expected `toolName` is included in the literal because we want to
2217
+ * avoid false positives — a connector tool that itself happens to emit a
2218
+ * "not found" message about some upstream resource (e.g. a Notion page
2219
+ * not_found error) should NOT be reclassified as transient.
2220
+ */
2221
+ export function isToolNotRegisteredError(output, expectedToolName) {
2222
+ if (typeof output !== "string" || output.length === 0)
2223
+ return false;
2224
+ const escapedName = expectedToolName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2225
+ return new RegExp(`^Tool "${escapedName}" not found\\. Did you mean`).test(output);
2226
+ }
2227
+ function firstFailureLine(lines) {
2228
+ const line = lines.find((candidate) => isLikelyGeminiFailure(candidate));
2229
+ return line?.trim() ?? null;
2230
+ }
2231
+ function readNumber(value) {
2232
+ return typeof value === "number" && Number.isFinite(value) ? value : 0;
2233
+ }
2234
+ /**
2235
+ * Parse `PA_GEMINI_OAUTH_GRACE_HOURS`. Returns `fallback` for undefined
2236
+ * or malformed values; a parseable 0 disables the grace entirely (the
2237
+ * intended escape hatch once the upstream CLI bug is fixed).
2238
+ */
2239
+ function parseGraceHours(value, fallback) {
2240
+ if (value === undefined)
2241
+ return fallback;
2242
+ const n = Number(value);
2243
+ if (!Number.isFinite(n) || n < 0)
2244
+ return fallback;
2245
+ return n;
2246
+ }
2247
+ /**
2248
+ * Append `@<relativePath>` tokens for every staged attachment to the tail
2249
+ * of the Gemini prompt. Gemini CLI v0.37+ expands these in non-interactive
2250
+ * mode by reading the file bytes and inlining them as multimodal content.
2251
+ *
2252
+ * The bracketed `[Attached files]` text block composed by the dispatcher
2253
+ * still describes what each file is; this helper only adds the
2254
+ * machine-readable `@`-tokens the CLI looks for. Kept on a single trailing
2255
+ * line so prompt hashing / diff comparisons remain stable when the list is
2256
+ * empty.
2257
+ *
2258
+ * Pure — exported for unit testing.
2259
+ */
2260
+ export function appendGeminiAttachmentTokens(prompt, staged) {
2261
+ if (!staged || staged.length === 0)
2262
+ return prompt;
2263
+ const tokens = staged.map((att) => `@${att.relativePath}`).join(" ");
2264
+ return `${prompt}\n\n${tokens}`;
2265
+ }
2266
+ /**
2267
+ * Read a Gemini config file (extension manifest or settings.json) and
2268
+ * collect every key under `mcpServers`. Tolerant of missing keys, malformed
2269
+ * JSON, and non-object payloads — best-effort host scan, not validation.
2270
+ *
2271
+ * Exported for unit testing.
2272
+ */
2273
+ export function collectMcpServerNames(filePath, out) {
2274
+ let raw;
2275
+ try {
2276
+ raw = readFileSync(filePath, "utf-8");
2277
+ }
2278
+ catch {
2279
+ return;
2280
+ }
2281
+ let parsed;
2282
+ try {
2283
+ parsed = JSON.parse(raw);
2284
+ }
2285
+ catch {
2286
+ return;
2287
+ }
2288
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
2289
+ return;
2290
+ const mcpServers = parsed.mcpServers;
2291
+ // typeof null === "object" and typeof [] === "object" — guard both. A
2292
+ // user who hand-edited settings.json with `mcpServers: [{...}]` (array
2293
+ // instead of dict) would otherwise have `Object.keys` return numeric
2294
+ // index strings ("0", "1") that get added as bogus server names.
2295
+ if (!mcpServers
2296
+ || typeof mcpServers !== "object"
2297
+ || Array.isArray(mcpServers)) {
2298
+ return;
2299
+ }
2300
+ for (const name of Object.keys(mcpServers)) {
2301
+ out.add(name);
2302
+ }
2303
+ }
2304
+ /**
2305
+ * Extract the MCP server name from a Gemini-convention `toolNamespace`.
2306
+ * Gemini's MCP namespace is `mcp_<server>_<rest>`, so the server name is
2307
+ * everything between the first `_` and the second `_` after the `mcp_`
2308
+ * prefix. Returns null if the namespace is not Gemini-shaped.
2309
+ *
2310
+ * Examples:
2311
+ * `mcp_google-workspace_gmail.` → `google-workspace`
2312
+ * `mcp_notion_` → `notion`
2313
+ * `mcp__claude_ai_Gmail__` → null (Claude double-underscore form)
2314
+ *
2315
+ * Exported for unit testing.
2316
+ */
2317
+ export function extractGeminiServerName(toolNamespace) {
2318
+ if (!toolNamespace.startsWith("mcp_"))
2319
+ return null;
2320
+ // Reject Claude / Codex double-underscore namespaces — they begin with
2321
+ // `mcp__` which also starts with `mcp_`. Single-underscore is the
2322
+ // distinguishing trait of Gemini's convention.
2323
+ if (toolNamespace.startsWith("mcp__"))
2324
+ return null;
2325
+ const rest = toolNamespace.slice("mcp_".length);
2326
+ const sep = rest.indexOf("_");
2327
+ if (sep === -1)
2328
+ return rest.length > 0 ? rest : null;
2329
+ return sep === 0 ? null : rest.slice(0, sep);
2330
+ }
2331
+ //# sourceMappingURL=gemini-cli-core.js.map