@runcore-sh/runcore 0.4.0 → 0.5.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 (351) hide show
  1. package/dictionary.json +2 -2
  2. package/dist/activity/log.js +2 -2
  3. package/dist/activity/log.js.map +1 -1
  4. package/dist/agents/governed-spawn.d.ts.map +1 -1
  5. package/dist/cli.js +101 -11
  6. package/dist/cli.js.map +1 -1
  7. package/dist/extensions/cache.d.ts +57 -0
  8. package/dist/extensions/cache.d.ts.map +1 -0
  9. package/dist/extensions/cache.js +173 -0
  10. package/dist/extensions/cache.js.map +1 -0
  11. package/dist/extensions/client.d.ts +55 -0
  12. package/dist/extensions/client.d.ts.map +1 -0
  13. package/dist/extensions/client.js +120 -0
  14. package/dist/extensions/client.js.map +1 -0
  15. package/dist/extensions/index.d.ts +13 -0
  16. package/dist/extensions/index.d.ts.map +1 -0
  17. package/dist/extensions/index.js +12 -0
  18. package/dist/extensions/index.js.map +1 -0
  19. package/dist/extensions/loader.d.ts +50 -0
  20. package/dist/extensions/loader.d.ts.map +1 -0
  21. package/dist/extensions/loader.js +166 -0
  22. package/dist/extensions/loader.js.map +1 -0
  23. package/dist/extensions/manifest.d.ts +38 -0
  24. package/dist/extensions/manifest.d.ts.map +1 -0
  25. package/dist/extensions/manifest.js +17 -0
  26. package/dist/extensions/manifest.js.map +1 -0
  27. package/dist/extensions/stubs.d.ts +27 -0
  28. package/dist/extensions/stubs.d.ts.map +1 -0
  29. package/dist/extensions/stubs.js +45 -0
  30. package/dist/extensions/stubs.js.map +1 -0
  31. package/dist/lib/audit.js +2 -2
  32. package/dist/lib/audit.js.map +1 -1
  33. package/dist/lib/brain-migrate.d.ts +21 -0
  34. package/dist/lib/brain-migrate.d.ts.map +1 -0
  35. package/dist/lib/brain-migrate.js +137 -0
  36. package/dist/lib/brain-migrate.js.map +1 -0
  37. package/dist/lib/paths.d.ts +27 -0
  38. package/dist/lib/paths.d.ts.map +1 -1
  39. package/dist/lib/paths.js +65 -0
  40. package/dist/lib/paths.js.map +1 -1
  41. package/dist/llm/call-log.d.ts +40 -0
  42. package/dist/llm/call-log.d.ts.map +1 -0
  43. package/dist/llm/call-log.js +35 -0
  44. package/dist/llm/call-log.js.map +1 -0
  45. package/dist/llm/complete.d.ts +6 -0
  46. package/dist/llm/complete.d.ts.map +1 -1
  47. package/dist/llm/complete.js +27 -0
  48. package/dist/llm/complete.js.map +1 -1
  49. package/dist/mcp-server.js +118 -2
  50. package/dist/mcp-server.js.map +1 -1
  51. package/dist/memory/file-backed.d.ts +4 -0
  52. package/dist/memory/file-backed.d.ts.map +1 -1
  53. package/dist/memory/file-backed.js +4 -0
  54. package/dist/memory/file-backed.js.map +1 -1
  55. package/dist/memory/vector-index.d.ts +4 -12
  56. package/dist/memory/vector-index.d.ts.map +1 -1
  57. package/dist/memory/vector-index.js +11 -93
  58. package/dist/memory/vector-index.js.map +1 -1
  59. package/dist/search/brain-docs.d.ts +17 -7
  60. package/dist/search/brain-docs.d.ts.map +1 -1
  61. package/dist/search/brain-docs.js +170 -52
  62. package/dist/search/brain-docs.js.map +1 -1
  63. package/dist/search/brain-rag.d.ts +45 -0
  64. package/dist/search/brain-rag.d.ts.map +1 -0
  65. package/dist/search/brain-rag.js +275 -0
  66. package/dist/search/brain-rag.js.map +1 -0
  67. package/dist/search/chunker.d.ts +24 -0
  68. package/dist/search/chunker.d.ts.map +1 -0
  69. package/dist/search/chunker.js +95 -0
  70. package/dist/search/chunker.js.map +1 -0
  71. package/dist/search/embedder.d.ts +16 -0
  72. package/dist/search/embedder.d.ts.map +1 -0
  73. package/dist/search/embedder.js +108 -0
  74. package/dist/search/embedder.js.map +1 -0
  75. package/dist/search/file-watcher.d.ts +11 -0
  76. package/dist/search/file-watcher.d.ts.map +1 -0
  77. package/dist/search/file-watcher.js +86 -0
  78. package/dist/search/file-watcher.js.map +1 -0
  79. package/dist/server.d.ts.map +1 -1
  80. package/dist/server.js +168 -20
  81. package/dist/server.js.map +1 -1
  82. package/dist/sessions/store.d.ts +9 -0
  83. package/dist/sessions/store.d.ts.map +1 -1
  84. package/dist/sessions/store.js.map +1 -1
  85. package/dist/settings.d.ts +26 -0
  86. package/dist/settings.d.ts.map +1 -1
  87. package/dist/settings.js +78 -2
  88. package/dist/settings.js.map +1 -1
  89. package/dist/tracing/init.d.ts +1 -1
  90. package/dist/tracing/init.d.ts.map +1 -1
  91. package/dist/utils/logger.js +2 -2
  92. package/dist/utils/logger.js.map +1 -1
  93. package/module-tiers.json +164 -0
  94. package/package.json +9 -13
  95. package/public/avatar/cache/1184385ec5522b57.mp4 +0 -0
  96. package/public/avatar/cache/1f15f6a1ebd7e439.mp4 +0 -0
  97. package/public/avatar/cache/2c7e47ff0bdeb8d1.mp4 +0 -0
  98. package/public/avatar/cache/5f308566f7abb8f2.mp4 +0 -0
  99. package/public/avatar/cache/62f9cfba848d724e.mp4 +0 -0
  100. package/public/avatar/cache/6d64e657e6bf2aab.mp4 +0 -0
  101. package/public/avatar/cache/763ad0349e0b6f26.mp4 +0 -0
  102. package/public/avatar/cache/81a516cfd461b2b9.mp4 +0 -0
  103. package/public/avatar/cache/9366de15fd6910ca.mp4 +0 -0
  104. package/public/avatar/cache/ade41a846b283895.mp4 +0 -0
  105. package/public/avatar/cache/b6066e5c65383eec.mp4 +0 -0
  106. package/public/avatar/cache/edadb75d37891fc7.mp4 +0 -0
  107. package/public/avatar/cache/f0ae159640621dd9.mp4 +0 -0
  108. package/public/avatar/cache/fc2e5419adf29d96.mp4 +0 -0
  109. package/public/index.html +379 -59
  110. package/dist/agents/autonomous.js +0 -749
  111. package/dist/agents/autonomous.js.map +0 -1
  112. package/dist/agents/commit.js +0 -113
  113. package/dist/agents/commit.js.map +0 -1
  114. package/dist/agents/continue.js +0 -158
  115. package/dist/agents/continue.js.map +0 -1
  116. package/dist/agents/cooldown.js +0 -397
  117. package/dist/agents/cooldown.js.map +0 -1
  118. package/dist/agents/dedup-guard.js +0 -131
  119. package/dist/agents/dedup-guard.js.map +0 -1
  120. package/dist/agents/feed.js +0 -176
  121. package/dist/agents/feed.js.map +0 -1
  122. package/dist/agents/governance.js +0 -292
  123. package/dist/agents/governance.js.map +0 -1
  124. package/dist/agents/governed-spawn.js +0 -192
  125. package/dist/agents/governed-spawn.js.map +0 -1
  126. package/dist/agents/heartbeat.js +0 -324
  127. package/dist/agents/heartbeat.js.map +0 -1
  128. package/dist/agents/instance-manager.js +0 -850
  129. package/dist/agents/instance-manager.js.map +0 -1
  130. package/dist/agents/issue-reporter.js +0 -123
  131. package/dist/agents/issue-reporter.js.map +0 -1
  132. package/dist/agents/issues.js +0 -141
  133. package/dist/agents/issues.js.map +0 -1
  134. package/dist/agents/locks.js +0 -234
  135. package/dist/agents/locks.js.map +0 -1
  136. package/dist/agents/memory.js +0 -93
  137. package/dist/agents/memory.js.map +0 -1
  138. package/dist/agents/monitor.js +0 -235
  139. package/dist/agents/monitor.js.map +0 -1
  140. package/dist/agents/orchestration.js +0 -715
  141. package/dist/agents/orchestration.js.map +0 -1
  142. package/dist/agents/recover.js +0 -166
  143. package/dist/agents/recover.js.map +0 -1
  144. package/dist/agents/reflection.js +0 -199
  145. package/dist/agents/reflection.js.map +0 -1
  146. package/dist/agents/runtime/bus.js +0 -174
  147. package/dist/agents/runtime/bus.js.map +0 -1
  148. package/dist/agents/runtime/config.js +0 -101
  149. package/dist/agents/runtime/config.js.map +0 -1
  150. package/dist/agents/runtime/driver.js +0 -214
  151. package/dist/agents/runtime/driver.js.map +0 -1
  152. package/dist/agents/runtime/errors.js +0 -40
  153. package/dist/agents/runtime/errors.js.map +0 -1
  154. package/dist/agents/runtime/index.js +0 -54
  155. package/dist/agents/runtime/index.js.map +0 -1
  156. package/dist/agents/runtime/lifecycle.js +0 -116
  157. package/dist/agents/runtime/lifecycle.js.map +0 -1
  158. package/dist/agents/runtime/manager.js +0 -948
  159. package/dist/agents/runtime/manager.js.map +0 -1
  160. package/dist/agents/runtime/registry.js +0 -195
  161. package/dist/agents/runtime/registry.js.map +0 -1
  162. package/dist/agents/runtime/resources.js +0 -146
  163. package/dist/agents/runtime/resources.js.map +0 -1
  164. package/dist/agents/runtime/types.js +0 -24
  165. package/dist/agents/runtime/types.js.map +0 -1
  166. package/dist/agents/spawn-policy.js +0 -202
  167. package/dist/agents/spawn-policy.js.map +0 -1
  168. package/dist/agents/spawn.js +0 -970
  169. package/dist/agents/spawn.js.map +0 -1
  170. package/dist/agents/triage.js +0 -81
  171. package/dist/agents/triage.js.map +0 -1
  172. package/dist/agents/workflow.js +0 -543
  173. package/dist/agents/workflow.js.map +0 -1
  174. package/dist/avatar/client.js +0 -172
  175. package/dist/avatar/client.js.map +0 -1
  176. package/dist/avatar/sidecar.js +0 -125
  177. package/dist/avatar/sidecar.js.map +0 -1
  178. package/dist/browser/sessions.js +0 -122
  179. package/dist/browser/sessions.js.map +0 -1
  180. package/dist/capabilities/definitions/browser.js +0 -242
  181. package/dist/capabilities/definitions/browser.js.map +0 -1
  182. package/dist/channels/whatsapp.js +0 -200
  183. package/dist/channels/whatsapp.js.map +0 -1
  184. package/dist/credentials/store.js +0 -189
  185. package/dist/credentials/store.js.map +0 -1
  186. package/dist/files/deep-index.js +0 -337
  187. package/dist/files/deep-index.js.map +0 -1
  188. package/dist/files/extract.js +0 -33
  189. package/dist/files/extract.js.map +0 -1
  190. package/dist/files/gdrive.js +0 -246
  191. package/dist/files/gdrive.js.map +0 -1
  192. package/dist/github/client.js +0 -408
  193. package/dist/github/client.js.map +0 -1
  194. package/dist/github/commit-analysis.js +0 -276
  195. package/dist/github/commit-analysis.js.map +0 -1
  196. package/dist/github/contributor-stats.js +0 -119
  197. package/dist/github/contributor-stats.js.map +0 -1
  198. package/dist/github/issue-sla.js +0 -220
  199. package/dist/github/issue-sla.js.map +0 -1
  200. package/dist/github/issue-triage.js +0 -286
  201. package/dist/github/issue-triage.js.map +0 -1
  202. package/dist/github/pr-readiness.js +0 -197
  203. package/dist/github/pr-readiness.js.map +0 -1
  204. package/dist/github/pr-review.js +0 -410
  205. package/dist/github/pr-review.js.map +0 -1
  206. package/dist/github/release-notes.js +0 -227
  207. package/dist/github/release-notes.js.map +0 -1
  208. package/dist/github/repo-health.js +0 -303
  209. package/dist/github/repo-health.js.map +0 -1
  210. package/dist/github/retry.js +0 -117
  211. package/dist/github/retry.js.map +0 -1
  212. package/dist/github/types.js +0 -8
  213. package/dist/github/types.js.map +0 -1
  214. package/dist/github/webhooks.js +0 -153
  215. package/dist/github/webhooks.js.map +0 -1
  216. package/dist/google/auth.js +0 -325
  217. package/dist/google/auth.js.map +0 -1
  218. package/dist/google/calendar-timer.js +0 -91
  219. package/dist/google/calendar-timer.js.map +0 -1
  220. package/dist/google/calendar.js +0 -270
  221. package/dist/google/calendar.js.map +0 -1
  222. package/dist/google/docs.js +0 -309
  223. package/dist/google/docs.js.map +0 -1
  224. package/dist/google/gmail-send.js +0 -219
  225. package/dist/google/gmail-send.js.map +0 -1
  226. package/dist/google/gmail-timer.js +0 -223
  227. package/dist/google/gmail-timer.js.map +0 -1
  228. package/dist/google/gmail.js +0 -470
  229. package/dist/google/gmail.js.map +0 -1
  230. package/dist/google/plugin.js +0 -169
  231. package/dist/google/plugin.js.map +0 -1
  232. package/dist/google/tasks-timer.js +0 -107
  233. package/dist/google/tasks-timer.js.map +0 -1
  234. package/dist/google/tasks.js +0 -331
  235. package/dist/google/tasks.js.map +0 -1
  236. package/dist/google/temporal.js +0 -176
  237. package/dist/google/temporal.js.map +0 -1
  238. package/dist/integrations/gate.js +0 -100
  239. package/dist/integrations/gate.js.map +0 -1
  240. package/dist/integrations/github.js +0 -331
  241. package/dist/integrations/github.js.map +0 -1
  242. package/dist/integrations/google-tasks.js +0 -432
  243. package/dist/integrations/google-tasks.js.map +0 -1
  244. package/dist/mdns.js +0 -110
  245. package/dist/mdns.js.map +0 -1
  246. package/dist/notifications/channel.js +0 -83
  247. package/dist/notifications/channel.js.map +0 -1
  248. package/dist/notifications/channels/adapter.js +0 -55
  249. package/dist/notifications/channels/adapter.js.map +0 -1
  250. package/dist/notifications/channels/index.js +0 -6
  251. package/dist/notifications/channels/index.js.map +0 -1
  252. package/dist/notifications/channels/log.js +0 -29
  253. package/dist/notifications/channels/log.js.map +0 -1
  254. package/dist/notifications/email.js +0 -72
  255. package/dist/notifications/email.js.map +0 -1
  256. package/dist/notifications/engine.js +0 -198
  257. package/dist/notifications/engine.js.map +0 -1
  258. package/dist/notifications/index.js +0 -24
  259. package/dist/notifications/index.js.map +0 -1
  260. package/dist/notifications/phone.js +0 -48
  261. package/dist/notifications/phone.js.map +0 -1
  262. package/dist/notifications/sms.js +0 -65
  263. package/dist/notifications/sms.js.map +0 -1
  264. package/dist/notifications/types.js +0 -14
  265. package/dist/notifications/types.js.map +0 -1
  266. package/dist/notifications/webhook.js +0 -65
  267. package/dist/notifications/webhook.js.map +0 -1
  268. package/dist/resend/inbox.js +0 -199
  269. package/dist/resend/inbox.js.map +0 -1
  270. package/dist/resend/webhooks.js +0 -244
  271. package/dist/resend/webhooks.js.map +0 -1
  272. package/dist/search/browse.js +0 -225
  273. package/dist/search/browse.js.map +0 -1
  274. package/dist/search/perplexity.js +0 -41
  275. package/dist/search/perplexity.js.map +0 -1
  276. package/dist/slack/channels.js +0 -277
  277. package/dist/slack/channels.js.map +0 -1
  278. package/dist/slack/client.js +0 -468
  279. package/dist/slack/client.js.map +0 -1
  280. package/dist/slack/retry.js +0 -100
  281. package/dist/slack/retry.js.map +0 -1
  282. package/dist/slack/types.js +0 -52
  283. package/dist/slack/types.js.map +0 -1
  284. package/dist/slack/webhooks.js +0 -285
  285. package/dist/slack/webhooks.js.map +0 -1
  286. package/dist/stt/client.js +0 -66
  287. package/dist/stt/client.js.map +0 -1
  288. package/dist/stt/sidecar.js +0 -115
  289. package/dist/stt/sidecar.js.map +0 -1
  290. package/dist/tracing/bridge.js +0 -70
  291. package/dist/tracing/bridge.js.map +0 -1
  292. package/dist/tracing/correlation.js +0 -49
  293. package/dist/tracing/correlation.js.map +0 -1
  294. package/dist/tracing/index.js +0 -18
  295. package/dist/tracing/index.js.map +0 -1
  296. package/dist/tracing/init.js +0 -81
  297. package/dist/tracing/init.js.map +0 -1
  298. package/dist/tracing/instrument.js +0 -145
  299. package/dist/tracing/instrument.js.map +0 -1
  300. package/dist/tracing/middleware.js +0 -69
  301. package/dist/tracing/middleware.js.map +0 -1
  302. package/dist/tracing/tracer.js +0 -327
  303. package/dist/tracing/tracer.js.map +0 -1
  304. package/dist/tts/client.js +0 -48
  305. package/dist/tts/client.js.map +0 -1
  306. package/dist/tts/sidecar.js +0 -148
  307. package/dist/tts/sidecar.js.map +0 -1
  308. package/dist/twilio/call.js +0 -79
  309. package/dist/twilio/call.js.map +0 -1
  310. package/dist/vault/matcher.js +0 -197
  311. package/dist/vault/matcher.js.map +0 -1
  312. package/dist/vault/personal.js +0 -163
  313. package/dist/vault/personal.js.map +0 -1
  314. package/dist/vault/policy.js +0 -159
  315. package/dist/vault/policy.js.map +0 -1
  316. package/dist/vault/store.js +0 -122
  317. package/dist/vault/store.js.map +0 -1
  318. package/dist/vault/transfer.js +0 -188
  319. package/dist/vault/transfer.js.map +0 -1
  320. package/dist/volumes/index.js +0 -2
  321. package/dist/volumes/index.js.map +0 -1
  322. package/dist/volumes/manager.js +0 -462
  323. package/dist/volumes/manager.js.map +0 -1
  324. package/dist/volumes/types.js +0 -8
  325. package/dist/volumes/types.js.map +0 -1
  326. package/dist/webhooks/config.js +0 -214
  327. package/dist/webhooks/config.js.map +0 -1
  328. package/dist/webhooks/event-log.js +0 -132
  329. package/dist/webhooks/event-log.js.map +0 -1
  330. package/dist/webhooks/handler.js +0 -103
  331. package/dist/webhooks/handler.js.map +0 -1
  332. package/dist/webhooks/handlers.js +0 -231
  333. package/dist/webhooks/handlers.js.map +0 -1
  334. package/dist/webhooks/index.js +0 -33
  335. package/dist/webhooks/index.js.map +0 -1
  336. package/dist/webhooks/mount.js +0 -400
  337. package/dist/webhooks/mount.js.map +0 -1
  338. package/dist/webhooks/registry.js +0 -143
  339. package/dist/webhooks/registry.js.map +0 -1
  340. package/dist/webhooks/relay.js +0 -53
  341. package/dist/webhooks/relay.js.map +0 -1
  342. package/dist/webhooks/retry.js +0 -270
  343. package/dist/webhooks/retry.js.map +0 -1
  344. package/dist/webhooks/router.js +0 -290
  345. package/dist/webhooks/router.js.map +0 -1
  346. package/dist/webhooks/twilio.js +0 -129
  347. package/dist/webhooks/twilio.js.map +0 -1
  348. package/dist/webhooks/types.js +0 -8
  349. package/dist/webhooks/types.js.map +0 -1
  350. package/dist/webhooks/verify.js +0 -154
  351. package/dist/webhooks/verify.js.map +0 -1
@@ -1,242 +0,0 @@
1
- /**
2
- * Browser capability — navigate, click, type, screenshot, extract, scroll
3
- * via Stagehand (AI-powered) + Playwright (deterministic).
4
- *
5
- * Pattern: action-block
6
- * Tag: BROWSER_ACTION
7
- *
8
- * The LLM emits [BROWSER_ACTION]{...}[/BROWSER_ACTION] blocks.
9
- * Each block specifies an `action` plus action-specific fields.
10
- *
11
- * Session management: Playwright browser contexts are persisted per-domain
12
- * as encrypted storageState JSON in brain/browser/sessions/ with 7-day expiry.
13
- */
14
- import { Stagehand } from "@browserbasehq/stagehand";
15
- import { logActivity } from "../../activity/log.js";
16
- import { pushNotification } from "../../goals/notifications.js";
17
- import { createLogger } from "../../utils/logger.js";
18
- import { saveSession, loadSession, purgeExpiredSessions } from "../../browser/sessions.js";
19
- const log = createLogger("browser");
20
- // ── Stagehand lifecycle ──────────────────────────────────────────────────────
21
- let _stagehand = null;
22
- /**
23
- * Get or create the shared Stagehand instance.
24
- * Uses LOCAL env with headless Chromium — no Browserbase dependency.
25
- */
26
- async function getStagehand() {
27
- if (_stagehand)
28
- return _stagehand;
29
- _stagehand = new Stagehand({
30
- env: "LOCAL",
31
- localBrowserLaunchOptions: { headless: true },
32
- });
33
- await _stagehand.init();
34
- log.info("Stagehand initialized (LOCAL, headless)");
35
- // Purge expired sessions on first launch
36
- purgeExpiredSessions().catch(() => { });
37
- return _stagehand;
38
- }
39
- /** Shut down the browser (called on server teardown). */
40
- export async function closeBrowser() {
41
- if (_stagehand) {
42
- await _stagehand.close();
43
- _stagehand = null;
44
- log.info("Stagehand closed");
45
- }
46
- }
47
- // ── Helpers ──────────────────────────────────────────────────────────────────
48
- function domainFromUrl(url) {
49
- try {
50
- return new URL(url).hostname;
51
- }
52
- catch {
53
- return "unknown";
54
- }
55
- }
56
- const actionLabel = (ctx) => ctx.origin === "autonomous" ? "AUTONOMOUS" : "PROMPTED";
57
- // ── Action handlers ──────────────────────────────────────────────────────────
58
- async function handleNavigate(req, ctx) {
59
- const url = req.url;
60
- if (!url)
61
- return { capabilityId: "browser", ok: false, message: "Missing required field: url" };
62
- const stagehand = await getStagehand();
63
- const domain = domainFromUrl(url);
64
- // Restore session if available
65
- const stored = await loadSession(domain);
66
- if (stored) {
67
- try {
68
- await stagehand.context.addCookies(stored.cookies ?? []);
69
- log.info(`Restored session for ${domain}`);
70
- }
71
- catch (err) {
72
- log.warn(`Failed to restore session for ${domain}`, { error: String(err) });
73
- }
74
- }
75
- const page = stagehand.context.pages()[0];
76
- await page.goto(url, { waitUntil: "domcontentloaded", timeoutMs: 30_000 });
77
- logActivity({ source: "browse", summary: `Navigated to ${url}`, actionLabel: actionLabel(ctx), reason: `browser navigate` });
78
- return { capabilityId: "browser", ok: true, message: `Navigated to ${url}` };
79
- }
80
- async function handleClick(req, ctx) {
81
- const instruction = req.instruction ?? req.selector;
82
- if (!instruction)
83
- return { capabilityId: "browser", ok: false, message: "Missing required field: instruction or selector" };
84
- const stagehand = await getStagehand();
85
- const result = await stagehand.act(`click ${instruction}`);
86
- logActivity({ source: "browse", summary: `Clicked: ${instruction}`, actionLabel: actionLabel(ctx), reason: `browser click` });
87
- return { capabilityId: "browser", ok: result.success, message: result.message ?? `Clicked: ${instruction}` };
88
- }
89
- async function handleType(req, ctx) {
90
- const instruction = req.instruction;
91
- const text = req.text;
92
- const selector = req.selector;
93
- if (!text)
94
- return { capabilityId: "browser", ok: false, message: "Missing required field: text" };
95
- const stagehand = await getStagehand();
96
- const actInstruction = instruction
97
- ?? (selector ? `type "${text}" into ${selector}` : `type "${text}" into the focused field`);
98
- const result = await stagehand.act(actInstruction);
99
- logActivity({ source: "browse", summary: `Typed into field`, actionLabel: actionLabel(ctx), reason: `browser type` });
100
- return { capabilityId: "browser", ok: result.success, message: result.message ?? `Typed text` };
101
- }
102
- async function handleScreenshot(_req, ctx) {
103
- const stagehand = await getStagehand();
104
- const page = stagehand.context.pages()[0];
105
- const buffer = await page.screenshot({ type: "png", fullPage: false });
106
- const base64 = buffer.toString("base64");
107
- logActivity({ source: "browse", summary: `Took screenshot`, actionLabel: actionLabel(ctx), reason: `browser screenshot` });
108
- return {
109
- capabilityId: "browser",
110
- ok: true,
111
- message: "Screenshot captured",
112
- data: { base64, mimeType: "image/png" },
113
- };
114
- }
115
- async function handleExtract(req, ctx) {
116
- const instruction = req.instruction;
117
- const stagehand = await getStagehand();
118
- let extracted;
119
- if (instruction) {
120
- extracted = await stagehand.extract(instruction);
121
- }
122
- else {
123
- extracted = await stagehand.extract();
124
- }
125
- logActivity({ source: "browse", summary: `Extracted content from page`, actionLabel: actionLabel(ctx), reason: `browser extract` });
126
- return {
127
- capabilityId: "browser",
128
- ok: true,
129
- message: "Content extracted",
130
- data: extracted,
131
- };
132
- }
133
- async function handleScroll(req, ctx) {
134
- const direction = req.direction ?? "down";
135
- const stagehand = await getStagehand();
136
- const result = await stagehand.act(`scroll ${direction}`);
137
- logActivity({ source: "browse", summary: `Scrolled ${direction}`, actionLabel: actionLabel(ctx), reason: `browser scroll` });
138
- return { capabilityId: "browser", ok: result.success, message: result.message ?? `Scrolled ${direction}` };
139
- }
140
- // ── Capability definition ────────────────────────────────────────────────────
141
- export const browserCapability = {
142
- id: "browser",
143
- pattern: "action",
144
- tag: "BROWSER_ACTION",
145
- keywords: ["browse", "browser", "website", "webpage", "click", "screenshot", "scrape", "navigate", "open page", "web page"],
146
- getPromptInstructions(ctx) {
147
- const name = ctx.name ?? "the user";
148
- return [
149
- `## Browser (via [BROWSER_ACTION] blocks)`,
150
- `To interact with web pages, include a [BROWSER_ACTION] block in your response.`,
151
- ``,
152
- `Navigate to a URL:`,
153
- `[BROWSER_ACTION]`,
154
- `{"action": "navigate", "url": "https://example.com"}`,
155
- `[/BROWSER_ACTION]`,
156
- ``,
157
- `Click an element (natural language):`,
158
- `[BROWSER_ACTION]`,
159
- `{"action": "click", "instruction": "the Sign In button"}`,
160
- `[/BROWSER_ACTION]`,
161
- ``,
162
- `Type text into a field:`,
163
- `[BROWSER_ACTION]`,
164
- `{"action": "type", "text": "hello world", "instruction": "the search input"}`,
165
- `[/BROWSER_ACTION]`,
166
- ``,
167
- `Take a screenshot of the current page:`,
168
- `[BROWSER_ACTION]`,
169
- `{"action": "screenshot"}`,
170
- `[/BROWSER_ACTION]`,
171
- ``,
172
- `Extract content from the page:`,
173
- `[BROWSER_ACTION]`,
174
- `{"action": "extract", "instruction": "the main article text and author"}`,
175
- `[/BROWSER_ACTION]`,
176
- ``,
177
- `Scroll the page:`,
178
- `[BROWSER_ACTION]`,
179
- `{"action": "scroll", "direction": "down"}`,
180
- `[/BROWSER_ACTION]`,
181
- ``,
182
- `Actions: navigate, click, type, screenshot, extract, scroll.`,
183
- `Sessions are persisted per domain — cookies and login state carry across requests.`,
184
- `Navigate, extract, screenshot, and scroll without confirmation — just do it and mention what you did. Confirm with ${name} before submitting forms (click on submit buttons, form POSTs).`,
185
- ].join("\n");
186
- },
187
- getPromptOverride(origin) {
188
- if (origin === "autonomous") {
189
- return [
190
- `## Browser (via [BROWSER_ACTION] blocks)`,
191
- `Navigate: {"action": "navigate", "url": "https://..."}`,
192
- `Click: {"action": "click", "instruction": "the button text"}`,
193
- `Type: {"action": "type", "text": "value", "instruction": "the input field"}`,
194
- `Screenshot: {"action": "screenshot"}`,
195
- `Extract: {"action": "extract", "instruction": "what to extract"}`,
196
- `Scroll: {"action": "scroll", "direction": "down|up"}`,
197
- `Wrap each in [BROWSER_ACTION]...[/BROWSER_ACTION].`,
198
- ].join("\n");
199
- }
200
- return null;
201
- },
202
- async execute(payload, ctx) {
203
- const req = payload;
204
- const action = req.action;
205
- try {
206
- switch (action) {
207
- case "navigate": return await handleNavigate(req, ctx);
208
- case "click": return await handleClick(req, ctx);
209
- case "type": return await handleType(req, ctx);
210
- case "screenshot": return await handleScreenshot(req, ctx);
211
- case "extract": return await handleExtract(req, ctx);
212
- case "scroll": return await handleScroll(req, ctx);
213
- default:
214
- return { capabilityId: "browser", ok: false, message: `Unknown browser action: ${action}` };
215
- }
216
- }
217
- catch (err) {
218
- const msg = err instanceof Error ? err.message : String(err);
219
- log.warn(`Browser action "${action}" failed`, { error: msg });
220
- pushNotification({ timestamp: new Date().toISOString(), source: "browse", message: `Browser action failed: ${msg}` });
221
- return { capabilityId: "browser", ok: false, message: msg };
222
- }
223
- finally {
224
- // Persist session after navigate (cookies may have changed)
225
- try {
226
- const stagehand = _stagehand;
227
- if (stagehand && action === "navigate") {
228
- const url = req.url;
229
- if (url) {
230
- const domain = domainFromUrl(url);
231
- const cookies = await stagehand.context.cookies();
232
- await saveSession(domain, { cookies });
233
- }
234
- }
235
- }
236
- catch {
237
- // Non-critical — session save failure shouldn't break the action
238
- }
239
- }
240
- },
241
- };
242
- //# sourceMappingURL=browser.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../../src/capabilities/definitions/browser.ts"],"names":[],"mappings":"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"}
@@ -1,200 +0,0 @@
1
- /**
2
- * WhatsApp messaging client via Twilio API.
3
- * Raw fetch, no SDK. Follows src/twilio/call.ts + src/slack/client.ts patterns.
4
- *
5
- * Credentials read from process.env (hydrated by vault):
6
- * - TWILIO_ACCOUNT_SID
7
- * - TWILIO_AUTH_TOKEN
8
- * - TWILIO_PHONE_NUMBER (WhatsApp-enabled sender)
9
- *
10
- * Never throws in public methods — returns { ok, data?, error? }.
11
- */
12
- import { readFile, writeFile, mkdir } from "node:fs/promises";
13
- import { join } from "node:path";
14
- import { logActivity } from "../activity/log.js";
15
- // ── Constants ────────────────────────────────────────────────────────────────
16
- const REQUIRED_VARS = [
17
- "TWILIO_ACCOUNT_SID",
18
- "TWILIO_AUTH_TOKEN",
19
- "TWILIO_PHONE_NUMBER",
20
- ];
21
- const HISTORY_DIR = "brain/channels/whatsapp";
22
- const HISTORY_FILE = "messages.jsonl";
23
- const CONTACTS_FILE = "contacts.json";
24
- // ── Lazy singleton ───────────────────────────────────────────────────────────
25
- let _client = null;
26
- let _lastSid = "";
27
- /**
28
- * Get or create the singleton WhatsApp client.
29
- * Returns null if Twilio credentials are not configured.
30
- */
31
- export function getClient() {
32
- const sid = process.env.TWILIO_ACCOUNT_SID;
33
- if (!sid)
34
- return null;
35
- if (sid !== _lastSid) {
36
- _client = new WhatsAppClient();
37
- _lastSid = sid;
38
- }
39
- return _client;
40
- }
41
- /**
42
- * Check if WhatsApp is configured (all required vault keys present).
43
- */
44
- export function isWhatsAppConfigured() {
45
- return REQUIRED_VARS.every((v) => !!process.env[v]);
46
- }
47
- // ── Client class ─────────────────────────────────────────────────────────────
48
- export class WhatsAppClient {
49
- lastErrorMessage = null;
50
- get accountSid() { return process.env.TWILIO_ACCOUNT_SID; }
51
- get authToken() { return process.env.TWILIO_AUTH_TOKEN; }
52
- get fromNumber() { return process.env.TWILIO_PHONE_NUMBER; }
53
- get auth() {
54
- return Buffer.from(`${this.accountSid}:${this.authToken}`).toString("base64");
55
- }
56
- // ── Send message ─────────────────────────────────────────────────────────
57
- /**
58
- * Send a WhatsApp message via Twilio API.
59
- * Phone numbers must include country code (e.g., +1234567890).
60
- */
61
- async sendMessage(to, body) {
62
- try {
63
- const missing = REQUIRED_VARS.filter((v) => !process.env[v]);
64
- if (missing.length > 0) {
65
- return { ok: false, message: `Missing vault keys: ${missing.join(", ")}` };
66
- }
67
- const url = `https://api.twilio.com/2010-04-01/Accounts/${this.accountSid}/Messages.json`;
68
- const params = new URLSearchParams({
69
- From: `whatsapp:${this.fromNumber}`,
70
- To: `whatsapp:${to}`,
71
- Body: body,
72
- });
73
- const res = await fetch(url, {
74
- method: "POST",
75
- headers: {
76
- Authorization: `Basic ${this.auth}`,
77
- "Content-Type": "application/x-www-form-urlencoded",
78
- },
79
- body: params.toString(),
80
- signal: AbortSignal.timeout(15_000),
81
- });
82
- if (!res.ok) {
83
- const errBody = await res.text();
84
- this.lastErrorMessage = `Twilio error (${res.status}): ${errBody}`;
85
- return { ok: false, message: this.lastErrorMessage };
86
- }
87
- const data = (await res.json());
88
- // Store outbound message in history
89
- await this.appendHistory({
90
- sid: data.sid ?? "",
91
- from: this.fromNumber,
92
- to,
93
- body,
94
- direction: "outbound",
95
- timestamp: new Date().toISOString(),
96
- });
97
- // Update contact
98
- await this.upsertContact({ phone: to, lastMessageAt: new Date().toISOString() });
99
- logActivity({
100
- source: "whatsapp",
101
- summary: `WhatsApp sent to ${to}: "${body.slice(0, 60)}"`,
102
- detail: `sid=${data.sid}`,
103
- });
104
- this.lastErrorMessage = null;
105
- return { ok: true, sid: data.sid, message: `Message sent to ${to}` };
106
- }
107
- catch (err) {
108
- this.lastErrorMessage = err.message;
109
- return { ok: false, message: `Send failed: ${err.message}` };
110
- }
111
- }
112
- // ── Contact management ───────────────────────────────────────────────────
113
- /**
114
- * List all known WhatsApp contacts.
115
- */
116
- async listContacts() {
117
- try {
118
- const filePath = join(HISTORY_DIR, CONTACTS_FILE);
119
- const raw = await readFile(filePath, "utf-8");
120
- return JSON.parse(raw);
121
- }
122
- catch {
123
- return [];
124
- }
125
- }
126
- /**
127
- * Add or update a contact.
128
- */
129
- async upsertContact(contact) {
130
- const contacts = await this.listContacts();
131
- const idx = contacts.findIndex((c) => c.phone === contact.phone);
132
- if (idx >= 0) {
133
- contacts[idx] = { ...contacts[idx], ...contact };
134
- }
135
- else {
136
- contacts.push(contact);
137
- }
138
- await mkdir(HISTORY_DIR, { recursive: true });
139
- await writeFile(join(HISTORY_DIR, CONTACTS_FILE), JSON.stringify(contacts, null, 2));
140
- }
141
- /**
142
- * Remove a contact by phone number.
143
- */
144
- async removeContact(phone) {
145
- const contacts = await this.listContacts();
146
- const filtered = contacts.filter((c) => c.phone !== phone);
147
- if (filtered.length === contacts.length)
148
- return false;
149
- await mkdir(HISTORY_DIR, { recursive: true });
150
- await writeFile(join(HISTORY_DIR, CONTACTS_FILE), JSON.stringify(filtered, null, 2));
151
- return true;
152
- }
153
- // ── Message history ──────────────────────────────────────────────────────
154
- /**
155
- * Append a message to the JSONL history file.
156
- */
157
- async appendHistory(entry) {
158
- await mkdir(HISTORY_DIR, { recursive: true });
159
- const line = JSON.stringify(entry) + "\n";
160
- const filePath = join(HISTORY_DIR, HISTORY_FILE);
161
- // Append-only — matches brain/memory JSONL pattern
162
- const { appendFile } = await import("node:fs/promises");
163
- await appendFile(filePath, line);
164
- }
165
- /**
166
- * Get message history, optionally filtered by phone number.
167
- * Returns most recent messages first.
168
- */
169
- async getHistory(opts) {
170
- try {
171
- const filePath = join(HISTORY_DIR, HISTORY_FILE);
172
- const raw = await readFile(filePath, "utf-8");
173
- let entries = raw
174
- .trim()
175
- .split("\n")
176
- .filter(Boolean)
177
- .map((line) => JSON.parse(line));
178
- if (opts?.phone) {
179
- entries = entries.filter((e) => e.from === opts.phone || e.to === opts.phone);
180
- }
181
- // Most recent first
182
- entries.reverse();
183
- if (opts?.limit && opts.limit > 0) {
184
- entries = entries.slice(0, opts.limit);
185
- }
186
- return entries;
187
- }
188
- catch {
189
- return [];
190
- }
191
- }
192
- // ── Health ───────────────────────────────────────────────────────────────
193
- getHealth() {
194
- return {
195
- available: isWhatsAppConfigured(),
196
- lastError: this.lastErrorMessage,
197
- };
198
- }
199
- }
200
- //# sourceMappingURL=whatsapp.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"whatsapp.js","sourceRoot":"","sources":["../../src/channels/whatsapp.ts"],"names":[],"mappings":"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"}
@@ -1,189 +0,0 @@
1
- /**
2
- * Credentials store — append-only encrypted JSONL persistence for secrets.
3
- * Follows ContactStore pattern (src/contacts/store.ts).
4
- *
5
- * File: brain/vault/credentials.enc.jsonl
6
- * Update strategy: append full updated record. On load, last occurrence per id wins.
7
- * Values stored directly (encrypted at rest via brain-io).
8
- */
9
- import { join } from "node:path";
10
- import { stat } from "node:fs/promises";
11
- import { createLogger } from "../utils/logger.js";
12
- import { readBrainLines, appendBrainLine, ensureBrainJsonl } from "../lib/brain-io.js";
13
- import { shouldHydrateKey } from "../integrations/gate.js";
14
- const log = createLogger("credentials.store");
15
- const SCHEMA = JSON.stringify({ _schema: "credentials", _version: "1.0" });
16
- // ── Helpers ──────────────────────────────────────────────────────────────────
17
- function generateId() {
18
- const ts = Date.now();
19
- const hex = Math.random().toString(16).slice(2, 10).padEnd(8, "0");
20
- return `cred_${ts}_${hex}`;
21
- }
22
- /** Mask a secret value: show first 4 + last 4 with **** in between, or •••••••• if short. */
23
- export function maskValue(val) {
24
- if (!val)
25
- return "••••••••";
26
- if (val.length < 12)
27
- return "••••••••";
28
- return val.slice(0, 4) + "****" + val.slice(-4);
29
- }
30
- // ── Store ────────────────────────────────────────────────────────────────────
31
- export class CredentialStore {
32
- filePath;
33
- cache = null;
34
- mtime = 0;
35
- lastStaleCheckMs = 0;
36
- constructor(brainDir) {
37
- this.filePath = join(brainDir, "vault", "credentials.enc.jsonl");
38
- }
39
- // ── File management ──────────────────────────────────────────────────────
40
- async ensureFile() {
41
- await ensureBrainJsonl(this.filePath, SCHEMA);
42
- }
43
- async checkStale() {
44
- const now = Date.now();
45
- if (now - this.lastStaleCheckMs < 5000)
46
- return;
47
- this.lastStaleCheckMs = now;
48
- try {
49
- if (this.cache) {
50
- const s = await stat(this.filePath);
51
- if (s.mtimeMs > this.mtime)
52
- this.cache = null;
53
- }
54
- }
55
- catch {
56
- // File may not exist yet
57
- }
58
- }
59
- // ── Load ────────────────────────────────────────────────────────────────
60
- async load() {
61
- await this.checkStale();
62
- if (this.cache)
63
- return this.cache;
64
- await this.ensureFile();
65
- const lines = await readBrainLines(this.filePath);
66
- const map = new Map();
67
- for (const line of lines) {
68
- try {
69
- const obj = JSON.parse(line);
70
- if (obj._schema)
71
- continue;
72
- if (!obj.id)
73
- continue;
74
- map.set(obj.id, obj);
75
- }
76
- catch {
77
- continue;
78
- }
79
- }
80
- this.cache = map;
81
- try {
82
- const s = await stat(this.filePath);
83
- this.mtime = s.mtimeMs;
84
- }
85
- catch { /* ok */ }
86
- return map;
87
- }
88
- invalidate() { this.cache = null; }
89
- // ── CRUD ────────────────────────────────────────────────────────────────
90
- async list(filter) {
91
- const map = await this.load();
92
- let creds = Array.from(map.values());
93
- if (filter?.type) {
94
- creds = creds.filter((c) => c.type === filter.type);
95
- }
96
- if (filter?.status) {
97
- creds = creds.filter((c) => c.status === filter.status);
98
- }
99
- else {
100
- creds = creds.filter((c) => c.status !== "archived");
101
- }
102
- if (filter?.search) {
103
- const q = filter.search.toLowerCase();
104
- creds = creds.filter((c) => c.name.toLowerCase().includes(q) ||
105
- c.service.toLowerCase().includes(q) ||
106
- c.tags.some((t) => t.toLowerCase().includes(q)));
107
- }
108
- creds.sort((a, b) => a.service.localeCompare(b.service) || a.name.localeCompare(b.name));
109
- return creds;
110
- }
111
- async get(id) {
112
- const map = await this.load();
113
- return map.get(id) ?? null;
114
- }
115
- async create(opts) {
116
- const now = new Date().toISOString();
117
- const cred = {
118
- id: generateId(),
119
- name: opts.name,
120
- service: opts.service,
121
- type: opts.type,
122
- value: opts.value,
123
- envVar: opts.envVar,
124
- notes: opts.notes,
125
- tags: opts.tags ?? [],
126
- status: "active",
127
- createdAt: now,
128
- updatedAt: now,
129
- };
130
- await appendBrainLine(this.filePath, JSON.stringify(cred));
131
- this.invalidate();
132
- log.info(`Created credential ${cred.id}: ${cred.name} (${cred.service})`);
133
- return cred;
134
- }
135
- async update(id, changes) {
136
- const existing = await this.get(id);
137
- if (!existing)
138
- return null;
139
- const updated = {
140
- ...existing,
141
- ...changes,
142
- updatedAt: new Date().toISOString(),
143
- };
144
- await appendBrainLine(this.filePath, JSON.stringify(updated));
145
- this.invalidate();
146
- log.info(`Updated credential ${id}: ${updated.name}`);
147
- return updated;
148
- }
149
- async archive(id) {
150
- return this.update(id, { status: "archived" });
151
- }
152
- // ── Hydrate ─────────────────────────────────────────────────────────────
153
- /** Inject credentials with envVar into process.env, filtered by integration gate. */
154
- async hydrate() {
155
- const map = await this.load();
156
- let count = 0;
157
- let skipped = 0;
158
- for (const cred of map.values()) {
159
- if (cred.status === "active" && cred.envVar && cred.value) {
160
- if (shouldHydrateKey(cred.envVar)) {
161
- process.env[cred.envVar] = cred.value;
162
- count++;
163
- }
164
- else {
165
- // Actively remove blocked keys from process.env
166
- delete process.env[cred.envVar];
167
- skipped++;
168
- }
169
- }
170
- }
171
- if (count > 0)
172
- log.info(`Hydrated ${count} credential(s) into process.env`);
173
- if (skipped > 0)
174
- log.info(`Skipped ${skipped} credential(s) — integration disabled`);
175
- return count;
176
- }
177
- }
178
- // ── Singleton ──────────────────────────────────────────────────────────────
179
- let _store = null;
180
- export function createCredentialStore(brainDir) {
181
- if (_store)
182
- return _store;
183
- _store = new CredentialStore(brainDir);
184
- return _store;
185
- }
186
- export function getCredentialStore() {
187
- return _store;
188
- }
189
- //# sourceMappingURL=store.js.map