crewly 1.20.197 → 1.20.199

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 (319) hide show
  1. package/config/roles/orchestrator/prompt.md +8 -9
  2. package/config/roles/team-leader/prompt.md +6 -0
  3. package/config/skills/agent/computer-use/SKILL.md +16 -0
  4. package/config/skills/agent/core/ask-owner/SKILL.md +14 -0
  5. package/config/skills/agent/core/ask-owner/execute.sh +19 -1
  6. package/config/skills/agent/core/ask-owner/execute.test.sh +12 -0
  7. package/config/skills/agent/core/gmail-send/SKILL.md +16 -0
  8. package/config/skills/agent/core/reply-channel/SKILL.md +16 -0
  9. package/config/skills/agent/core/slack-post/SKILL.md +16 -0
  10. package/config/skills/agent/core/whatsapp-send/SKILL.md +16 -0
  11. package/config/skills/agent/remote-browser/SKILL.md +43 -7
  12. package/config/skills/registry.json +7 -7
  13. package/dist/backend/backend/src/constants.d.ts +159 -0
  14. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  15. package/dist/backend/backend/src/constants.js +175 -0
  16. package/dist/backend/backend/src/constants.js.map +1 -1
  17. package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts +12 -1
  18. package/dist/backend/backend/src/controllers/browser/browser.controller.d.ts.map +1 -1
  19. package/dist/backend/backend/src/controllers/browser/browser.controller.js +118 -3
  20. package/dist/backend/backend/src/controllers/browser/browser.controller.js.map +1 -1
  21. package/dist/backend/backend/src/controllers/browser/browser.routes.d.ts.map +1 -1
  22. package/dist/backend/backend/src/controllers/browser/browser.routes.js +5 -1
  23. package/dist/backend/backend/src/controllers/browser/browser.routes.js.map +1 -1
  24. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
  25. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +37 -52
  26. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
  27. package/dist/backend/backend/src/controllers/system/usage.controller.d.ts +14 -0
  28. package/dist/backend/backend/src/controllers/system/usage.controller.d.ts.map +1 -1
  29. package/dist/backend/backend/src/controllers/system/usage.controller.js +35 -1
  30. package/dist/backend/backend/src/controllers/system/usage.controller.js.map +1 -1
  31. package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
  32. package/dist/backend/backend/src/controllers/team/team.controller.js +13 -0
  33. package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
  34. package/dist/backend/backend/src/index.d.ts +17 -0
  35. package/dist/backend/backend/src/index.d.ts.map +1 -1
  36. package/dist/backend/backend/src/index.js +113 -2
  37. package/dist/backend/backend/src/index.js.map +1 -1
  38. package/dist/backend/backend/src/services/agent/agent-heartbeat-monitor.service.d.ts.map +1 -1
  39. package/dist/backend/backend/src/services/agent/agent-heartbeat-monitor.service.js +5 -8
  40. package/dist/backend/backend/src/services/agent/agent-heartbeat-monitor.service.js.map +1 -1
  41. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +12 -0
  42. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  43. package/dist/backend/backend/src/services/agent/agent-registration.service.js +275 -241
  44. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  45. package/dist/backend/backend/src/services/agent/context-window-monitor.service.d.ts.map +1 -1
  46. package/dist/backend/backend/src/services/agent/context-window-monitor.service.js +5 -6
  47. package/dist/backend/backend/src/services/agent/context-window-monitor.service.js.map +1 -1
  48. package/dist/backend/backend/src/services/agent/control-plane-guard.service.d.ts +6 -0
  49. package/dist/backend/backend/src/services/agent/control-plane-guard.service.d.ts.map +1 -1
  50. package/dist/backend/backend/src/services/agent/control-plane-guard.service.js +2 -1
  51. package/dist/backend/backend/src/services/agent/control-plane-guard.service.js.map +1 -1
  52. package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.d.ts.map +1 -1
  53. package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.js +12 -8
  54. package/dist/backend/backend/src/services/agent/fresh-task-conversation.service.js.map +1 -1
  55. package/dist/backend/backend/src/services/agent/gemini-runtime.service.d.ts.map +1 -1
  56. package/dist/backend/backend/src/services/agent/gemini-runtime.service.js +32 -27
  57. package/dist/backend/backend/src/services/agent/gemini-runtime.service.js.map +1 -1
  58. package/dist/backend/backend/src/services/agent/owner-stopped.registry.d.ts +44 -0
  59. package/dist/backend/backend/src/services/agent/owner-stopped.registry.d.ts.map +1 -0
  60. package/dist/backend/backend/src/services/agent/owner-stopped.registry.js +54 -0
  61. package/dist/backend/backend/src/services/agent/owner-stopped.registry.js.map +1 -0
  62. package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js +4 -4
  63. package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -1
  64. package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.d.ts.map +1 -1
  65. package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.js +4 -8
  66. package/dist/backend/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -1
  67. package/dist/backend/backend/src/services/ai/prompt-modules/decision-rights.module.d.ts +19 -4
  68. package/dist/backend/backend/src/services/ai/prompt-modules/decision-rights.module.d.ts.map +1 -1
  69. package/dist/backend/backend/src/services/ai/prompt-modules/decision-rights.module.js +28 -5
  70. package/dist/backend/backend/src/services/ai/prompt-modules/decision-rights.module.js.map +1 -1
  71. package/dist/backend/backend/src/services/browser/browser-approval.service.d.ts +2 -2
  72. package/dist/backend/backend/src/services/browser/browser-approval.service.d.ts.map +1 -1
  73. package/dist/backend/backend/src/services/browser/browser-approval.service.js +13 -2
  74. package/dist/backend/backend/src/services/browser/browser-approval.service.js.map +1 -1
  75. package/dist/backend/backend/src/services/browser/browser-outbound-guard.d.ts +214 -0
  76. package/dist/backend/backend/src/services/browser/browser-outbound-guard.d.ts.map +1 -0
  77. package/dist/backend/backend/src/services/browser/browser-outbound-guard.js +466 -0
  78. package/dist/backend/backend/src/services/browser/browser-outbound-guard.js.map +1 -0
  79. package/dist/backend/backend/src/services/browser/browser-session.service.d.ts +23 -2
  80. package/dist/backend/backend/src/services/browser/browser-session.service.d.ts.map +1 -1
  81. package/dist/backend/backend/src/services/browser/browser-session.service.js +110 -62
  82. package/dist/backend/backend/src/services/browser/browser-session.service.js.map +1 -1
  83. package/dist/backend/backend/src/services/browser/held-action-store.d.ts +4 -0
  84. package/dist/backend/backend/src/services/browser/held-action-store.d.ts.map +1 -1
  85. package/dist/backend/backend/src/services/browser/held-action-store.js.map +1 -1
  86. package/dist/backend/backend/src/services/cloud/cloud-initializer.d.ts.map +1 -1
  87. package/dist/backend/backend/src/services/cloud/cloud-initializer.js +6 -8
  88. package/dist/backend/backend/src/services/cloud/cloud-initializer.js.map +1 -1
  89. package/dist/backend/backend/src/services/experiments/experiment.service.d.ts +15 -1
  90. package/dist/backend/backend/src/services/experiments/experiment.service.d.ts.map +1 -1
  91. package/dist/backend/backend/src/services/experiments/experiment.service.js +41 -12
  92. package/dist/backend/backend/src/services/experiments/experiment.service.js.map +1 -1
  93. package/dist/backend/backend/src/services/messaging/input-blocked-retry.service.d.ts +129 -0
  94. package/dist/backend/backend/src/services/messaging/input-blocked-retry.service.d.ts.map +1 -0
  95. package/dist/backend/backend/src/services/messaging/input-blocked-retry.service.js +196 -0
  96. package/dist/backend/backend/src/services/messaging/input-blocked-retry.service.js.map +1 -0
  97. package/dist/backend/backend/src/services/messaging/message-queue.service.d.ts +21 -0
  98. package/dist/backend/backend/src/services/messaging/message-queue.service.d.ts.map +1 -1
  99. package/dist/backend/backend/src/services/messaging/message-queue.service.js +86 -11
  100. package/dist/backend/backend/src/services/messaging/message-queue.service.js.map +1 -1
  101. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +46 -0
  102. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -1
  103. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js +143 -22
  104. package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -1
  105. package/dist/backend/backend/src/services/monitoring/agent-hook-state.d.ts.map +1 -1
  106. package/dist/backend/backend/src/services/monitoring/agent-hook-state.js +5 -0
  107. package/dist/backend/backend/src/services/monitoring/agent-hook-state.js.map +1 -1
  108. package/dist/backend/backend/src/services/monitoring/antigravity-usage-sync.service.d.ts +7 -0
  109. package/dist/backend/backend/src/services/monitoring/antigravity-usage-sync.service.d.ts.map +1 -1
  110. package/dist/backend/backend/src/services/monitoring/antigravity-usage-sync.service.js +21 -6
  111. package/dist/backend/backend/src/services/monitoring/antigravity-usage-sync.service.js.map +1 -1
  112. package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.d.ts +49 -2
  113. package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.d.ts.map +1 -1
  114. package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.js +160 -55
  115. package/dist/backend/backend/src/services/monitoring/claude-transcript-sync.service.js.map +1 -1
  116. package/dist/backend/backend/src/services/monitoring/codex-rollout-sync.service.d.ts +7 -0
  117. package/dist/backend/backend/src/services/monitoring/codex-rollout-sync.service.d.ts.map +1 -1
  118. package/dist/backend/backend/src/services/monitoring/codex-rollout-sync.service.js +21 -7
  119. package/dist/backend/backend/src/services/monitoring/codex-rollout-sync.service.js.map +1 -1
  120. package/dist/backend/backend/src/services/monitoring/token-usage.service.d.ts +71 -1
  121. package/dist/backend/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -1
  122. package/dist/backend/backend/src/services/monitoring/token-usage.service.js +193 -20
  123. package/dist/backend/backend/src/services/monitoring/token-usage.service.js.map +1 -1
  124. package/dist/backend/backend/src/services/orchestrator/orchestrator-heartbeat-monitor.service.d.ts.map +1 -1
  125. package/dist/backend/backend/src/services/orchestrator/orchestrator-heartbeat-monitor.service.js +5 -9
  126. package/dist/backend/backend/src/services/orchestrator/orchestrator-heartbeat-monitor.service.js.map +1 -1
  127. package/dist/backend/backend/src/services/session/pty/pty-session-backend.d.ts +11 -0
  128. package/dist/backend/backend/src/services/session/pty/pty-session-backend.d.ts.map +1 -1
  129. package/dist/backend/backend/src/services/session/pty/pty-session-backend.js +14 -0
  130. package/dist/backend/backend/src/services/session/pty/pty-session-backend.js.map +1 -1
  131. package/dist/backend/backend/src/services/session/pty/pty-terminal-buffer.d.ts +37 -0
  132. package/dist/backend/backend/src/services/session/pty/pty-terminal-buffer.d.ts.map +1 -1
  133. package/dist/backend/backend/src/services/session/pty/pty-terminal-buffer.js +78 -0
  134. package/dist/backend/backend/src/services/session/pty/pty-terminal-buffer.js.map +1 -1
  135. package/dist/backend/backend/src/services/session/session-backend.interface.d.ts +13 -0
  136. package/dist/backend/backend/src/services/session/session-backend.interface.d.ts.map +1 -1
  137. package/dist/backend/backend/src/services/session/session-backend.interface.js.map +1 -1
  138. package/dist/backend/backend/src/services/session/session-command-helper.d.ts +118 -105
  139. package/dist/backend/backend/src/services/session/session-command-helper.d.ts.map +1 -1
  140. package/dist/backend/backend/src/services/session/session-command-helper.js +267 -298
  141. package/dist/backend/backend/src/services/session/session-command-helper.js.map +1 -1
  142. package/dist/backend/backend/src/services/session/tui-input-guard.d.ts +144 -0
  143. package/dist/backend/backend/src/services/session/tui-input-guard.d.ts.map +1 -0
  144. package/dist/backend/backend/src/services/session/tui-input-guard.js +312 -0
  145. package/dist/backend/backend/src/services/session/tui-input-guard.js.map +1 -0
  146. package/dist/backend/backend/src/services/slack/slack-agent-identity.service.d.ts.map +1 -1
  147. package/dist/backend/backend/src/services/slack/slack-agent-identity.service.js +5 -0
  148. package/dist/backend/backend/src/services/slack/slack-agent-identity.service.js.map +1 -1
  149. package/dist/backend/backend/src/services/slack/slack-cloud-config.service.d.ts.map +1 -1
  150. package/dist/backend/backend/src/services/slack/slack-cloud-config.service.js +5 -0
  151. package/dist/backend/backend/src/services/slack/slack-cloud-config.service.js.map +1 -1
  152. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  153. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +14 -0
  154. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  155. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts +31 -0
  156. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  157. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +87 -4
  158. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  159. package/dist/backend/backend/src/services/spend/spend-cap.service.d.ts +24 -1
  160. package/dist/backend/backend/src/services/spend/spend-cap.service.d.ts.map +1 -1
  161. package/dist/backend/backend/src/services/spend/spend-cap.service.js +57 -0
  162. package/dist/backend/backend/src/services/spend/spend-cap.service.js.map +1 -1
  163. package/dist/backend/backend/src/services/spend/spend-cap.store.d.ts +37 -1
  164. package/dist/backend/backend/src/services/spend/spend-cap.store.d.ts.map +1 -1
  165. package/dist/backend/backend/src/services/spend/spend-cap.store.js +85 -14
  166. package/dist/backend/backend/src/services/spend/spend-cap.store.js.map +1 -1
  167. package/dist/backend/backend/src/services/spend/spend-cap.wiring.d.ts.map +1 -1
  168. package/dist/backend/backend/src/services/spend/spend-cap.wiring.js +1 -1
  169. package/dist/backend/backend/src/services/spend/spend-cap.wiring.js.map +1 -1
  170. package/dist/backend/backend/src/services/trace/trace-store.d.ts +3 -1
  171. package/dist/backend/backend/src/services/trace/trace-store.d.ts.map +1 -1
  172. package/dist/backend/backend/src/services/trace/trace-store.js +27 -15
  173. package/dist/backend/backend/src/services/trace/trace-store.js.map +1 -1
  174. package/dist/backend/backend/src/services/trace/trace.types.d.ts +2 -2
  175. package/dist/backend/backend/src/services/trace/trace.types.d.ts.map +1 -1
  176. package/dist/backend/backend/src/services/trace/trace.types.js +4 -0
  177. package/dist/backend/backend/src/services/trace/trace.types.js.map +1 -1
  178. package/dist/backend/backend/src/services/trace/turn-origin.d.ts +70 -0
  179. package/dist/backend/backend/src/services/trace/turn-origin.d.ts.map +1 -0
  180. package/dist/backend/backend/src/services/trace/turn-origin.js +198 -0
  181. package/dist/backend/backend/src/services/trace/turn-origin.js.map +1 -0
  182. package/dist/backend/backend/src/services/usage/usage-backfill.service.d.ts +96 -0
  183. package/dist/backend/backend/src/services/usage/usage-backfill.service.d.ts.map +1 -0
  184. package/dist/backend/backend/src/services/usage/usage-backfill.service.js +257 -0
  185. package/dist/backend/backend/src/services/usage/usage-backfill.service.js.map +1 -0
  186. package/dist/backend/backend/src/services/v3/kr-tracking.service.d.ts.map +1 -1
  187. package/dist/backend/backend/src/services/v3/kr-tracking.service.js +2 -1
  188. package/dist/backend/backend/src/services/v3/kr-tracking.service.js.map +1 -1
  189. package/dist/backend/backend/src/services/v3/okr-cascade.service.d.ts.map +1 -1
  190. package/dist/backend/backend/src/services/v3/okr-cascade.service.js +2 -1
  191. package/dist/backend/backend/src/services/v3/okr-cascade.service.js.map +1 -1
  192. package/dist/backend/backend/src/services/workflow/cron-task.service.d.ts +28 -0
  193. package/dist/backend/backend/src/services/workflow/cron-task.service.d.ts.map +1 -1
  194. package/dist/backend/backend/src/services/workflow/cron-task.service.js +121 -68
  195. package/dist/backend/backend/src/services/workflow/cron-task.service.js.map +1 -1
  196. package/dist/backend/backend/src/types/slack.types.d.ts +8 -0
  197. package/dist/backend/backend/src/types/slack.types.d.ts.map +1 -1
  198. package/dist/backend/backend/src/types/slack.types.js.map +1 -1
  199. package/dist/backend/backend/src/utils/file-io.utils.d.ts +114 -1
  200. package/dist/backend/backend/src/utils/file-io.utils.d.ts.map +1 -1
  201. package/dist/backend/backend/src/utils/file-io.utils.js +236 -6
  202. package/dist/backend/backend/src/utils/file-io.utils.js.map +1 -1
  203. package/dist/backend/backend/src/utils/terminal-string-ops.d.ts.map +1 -1
  204. package/dist/backend/backend/src/utils/terminal-string-ops.js +3 -2
  205. package/dist/backend/backend/src/utils/terminal-string-ops.js.map +1 -1
  206. package/dist/backend/build-info.json +2 -2
  207. package/dist/cli/backend/src/constants.d.ts +159 -0
  208. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  209. package/dist/cli/backend/src/constants.js +175 -0
  210. package/dist/cli/backend/src/constants.js.map +1 -1
  211. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts +12 -0
  212. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  213. package/dist/cli/backend/src/services/agent/agent-registration.service.js +275 -241
  214. package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
  215. package/dist/cli/backend/src/services/agent/context-window-monitor.service.d.ts.map +1 -1
  216. package/dist/cli/backend/src/services/agent/context-window-monitor.service.js +5 -6
  217. package/dist/cli/backend/src/services/agent/context-window-monitor.service.js.map +1 -1
  218. package/dist/cli/backend/src/services/agent/control-plane-guard.service.d.ts +6 -0
  219. package/dist/cli/backend/src/services/agent/control-plane-guard.service.d.ts.map +1 -1
  220. package/dist/cli/backend/src/services/agent/control-plane-guard.service.js +2 -1
  221. package/dist/cli/backend/src/services/agent/control-plane-guard.service.js.map +1 -1
  222. package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.d.ts.map +1 -1
  223. package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.js +12 -8
  224. package/dist/cli/backend/src/services/agent/fresh-task-conversation.service.js.map +1 -1
  225. package/dist/cli/backend/src/services/agent/gemini-runtime.service.d.ts.map +1 -1
  226. package/dist/cli/backend/src/services/agent/gemini-runtime.service.js +32 -27
  227. package/dist/cli/backend/src/services/agent/gemini-runtime.service.js.map +1 -1
  228. package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.js +4 -4
  229. package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -1
  230. package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.d.ts.map +1 -1
  231. package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js +4 -8
  232. package/dist/cli/backend/src/services/agent/runtime-exit-monitor.service.js.map +1 -1
  233. package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.d.ts +19 -4
  234. package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.d.ts.map +1 -1
  235. package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.js +28 -5
  236. package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.js.map +1 -1
  237. package/dist/cli/backend/src/services/messaging/input-blocked-retry.service.d.ts +129 -0
  238. package/dist/cli/backend/src/services/messaging/input-blocked-retry.service.d.ts.map +1 -0
  239. package/dist/cli/backend/src/services/messaging/input-blocked-retry.service.js +196 -0
  240. package/dist/cli/backend/src/services/messaging/input-blocked-retry.service.js.map +1 -0
  241. package/dist/cli/backend/src/services/messaging/message-queue.service.d.ts +21 -0
  242. package/dist/cli/backend/src/services/messaging/message-queue.service.d.ts.map +1 -1
  243. package/dist/cli/backend/src/services/messaging/message-queue.service.js +86 -11
  244. package/dist/cli/backend/src/services/messaging/message-queue.service.js.map +1 -1
  245. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +46 -0
  246. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -1
  247. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js +143 -22
  248. package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -1
  249. package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts +71 -1
  250. package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -1
  251. package/dist/cli/backend/src/services/monitoring/token-usage.service.js +193 -20
  252. package/dist/cli/backend/src/services/monitoring/token-usage.service.js.map +1 -1
  253. package/dist/cli/backend/src/services/session/pty/pty-session-backend.d.ts +11 -0
  254. package/dist/cli/backend/src/services/session/pty/pty-session-backend.d.ts.map +1 -1
  255. package/dist/cli/backend/src/services/session/pty/pty-session-backend.js +14 -0
  256. package/dist/cli/backend/src/services/session/pty/pty-session-backend.js.map +1 -1
  257. package/dist/cli/backend/src/services/session/pty/pty-terminal-buffer.d.ts +37 -0
  258. package/dist/cli/backend/src/services/session/pty/pty-terminal-buffer.d.ts.map +1 -1
  259. package/dist/cli/backend/src/services/session/pty/pty-terminal-buffer.js +78 -0
  260. package/dist/cli/backend/src/services/session/pty/pty-terminal-buffer.js.map +1 -1
  261. package/dist/cli/backend/src/services/session/session-backend.interface.d.ts +13 -0
  262. package/dist/cli/backend/src/services/session/session-backend.interface.d.ts.map +1 -1
  263. package/dist/cli/backend/src/services/session/session-backend.interface.js.map +1 -1
  264. package/dist/cli/backend/src/services/session/session-command-helper.d.ts +118 -105
  265. package/dist/cli/backend/src/services/session/session-command-helper.d.ts.map +1 -1
  266. package/dist/cli/backend/src/services/session/session-command-helper.js +267 -298
  267. package/dist/cli/backend/src/services/session/session-command-helper.js.map +1 -1
  268. package/dist/cli/backend/src/services/session/tui-input-guard.d.ts +144 -0
  269. package/dist/cli/backend/src/services/session/tui-input-guard.d.ts.map +1 -0
  270. package/dist/cli/backend/src/services/session/tui-input-guard.js +312 -0
  271. package/dist/cli/backend/src/services/session/tui-input-guard.js.map +1 -0
  272. package/dist/cli/backend/src/services/slack/slack-agent-identity.service.d.ts.map +1 -1
  273. package/dist/cli/backend/src/services/slack/slack-agent-identity.service.js +5 -0
  274. package/dist/cli/backend/src/services/slack/slack-agent-identity.service.js.map +1 -1
  275. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  276. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js +14 -0
  277. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  278. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts +31 -0
  279. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  280. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +87 -4
  281. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  282. package/dist/cli/backend/src/services/trace/trace-store.d.ts +3 -1
  283. package/dist/cli/backend/src/services/trace/trace-store.d.ts.map +1 -1
  284. package/dist/cli/backend/src/services/trace/trace-store.js +27 -15
  285. package/dist/cli/backend/src/services/trace/trace-store.js.map +1 -1
  286. package/dist/cli/backend/src/services/trace/trace.types.d.ts +2 -2
  287. package/dist/cli/backend/src/services/trace/trace.types.d.ts.map +1 -1
  288. package/dist/cli/backend/src/services/trace/trace.types.js +4 -0
  289. package/dist/cli/backend/src/services/trace/trace.types.js.map +1 -1
  290. package/dist/cli/backend/src/services/trace/turn-origin.d.ts +70 -0
  291. package/dist/cli/backend/src/services/trace/turn-origin.d.ts.map +1 -0
  292. package/dist/cli/backend/src/services/trace/turn-origin.js +198 -0
  293. package/dist/cli/backend/src/services/trace/turn-origin.js.map +1 -0
  294. package/dist/cli/backend/src/services/v3/kr-tracking.service.d.ts.map +1 -1
  295. package/dist/cli/backend/src/services/v3/kr-tracking.service.js +2 -1
  296. package/dist/cli/backend/src/services/v3/kr-tracking.service.js.map +1 -1
  297. package/dist/cli/backend/src/services/workflow/cron-task.service.d.ts +28 -0
  298. package/dist/cli/backend/src/services/workflow/cron-task.service.d.ts.map +1 -1
  299. package/dist/cli/backend/src/services/workflow/cron-task.service.js +121 -68
  300. package/dist/cli/backend/src/services/workflow/cron-task.service.js.map +1 -1
  301. package/dist/cli/backend/src/types/slack.types.d.ts +8 -0
  302. package/dist/cli/backend/src/types/slack.types.d.ts.map +1 -1
  303. package/dist/cli/backend/src/types/slack.types.js.map +1 -1
  304. package/dist/cli/backend/src/utils/file-io.utils.d.ts +114 -1
  305. package/dist/cli/backend/src/utils/file-io.utils.d.ts.map +1 -1
  306. package/dist/cli/backend/src/utils/file-io.utils.js +236 -6
  307. package/dist/cli/backend/src/utils/file-io.utils.js.map +1 -1
  308. package/dist/cli/backend/src/utils/terminal-string-ops.d.ts.map +1 -1
  309. package/dist/cli/backend/src/utils/terminal-string-ops.js +3 -2
  310. package/dist/cli/backend/src/utils/terminal-string-ops.js.map +1 -1
  311. package/package.json +1 -1
  312. package/dist/cli/backend/src/services/agent/agent-suspend.service.d.ts +0 -118
  313. package/dist/cli/backend/src/services/agent/agent-suspend.service.d.ts.map +0 -1
  314. package/dist/cli/backend/src/services/agent/agent-suspend.service.js +0 -304
  315. package/dist/cli/backend/src/services/agent/agent-suspend.service.js.map +0 -1
  316. package/dist/cli/backend/src/services/agent/disk-cleanup.service.d.ts +0 -100
  317. package/dist/cli/backend/src/services/agent/disk-cleanup.service.d.ts.map +0 -1
  318. package/dist/cli/backend/src/services/agent/disk-cleanup.service.js +0 -149
  319. package/dist/cli/backend/src/services/agent/disk-cleanup.service.js.map +0 -1
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Browser outbound guard — which agent browser actions publish something as
3
+ * the owner, so they must be held for an owner approval card.
4
+ *
5
+ * Why (2026-10-03): an agent posted a LinkedIn reply as the owner without
6
+ * approval. The existing check (`matchIrreversible`) only read a short word
7
+ * list against the agent's selector, so a LinkedIn reply went through:
8
+ * `button.comments-comment-box__submit-button` hides "submit" behind `__`
9
+ * (a word character, so `\bsubmit\b` never matched), "Reply" and "Comment"
10
+ * were not on the list, a click by coordinates or by element ref carried no
11
+ * words at all, `type` with a trailing newline and `Ctrl+Enter`/`Cmd+Enter`
12
+ * keys were not checked, and `el['click']()` in a page script was not seen
13
+ * as acting.
14
+ *
15
+ * This module closes those paths, without holding what only reads:
16
+ *
17
+ * - Descriptors are split into words at punctuation (`__submit-button` →
18
+ * "submit button"), not at camelCase (code identifiers are not controls).
19
+ * - A control whose whole label is Reply/Comment/Post/Send/Tweet (plus
20
+ * Share/Connect/Invite on social sites) is held; bare "comment"/"tweet"
21
+ * in class names (a comment item, a tweet being read) are not.
22
+ * - Any key that submits (Enter, Return, with or without modifiers) and any
23
+ * typed text containing a newline or a submit flag is held.
24
+ * - A page script is held when it acts AND sends a writing request or names
25
+ * a submit control — not for clicking "See more".
26
+ * - On social and messaging sites (LinkedIn, X, Facebook, Instagram, Reddit,
27
+ * Gmail/Outlook web, Slack web, WhatsApp web, …) a click that names no
28
+ * control (coordinates, refs) is held: there the harness cannot tell a
29
+ * "Post" from any other button.
30
+ *
31
+ * @module services/browser/browser-outbound-guard
32
+ */
33
+ /** Where the action happens, as far as the harness knows. */
34
+ export interface OutboundContext {
35
+ /** URL of the tab the action is in (read from the browser), when known */
36
+ url?: string;
37
+ /** The tab the action is in, when known */
38
+ tabId?: number;
39
+ }
40
+ /**
41
+ * Host of a URL, lower case, '' when unknown or unparsable.
42
+ *
43
+ * @param url - URL
44
+ * @returns Host
45
+ */
46
+ export declare function siteOf(url: string | undefined): string;
47
+ /**
48
+ * The page an action is on, for scoping a draft: host + path + hash (Gmail
49
+ * keeps the compose/thread context in the hash). '' when unknown.
50
+ *
51
+ * @param url - URL
52
+ * @returns Page key
53
+ */
54
+ export declare function pageOf(url: string | undefined): string;
55
+ /**
56
+ * Whether an input is a search field — typing a query there is not a draft:
57
+ * `type=search`, `role=searchbox`, a name of `q`/`query`/`search` (Gmail's
58
+ * `input[name="q"]`), an aria-label or placeholder naming search, or a
59
+ * `role=combobox` input. A combobox that is contenteditable or a textarea is
60
+ * a compose box (LinkedIn, X), not search.
61
+ *
62
+ * @param params - Tool params
63
+ * @returns True for a search field
64
+ */
65
+ export declare function isSearchField(params: Record<string, unknown> | undefined): boolean;
66
+ /**
67
+ * Whether a key press pastes (Cmd/Ctrl+V): pasting into an editable writes a
68
+ * draft the harness cannot read.
69
+ *
70
+ * @param params - pressKey params
71
+ * @returns True for a paste chord
72
+ */
73
+ export declare function isPasteKey(params: Record<string, unknown> | undefined): boolean;
74
+ /**
75
+ * Whether a key press activates a focused button or link (Space / Enter).
76
+ *
77
+ * @param params - pressKey params
78
+ * @returns True for Space or Enter
79
+ */
80
+ export declare function isActivateKey(params: Record<string, unknown> | undefined): boolean;
81
+ /**
82
+ * Whether a URL is on a social or messaging site, where posting reaches
83
+ * other people as the owner.
84
+ *
85
+ * @param url - Page URL
86
+ * @returns True for a listed host or any of its subdomains
87
+ */
88
+ export declare function isSocialOrMessagingSite(url: string | undefined): boolean;
89
+ /**
90
+ * Split a selector/label/script into words at punctuation, so word-boundary
91
+ * matching sees through CSS naming (`comments-comment-box__submit-button` →
92
+ * "comments comment box submit button"). camelCase is NOT split: code
93
+ * identifiers (`postCount`, `commentsList`) are not controls.
94
+ *
95
+ * @param text - Raw descriptor
96
+ * @returns Space-separated words
97
+ */
98
+ export declare function toWords(text: string): string;
99
+ /**
100
+ * The words that describe what a click/select names: selector, text, value,
101
+ * aria label, label, name, title.
102
+ *
103
+ * @param params - Tool params
104
+ * @returns Descriptor text ('' when the action names nothing)
105
+ */
106
+ export declare function descriptorOf(params: Record<string, unknown> | undefined): string;
107
+ /**
108
+ * Whole labels an action names: its `text`/`ariaLabel`/`label`, and labels
109
+ * quoted inside a selector (`:has-text("Reply")`, `[aria-label="Post"]`,
110
+ * `text=Send`) or a script (`b.innerText === 'Reply'`).
111
+ *
112
+ * @param params - Tool params
113
+ * @returns Labels, lower case, trimmed
114
+ */
115
+ export declare function labelsOf(params: Record<string, unknown> | undefined): string[];
116
+ /**
117
+ * Whether a key name submits: Enter/Return in any spelling, alone or with
118
+ * modifiers ("Enter", "NumpadEnter", "Return", "Ctrl+Enter", "Cmd+Enter",
119
+ * "Meta+Enter", "\n").
120
+ *
121
+ * @param key - Key name as passed
122
+ * @returns True for a submitting key
123
+ */
124
+ export declare function isSubmitKey(key: string): boolean;
125
+ /**
126
+ * Whether typed text submits: it contains a newline, or the call asks to
127
+ * press Enter / submit after typing.
128
+ *
129
+ * @param params - `type` / `fill` / `insertText` params
130
+ * @returns True when the call submits
131
+ */
132
+ export declare function typedTextSubmits(params: Record<string, unknown> | undefined): boolean;
133
+ /**
134
+ * Whether a page script sends a request that writes: `sendBeacon`, an XHR
135
+ * opened with a writing method, or a `fetch` that is not provably a GET —
136
+ * a literal writing method anywhere in the script, or any options argument
137
+ * (it may carry `method: 'POST'` through a variable).
138
+ *
139
+ * @param code - Script source
140
+ * @returns True when it may write
141
+ */
142
+ export declare function scriptWritesRequest(code: string): boolean;
143
+ /**
144
+ * Whether a page script acts (rather than reads): clicks in any form,
145
+ * submits, fires events, edits content, or sends a request that writes.
146
+ *
147
+ * @param code - Script source
148
+ * @returns True when it acts
149
+ */
150
+ export declare function scriptActs(code: string): boolean;
151
+ /**
152
+ * Whether a script writes text into the page — a draft being composed.
153
+ *
154
+ * @param code - Script source
155
+ * @returns True when it edits content
156
+ */
157
+ export declare function scriptEditsContent(code: string): boolean;
158
+ /**
159
+ * The selectors a script looks elements up by (`querySelector('…')`,
160
+ * `closest('…')`, `getElementById('…')`, …). Words are matched in these
161
+ * only — never in identifiers (`x.send()` is not sending, `postCount` is not
162
+ * posting) nor in text the script writes (a draft saying "Agree.").
163
+ *
164
+ * @param code - Script source
165
+ * @returns The selectors joined with spaces
166
+ */
167
+ export declare function scriptLiterals(code: string): string;
168
+ /**
169
+ * Match the outward-facing words against a descriptor (already split into
170
+ * words at punctuation).
171
+ *
172
+ * @param words - Descriptor words
173
+ * @returns Label, or null
174
+ */
175
+ export declare function matchOutboundWords(words: string): string | null;
176
+ /**
177
+ * Decide whether an action publishes or submits something outward, beyond
178
+ * the base irreversible-word check. Returns a short label, or null.
179
+ *
180
+ * @param tool - Browser tool
181
+ * @param params - Its params
182
+ * @param context - Where it happens
183
+ * @returns Label for the hold, or null
184
+ *
185
+ * @example
186
+ * ```typescript
187
+ * matchOutbound('click', { selector: 'button.comments-comment-box__submit-button' }, { url: 'https://www.linkedin.com/feed/' });
188
+ * // 'submitting'
189
+ * matchOutbound('click', { selector: 'article[data-testid="tweet"]' }, { url: 'https://x.com/home' });
190
+ * // null — reading a tweet
191
+ * ```
192
+ */
193
+ export declare function matchOutbound(tool: string, params: Record<string, unknown> | undefined, context?: OutboundContext): string | null;
194
+ /**
195
+ * The text an action would put on the page (what a post would say), for the
196
+ * approval card. Only `type`/`fill`/`insertText` carry it directly; a script
197
+ * is shown as source. Never for a field that looks secret (password, code,
198
+ * token): the card goes to Slack.
199
+ *
200
+ * @param tool - Browser tool
201
+ * @param params - Its params
202
+ * @returns Text, or undefined
203
+ */
204
+ export declare function draftTextOf(tool: string, params: Record<string, unknown> | undefined): string | undefined;
205
+ /**
206
+ * Identity of an action for one-time approvals: an approval is spent only
207
+ * by the action the owner approved (same tool, same target, same text).
208
+ *
209
+ * @param tool - Browser tool
210
+ * @param params - Its params
211
+ * @returns Stable fingerprint
212
+ */
213
+ export declare function actionFingerprint(tool: string, params: Record<string, unknown> | undefined): string;
214
+ //# sourceMappingURL=browser-outbound-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-outbound-guard.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/browser/browser-outbound-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC/B,0EAA0E;IAC1E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAEtD;AAED;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAQtD;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,OAAO,CAelF;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,OAAO,CAQ/E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,OAAO,CAGlF;AAiBD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAIxE;AAED;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK5C;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,CAMhF;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,EAAE,CAsB9E;AAgCD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,OAAO,CAIrF;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAsBzD;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAIhD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK/D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC3C,OAAO,GAAE,eAAoB,GAC3B,MAAM,GAAG,IAAI,CA+Cf;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAYzG;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,CAMnG"}
@@ -0,0 +1,466 @@
1
+ /**
2
+ * Browser outbound guard — which agent browser actions publish something as
3
+ * the owner, so they must be held for an owner approval card.
4
+ *
5
+ * Why (2026-10-03): an agent posted a LinkedIn reply as the owner without
6
+ * approval. The existing check (`matchIrreversible`) only read a short word
7
+ * list against the agent's selector, so a LinkedIn reply went through:
8
+ * `button.comments-comment-box__submit-button` hides "submit" behind `__`
9
+ * (a word character, so `\bsubmit\b` never matched), "Reply" and "Comment"
10
+ * were not on the list, a click by coordinates or by element ref carried no
11
+ * words at all, `type` with a trailing newline and `Ctrl+Enter`/`Cmd+Enter`
12
+ * keys were not checked, and `el['click']()` in a page script was not seen
13
+ * as acting.
14
+ *
15
+ * This module closes those paths, without holding what only reads:
16
+ *
17
+ * - Descriptors are split into words at punctuation (`__submit-button` →
18
+ * "submit button"), not at camelCase (code identifiers are not controls).
19
+ * - A control whose whole label is Reply/Comment/Post/Send/Tweet (plus
20
+ * Share/Connect/Invite on social sites) is held; bare "comment"/"tweet"
21
+ * in class names (a comment item, a tweet being read) are not.
22
+ * - Any key that submits (Enter, Return, with or without modifiers) and any
23
+ * typed text containing a newline or a submit flag is held.
24
+ * - A page script is held when it acts AND sends a writing request or names
25
+ * a submit control — not for clicking "See more".
26
+ * - On social and messaging sites (LinkedIn, X, Facebook, Instagram, Reddit,
27
+ * Gmail/Outlook web, Slack web, WhatsApp web, …) a click that names no
28
+ * control (coordinates, refs) is held: there the harness cannot tell a
29
+ * "Post" from any other button.
30
+ *
31
+ * @module services/browser/browser-outbound-guard
32
+ */
33
+ import { createHash } from 'crypto';
34
+ import { BROWSER_OUTBOUND_GUARD } from '../../constants.js';
35
+ /**
36
+ * Host of a URL, lower case, '' when unknown or unparsable.
37
+ *
38
+ * @param url - URL
39
+ * @returns Host
40
+ */
41
+ export function siteOf(url) {
42
+ return hostOf(url);
43
+ }
44
+ /**
45
+ * The page an action is on, for scoping a draft: host + path + hash (Gmail
46
+ * keeps the compose/thread context in the hash). '' when unknown.
47
+ *
48
+ * @param url - URL
49
+ * @returns Page key
50
+ */
51
+ export function pageOf(url) {
52
+ if (!url)
53
+ return '';
54
+ try {
55
+ const u = new URL(url.includes('://') ? url : `https://${url}`);
56
+ return `${u.hostname.toLowerCase()}${u.pathname.replace(/\/+$/, '')}${u.hash}`;
57
+ }
58
+ catch {
59
+ return '';
60
+ }
61
+ }
62
+ /**
63
+ * Whether an input is a search field — typing a query there is not a draft:
64
+ * `type=search`, `role=searchbox`, a name of `q`/`query`/`search` (Gmail's
65
+ * `input[name="q"]`), an aria-label or placeholder naming search, or a
66
+ * `role=combobox` input. A combobox that is contenteditable or a textarea is
67
+ * a compose box (LinkedIn, X), not search.
68
+ *
69
+ * @param params - Tool params
70
+ * @returns True for a search field
71
+ */
72
+ export function isSearchField(params) {
73
+ const str = (v) => (typeof v === 'string' ? v : '');
74
+ const selector = str(params?.selector);
75
+ const role = `${str(params?.role)} ${(/\[\s*role\s*=\s*["']?([a-z]+)/i.exec(selector) ?? [])[1] ?? ''}`.toLowerCase();
76
+ const compose = /contenteditable|textarea/i.test(selector) || params?.contentEditable === true || /textarea/i.test(str(params?.tagName));
77
+ if (/combobox/.test(role) && compose)
78
+ return false;
79
+ if (/searchbox/.test(role) || /combobox/.test(role))
80
+ return true;
81
+ const name = str(params?.name) || ((/\[\s*name\s*=\s*["']?([^"'\]\s]+)/i.exec(selector) ?? [])[1] ?? '');
82
+ if (/^(q|query|search|search_query|keywords?)$/i.test(name))
83
+ return true;
84
+ if (/^search$/i.test(str(params?.type)) || /\[\s*type\s*=\s*["']?search/i.test(selector))
85
+ return true;
86
+ const labelled = [params?.ariaLabel, params?.label, params?.placeholder]
87
+ .map(str)
88
+ .join(' ');
89
+ if (/search|搜索/i.test(labelled) || /aria-label\s*=\s*["'][^"']*search/i.test(selector))
90
+ return true;
91
+ return !compose && /search|搜索/i.test(selector);
92
+ }
93
+ /**
94
+ * Whether a key press pastes (Cmd/Ctrl+V): pasting into an editable writes a
95
+ * draft the harness cannot read.
96
+ *
97
+ * @param params - pressKey params
98
+ * @returns True for a paste chord
99
+ */
100
+ export function isPasteKey(params) {
101
+ const key = typeof params?.key === 'string' ? params.key.trim() : '';
102
+ const modifiers = (Array.isArray(params?.modifiers) ? params.modifiers : [])
103
+ .filter((v) => typeof v === 'string')
104
+ .join('+');
105
+ const chord = `${modifiers}+${key}`;
106
+ const keyIsV = /(^|\+)v$/i.test(key);
107
+ return keyIsV && /(meta|cmd|command|ctrl|control)/i.test(chord);
108
+ }
109
+ /**
110
+ * Whether a key press activates a focused button or link (Space / Enter).
111
+ *
112
+ * @param params - pressKey params
113
+ * @returns True for Space or Enter
114
+ */
115
+ export function isActivateKey(params) {
116
+ const key = typeof params?.key === 'string' ? params.key : '';
117
+ return key === ' ' || /^space(bar)?$/i.test(key) || isSubmitKey(key);
118
+ }
119
+ /**
120
+ * Host of a URL, lower case, '' when it cannot be parsed.
121
+ *
122
+ * @param url - URL
123
+ * @returns Host
124
+ */
125
+ function hostOf(url) {
126
+ if (!url)
127
+ return '';
128
+ try {
129
+ return new URL(url.includes('://') ? url : `https://${url}`).hostname.toLowerCase();
130
+ }
131
+ catch {
132
+ return '';
133
+ }
134
+ }
135
+ /**
136
+ * Whether a URL is on a social or messaging site, where posting reaches
137
+ * other people as the owner.
138
+ *
139
+ * @param url - Page URL
140
+ * @returns True for a listed host or any of its subdomains
141
+ */
142
+ export function isSocialOrMessagingSite(url) {
143
+ const host = hostOf(url);
144
+ if (!host)
145
+ return false;
146
+ return BROWSER_OUTBOUND_GUARD.SOCIAL_MESSAGING_HOSTS.some((h) => host === h || host.endsWith(`.${h}`));
147
+ }
148
+ /**
149
+ * Split a selector/label/script into words at punctuation, so word-boundary
150
+ * matching sees through CSS naming (`comments-comment-box__submit-button` →
151
+ * "comments comment box submit button"). camelCase is NOT split: code
152
+ * identifiers (`postCount`, `commentsList`) are not controls.
153
+ *
154
+ * @param text - Raw descriptor
155
+ * @returns Space-separated words
156
+ */
157
+ export function toWords(text) {
158
+ return text
159
+ .replace(/[_\-.#[\]=:"'`()>+~*^$|/\\,;{}]+/g, ' ')
160
+ .replace(/\s+/g, ' ')
161
+ .trim();
162
+ }
163
+ /**
164
+ * The words that describe what a click/select names: selector, text, value,
165
+ * aria label, label, name, title.
166
+ *
167
+ * @param params - Tool params
168
+ * @returns Descriptor text ('' when the action names nothing)
169
+ */
170
+ export function descriptorOf(params) {
171
+ const fields = ['selector', 'text', 'value', 'ariaLabel', 'label', 'name', 'title'];
172
+ return fields
173
+ .map((f) => params?.[f])
174
+ .filter((v) => typeof v === 'string' && v.trim() !== '')
175
+ .join(' ');
176
+ }
177
+ /**
178
+ * Whole labels an action names: its `text`/`ariaLabel`/`label`, and labels
179
+ * quoted inside a selector (`:has-text("Reply")`, `[aria-label="Post"]`,
180
+ * `text=Send`) or a script (`b.innerText === 'Reply'`).
181
+ *
182
+ * @param params - Tool params
183
+ * @returns Labels, lower case, trimmed
184
+ */
185
+ export function labelsOf(params) {
186
+ const labels = [];
187
+ for (const f of ['text', 'ariaLabel', 'label', 'value']) {
188
+ const v = params?.[f];
189
+ if (typeof v === 'string' && v.trim())
190
+ labels.push(v);
191
+ }
192
+ for (const f of ['selector', 'code']) {
193
+ const v = params?.[f];
194
+ if (typeof v !== 'string')
195
+ continue;
196
+ // Attribute labels and text pseudo-selectors (in a selector, or a
197
+ // selector string inside a script). Not data-testid & co: those name
198
+ // what an element is (a tweet), not what a button says.
199
+ for (const m of v.matchAll(/\[\s*(?:aria-label|title|value|name|alt)\s*[*^$~|]?=\s*\\?["']([^"'\\]{1,40})\\?["']\s*\]/gi))
200
+ labels.push(m[1]);
201
+ for (const m of v.matchAll(/:(?:has-text|text|contains|text-is)\(\s*\\?["']([^"'\\]{1,40})\\?["']\s*\)/gi))
202
+ labels.push(m[1]);
203
+ const textEq = /^text\s*=\s*(.+)$/i.exec(v.trim());
204
+ if (f === 'selector' && textEq)
205
+ labels.push(textEq[1]);
206
+ if (f === 'code') {
207
+ // A script finding a button by its text: `b.innerText === 'Reply'`.
208
+ for (const m of v.matchAll(/(?:===?|includes\(|startsWith\()\s*['"`]([^'"`\n]{1,40})['"`]/g))
209
+ labels.push(m[1]);
210
+ }
211
+ }
212
+ return labels.map((l) => l.trim().toLowerCase()).filter((l) => l.length > 0);
213
+ }
214
+ /**
215
+ * Whether an action names a control whose whole label submits.
216
+ *
217
+ * @param params - Tool params
218
+ * @param social - On a social/messaging site (adds Share/Connect/…)
219
+ * @returns The label, or null
220
+ */
221
+ function submitLabel(params, social) {
222
+ const set = new Set([
223
+ ...BROWSER_OUTBOUND_GUARD.SUBMIT_LABELS,
224
+ ...(social ? BROWSER_OUTBOUND_GUARD.SOCIAL_ONLY_LABELS : []),
225
+ ]);
226
+ return labelsOf(params).find((l) => set.has(l)) ?? null;
227
+ }
228
+ /**
229
+ * What a submit label does, in the hold's words: "Send" → sending,
230
+ * "Reply"/"Comment" → replying, "Post"/"Tweet" → publishing, …
231
+ *
232
+ * @param label - Lower-case label
233
+ * @returns Short description
234
+ */
235
+ function labelCategory(label) {
236
+ const byWords = matchOutboundWords(label);
237
+ if (byWords)
238
+ return byWords;
239
+ if (/reply|comment|回复|评论/.test(label))
240
+ return 'replying';
241
+ if (/post|tweet|发布|发表/.test(label))
242
+ return 'publishing';
243
+ return 'sharing';
244
+ }
245
+ /**
246
+ * Whether a key name submits: Enter/Return in any spelling, alone or with
247
+ * modifiers ("Enter", "NumpadEnter", "Return", "Ctrl+Enter", "Cmd+Enter",
248
+ * "Meta+Enter", "\n").
249
+ *
250
+ * @param key - Key name as passed
251
+ * @returns True for a submitting key
252
+ */
253
+ export function isSubmitKey(key) {
254
+ return /enter|return/i.test(key) || /[\r\n]/.test(key);
255
+ }
256
+ /**
257
+ * Whether typed text submits: it contains a newline, or the call asks to
258
+ * press Enter / submit after typing.
259
+ *
260
+ * @param params - `type` / `fill` / `insertText` params
261
+ * @returns True when the call submits
262
+ */
263
+ export function typedTextSubmits(params) {
264
+ const text = [params?.text, params?.value].filter((v) => typeof v === 'string').join('');
265
+ if (/[\r\n]/.test(text))
266
+ return true;
267
+ return ['submit', 'pressEnter', 'enter', 'sendEnter'].some((k) => params?.[k] === true);
268
+ }
269
+ /**
270
+ * Whether a page script sends a request that writes: `sendBeacon`, an XHR
271
+ * opened with a writing method, or a `fetch` that is not provably a GET —
272
+ * a literal writing method anywhere in the script, or any options argument
273
+ * (it may carry `method: 'POST'` through a variable).
274
+ *
275
+ * @param code - Script source
276
+ * @returns True when it may write
277
+ */
278
+ export function scriptWritesRequest(code) {
279
+ if (/sendBeacon\s*\(/.test(code))
280
+ return true;
281
+ if (/\.open\s*\(\s*['"`](POST|PUT|PATCH|DELETE)['"`]/i.test(code))
282
+ return true;
283
+ if (!/\bfetch\s*\(/.test(code))
284
+ return false;
285
+ if (/method\s*:\s*['"`](POST|PUT|PATCH|DELETE)['"`]/i.test(code))
286
+ return true;
287
+ const onlyGet = /method\s*:\s*['"`]GET['"`]/i.test(code);
288
+ for (const m of code.matchAll(/\bfetch\s*\(/g)) {
289
+ // Walk the call's arguments; a top-level comma means an options argument.
290
+ let depth = 0;
291
+ for (let i = (m.index ?? 0) + m[0].length; i < code.length; i++) {
292
+ const c = code[i];
293
+ if (c === '(' || c === '[' || c === '{')
294
+ depth++;
295
+ else if (c === ')' || c === ']' || c === '}') {
296
+ if (depth === 0)
297
+ break;
298
+ depth--;
299
+ }
300
+ else if (c === ',' && depth === 0) {
301
+ if (!onlyGet)
302
+ return true;
303
+ break;
304
+ }
305
+ }
306
+ }
307
+ return false;
308
+ }
309
+ /**
310
+ * Whether a page script acts (rather than reads): clicks in any form,
311
+ * submits, fires events, edits content, or sends a request that writes.
312
+ *
313
+ * @param code - Script source
314
+ * @returns True when it acts
315
+ */
316
+ export function scriptActs(code) {
317
+ return BROWSER_OUTBOUND_GUARD.SCRIPT_ACTS.test(code)
318
+ || BROWSER_OUTBOUND_GUARD.SCRIPT_EDITS_CONTENT.test(code)
319
+ || scriptWritesRequest(code);
320
+ }
321
+ /**
322
+ * Whether a script writes text into the page — a draft being composed.
323
+ *
324
+ * @param code - Script source
325
+ * @returns True when it edits content
326
+ */
327
+ export function scriptEditsContent(code) {
328
+ return BROWSER_OUTBOUND_GUARD.SCRIPT_EDITS_CONTENT.test(code);
329
+ }
330
+ /**
331
+ * The selectors a script looks elements up by (`querySelector('…')`,
332
+ * `closest('…')`, `getElementById('…')`, …). Words are matched in these
333
+ * only — never in identifiers (`x.send()` is not sending, `postCount` is not
334
+ * posting) nor in text the script writes (a draft saying "Agree.").
335
+ *
336
+ * @param code - Script source
337
+ * @returns The selectors joined with spaces
338
+ */
339
+ export function scriptLiterals(code) {
340
+ const re = /(?:querySelector(?:All)?|closest|matches|getElementById|getElementsByClassName|getElementsByName|getElementsByTagName)\s*\(\s*(['"`])((?:\\.|(?!\1)[^\\\n])*)\1/g;
341
+ return [...code.matchAll(re)].map((m) => m[2]).join(' ');
342
+ }
343
+ /**
344
+ * Match the outward-facing words against a descriptor (already split into
345
+ * words at punctuation).
346
+ *
347
+ * @param words - Descriptor words
348
+ * @returns Label, or null
349
+ */
350
+ export function matchOutboundWords(words) {
351
+ for (const [pattern, label] of BROWSER_OUTBOUND_GUARD.OUTBOUND_WORDS) {
352
+ if (pattern.test(words))
353
+ return label;
354
+ }
355
+ return null;
356
+ }
357
+ /**
358
+ * Decide whether an action publishes or submits something outward, beyond
359
+ * the base irreversible-word check. Returns a short label, or null.
360
+ *
361
+ * @param tool - Browser tool
362
+ * @param params - Its params
363
+ * @param context - Where it happens
364
+ * @returns Label for the hold, or null
365
+ *
366
+ * @example
367
+ * ```typescript
368
+ * matchOutbound('click', { selector: 'button.comments-comment-box__submit-button' }, { url: 'https://www.linkedin.com/feed/' });
369
+ * // 'submitting'
370
+ * matchOutbound('click', { selector: 'article[data-testid="tweet"]' }, { url: 'https://x.com/home' });
371
+ * // null — reading a tweet
372
+ * ```
373
+ */
374
+ export function matchOutbound(tool, params, context = {}) {
375
+ const social = isSocialOrMessagingSite(context.url);
376
+ switch (tool) {
377
+ case 'pressKey': {
378
+ const key = [params?.key, ...(Array.isArray(params?.modifiers) ? params.modifiers : [])]
379
+ .filter((v) => typeof v === 'string')
380
+ .join('+');
381
+ return isSubmitKey(key) ? 'submitting with a keystroke' : null;
382
+ }
383
+ case 'type':
384
+ case 'fill':
385
+ case 'insertText':
386
+ return typedTextSubmits(params) ? 'submitting typed text' : null;
387
+ case 'executeJs':
388
+ case 'executeScript': {
389
+ const code = typeof params?.code === 'string' ? params.code : '';
390
+ const operation = typeof params?.operation === 'string' ? params.operation : '';
391
+ const acts = scriptActs(code) || /click|submit|press|dispatch/i.test(operation);
392
+ if (!acts)
393
+ return null;
394
+ // Acting alone is not outbound ("See more", expanding a thread):
395
+ // held when it submits a form, sends a writing request, or names a
396
+ // submit control in its strings.
397
+ if (BROWSER_OUTBOUND_GUARD.SCRIPT_SUBMITS_FORM.test(code))
398
+ return 'submitting';
399
+ const label = submitLabel(params, social);
400
+ if (label)
401
+ return labelCategory(label);
402
+ const words = matchOutboundWords(toWords(`${scriptLiterals(code)} ${descriptorOf(params)}`));
403
+ if (words)
404
+ return words;
405
+ return scriptWritesRequest(code) ? 'sending a request' : null;
406
+ }
407
+ case 'setFileInput':
408
+ return matchOutboundWords(toWords(descriptorOf(params)));
409
+ case 'click':
410
+ case 'selectOption': {
411
+ const descriptor = descriptorOf(params);
412
+ if (!descriptor) {
413
+ // Coordinates or an element ref: on a social site there is no
414
+ // telling a "Post" from any other button.
415
+ return social ? 'clicking an unnamed control on a social or messaging site' : null;
416
+ }
417
+ const label = submitLabel(params, social);
418
+ if (label)
419
+ return labelCategory(label);
420
+ return matchOutboundWords(toWords(descriptor));
421
+ }
422
+ default:
423
+ return null;
424
+ }
425
+ }
426
+ /**
427
+ * The text an action would put on the page (what a post would say), for the
428
+ * approval card. Only `type`/`fill`/`insertText` carry it directly; a script
429
+ * is shown as source. Never for a field that looks secret (password, code,
430
+ * token): the card goes to Slack.
431
+ *
432
+ * @param tool - Browser tool
433
+ * @param params - Its params
434
+ * @returns Text, or undefined
435
+ */
436
+ export function draftTextOf(tool, params) {
437
+ if (BROWSER_OUTBOUND_GUARD.SECRET_FIELD.test(toWords(descriptorOf(params))) || params?.isPassword === true) {
438
+ return undefined;
439
+ }
440
+ if (tool === 'type' || tool === 'fill' || tool === 'insertText') {
441
+ const text = [params?.text, params?.value].find((v) => typeof v === 'string' && v.trim() !== '');
442
+ return text?.trim();
443
+ }
444
+ if ((tool === 'executeJs' || tool === 'executeScript') && typeof params?.code === 'string') {
445
+ return params.code.trim();
446
+ }
447
+ return undefined;
448
+ }
449
+ /**
450
+ * Identity of an action for one-time approvals: an approval is spent only
451
+ * by the action the owner approved (same tool, same target, same text).
452
+ *
453
+ * @param tool - Browser tool
454
+ * @param params - Its params
455
+ * @returns Stable fingerprint
456
+ */
457
+ export function actionFingerprint(tool, params) {
458
+ const keys = ['selector', 'text', 'value', 'code', 'key', 'modifiers', 'x', 'y', 'ref', 'index', 'operation', 'ariaLabel', 'label', 'name'];
459
+ const picked = {};
460
+ for (const k of keys)
461
+ if (params?.[k] !== undefined)
462
+ picked[k] = params[k];
463
+ // Hashed: held actions are persisted, and their params (typed text) must not be.
464
+ return `${tool}:${createHash('sha256').update(JSON.stringify(picked)).digest('hex').slice(0, 32)}`;
465
+ }
466
+ //# sourceMappingURL=browser-outbound-guard.js.map