@xingular/harness 0.1.6 → 1.0.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 (593) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE.md +60 -0
  4. package/README.md +265 -71
  5. package/THIRD_PARTY_LICENSES.md +942 -0
  6. package/dist/cli.js +14842 -9445
  7. package/dist/sdk/accounts/accounts.d.ts +165 -0
  8. package/dist/sdk/accounts/accounts.js +730 -0
  9. package/dist/sdk/accounts/choices.d.ts +23 -0
  10. package/dist/sdk/accounts/choices.js +62 -0
  11. package/dist/sdk/accounts/env.d.ts +78 -0
  12. package/dist/sdk/accounts/env.js +294 -0
  13. package/dist/sdk/accounts/secrets.d.ts +16 -0
  14. package/dist/sdk/accounts/secrets.js +40 -0
  15. package/dist/sdk/accounts/store.d.ts +114 -0
  16. package/dist/sdk/accounts/store.js +255 -0
  17. package/dist/sdk/browser/config.d.ts +16 -0
  18. package/dist/sdk/browser/config.js +22 -0
  19. package/dist/sdk/browser/diagnostics.d.ts +4 -0
  20. package/dist/sdk/browser/diagnostics.js +38 -0
  21. package/dist/sdk/browser/index.d.ts +17 -0
  22. package/dist/sdk/browser/index.js +65 -0
  23. package/dist/sdk/browser/network.d.ts +10 -0
  24. package/dist/sdk/browser/network.js +59 -0
  25. package/dist/sdk/browser/session.d.ts +84 -0
  26. package/dist/sdk/browser/session.js +192 -0
  27. package/dist/sdk/browser/tools.d.ts +8 -0
  28. package/dist/sdk/browser/tools.js +329 -0
  29. package/dist/sdk/capabilities/api.d.ts +22 -0
  30. package/dist/sdk/capabilities/api.js +54 -0
  31. package/dist/sdk/capabilities/runSnapshot.d.ts +18 -0
  32. package/dist/sdk/capabilities/runSnapshot.js +47 -0
  33. package/dist/sdk/capabilities/types.d.ts +29 -0
  34. package/dist/sdk/capabilities/types.js +1 -0
  35. package/dist/sdk/cli.d.ts +2 -0
  36. package/dist/sdk/cli.js +142 -0
  37. package/dist/sdk/core/bus.d.ts +23 -0
  38. package/dist/sdk/core/bus.js +76 -0
  39. package/dist/sdk/core/caller.d.ts +22 -0
  40. package/dist/sdk/core/caller.js +16 -0
  41. package/dist/sdk/core/changes.d.ts +15 -0
  42. package/dist/sdk/core/changes.js +15 -0
  43. package/dist/sdk/core/effort.d.ts +2 -0
  44. package/dist/sdk/core/effort.js +1 -0
  45. package/dist/sdk/core/env.d.ts +18 -0
  46. package/dist/sdk/core/env.js +8 -0
  47. package/dist/sdk/core/errors.d.ts +15 -0
  48. package/dist/sdk/core/errors.js +24 -0
  49. package/dist/sdk/core/frontmatter.d.ts +12 -0
  50. package/dist/sdk/core/frontmatter.js +50 -0
  51. package/dist/sdk/core/fs.d.ts +18 -0
  52. package/dist/sdk/core/fs.js +106 -0
  53. package/dist/sdk/core/index.d.ts +24 -0
  54. package/dist/sdk/core/index.js +187 -0
  55. package/dist/sdk/core/path.d.ts +7 -0
  56. package/dist/sdk/core/path.js +79 -0
  57. package/dist/sdk/core/projects.d.ts +18 -0
  58. package/dist/sdk/core/projects.js +67 -0
  59. package/dist/sdk/core/secrets.d.ts +2 -0
  60. package/dist/sdk/core/secrets.js +5 -0
  61. package/dist/sdk/core/text.d.ts +7 -0
  62. package/dist/sdk/core/text.js +40 -0
  63. package/dist/sdk/doctor/checks.d.ts +5 -0
  64. package/dist/sdk/doctor/checks.js +208 -0
  65. package/dist/sdk/doctor/probe.d.ts +4 -0
  66. package/dist/sdk/doctor/probe.js +92 -0
  67. package/dist/sdk/doctor/service.d.ts +23 -0
  68. package/dist/sdk/doctor/service.js +144 -0
  69. package/dist/sdk/doctor/types.d.ts +141 -0
  70. package/dist/sdk/doctor/types.js +29 -0
  71. package/dist/sdk/harness.d.ts +133 -0
  72. package/dist/sdk/harness.js +299 -0
  73. package/dist/sdk/history/lessonPrompt.d.ts +2 -0
  74. package/dist/sdk/history/lessonPrompt.js +15 -0
  75. package/dist/sdk/history/lessons.d.ts +52 -0
  76. package/dist/sdk/history/lessons.js +173 -0
  77. package/dist/sdk/history/recall.d.ts +68 -0
  78. package/dist/sdk/history/recall.js +199 -0
  79. package/dist/sdk/history/trajectory.d.ts +7 -0
  80. package/dist/sdk/history/trajectory.js +216 -0
  81. package/dist/sdk/hub/catalog.json +123 -0
  82. package/dist/sdk/hub/cli.d.ts +7 -0
  83. package/dist/sdk/hub/cli.js +81 -0
  84. package/dist/sdk/hub/hub.d.ts +74 -0
  85. package/dist/sdk/hub/hub.js +474 -0
  86. package/dist/sdk/hub/schema.d.ts +280 -0
  87. package/dist/sdk/hub/schema.js +78 -0
  88. package/dist/sdk/index.d.ts +63 -0
  89. package/dist/sdk/index.js +48 -0
  90. package/dist/sdk/mcp/connections.d.ts +83 -0
  91. package/dist/sdk/mcp/connections.js +669 -0
  92. package/dist/sdk/mcp/manager.d.ts +26 -0
  93. package/dist/sdk/mcp/manager.js +124 -0
  94. package/dist/sdk/mcp/oauth.d.ts +35 -0
  95. package/dist/sdk/mcp/oauth.js +171 -0
  96. package/dist/sdk/mcp/scopeMigration.d.ts +19 -0
  97. package/dist/sdk/mcp/scopeMigration.js +198 -0
  98. package/dist/sdk/mcp/service.d.ts +160 -0
  99. package/dist/sdk/mcp/service.js +510 -0
  100. package/dist/sdk/mcp/types.d.ts +131 -0
  101. package/dist/sdk/mcp/types.js +49 -0
  102. package/dist/sdk/pi/runtime.d.ts +13 -0
  103. package/dist/sdk/pi/runtime.js +31 -0
  104. package/dist/sdk/plugins/api.d.ts +66 -0
  105. package/dist/sdk/plugins/api.js +155 -0
  106. package/dist/sdk/plugins/attachments.d.ts +46 -0
  107. package/dist/sdk/plugins/attachments.js +111 -0
  108. package/dist/sdk/plugins/builtin.d.ts +6 -0
  109. package/dist/sdk/plugins/builtin.js +68 -0
  110. package/dist/sdk/plugins/catalogue.d.ts +29 -0
  111. package/dist/sdk/plugins/catalogue.js +196 -0
  112. package/dist/sdk/plugins/cli.d.ts +13 -0
  113. package/dist/sdk/plugins/cli.js +187 -0
  114. package/dist/sdk/plugins/discover.d.ts +42 -0
  115. package/dist/sdk/plugins/discover.js +115 -0
  116. package/dist/sdk/plugins/firstParty.d.ts +50 -0
  117. package/dist/sdk/plugins/firstParty.js +113 -0
  118. package/dist/sdk/plugins/hooks.d.ts +94 -0
  119. package/dist/sdk/plugins/hooks.js +162 -0
  120. package/dist/sdk/plugins/identity.d.ts +19 -0
  121. package/dist/sdk/plugins/identity.js +48 -0
  122. package/dist/sdk/plugins/install.d.ts +20 -0
  123. package/dist/sdk/plugins/install.js +110 -0
  124. package/dist/sdk/plugins/inventory.d.ts +22 -0
  125. package/dist/sdk/plugins/inventory.js +110 -0
  126. package/dist/sdk/plugins/manifest.d.ts +13 -0
  127. package/dist/sdk/plugins/manifest.js +56 -0
  128. package/dist/sdk/plugins/plugins.d.ts +104 -0
  129. package/dist/sdk/plugins/plugins.js +164 -0
  130. package/dist/sdk/plugins/runtime.d.ts +9 -0
  131. package/dist/sdk/plugins/runtime.js +95 -0
  132. package/dist/sdk/plugins/trust.d.ts +44 -0
  133. package/dist/sdk/plugins/trust.js +120 -0
  134. package/dist/sdk/plugins/types.d.ts +159 -0
  135. package/dist/sdk/plugins/types.js +7 -0
  136. package/dist/sdk/prompt/compile.d.ts +174 -0
  137. package/dist/sdk/prompt/compile.js +396 -0
  138. package/dist/sdk/refine/cli.d.ts +4 -0
  139. package/dist/sdk/refine/cli.js +186 -0
  140. package/dist/sdk/refine/demo.d.ts +21 -0
  141. package/dist/sdk/refine/demo.js +114 -0
  142. package/dist/sdk/refine/evidence.d.ts +55 -0
  143. package/dist/sdk/refine/evidence.js +330 -0
  144. package/dist/sdk/refine/host.d.ts +51 -0
  145. package/dist/sdk/refine/host.js +76 -0
  146. package/dist/sdk/refine/ledger.d.ts +48 -0
  147. package/dist/sdk/refine/ledger.js +76 -0
  148. package/dist/sdk/refine/library.d.ts +55 -0
  149. package/dist/sdk/refine/library.js +177 -0
  150. package/dist/sdk/refine/pi.d.ts +72 -0
  151. package/dist/sdk/refine/pi.js +248 -0
  152. package/dist/sdk/refine/prompts.d.ts +45 -0
  153. package/dist/sdk/refine/prompts.js +390 -0
  154. package/dist/sdk/refine/recursion.d.ts +113 -0
  155. package/dist/sdk/refine/recursion.js +258 -0
  156. package/dist/sdk/refine/runner.d.ts +81 -0
  157. package/dist/sdk/refine/runner.js +150 -0
  158. package/dist/sdk/refine/selection.d.ts +57 -0
  159. package/dist/sdk/refine/selection.js +251 -0
  160. package/dist/sdk/refine/service.d.ts +84 -0
  161. package/dist/sdk/refine/service.js +165 -0
  162. package/dist/sdk/refine/suite.d.ts +67 -0
  163. package/dist/sdk/refine/suite.js +174 -0
  164. package/dist/sdk/refine/trajectory.d.ts +9 -0
  165. package/dist/sdk/refine/trajectory.js +68 -0
  166. package/dist/sdk/refine/types.d.ts +77 -0
  167. package/dist/sdk/refine/types.js +10 -0
  168. package/dist/sdk/server/methods.d.ts +3 -0
  169. package/dist/sdk/server/methods.js +370 -0
  170. package/dist/sdk/server/remote.d.ts +19 -0
  171. package/dist/sdk/server/remote.js +84 -0
  172. package/dist/sdk/server/rpc.d.ts +20 -0
  173. package/dist/sdk/server/rpc.js +102 -0
  174. package/dist/sdk/server/serve.d.ts +10 -0
  175. package/dist/sdk/server/serve.js +18 -0
  176. package/dist/sdk/sessions/approvals.d.ts +47 -0
  177. package/dist/sdk/sessions/approvals.js +119 -0
  178. package/dist/sdk/sessions/continuation.d.ts +48 -0
  179. package/dist/sdk/sessions/continuation.js +85 -0
  180. package/dist/sdk/sessions/contracts.d.ts +534 -0
  181. package/dist/sdk/sessions/contracts.js +299 -0
  182. package/dist/sdk/sessions/extensionUi.d.ts +19 -0
  183. package/dist/sdk/sessions/extensionUi.js +64 -0
  184. package/dist/sdk/sessions/history.d.ts +16 -0
  185. package/dist/sdk/sessions/history.js +68 -0
  186. package/dist/sdk/sessions/lineageJoin.d.ts +2 -0
  187. package/dist/sdk/sessions/lineageJoin.js +61 -0
  188. package/dist/sdk/sessions/planMode.d.ts +36 -0
  189. package/dist/sdk/sessions/planMode.js +84 -0
  190. package/dist/sdk/sessions/policy.d.ts +43 -0
  191. package/dist/sdk/sessions/policy.js +1 -0
  192. package/dist/sdk/sessions/pricing.d.ts +34 -0
  193. package/dist/sdk/sessions/pricing.js +40 -0
  194. package/dist/sdk/sessions/reasoningSummaries.d.ts +11 -0
  195. package/dist/sdk/sessions/reasoningSummaries.js +61 -0
  196. package/dist/sdk/sessions/registry.d.ts +102 -0
  197. package/dist/sdk/sessions/registry.js +383 -0
  198. package/dist/sdk/sessions/runIndex.d.ts +21 -0
  199. package/dist/sdk/sessions/runIndex.js +65 -0
  200. package/dist/sdk/sessions/runStore.d.ts +66 -0
  201. package/dist/sdk/sessions/runStore.js +335 -0
  202. package/dist/sdk/sessions/runner.d.ts +213 -0
  203. package/dist/sdk/sessions/runner.js +589 -0
  204. package/dist/sdk/sessions/sessions.d.ts +140 -0
  205. package/dist/sdk/sessions/sessions.js +394 -0
  206. package/dist/sdk/sessions/subagentService.d.ts +41 -0
  207. package/dist/sdk/sessions/subagentService.js +247 -0
  208. package/dist/sdk/sessions/subagents.d.ts +50 -0
  209. package/dist/sdk/sessions/subagents.js +68 -0
  210. package/dist/sdk/terminal/accountsMenu.d.ts +46 -0
  211. package/dist/sdk/terminal/accountsMenu.js +392 -0
  212. package/dist/sdk/terminal/cli.d.ts +20 -0
  213. package/dist/sdk/terminal/cli.js +121 -0
  214. package/dist/sdk/terminal/client.d.ts +15 -0
  215. package/dist/sdk/terminal/client.js +126 -0
  216. package/dist/sdk/terminal/control.d.ts +4 -0
  217. package/dist/sdk/terminal/control.js +25 -0
  218. package/dist/sdk/terminal/controller.d.ts +72 -0
  219. package/dist/sdk/terminal/controller.js +351 -0
  220. package/dist/sdk/terminal/hubMenu.d.ts +10 -0
  221. package/dist/sdk/terminal/hubMenu.js +34 -0
  222. package/dist/sdk/terminal/launch.d.ts +5 -0
  223. package/dist/sdk/terminal/launch.js +27 -0
  224. package/dist/sdk/terminal/logs.d.ts +14 -0
  225. package/dist/sdk/terminal/logs.js +59 -0
  226. package/dist/sdk/terminal/piExtension.d.ts +6 -0
  227. package/dist/sdk/terminal/piExtension.js +392 -0
  228. package/dist/sdk/terminal/pluginMenu.d.ts +34 -0
  229. package/dist/sdk/terminal/pluginMenu.js +101 -0
  230. package/dist/sdk/terminal/socket.d.ts +70 -0
  231. package/dist/sdk/terminal/socket.js +256 -0
  232. package/dist/sdk/terminal/standalone.d.ts +18 -0
  233. package/dist/sdk/terminal/standalone.js +146 -0
  234. package/dist/sdk/terminal/terminals.d.ts +176 -0
  235. package/dist/sdk/terminal/terminals.js +767 -0
  236. package/dist/sdk/terminal/trajectory.d.ts +10 -0
  237. package/dist/sdk/terminal/trajectory.js +30 -0
  238. package/dist/sdk/terminal/tui/chrome.d.ts +64 -0
  239. package/dist/sdk/terminal/tui/chrome.js +169 -0
  240. package/dist/sdk/terminal/tui/clipboardFiles.d.ts +11 -0
  241. package/dist/sdk/terminal/tui/clipboardFiles.js +74 -0
  242. package/dist/sdk/terminal/tui/commandPages.d.ts +7 -0
  243. package/dist/sdk/terminal/tui/commandPages.js +63 -0
  244. package/dist/sdk/terminal/tui/commands.d.ts +42 -0
  245. package/dist/sdk/terminal/tui/commands.js +276 -0
  246. package/dist/sdk/terminal/tui/dialogGeometry.d.ts +27 -0
  247. package/dist/sdk/terminal/tui/dialogGeometry.js +50 -0
  248. package/dist/sdk/terminal/tui/dialogs.d.ts +75 -0
  249. package/dist/sdk/terminal/tui/dialogs.js +363 -0
  250. package/dist/sdk/terminal/tui/keybindings.d.ts +11 -0
  251. package/dist/sdk/terminal/tui/keybindings.js +49 -0
  252. package/dist/sdk/terminal/tui/list.d.ts +73 -0
  253. package/dist/sdk/terminal/tui/list.js +196 -0
  254. package/dist/sdk/terminal/tui/modeChoices.d.ts +42 -0
  255. package/dist/sdk/terminal/tui/modeChoices.js +70 -0
  256. package/dist/sdk/terminal/tui/modelPicker.d.ts +55 -0
  257. package/dist/sdk/terminal/tui/modelPicker.js +155 -0
  258. package/dist/sdk/terminal/tui/mouse.d.ts +3 -0
  259. package/dist/sdk/terminal/tui/mouse.js +3 -0
  260. package/dist/sdk/terminal/tui/page.d.ts +14 -0
  261. package/dist/sdk/terminal/tui/page.js +1 -0
  262. package/dist/sdk/terminal/tui/pageOverlay.d.ts +27 -0
  263. package/dist/sdk/terminal/tui/pageOverlay.js +145 -0
  264. package/dist/sdk/terminal/tui/pages/accountsPage.d.ts +54 -0
  265. package/dist/sdk/terminal/tui/pages/accountsPage.js +181 -0
  266. package/dist/sdk/terminal/tui/pages/componentsPage.d.ts +47 -0
  267. package/dist/sdk/terminal/tui/pages/componentsPage.js +119 -0
  268. package/dist/sdk/terminal/tui/pages/doctorPage.d.ts +37 -0
  269. package/dist/sdk/terminal/tui/pages/doctorPage.js +145 -0
  270. package/dist/sdk/terminal/tui/pages/hubPage.d.ts +39 -0
  271. package/dist/sdk/terminal/tui/pages/hubPage.js +128 -0
  272. package/dist/sdk/terminal/tui/pages/logPage.d.ts +38 -0
  273. package/dist/sdk/terminal/tui/pages/logPage.js +189 -0
  274. package/dist/sdk/terminal/tui/pages/permissionsPage.d.ts +44 -0
  275. package/dist/sdk/terminal/tui/pages/permissionsPage.js +124 -0
  276. package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +57 -0
  277. package/dist/sdk/terminal/tui/pages/pluginsPage.js +243 -0
  278. package/dist/sdk/terminal/tui/pages/settingsPage.d.ts +55 -0
  279. package/dist/sdk/terminal/tui/pages/settingsPage.js +88 -0
  280. package/dist/sdk/terminal/tui/pages/trajectoryPage.d.ts +58 -0
  281. package/dist/sdk/terminal/tui/pages/trajectoryPage.js +377 -0
  282. package/dist/sdk/terminal/tui/piAdapter.d.ts +18 -0
  283. package/dist/sdk/terminal/tui/piAdapter.js +48 -0
  284. package/dist/sdk/terminal/tui/planMode.d.ts +2 -0
  285. package/dist/sdk/terminal/tui/planMode.js +2 -0
  286. package/dist/sdk/terminal/tui/questionPicker.d.ts +20 -0
  287. package/dist/sdk/terminal/tui/questionPicker.js +150 -0
  288. package/dist/sdk/terminal/tui/questions.d.ts +19 -0
  289. package/dist/sdk/terminal/tui/questions.js +42 -0
  290. package/dist/sdk/terminal/tui/runtime.d.ts +114 -0
  291. package/dist/sdk/terminal/tui/runtime.js +441 -0
  292. package/dist/sdk/terminal/tui/search.d.ts +22 -0
  293. package/dist/sdk/terminal/tui/search.js +60 -0
  294. package/dist/sdk/terminal/tui/selection.d.ts +16 -0
  295. package/dist/sdk/terminal/tui/selection.js +16 -0
  296. package/dist/sdk/terminal/tui/sessionUi.d.ts +3 -0
  297. package/dist/sdk/terminal/tui/sessionUi.js +30 -0
  298. package/dist/sdk/terminal/tui/settingsModel.d.ts +12 -0
  299. package/dist/sdk/terminal/tui/settingsModel.js +84 -0
  300. package/dist/sdk/terminal/tui/sideQuestion.d.ts +53 -0
  301. package/dist/sdk/terminal/tui/sideQuestion.js +197 -0
  302. package/dist/sdk/terminal/tui/skillInvocation.d.ts +9 -0
  303. package/dist/sdk/terminal/tui/skillInvocation.js +43 -0
  304. package/dist/sdk/terminal/tui/status.d.ts +18 -0
  305. package/dist/sdk/terminal/tui/status.js +67 -0
  306. package/dist/sdk/terminal/tui/theme.d.ts +45 -0
  307. package/dist/sdk/terminal/tui/theme.js +176 -0
  308. package/dist/sdk/terminal/tui/treeModel.d.ts +79 -0
  309. package/dist/sdk/terminal/tui/treeModel.js +483 -0
  310. package/dist/sdk/terminal/tui/treePicker.d.ts +49 -0
  311. package/dist/sdk/terminal/tui/treePicker.js +251 -0
  312. package/dist/sdk/terminal/tui/ui.d.ts +47 -0
  313. package/dist/sdk/terminal/tui/ui.js +148 -0
  314. package/dist/sdk/terminal/tui/workingStatus.d.ts +9 -0
  315. package/dist/sdk/terminal/tui/workingStatus.js +229 -0
  316. package/dist/sdk/tools/askUser.d.ts +6 -0
  317. package/dist/sdk/tools/askUser.js +74 -0
  318. package/dist/sdk/tools/checklist.d.ts +9 -0
  319. package/dist/sdk/tools/checklist.js +54 -0
  320. package/dist/sdk/tools/definitions.d.ts +30 -0
  321. package/dist/sdk/tools/definitions.js +117 -0
  322. package/dist/sdk/tools/dispatch.d.ts +16 -0
  323. package/dist/sdk/tools/dispatch.js +67 -0
  324. package/dist/sdk/tools/harnessTools.d.ts +6 -0
  325. package/dist/sdk/tools/harnessTools.js +20 -0
  326. package/dist/sdk/tools/sessionName.d.ts +7 -0
  327. package/dist/sdk/tools/sessionName.js +31 -0
  328. package/dist/sdk/tools/spawnSubagent.d.ts +4 -0
  329. package/dist/sdk/tools/spawnSubagent.js +49 -0
  330. package/dist/sdk/tools/types.d.ts +48 -0
  331. package/dist/sdk/tools/types.js +1 -0
  332. package/dist/sdk/variant/components.d.ts +34 -0
  333. package/dist/sdk/variant/components.js +230 -0
  334. package/dist/sdk/variant/materialise.d.ts +66 -0
  335. package/dist/sdk/variant/materialise.js +81 -0
  336. package/dist/sdk/variant/migrate.d.ts +4 -0
  337. package/dist/sdk/variant/migrate.js +41 -0
  338. package/dist/sdk/variant/seed.d.ts +20 -0
  339. package/dist/sdk/variant/seed.js +116 -0
  340. package/dist/sdk/variant/store.d.ts +82 -0
  341. package/dist/sdk/variant/store.js +151 -0
  342. package/dist/sdk/variant/surface.d.ts +56 -0
  343. package/dist/sdk/variant/surface.js +81 -0
  344. package/dist/sdk/variant/trust.d.ts +27 -0
  345. package/dist/sdk/variant/trust.js +64 -0
  346. package/dist/sdk/variant/variant.d.ts +71 -0
  347. package/dist/sdk/variant/variant.js +331 -0
  348. package/dist/sdk/web/markdown.d.ts +10 -0
  349. package/dist/sdk/web/markdown.js +66 -0
  350. package/dist/sdk/web/safeRequest.d.ts +34 -0
  351. package/dist/sdk/web/safeRequest.js +175 -0
  352. package/dist/sdk/web/search.d.ts +53 -0
  353. package/dist/sdk/web/search.js +168 -0
  354. package/dist/sdk/web/text.d.ts +2 -0
  355. package/dist/sdk/web/text.js +7 -0
  356. package/dist/sdk/web/tools.d.ts +22 -0
  357. package/dist/sdk/web/tools.js +195 -0
  358. package/dist/sdk/web/turndown-plugin-gfm.d.ts +4 -0
  359. package/dist/sdk/wiki/notes.d.ts +68 -0
  360. package/dist/sdk/wiki/notes.js +297 -0
  361. package/dist/sdk/world/actions.d.ts +23 -0
  362. package/dist/sdk/world/actions.js +31 -0
  363. package/dist/sdk/world/cli.d.ts +12 -0
  364. package/dist/sdk/world/cli.js +166 -0
  365. package/dist/sdk/world/images.d.ts +20 -0
  366. package/dist/sdk/world/images.js +48 -0
  367. package/dist/sdk/world/untrusted.d.ts +12 -0
  368. package/dist/sdk/world/untrusted.js +20 -0
  369. package/dist/sdk/world/world.d.ts +65 -0
  370. package/dist/sdk/world/world.js +80 -0
  371. package/dist/terminal-opentui.js +13612 -0
  372. package/dist/terminal-pi.js +1170 -62
  373. package/docs/README.md +34 -0
  374. package/docs/architecture/00-overview.md +159 -0
  375. package/docs/architecture/01-extension-points.md +78 -0
  376. package/docs/architecture/02-sessions-and-runs.md +146 -0
  377. package/docs/architecture/03-variants.md +95 -0
  378. package/docs/architecture/04-prompt.md +102 -0
  379. package/docs/architecture/05-refinement.md +107 -0
  380. package/docs/architecture/06-plugins-and-capabilities.md +93 -0
  381. package/docs/architecture/07-tools-and-gate.md +88 -0
  382. package/docs/architecture/08-memory-and-history.md +94 -0
  383. package/docs/architecture/09-accounts-and-connectors.md +90 -0
  384. package/docs/architecture/10-server-protocol.md +84 -0
  385. package/docs/architecture/11-terminal.md +81 -0
  386. package/docs/architecture/12-storage.md +61 -0
  387. package/docs/architecture/13-world-tools.md +23 -0
  388. package/docs/architecture/README.md +114 -0
  389. package/docs/architecture/proposals/PROP-0001-reporting-section.md +106 -0
  390. package/docs/architecture/proposals/PROP-0002-retain-rollout-workspaces.md +104 -0
  391. package/docs/architecture/proposals/PROP-0003-executor-settings.md +81 -0
  392. package/docs/architecture/proposals/PROP-0004-flexible-reporting-guidance.md +71 -0
  393. package/docs/architecture/proposals/PROP-0005-xharness-cli-name.md +78 -0
  394. package/docs/architecture/proposals/PROP-0006-run-checklist.md +68 -0
  395. package/docs/architecture/proposals/PROP-0007-run-continuation.md +80 -0
  396. package/docs/architecture/proposals/PROP-0008-lessons-from-runs.md +80 -0
  397. package/docs/architecture/proposals/PROP-0009-foundation-and-variants.md +78 -0
  398. package/docs/architecture/proposals/PROP-0010-session-names.md +73 -0
  399. package/docs/architecture/proposals/PROP-0011-doctor.md +63 -0
  400. package/docs/architecture/proposals/PROP-0012-release-baseline.md +56 -0
  401. package/docs/architecture/proposals/README.md +76 -0
  402. package/docs/decisions/ADR-0001-owned-terminal.md +87 -0
  403. package/docs/decisions/ADR-0002-native-subagent-lifecycle.md +49 -0
  404. package/docs/decisions/ADR-0003-shared-asynchronous-subagents.md +70 -0
  405. package/docs/decisions/ADR-0004-fullscreen-terminal-layout.md +50 -0
  406. package/docs/decisions/ADR-0005-app-provided-oauth-clients.md +54 -0
  407. package/docs/decisions/ADR-0006-opentui-only-terminal.md +47 -0
  408. package/docs/decisions/ADR-0007-reporting-section.md +33 -0
  409. package/docs/decisions/ADR-0008-flexible-reporting-guidance.md +38 -0
  410. package/docs/decisions/ADR-0009-xharness-command.md +38 -0
  411. package/docs/decisions/ADR-0010-lessons-in-the-wiki.md +31 -0
  412. package/docs/decisions/ADR-0011-foundation-and-variants.md +28 -0
  413. package/docs/decisions/ADR-0012-native-session-names.md +34 -0
  414. package/docs/decisions/ADR-0013-doctor.md +27 -0
  415. package/docs/decisions/ADR-0014-public-release-baseline.md +21 -0
  416. package/docs/doctor.md +74 -0
  417. package/docs/experiments/EXP-0001-terminal-input-latency/plan.md +81 -0
  418. package/docs/experiments/EXP-0001-terminal-input-latency/results.md +46 -0
  419. package/docs/experiments/EXP-0002-opentui-typing-latency/plan.md +70 -0
  420. package/docs/experiments/EXP-0002-opentui-typing-latency/results.md +92 -0
  421. package/docs/features/README.md +20 -0
  422. package/docs/features/automations/README.md +41 -0
  423. package/docs/features/cores/README.md +39 -0
  424. package/docs/features/google-harness2/README.md +52 -0
  425. package/docs/features/integrations/README.md +40 -0
  426. package/docs/features/interfaces/README.md +29 -0
  427. package/docs/features/memory/README.md +28 -0
  428. package/docs/releases/1.0.0.md +40 -0
  429. package/docs/releases/README.md +36 -0
  430. package/docs/study/00-index.md +78 -0
  431. package/docs/study/arms/00-matrix.md +20 -0
  432. package/docs/study/arms/01-system-prompt.md +211 -0
  433. package/docs/study/arms/02-tools.md +79 -0
  434. package/docs/study/arms/03-subagents.md +90 -0
  435. package/docs/study/arms/04-skills.md +75 -0
  436. package/docs/study/arms/05-context-management.md +90 -0
  437. package/docs/study/arms/06-memory.md +90 -0
  438. package/docs/study/arms/07-governance.md +71 -0
  439. package/docs/study/arms/08-execution.md +69 -0
  440. package/docs/study/arms/09-observability.md +60 -0
  441. package/docs/study/arms/10-refinement.md +110 -0
  442. package/docs/study/btw-comparison.md +37 -0
  443. package/docs/study/feature-gap-review.md +42 -0
  444. package/docs/study/insights.md +123 -0
  445. package/docs/study/roadmap.md +72 -0
  446. package/docs/study/sources/claude-code.md +44 -0
  447. package/docs/study/sources/deepseek-harness.md +102 -0
  448. package/docs/study/sources/harness2.md +50 -0
  449. package/docs/study/sources/kimi-cli.md +42 -0
  450. package/docs/study/sources/omp.md +93 -0
  451. package/docs/study/sources/opencode.md +43 -0
  452. package/docs/study/sources/openhands.md +46 -0
  453. package/docs/study/sources/smolagents.md +40 -0
  454. package/docs/study/sources/swe-agent.md +34 -0
  455. package/docs/system-prompt-design.md +196 -0
  456. package/docs/terminal-tui.md +671 -0
  457. package/package.json +48 -12
  458. package/src/accounts/accounts.test.ts +0 -223
  459. package/src/accounts/accounts.ts +0 -522
  460. package/src/accounts/env.test.ts +0 -95
  461. package/src/accounts/env.ts +0 -338
  462. package/src/accounts/secrets.ts +0 -50
  463. package/src/accounts/store.ts +0 -338
  464. package/src/capabilities/api.ts +0 -75
  465. package/src/capabilities/runSnapshot.ts +0 -59
  466. package/src/capabilities/types.ts +0 -34
  467. package/src/cli.ts +0 -114
  468. package/src/core/bus.ts +0 -34
  469. package/src/core/changes.ts +0 -33
  470. package/src/core/env.ts +0 -27
  471. package/src/core/errors.ts +0 -32
  472. package/src/core/frontmatter.ts +0 -47
  473. package/src/core/fs.test.ts +0 -38
  474. package/src/core/fs.ts +0 -92
  475. package/src/core/index.ts +0 -193
  476. package/src/core/path.test.ts +0 -14
  477. package/src/core/path.ts +0 -79
  478. package/src/core/projects.ts +0 -90
  479. package/src/core/text.ts +0 -39
  480. package/src/harness.ts +0 -299
  481. package/src/index.ts +0 -70
  482. package/src/mcp/connections.ts +0 -614
  483. package/src/mcp/manager.ts +0 -130
  484. package/src/mcp/oauth.ts +0 -195
  485. package/src/mcp/scopeMigration.test.ts +0 -79
  486. package/src/mcp/scopeMigration.ts +0 -204
  487. package/src/mcp/service.test.ts +0 -376
  488. package/src/mcp/service.ts +0 -549
  489. package/src/mcp/types.ts +0 -108
  490. package/src/memory/api.test.ts +0 -82
  491. package/src/memory/api.ts +0 -289
  492. package/src/memory/blocks.test.ts +0 -78
  493. package/src/memory/blocks.ts +0 -406
  494. package/src/memory/caller.ts +0 -57
  495. package/src/memory/dispatch.ts +0 -59
  496. package/src/memory/facts.test.ts +0 -41
  497. package/src/memory/facts.ts +0 -248
  498. package/src/memory/graph.ts +0 -103
  499. package/src/memory/health.test.ts +0 -130
  500. package/src/memory/health.ts +0 -74
  501. package/src/memory/maintainer.ts +0 -272
  502. package/src/memory/maintenance.test.ts +0 -176
  503. package/src/memory/maintenance.ts +0 -330
  504. package/src/memory/migrate.ts +0 -79
  505. package/src/memory/operations.ts +0 -138
  506. package/src/memory/proposals.test.ts +0 -168
  507. package/src/memory/proposals.ts +0 -576
  508. package/src/memory/recall.test.ts +0 -104
  509. package/src/memory/recall.ts +0 -271
  510. package/src/memory/references.ts +0 -77
  511. package/src/memory/runContext.ts +0 -93
  512. package/src/memory/secrets.ts +0 -6
  513. package/src/memory/store.test.ts +0 -66
  514. package/src/memory/store.ts +0 -385
  515. package/src/memory/wiki.test.ts +0 -47
  516. package/src/memory/wiki.ts +0 -422
  517. package/src/memory/wikiIndex.test.ts +0 -88
  518. package/src/memory/wikiIndex.ts +0 -116
  519. package/src/plugins/api.ts +0 -181
  520. package/src/plugins/attachments.test.ts +0 -84
  521. package/src/plugins/attachments.ts +0 -141
  522. package/src/plugins/builtin.ts +0 -82
  523. package/src/plugins/catalogue.test.ts +0 -254
  524. package/src/plugins/catalogue.ts +0 -251
  525. package/src/plugins/cli.ts +0 -184
  526. package/src/plugins/discover.ts +0 -151
  527. package/src/plugins/firstParty.test.ts +0 -143
  528. package/src/plugins/firstParty.ts +0 -129
  529. package/src/plugins/hooks.test.ts +0 -250
  530. package/src/plugins/hooks.ts +0 -239
  531. package/src/plugins/identity.ts +0 -37
  532. package/src/plugins/install.test.ts +0 -107
  533. package/src/plugins/install.ts +0 -106
  534. package/src/plugins/inventory.ts +0 -123
  535. package/src/plugins/manifest.ts +0 -76
  536. package/src/plugins/plugins.test.ts +0 -205
  537. package/src/plugins/plugins.ts +0 -189
  538. package/src/plugins/proposal.ts +0 -121
  539. package/src/plugins/runtime.test.ts +0 -40
  540. package/src/plugins/runtime.ts +0 -82
  541. package/src/plugins/trust.ts +0 -142
  542. package/src/plugins/types.ts +0 -149
  543. package/src/prompt/compile.test.ts +0 -261
  544. package/src/prompt/compile.ts +0 -732
  545. package/src/server/methods.ts +0 -314
  546. package/src/server/remote.ts +0 -77
  547. package/src/server/rpc.ts +0 -116
  548. package/src/server/serve.ts +0 -28
  549. package/src/server/server.test.ts +0 -174
  550. package/src/sessions/approvals.ts +0 -118
  551. package/src/sessions/contracts.ts +0 -310
  552. package/src/sessions/conversation.test.ts +0 -150
  553. package/src/sessions/extensionSession.test.ts +0 -74
  554. package/src/sessions/extensionUi.test.ts +0 -65
  555. package/src/sessions/extensionUi.ts +0 -102
  556. package/src/sessions/history.ts +0 -51
  557. package/src/sessions/lineageJoin.ts +0 -75
  558. package/src/sessions/policy.ts +0 -32
  559. package/src/sessions/pricing.ts +0 -60
  560. package/src/sessions/reasoningSummaries.ts +0 -59
  561. package/src/sessions/registry.ts +0 -294
  562. package/src/sessions/runIndex.ts +0 -99
  563. package/src/sessions/runStore.test.ts +0 -152
  564. package/src/sessions/runStore.ts +0 -332
  565. package/src/sessions/runner.ts +0 -569
  566. package/src/sessions/runtimeResources.test.ts +0 -61
  567. package/src/sessions/sessions.test.ts +0 -455
  568. package/src/sessions/sessions.ts +0 -295
  569. package/src/skills/registry.test.ts +0 -104
  570. package/src/skills/registry.ts +0 -407
  571. package/src/terminal/cli.ts +0 -149
  572. package/src/terminal/client.ts +0 -74
  573. package/src/terminal/controller.ts +0 -227
  574. package/src/terminal/launch.test.ts +0 -34
  575. package/src/terminal/launch.ts +0 -88
  576. package/src/terminal/piExtension.ts +0 -210
  577. package/src/terminal/pluginControl.test.ts +0 -146
  578. package/src/terminal/pluginMenu.ts +0 -112
  579. package/src/terminal/socket.test.ts +0 -71
  580. package/src/terminal/socket.ts +0 -221
  581. package/src/terminal/standalone.test.ts +0 -130
  582. package/src/terminal/standalone.ts +0 -144
  583. package/src/terminal/terminal.test.ts +0 -330
  584. package/src/terminal/terminals.ts +0 -443
  585. package/src/tools/askUser.ts +0 -45
  586. package/src/tools/definitions.ts +0 -187
  587. package/src/tools/memoryTools.ts +0 -22
  588. package/src/tools/pluginPropose.ts +0 -41
  589. package/src/tools/types.ts +0 -39
  590. package/src/web/safeRequest.ts +0 -171
  591. package/src/web/text.ts +0 -53
  592. package/src/web/tools.ts +0 -134
  593. package/src/web/web.test.ts +0 -141
@@ -0,0 +1,192 @@
1
+ // One live browser for one session: an isolated profile, numbered tabs, and the refs of each
2
+ // tab's latest snapshot. Calls run one at a time; the browser starts on first use and closes when
3
+ // the session ends or sits idle.
4
+ import { mkdirSync, mkdtempSync, rmSync } from 'node:fs';
5
+ import { tmpdir } from 'node:os';
6
+ import { join } from 'node:path';
7
+ /** Any name as a file or folder name: other characters become `_`. */
8
+ export const fileName = (name) => name.replace(/[^A-Za-z0-9._-]/g, '_').replace(/^\.+/, '_').slice(0, 100) || '_';
9
+ export const VIEWPORT = { width: 1280, height: 800 };
10
+ export const ACTION_TIMEOUT_MS = 15_000;
11
+ export const NAVIGATION_TIMEOUT_MS = 30_000;
12
+ export const launchBrowser = async ({ profileDir, downloads, config }) => {
13
+ const { chromium } = await import('playwright-core');
14
+ if (config.cdpUrl) {
15
+ // A browser a person runs: we open our own context in it and never close the browser itself.
16
+ const browser = await chromium.connectOverCDP(config.cdpUrl);
17
+ const context = await browser.newContext({ viewport: VIEWPORT, acceptDownloads: true });
18
+ return { context, browser, attached: true };
19
+ }
20
+ const options = { headless: !config.headed, viewport: VIEWPORT, acceptDownloads: true, downloadsPath: downloads };
21
+ const attempts = config.executablePath ? [{ executablePath: config.executablePath }] : [{ channel: 'chrome' }, { channel: 'msedge' }, {}];
22
+ let last = null;
23
+ for (const attempt of attempts) {
24
+ try {
25
+ const context = profileDir
26
+ ? await chromium.launchPersistentContext(profileDir, { ...options, ...attempt })
27
+ : await (await chromium.launch({ ...options, ...attempt })).newContext({ viewport: VIEWPORT, acceptDownloads: true });
28
+ return { context, browser: context.browser(), attached: false };
29
+ }
30
+ catch (error) {
31
+ last = error;
32
+ }
33
+ }
34
+ throw new Error(`No browser could be started. Install Google Chrome, or run \`npx playwright install chromium\`. (${last instanceof Error ? last.message.split('\n')[0] : String(last)})`);
35
+ };
36
+ export class BrowserSession {
37
+ options;
38
+ closed = false;
39
+ context = null;
40
+ browser = null;
41
+ attached = false;
42
+ starting = null;
43
+ tabs = new Map();
44
+ current = null;
45
+ nextTab = 1;
46
+ queue = Promise.resolve();
47
+ idle = null;
48
+ temporaryProfile = null;
49
+ downloads = [];
50
+ /** Set when the kept profile was in use and a throwaway one was opened instead. */
51
+ profileNote = null;
52
+ constructor(options) {
53
+ this.options = options;
54
+ }
55
+ /** Runs `work` after every earlier call of this session has finished. */
56
+ run(work) {
57
+ const next = this.queue.then(work, work);
58
+ this.queue = next.catch(() => undefined);
59
+ this.touch();
60
+ return next;
61
+ }
62
+ touch() {
63
+ if (this.idle)
64
+ clearTimeout(this.idle);
65
+ this.idle = setTimeout(() => this.options.onIdle(), this.options.idleMs);
66
+ this.idle.unref?.();
67
+ }
68
+ async start() {
69
+ if (this.closed)
70
+ throw new Error('The browser session has ended.');
71
+ if (this.context)
72
+ return;
73
+ this.starting ??= (async () => {
74
+ mkdirSync(this.options.downloadsDir, { recursive: true });
75
+ let launched;
76
+ try {
77
+ launched = await this.options.launch({ profileDir: this.options.profileDir, downloads: this.options.downloadsDir, config: this.options.config() });
78
+ }
79
+ catch (error) {
80
+ // Another session holds the kept profile: work in a throwaway one rather than wait.
81
+ if (!this.options.profileDir || !/ProcessSingleton|already in use|lock/i.test(String(error)))
82
+ throw error;
83
+ this.temporaryProfile = mkdtempSync(join(tmpdir(), `harness-browser-${fileName(this.options.key)}-`));
84
+ launched = await this.options.launch({ profileDir: this.temporaryProfile, downloads: this.options.downloadsDir, config: this.options.config() });
85
+ this.profileNote = 'The saved browser profile is in use by another session, so this one started without its sign-ins.';
86
+ }
87
+ this.context = launched.context;
88
+ this.browser = launched.browser;
89
+ this.attached = launched.attached;
90
+ this.context.setDefaultTimeout(ACTION_TIMEOUT_MS);
91
+ this.context.setDefaultNavigationTimeout(NAVIGATION_TIMEOUT_MS);
92
+ await this.context.route('**/*', async (route) => {
93
+ const refusal = await this.options.network.refusal(route.request().url());
94
+ if (refusal)
95
+ await route.abort('blockedbyclient');
96
+ else
97
+ await route.continue();
98
+ });
99
+ this.context.on('page', (page) => this.adopt(page));
100
+ for (const page of this.context.pages())
101
+ this.adopt(page);
102
+ })();
103
+ try {
104
+ await this.starting;
105
+ if (this.closed)
106
+ throw new Error('The browser session has ended.');
107
+ }
108
+ finally {
109
+ this.starting = null;
110
+ }
111
+ }
112
+ adopt(page) {
113
+ const existing = [...this.tabs.values()].find((tab) => tab.page === page);
114
+ if (existing)
115
+ return existing;
116
+ const tab = { id: `t${this.nextTab++}`, page, generation: 0, refs: new Map(), refsGeneration: -1 };
117
+ this.tabs.set(tab.id, tab);
118
+ this.current ??= tab.id;
119
+ page.on('framenavigated', (frame) => {
120
+ if (frame === page.mainFrame())
121
+ tab.generation += 1;
122
+ });
123
+ page.on('close', () => {
124
+ this.tabs.delete(tab.id);
125
+ if (this.current === tab.id)
126
+ this.current = this.tabs.keys().next().value ?? null;
127
+ });
128
+ page.on('download', (download) => {
129
+ const name = fileName(download.suggestedFilename() || 'download');
130
+ const path = join(this.options.downloadsDir, `${Date.now()}-${name}`);
131
+ void download.saveAs(path).then(() => this.downloads.push({ tab: tab.id, path, name })).catch(() => undefined);
132
+ });
133
+ return tab;
134
+ }
135
+ /** A tab by id, or the current one, starting the browser and opening a first tab when needed. */
136
+ async tab(id) {
137
+ await this.start();
138
+ if (id) {
139
+ const tab = this.tabs.get(id);
140
+ if (!tab)
141
+ throw new Error(`There is no tab ${id}. browser_tabs lists them.`);
142
+ return tab;
143
+ }
144
+ if (this.current && this.tabs.has(this.current))
145
+ return this.tabs.get(this.current);
146
+ return this.open();
147
+ }
148
+ async open() {
149
+ await this.start();
150
+ const tab = this.adopt(await this.context.newPage());
151
+ this.current = tab.id;
152
+ return tab;
153
+ }
154
+ select(id) {
155
+ const tab = this.tabs.get(id);
156
+ if (!tab)
157
+ throw new Error(`There is no tab ${id}.`);
158
+ this.current = id;
159
+ return tab;
160
+ }
161
+ list() {
162
+ return [...this.tabs.values()].map((tab) => ({ id: tab.id, url: tab.page.url(), current: tab.id === this.current }));
163
+ }
164
+ /** What pages in this browser may reach. */
165
+ get network() {
166
+ return this.options.network;
167
+ }
168
+ get currentId() {
169
+ return this.current;
170
+ }
171
+ get started() {
172
+ return this.context !== null;
173
+ }
174
+ async close() {
175
+ this.closed = true;
176
+ await this.starting?.catch(() => undefined);
177
+ if (this.idle)
178
+ clearTimeout(this.idle);
179
+ const { context, browser, attached } = this;
180
+ this.context = null;
181
+ this.browser = null;
182
+ this.tabs.clear();
183
+ this.current = null;
184
+ await context?.close().catch(() => undefined);
185
+ // An attached browser belongs to a person: only our context goes.
186
+ if (!attached)
187
+ await browser?.close().catch(() => undefined);
188
+ if (this.temporaryProfile)
189
+ rmSync(this.temporaryProfile, { recursive: true, force: true });
190
+ this.temporaryProfile = null;
191
+ }
192
+ }
@@ -0,0 +1,8 @@
1
+ import type { ToolSpec } from "../tools/types.js";
2
+ import type { WorldContext } from "../world/world.js";
3
+ import type { BrowserSession } from "./session.js";
4
+ /** Longest snapshot sent, in lines and characters. */
5
+ export declare const SNAPSHOT_LINES = 500;
6
+ export declare const SNAPSHOT_CHARS = 40000;
7
+ export declare const BROWSER_TOOL_NAMES: readonly ["browser_navigate", "browser_snapshot", "browser_read", "browser_screenshot", "browser_click", "browser_type", "browser_select", "browser_press", "browser_scroll", "browser_wait", "browser_tabs"];
8
+ export declare function browserTools(context: WorldContext, session: () => BrowserSession): ToolSpec[];
@@ -0,0 +1,329 @@
1
+ import { askForAction, classifyAction, SENSITIVE_FIELD } from "../world/actions.js";
2
+ import { untrusted } from "../world/untrusted.js";
3
+ import { htmlToMarkdown } from "../web/markdown.js";
4
+ import { PAGE_CHARS } from "../web/tools.js";
5
+ /** Longest snapshot sent, in lines and characters. */
6
+ export const SNAPSHOT_LINES = 500;
7
+ export const SNAPSHOT_CHARS = 40_000;
8
+ export const BROWSER_TOOL_NAMES = ['browser_navigate', 'browser_snapshot', 'browser_read', 'browser_screenshot', 'browser_click', 'browser_type', 'browser_select', 'browser_press', 'browser_scroll', 'browser_wait', 'browser_tabs'];
9
+ const message = (error) => (error instanceof Error ? error.message.split('\n')[0] : String(error));
10
+ const isTimeout = (error) => error instanceof Error && (error.name === 'TimeoutError' || /Timeout \d+ms exceeded/.test(error.message));
11
+ const UNKNOWN = 'Its outcome is unknown: take browser_snapshot before trying again, so nothing is clicked, sent or bought twice.';
12
+ const tabParam = { type: 'string', description: 'Tab id from browser_tabs, such as t2. Defaults to the current tab.' };
13
+ const refParam = { type: 'string', description: 'The element\'s ref from the latest browser_snapshot of the tab, such as e12.' };
14
+ const text = (value) => (typeof value === 'string' ? value : '');
15
+ async function where(tab) {
16
+ const title = await tab.page.title().catch(() => '');
17
+ return `Tab ${tab.id}: ${tab.page.url()}${title ? ` — ${title}` : ''}`;
18
+ }
19
+ /** An element named by a ref of the tab's latest snapshot. */
20
+ function element(tab, ref) {
21
+ const id = ref.trim().replace(/^@/, '').replace(/^ref=/, '');
22
+ if (tab.refsGeneration !== tab.generation)
23
+ throw new Error(`The page in ${tab.id} changed since its last snapshot. Take browser_snapshot again and use a ref from it.`);
24
+ const line = tab.refs.get(id);
25
+ if (!line)
26
+ throw new Error(`There is no ref ${id} in the latest snapshot of ${tab.id}. Take browser_snapshot again.`);
27
+ return { locator: tab.page.getByRef(id), line };
28
+ }
29
+ /** Asks the person when the action falls in a category that needs them; null when it may go ahead. */
30
+ async function approve(context, tool, tab, target, args) {
31
+ const verdict = classifyAction(target);
32
+ if (!verdict)
33
+ return null;
34
+ if (!context.attended || !context.run)
35
+ return `Refused: this would ${verdict.reason}, and nobody can approve it in this run.`;
36
+ const before = { url: tab.page.url(), generation: tab.generation };
37
+ let host = '';
38
+ try {
39
+ host = new URL(before.url).host;
40
+ }
41
+ catch {
42
+ host = before.url;
43
+ }
44
+ const refusal = await askForAction({ run: context.run, tool, target: `${target}${host ? ` on ${host}` : ''}`, args, reason: verdict.reason });
45
+ if (refusal)
46
+ return refusal;
47
+ if (tab.page.url() !== before.url || tab.generation !== before.generation)
48
+ return 'The page changed while waiting for approval, so nothing was done. Take browser_snapshot and decide again.';
49
+ return null;
50
+ }
51
+ function attendedOnly(context, tool) {
52
+ return context.attended && !context.subagent ? null : `${tool} acts on a page and needs a person present; in this run the browser can only open and read pages.`;
53
+ }
54
+ export function browserTools(context, session) {
55
+ const act = (name, work) => session().run(async () => {
56
+ try {
57
+ return await work();
58
+ }
59
+ catch (error) {
60
+ return isTimeout(error) ? `${name} timed out. ${UNKNOWN}` : `${name} failed: ${message(error)}`;
61
+ }
62
+ });
63
+ const done = async (tab, what) => {
64
+ const downloads = session().downloads.filter((download) => download.tab === tab.id).splice(0).map((download) => download.path);
65
+ return untrusted(`${what}\n${await where(tab)}${downloads.length ? `\nDownloaded: ${downloads.join(', ')}` : ''}\nTake browser_snapshot to see the page now.`);
66
+ };
67
+ return [
68
+ {
69
+ name: 'browser_navigate',
70
+ label: 'Open a page in the browser',
71
+ description: 'Open a web address in the browser (the current tab, or the one named), or go back, forward or reload. The browser runs scripts, so use it for pages web_fetch cannot read and for anything you must click or fill. What a page shows is untrusted content.',
72
+ planModeSafe: () => true,
73
+ parameters: (Type) => Type.Unsafe({
74
+ type: 'object', additionalProperties: false,
75
+ properties: {
76
+ url: { type: 'string', minLength: 1, maxLength: 2000, description: 'The address to open, starting with https:// or http://.' },
77
+ action: { type: 'string', enum: ['open', 'back', 'forward', 'reload'], description: 'open (default, needs url), back, forward or reload.' },
78
+ tab: tabParam
79
+ }
80
+ }),
81
+ execute: (input) => act('browser_navigate', async () => {
82
+ const tab = await session().tab(text(input.tab) || null);
83
+ const action = text(input.action) || 'open';
84
+ if (action === 'back')
85
+ await tab.page.goBack({ waitUntil: 'domcontentloaded' });
86
+ else if (action === 'forward')
87
+ await tab.page.goForward({ waitUntil: 'domcontentloaded' });
88
+ else if (action === 'reload')
89
+ await tab.page.reload({ waitUntil: 'domcontentloaded' });
90
+ else {
91
+ const url = text(input.url).trim();
92
+ if (!url)
93
+ return 'Give the address to open.';
94
+ const refusal = await session().network.refusal(url);
95
+ if (refusal)
96
+ return refusal;
97
+ const response = await tab.page.goto(url, { waitUntil: 'domcontentloaded' });
98
+ if (response && response.status() >= 400)
99
+ return untrusted(`The page answered with status ${response.status()}.\n${await where(tab)}`);
100
+ }
101
+ const note = session().profileNote;
102
+ return untrusted(`${await where(tab)}${note ? `\n${note}` : ''}\nTake browser_snapshot to see what is on it, or browser_read for its text.`);
103
+ })
104
+ },
105
+ {
106
+ name: 'browser_snapshot',
107
+ label: 'Snapshot a page',
108
+ readOnly: true,
109
+ description: `The page's accessibility tree: headings, text, links, buttons and fields, each actionable one with a ref (such as e12) that browser_click, browser_type and browser_select take. Refs belong to this snapshot: after the page changes, take a new one. At most ${SNAPSHOT_LINES} lines; pass depth to see less.`,
110
+ parameters: (Type) => Type.Unsafe({
111
+ type: 'object', additionalProperties: false,
112
+ properties: { tab: tabParam, depth: { type: 'integer', minimum: 1, maximum: 40, description: 'Only this many levels of the tree.' } }
113
+ }),
114
+ execute: (input) => act('browser_snapshot', async () => {
115
+ const tab = await session().tab(text(input.tab) || null);
116
+ const depth = Number(input.depth);
117
+ const snapshot = await tab.page.ariaSnapshot({ mode: 'ai', ...(Number.isInteger(depth) && depth > 0 ? { depth } : {}), timeout: 15_000 });
118
+ tab.refs = new Map();
119
+ for (const line of snapshot.split('\n')) {
120
+ const ref = /\[ref=([a-z0-9]+)\]/i.exec(line)?.[1];
121
+ if (ref)
122
+ tab.refs.set(ref, line.trim().replace(/^- /, '').slice(0, 240));
123
+ }
124
+ tab.refsGeneration = tab.generation;
125
+ const lines = snapshot.split('\n');
126
+ let shown = lines.slice(0, SNAPSHOT_LINES).join('\n');
127
+ const cut = lines.length > SNAPSHOT_LINES || shown.length > SNAPSHOT_CHARS;
128
+ if (shown.length > SNAPSHOT_CHARS)
129
+ shown = shown.slice(0, SNAPSHOT_CHARS);
130
+ return untrusted(`${await where(tab)}\n\n${shown}${cut ? `\n\n(The snapshot was cut at ${SNAPSHOT_LINES} lines. Pass a smaller depth, scroll, or use browser_read for the text.)` : ''}`);
131
+ })
132
+ },
133
+ {
134
+ name: 'browser_read',
135
+ label: 'Read a page as text',
136
+ readOnly: true,
137
+ description: `The visible text of the tab's page as Markdown, after its scripts ran. Up to ${PAGE_CHARS.toLocaleString('en-US')} characters; pass offset to read on.`,
138
+ parameters: (Type) => Type.Unsafe({
139
+ type: 'object', additionalProperties: false,
140
+ properties: { tab: tabParam, offset: { type: 'integer', minimum: 0, description: 'Character to start from.' } }
141
+ }),
142
+ execute: (input) => act('browser_read', async () => {
143
+ const tab = await session().tab(text(input.tab) || null);
144
+ const { title, text: markdown } = htmlToMarkdown(await tab.page.content());
145
+ const offset = Math.max(0, Math.floor(Number(input.offset)) || 0);
146
+ const end = Math.min(markdown.length, offset + PAGE_CHARS);
147
+ const more = end < markdown.length ? `\n\n(More: call browser_read with offset ${end}.)` : '';
148
+ return untrusted(`Tab ${tab.id}: ${tab.page.url()}${title ? ` — ${title}` : ''}\nCharacters ${offset}–${end} of ${markdown.length}\n\n${markdown.slice(offset, end)}${more}`);
149
+ })
150
+ },
151
+ {
152
+ name: 'browser_screenshot',
153
+ label: 'Screenshot a page',
154
+ readOnly: true,
155
+ description: 'A picture of what the tab shows (1280×800), or of one element by ref. Use it when layout or images matter; a snapshot is cheaper for finding what to click.',
156
+ parameters: (Type) => Type.Unsafe({ type: 'object', additionalProperties: false, properties: { tab: tabParam, ref: refParam } }),
157
+ execute: (input) => act('browser_screenshot', async () => {
158
+ const tab = await session().tab(text(input.tab) || null);
159
+ const ref = text(input.ref);
160
+ const shot = ref ? await element(tab, ref).locator.screenshot({ type: 'jpeg', quality: 70 }) : await tab.page.screenshot({ type: 'jpeg', quality: 70 });
161
+ return { text: untrusted(`Screenshot of ${ref ? `element ${ref} in ` : ''}${await where(tab)}`), image: { data: shot.toString('base64'), mimeType: 'image/jpeg' } };
162
+ })
163
+ },
164
+ {
165
+ name: 'browser_click',
166
+ label: 'Click on a page',
167
+ description: 'Click an element by its ref. A click that would send, buy, delete, change an account or grant access asks the user first.',
168
+ parameters: (Type) => Type.Unsafe({
169
+ type: 'object', additionalProperties: false, required: ['ref'],
170
+ properties: { ref: refParam, tab: tabParam, double: { type: 'boolean', description: 'Double-click.' }, button: { type: 'string', enum: ['left', 'right', 'middle'] } }
171
+ }),
172
+ execute: async (input) => attendedOnly(context, 'browser_click') ?? act('browser_click', async () => {
173
+ const tab = await session().tab(text(input.tab) || null);
174
+ const { locator, line } = element(tab, text(input.ref));
175
+ const refusal = await approve(context, 'browser_click', tab, line, input);
176
+ if (refusal)
177
+ return refusal;
178
+ const button = input.button === 'right' || input.button === 'middle' ? input.button : 'left';
179
+ if (input.double === true)
180
+ await locator.dblclick({ button });
181
+ else
182
+ await locator.click({ button });
183
+ return done(tab, `Clicked ${line}.`);
184
+ })
185
+ },
186
+ {
187
+ name: 'browser_type',
188
+ label: 'Type into a page',
189
+ description: 'Type text into a field by its ref, replacing what is there; submit presses Enter afterwards. Password, card and one-time-code fields are refused: ask the user to fill those. Submitting a form that sends, buys or deletes asks the user first.',
190
+ parameters: (Type) => Type.Unsafe({
191
+ type: 'object', additionalProperties: false, required: ['ref', 'text'],
192
+ properties: { ref: refParam, text: { type: 'string', maxLength: 20_000 }, submit: { type: 'boolean', description: 'Press Enter after typing.' }, tab: tabParam }
193
+ }),
194
+ execute: async (input) => attendedOnly(context, 'browser_type') ?? act('browser_type', async () => {
195
+ const tab = await session().tab(text(input.tab) || null);
196
+ const { locator, line } = element(tab, text(input.ref));
197
+ const secret = SENSITIVE_FIELD.test(line) || await locator.evaluate(field => field.getAttribute('type') === 'password' || /cc-|one-time-code|current-password|new-password/.test(field.getAttribute('autocomplete') ?? '')).catch(() => false);
198
+ if (secret)
199
+ return 'That field takes a password, a card number or a code. Ask the user to fill it themselves.';
200
+ if (input.submit === true) {
201
+ const refusal = await approve(context, 'browser_type', tab, `submit ${line}`, { ...input, text: `[${text(input.text).length} characters]` });
202
+ if (refusal)
203
+ return refusal;
204
+ }
205
+ await locator.fill(text(input.text));
206
+ if (input.submit === true)
207
+ await locator.press('Enter');
208
+ return done(tab, `Typed ${text(input.text).length} characters into ${line}${input.submit === true ? ' and submitted' : ''}.`);
209
+ })
210
+ },
211
+ {
212
+ name: 'browser_select',
213
+ label: 'Choose in a list',
214
+ description: 'Choose one or more options of a drop-down list by its ref, by the options\' labels or values.',
215
+ parameters: (Type) => Type.Unsafe({
216
+ type: 'object', additionalProperties: false, required: ['ref', 'values'],
217
+ properties: { ref: refParam, values: { type: 'array', minItems: 1, items: { type: 'string' } }, tab: tabParam }
218
+ }),
219
+ execute: async (input) => attendedOnly(context, 'browser_select') ?? act('browser_select', async () => {
220
+ const tab = await session().tab(text(input.tab) || null);
221
+ const { locator, line } = element(tab, text(input.ref));
222
+ const values = Array.isArray(input.values) ? input.values.filter((value) => typeof value === 'string') : [];
223
+ const chosen = await locator.selectOption(values);
224
+ return done(tab, `Chose ${chosen.join(', ') || 'nothing'} in ${line}.`);
225
+ })
226
+ },
227
+ {
228
+ name: 'browser_press',
229
+ label: 'Press a key on a page',
230
+ description: 'Press a key or a combination in the tab, such as Enter, Escape, Tab, ArrowDown or Control+A. Enter in a message box asks the user first.',
231
+ parameters: (Type) => Type.Unsafe({
232
+ type: 'object', additionalProperties: false, required: ['key'],
233
+ properties: { key: { type: 'string', minLength: 1, maxLength: 60 }, tab: tabParam }
234
+ }),
235
+ execute: async (input) => attendedOnly(context, 'browser_press') ?? act('browser_press', async () => {
236
+ const tab = await session().tab(text(input.tab) || null);
237
+ const key = text(input.key).trim();
238
+ if (/(^|\+)Enter$/i.test(key)) {
239
+ // Runs in the page: what has focus, and whether Enter there would send something.
240
+ const focused = await tab.page.evaluate(`(() => {
241
+ const node = document.activeElement
242
+ if (!node) return ''
243
+ const sends = node.tagName === 'TEXTAREA' || node.isContentEditable || !!node.closest('form')
244
+ return sends ? 'submit ' + (node.getAttribute('aria-label') || node.getAttribute('placeholder') || node.tagName.toLowerCase()) + ' form' : ''
245
+ })()`).then((value) => String(value ?? '')).catch(() => '');
246
+ if (focused) {
247
+ const refusal = await approve(context, 'browser_press', tab, `${focused} (send)`, input);
248
+ if (refusal)
249
+ return refusal;
250
+ }
251
+ }
252
+ await tab.page.keyboard.press(key);
253
+ return done(tab, `Pressed ${key}.`);
254
+ })
255
+ },
256
+ {
257
+ name: 'browser_scroll',
258
+ label: 'Scroll a page',
259
+ readOnly: true,
260
+ description: 'Scroll the tab up or down by about a screen, or bring an element (by ref) into view.',
261
+ parameters: (Type) => Type.Unsafe({
262
+ type: 'object', additionalProperties: false,
263
+ properties: { direction: { type: 'string', enum: ['up', 'down'] }, ref: refParam, tab: tabParam }
264
+ }),
265
+ execute: (input) => act('browser_scroll', async () => {
266
+ const tab = await session().tab(text(input.tab) || null);
267
+ if (text(input.ref))
268
+ await element(tab, text(input.ref)).locator.scrollIntoViewIfNeeded();
269
+ else
270
+ await tab.page.mouse.wheel(0, input.direction === 'up' ? -650 : 650);
271
+ return untrusted(`Scrolled. ${await where(tab)}`);
272
+ })
273
+ },
274
+ {
275
+ name: 'browser_wait',
276
+ label: 'Wait on a page',
277
+ readOnly: true,
278
+ description: 'Wait until some text appears in the tab (up to 30 seconds), or for a number of milliseconds (up to 10,000).',
279
+ parameters: (Type) => Type.Unsafe({
280
+ type: 'object', additionalProperties: false,
281
+ properties: { text: { type: 'string', minLength: 1, maxLength: 200 }, ms: { type: 'integer', minimum: 1, maximum: 10_000 }, tab: tabParam }
282
+ }),
283
+ execute: (input) => act('browser_wait', async () => {
284
+ const tab = await session().tab(text(input.tab) || null);
285
+ if (text(input.text)) {
286
+ await tab.page.getByText(text(input.text)).first().waitFor({ timeout: 30_000 });
287
+ return untrusted(`"${text(input.text)}" is on the page. ${await where(tab)}`);
288
+ }
289
+ await tab.page.waitForTimeout(Math.min(10_000, Math.max(1, Math.floor(Number(input.ms)) || 1000)));
290
+ return untrusted(`Waited. ${await where(tab)}`);
291
+ })
292
+ },
293
+ {
294
+ name: 'browser_tabs',
295
+ label: 'Browser tabs',
296
+ description: 'List the tabs, open a new one (optionally at an address), switch to one, or close one.',
297
+ planModeSafe: (input) => input.op !== 'close',
298
+ parameters: (Type) => Type.Unsafe({
299
+ type: 'object', additionalProperties: false, required: ['op'],
300
+ properties: { op: { type: 'string', enum: ['list', 'new', 'switch', 'close'] }, tab: tabParam, url: { type: 'string', maxLength: 2000 } }
301
+ }),
302
+ execute: (input) => act('browser_tabs', async () => {
303
+ const browser = session();
304
+ if (input.op === 'new') {
305
+ const url = text(input.url).trim();
306
+ if (url) {
307
+ const refusal = await browser.network.refusal(url);
308
+ if (refusal)
309
+ return refusal;
310
+ }
311
+ const tab = await browser.open();
312
+ if (url)
313
+ await tab.page.goto(url, { waitUntil: 'domcontentloaded' });
314
+ return untrusted(`Opened ${await where(tab)}`);
315
+ }
316
+ if (input.op === 'switch')
317
+ return untrusted(`Now in ${await where(browser.select(text(input.tab)))}`);
318
+ if (input.op === 'close') {
319
+ const tab = await browser.tab(text(input.tab) || null);
320
+ await tab.page.close();
321
+ return `Closed ${tab.id}.`;
322
+ }
323
+ if (!browser.started)
324
+ return 'No tabs are open yet. browser_navigate opens one.';
325
+ return untrusted(browser.list().map((tab) => `${tab.current ? '*' : ' '} ${tab.id} ${tab.url}`).join('\n'));
326
+ })
327
+ }
328
+ ];
329
+ }
@@ -0,0 +1,22 @@
1
+ import type { Harness } from "../harness.js";
2
+ import type { CallerContext } from "../core/caller.js";
3
+ import type { Launch } from "../prompt/compile.js";
4
+ import * as pluginApi from "../plugins/api.js";
5
+ import type { CapabilityCatalogue, CapabilityScope, CapabilitySet } from "./types.js";
6
+ export interface ListParams extends CapabilityScope {
7
+ }
8
+ export interface InventoryParams extends CapabilityScope {
9
+ context?: CallerContext;
10
+ launch?: Launch;
11
+ tools?: string[];
12
+ connections?: boolean;
13
+ }
14
+ export declare function list(harness: Harness, params?: ListParams): Promise<CapabilityCatalogue>;
15
+ /** The resolved callable set for one caller, based on the stores and caller-supplied tool list. */
16
+ export declare function resolve(harness: Harness, params: ListParams & {
17
+ tools?: readonly string[];
18
+ }): Promise<CapabilitySet>;
19
+ export declare function toolIntersection(parent: CapabilitySet, assignee: CapabilitySet, taskTools?: readonly string[]): CapabilitySet;
20
+ export declare function inventory(harness: Harness, params?: InventoryParams): Promise<import("../index.js").Inventory>;
21
+ export declare function attach(harness: Harness, params: pluginApi.AttachParams, on: boolean): Promise<CapabilityCatalogue>;
22
+ export declare function switchCapability(harness: Harness, params: pluginApi.AttachParams, on: boolean): Promise<CapabilityCatalogue>;
@@ -0,0 +1,54 @@
1
+ // A generic view of what is available to a caller. The existing plugin, registry, and connector
2
+ // stores remain the source of truth; this module gives hosts one capability-shaped contract.
3
+ import { invalid } from "../core/errors.js";
4
+ import * as pluginApi from "../plugins/api.js";
5
+ const unique = (values) => [...new Set(values.filter((value) => value.length > 0))];
6
+ function contributions(plugins) {
7
+ return plugins.flatMap((plugin) => plugin.contributions.map((item) => ({
8
+ id: item.id,
9
+ pluginId: plugin.id,
10
+ kind: item.kind,
11
+ name: item.name,
12
+ description: item.description,
13
+ source: plugin.source,
14
+ state: item.state,
15
+ attachment: item.attachment
16
+ })));
17
+ }
18
+ export async function list(harness, params = {}) {
19
+ const plugins = await pluginApi.list(harness, params);
20
+ return { plugins, capabilities: contributions(plugins) };
21
+ }
22
+ /** The resolved callable set for one caller, based on the stores and caller-supplied tool list. */
23
+ export async function resolve(harness, params) {
24
+ const caller = { agentId: params.agentId ?? null, projectId: params.projectId ?? null };
25
+ const catalogue = await list(harness, params);
26
+ const connectors = harness.apps.connections.forScope(caller).map((connection) => connection.id);
27
+ return {
28
+ version: 1,
29
+ tools: unique(params.tools ?? []),
30
+ connectors: unique(connectors),
31
+ contributions: catalogue.capabilities.filter((item) => item.state === 'on').map((item) => item.id)
32
+ };
33
+ }
34
+ export function toolIntersection(parent, assignee, taskTools) {
35
+ const permitted = taskTools === undefined ? null : new Set(taskTools);
36
+ return {
37
+ version: 1,
38
+ tools: parent.tools.filter((tool) => assignee.tools.includes(tool) && (!permitted || permitted.has(tool))),
39
+ connectors: parent.connectors.filter((id) => assignee.connectors.includes(id)),
40
+ contributions: parent.contributions.filter((id) => assignee.contributions.includes(id))
41
+ };
42
+ }
43
+ export function inventory(harness, params = {}) {
44
+ return pluginApi.inventoryFor(harness, params);
45
+ }
46
+ export async function attach(harness, params, on) {
47
+ const plugins = await pluginApi.attach(harness, params, on);
48
+ return { plugins, capabilities: contributions(plugins) };
49
+ }
50
+ export async function switchCapability(harness, params, on) {
51
+ if (!params.id.trim())
52
+ throw invalid('A capability id is required.');
53
+ return attach(harness, params, on);
54
+ }
@@ -0,0 +1,18 @@
1
+ import type { CapabilitySet } from "./types.js";
2
+ export interface RunCapabilitySnapshot {
3
+ version: 1;
4
+ caller: {
5
+ agentId: string | null;
6
+ projectId: string | null;
7
+ };
8
+ tools: string[];
9
+ connectors: string[];
10
+ contributions: string[];
11
+ }
12
+ export declare function capabilitySet(value: unknown): CapabilitySet;
13
+ /** Writes a run's capability set once. A resumed or duplicate launch cannot replace it. */
14
+ export declare function freezeRun(root: string, runId: string, caller: {
15
+ agentId?: string | null;
16
+ projectId?: string | null;
17
+ }, set: CapabilitySet): RunCapabilitySnapshot;
18
+ export declare function loadRun(root: string, runId: string): RunCapabilitySnapshot | null;