@xingular/harness 0.1.7 → 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 (683) hide show
  1. package/CHANGELOG.md +97 -1
  2. package/LICENSE +202 -0
  3. package/NOTICE.md +22 -0
  4. package/README.md +187 -85
  5. package/THIRD_PARTY_LICENSES.md +942 -0
  6. package/dist/cli.js +13701 -13498
  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 +808 -151
  373. package/docs/README.md +22 -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-0002-native-subagent-lifecycle.md +49 -0
  403. package/docs/decisions/ADR-0003-shared-asynchronous-subagents.md +70 -0
  404. package/docs/decisions/ADR-0004-fullscreen-terminal-layout.md +50 -0
  405. package/docs/decisions/ADR-0005-app-provided-oauth-clients.md +54 -0
  406. package/docs/decisions/ADR-0006-opentui-only-terminal.md +47 -0
  407. package/docs/decisions/ADR-0007-reporting-section.md +33 -0
  408. package/docs/decisions/ADR-0008-flexible-reporting-guidance.md +38 -0
  409. package/docs/decisions/ADR-0009-xharness-command.md +38 -0
  410. package/docs/decisions/ADR-0010-lessons-in-the-wiki.md +31 -0
  411. package/docs/decisions/ADR-0011-foundation-and-variants.md +28 -0
  412. package/docs/decisions/ADR-0012-native-session-names.md +34 -0
  413. package/docs/decisions/ADR-0013-doctor.md +27 -0
  414. package/docs/decisions/ADR-0014-public-release-baseline.md +21 -0
  415. package/docs/doctor.md +74 -0
  416. package/docs/experiments/EXP-0001-terminal-input-latency/plan.md +81 -0
  417. package/docs/experiments/EXP-0001-terminal-input-latency/results.md +46 -0
  418. package/docs/experiments/EXP-0002-opentui-typing-latency/plan.md +70 -0
  419. package/docs/experiments/EXP-0002-opentui-typing-latency/results.md +92 -0
  420. package/docs/features/README.md +20 -0
  421. package/docs/features/automations/README.md +41 -0
  422. package/docs/features/cores/README.md +39 -0
  423. package/docs/features/google-harness2/README.md +52 -0
  424. package/docs/features/integrations/README.md +40 -0
  425. package/docs/features/interfaces/README.md +29 -0
  426. package/docs/features/memory/README.md +28 -0
  427. package/docs/releases/1.0.0.md +40 -0
  428. package/docs/releases/README.md +36 -0
  429. package/docs/study/00-index.md +78 -0
  430. package/docs/study/arms/00-matrix.md +20 -0
  431. package/docs/study/arms/01-system-prompt.md +211 -0
  432. package/docs/study/arms/02-tools.md +79 -0
  433. package/docs/study/arms/03-subagents.md +90 -0
  434. package/docs/study/arms/04-skills.md +75 -0
  435. package/docs/study/arms/05-context-management.md +90 -0
  436. package/docs/study/arms/06-memory.md +90 -0
  437. package/docs/study/arms/07-governance.md +71 -0
  438. package/docs/study/arms/08-execution.md +69 -0
  439. package/docs/study/arms/09-observability.md +60 -0
  440. package/docs/study/arms/10-refinement.md +110 -0
  441. package/docs/study/btw-comparison.md +37 -0
  442. package/docs/study/feature-gap-review.md +42 -0
  443. package/docs/study/insights.md +123 -0
  444. package/docs/study/roadmap.md +72 -0
  445. package/docs/study/sources/claude-code.md +44 -0
  446. package/docs/study/sources/deepseek-harness.md +102 -0
  447. package/docs/study/sources/harness2.md +50 -0
  448. package/docs/study/sources/kimi-cli.md +42 -0
  449. package/docs/study/sources/omp.md +93 -0
  450. package/docs/study/sources/opencode.md +43 -0
  451. package/docs/study/sources/openhands.md +46 -0
  452. package/docs/study/sources/smolagents.md +40 -0
  453. package/docs/study/sources/swe-agent.md +34 -0
  454. package/docs/system-prompt-design.md +196 -0
  455. package/docs/terminal-tui.md +473 -56
  456. package/package.json +43 -13
  457. package/docs/evidence/terminal-2026-10-17/120x40-completed-transcript.ansi.gz +0 -0
  458. package/docs/evidence/terminal-2026-10-17/40x20-settings-interaction.ansi.gz +0 -0
  459. package/docs/evidence/terminal-2026-10-17/40x20-settings-keyboard.ansi.gz +0 -0
  460. package/docs/evidence/terminal-2026-10-17/40x20-welcome.ansi.gz +0 -0
  461. package/docs/evidence/terminal-2026-10-17/80x24-approval-0.ansi.gz +0 -0
  462. package/docs/evidence/terminal-2026-10-17/80x24-question.ansi.gz +0 -0
  463. package/docs/evidence/terminal-2026-10-17/verification.json +0 -130
  464. package/docs/evidence/terminal-2026-10-17-followup/120x40-completed-transcript.ansi.gz +0 -0
  465. package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-interaction.ansi.gz +0 -0
  466. package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-keyboard.ansi.gz +0 -0
  467. package/docs/evidence/terminal-2026-10-17-followup/40x20-welcome.ansi.gz +0 -0
  468. package/docs/evidence/terminal-2026-10-17-followup/80x24-approval-0.ansi.gz +0 -0
  469. package/docs/evidence/terminal-2026-10-17-followup/80x24-plugin-light.ansi.gz +0 -0
  470. package/docs/evidence/terminal-2026-10-17-followup/80x24-question-batch.ansi.gz +0 -0
  471. package/docs/evidence/terminal-2026-10-17-followup/80x24-question.ansi.gz +0 -0
  472. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-approval-0.ansi.gz +0 -0
  473. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-plugin-light.ansi.gz +0 -0
  474. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question-batch.ansi.gz +0 -0
  475. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question.ansi.gz +0 -0
  476. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/verification.json +0 -95
  477. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-approval-0.ansi.gz +0 -0
  478. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-plugin-light.ansi.gz +0 -0
  479. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question-batch.ansi.gz +0 -0
  480. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question.ansi.gz +0 -0
  481. package/docs/evidence/terminal-2026-10-17-followup/global-install/README.md +0 -27
  482. package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command-80x24.ansi.gz +0 -0
  483. package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command.json +0 -18
  484. package/docs/evidence/terminal-2026-10-17-followup/global-install/verification.json +0 -95
  485. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-80x24.json.gz +0 -0
  486. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-final-80x24.json.gz +0 -0
  487. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-scenario.json +0 -60
  488. package/docs/evidence/terminal-2026-10-17-followup/live-codex/README.md +0 -24
  489. package/docs/evidence/terminal-2026-10-17-followup/live-codex/complete-80x24.ansi.gz +0 -0
  490. package/docs/evidence/terminal-2026-10-17-followup/live-codex/verification.json +0 -57
  491. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24-early.json.gz +0 -0
  492. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24.json.gz +0 -0
  493. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-scenario.json +0 -58
  494. package/docs/evidence/terminal-2026-10-17-followup/omp-supplemental-static.json.gz +0 -0
  495. package/docs/evidence/terminal-2026-10-17-followup/rea-artifacts.json +0 -320
  496. package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.json +0 -30
  497. package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.md +0 -133
  498. package/docs/evidence/terminal-2026-10-17-followup/reference-source-observations.json +0 -20
  499. package/docs/evidence/terminal-2026-10-17-followup/verification.json +0 -207
  500. package/src/accounts/accounts.test.ts +0 -333
  501. package/src/accounts/accounts.ts +0 -658
  502. package/src/accounts/env.test.ts +0 -95
  503. package/src/accounts/env.ts +0 -338
  504. package/src/accounts/secrets.ts +0 -50
  505. package/src/accounts/store.ts +0 -338
  506. package/src/capabilities/api.ts +0 -75
  507. package/src/capabilities/runSnapshot.ts +0 -59
  508. package/src/capabilities/types.ts +0 -34
  509. package/src/cli.ts +0 -118
  510. package/src/core/bus.ts +0 -34
  511. package/src/core/changes.ts +0 -33
  512. package/src/core/env.ts +0 -27
  513. package/src/core/errors.ts +0 -32
  514. package/src/core/frontmatter.ts +0 -47
  515. package/src/core/fs.test.ts +0 -38
  516. package/src/core/fs.ts +0 -92
  517. package/src/core/index.ts +0 -193
  518. package/src/core/path.test.ts +0 -14
  519. package/src/core/path.ts +0 -79
  520. package/src/core/projects.ts +0 -90
  521. package/src/core/text.ts +0 -39
  522. package/src/harness.ts +0 -312
  523. package/src/hub/catalog.json +0 -123
  524. package/src/hub/cli.ts +0 -59
  525. package/src/hub/hub.test.ts +0 -205
  526. package/src/hub/hub.ts +0 -256
  527. package/src/hub/schema.ts +0 -81
  528. package/src/index.ts +0 -75
  529. package/src/mcp/connections.ts +0 -614
  530. package/src/mcp/manager.ts +0 -130
  531. package/src/mcp/oauth.ts +0 -195
  532. package/src/mcp/scopeMigration.test.ts +0 -79
  533. package/src/mcp/scopeMigration.ts +0 -204
  534. package/src/mcp/service.test.ts +0 -376
  535. package/src/mcp/service.ts +0 -549
  536. package/src/mcp/types.ts +0 -108
  537. package/src/memory/api.test.ts +0 -82
  538. package/src/memory/api.ts +0 -303
  539. package/src/memory/blocks.test.ts +0 -78
  540. package/src/memory/blocks.ts +0 -408
  541. package/src/memory/caller.ts +0 -69
  542. package/src/memory/curation.test.ts +0 -163
  543. package/src/memory/curation.ts +0 -64
  544. package/src/memory/dispatch.ts +0 -59
  545. package/src/memory/facts.test.ts +0 -41
  546. package/src/memory/facts.ts +0 -248
  547. package/src/memory/graph.ts +0 -103
  548. package/src/memory/health.test.ts +0 -130
  549. package/src/memory/health.ts +0 -74
  550. package/src/memory/maintainer.ts +0 -272
  551. package/src/memory/maintenance.test.ts +0 -176
  552. package/src/memory/maintenance.ts +0 -518
  553. package/src/memory/migrate.ts +0 -79
  554. package/src/memory/operations.ts +0 -150
  555. package/src/memory/proposals.test.ts +0 -168
  556. package/src/memory/proposals.ts +0 -584
  557. package/src/memory/recall.test.ts +0 -115
  558. package/src/memory/recall.ts +0 -278
  559. package/src/memory/references.ts +0 -77
  560. package/src/memory/runContext.ts +0 -93
  561. package/src/memory/secrets.ts +0 -6
  562. package/src/memory/store.test.ts +0 -66
  563. package/src/memory/store.ts +0 -385
  564. package/src/memory/wiki.test.ts +0 -47
  565. package/src/memory/wiki.ts +0 -422
  566. package/src/memory/wikiIndex.test.ts +0 -88
  567. package/src/memory/wikiIndex.ts +0 -116
  568. package/src/plugins/api.ts +0 -181
  569. package/src/plugins/attachments.test.ts +0 -84
  570. package/src/plugins/attachments.ts +0 -141
  571. package/src/plugins/builtin.ts +0 -82
  572. package/src/plugins/catalogue.test.ts +0 -254
  573. package/src/plugins/catalogue.ts +0 -251
  574. package/src/plugins/cli.ts +0 -184
  575. package/src/plugins/discover.ts +0 -151
  576. package/src/plugins/firstParty.test.ts +0 -143
  577. package/src/plugins/firstParty.ts +0 -129
  578. package/src/plugins/hooks.test.ts +0 -250
  579. package/src/plugins/hooks.ts +0 -239
  580. package/src/plugins/identity.ts +0 -37
  581. package/src/plugins/install.test.ts +0 -107
  582. package/src/plugins/install.ts +0 -106
  583. package/src/plugins/inventory.ts +0 -123
  584. package/src/plugins/manifest.ts +0 -76
  585. package/src/plugins/plugins.test.ts +0 -205
  586. package/src/plugins/plugins.ts +0 -189
  587. package/src/plugins/proposal.ts +0 -121
  588. package/src/plugins/runtime.test.ts +0 -40
  589. package/src/plugins/runtime.ts +0 -82
  590. package/src/plugins/trust.ts +0 -142
  591. package/src/plugins/types.ts +0 -149
  592. package/src/prompt/compile.test.ts +0 -261
  593. package/src/prompt/compile.ts +0 -732
  594. package/src/server/methods.ts +0 -349
  595. package/src/server/remote.ts +0 -77
  596. package/src/server/rpc.ts +0 -116
  597. package/src/server/serve.ts +0 -28
  598. package/src/server/server.test.ts +0 -174
  599. package/src/sessions/approvals.ts +0 -118
  600. package/src/sessions/contracts.ts +0 -336
  601. package/src/sessions/conversation.test.ts +0 -177
  602. package/src/sessions/extensionSession.test.ts +0 -74
  603. package/src/sessions/extensionUi.test.ts +0 -65
  604. package/src/sessions/extensionUi.ts +0 -102
  605. package/src/sessions/history.ts +0 -51
  606. package/src/sessions/lineageJoin.ts +0 -75
  607. package/src/sessions/policy.ts +0 -36
  608. package/src/sessions/pricing.ts +0 -60
  609. package/src/sessions/questionBatches.test.ts +0 -110
  610. package/src/sessions/reasoningSummaries.ts +0 -59
  611. package/src/sessions/registry.ts +0 -381
  612. package/src/sessions/runIndex.ts +0 -99
  613. package/src/sessions/runStore.test.ts +0 -152
  614. package/src/sessions/runStore.ts +0 -332
  615. package/src/sessions/runner.ts +0 -604
  616. package/src/sessions/runtimeResources.test.ts +0 -61
  617. package/src/sessions/sessions.test.ts +0 -549
  618. package/src/sessions/sessions.ts +0 -339
  619. package/src/skills/registry.test.ts +0 -104
  620. package/src/skills/registry.ts +0 -413
  621. package/src/terminal/accountsMenu.test.ts +0 -225
  622. package/src/terminal/accountsMenu.ts +0 -382
  623. package/src/terminal/cli.ts +0 -149
  624. package/src/terminal/client.ts +0 -74
  625. package/src/terminal/control.test.ts +0 -23
  626. package/src/terminal/control.ts +0 -23
  627. package/src/terminal/controller.ts +0 -291
  628. package/src/terminal/hubMenu.ts +0 -24
  629. package/src/terminal/launch.test.ts +0 -25
  630. package/src/terminal/launch.ts +0 -48
  631. package/src/terminal/piExtension.lifecycle.test.ts +0 -55
  632. package/src/terminal/piExtension.ts +0 -259
  633. package/src/terminal/pluginControl.test.ts +0 -146
  634. package/src/terminal/pluginMenu.ts +0 -112
  635. package/src/terminal/socket.test.ts +0 -71
  636. package/src/terminal/socket.ts +0 -232
  637. package/src/terminal/standalone.test.ts +0 -167
  638. package/src/terminal/standalone.ts +0 -153
  639. package/src/terminal/terminal.test.ts +0 -399
  640. package/src/terminal/terminals.ts +0 -553
  641. package/src/terminal/tui/application.test.ts +0 -114
  642. package/src/terminal/tui/application.ts +0 -491
  643. package/src/terminal/tui/commands.test.ts +0 -218
  644. package/src/terminal/tui/commands.ts +0 -361
  645. package/src/terminal/tui/dialogs.ts +0 -301
  646. package/src/terminal/tui/editor.test.ts +0 -84
  647. package/src/terminal/tui/editor.ts +0 -79
  648. package/src/terminal/tui/keybindings.test.ts +0 -22
  649. package/src/terminal/tui/keybindings.ts +0 -50
  650. package/src/terminal/tui/piAdapter.ts +0 -62
  651. package/src/terminal/tui/presentation.test.ts +0 -79
  652. package/src/terminal/tui/questions.test.ts +0 -41
  653. package/src/terminal/tui/questions.ts +0 -47
  654. package/src/terminal/tui/runtime.socket.test.ts +0 -104
  655. package/src/terminal/tui/runtime.test.ts +0 -215
  656. package/src/terminal/tui/runtime.ts +0 -388
  657. package/src/terminal/tui/sessionUi.ts +0 -24
  658. package/src/terminal/tui/settings.test.ts +0 -150
  659. package/src/terminal/tui/settings.ts +0 -188
  660. package/src/terminal/tui/status.test.ts +0 -70
  661. package/src/terminal/tui/status.ts +0 -109
  662. package/src/terminal/tui/theme.ts +0 -174
  663. package/src/terminal/tui/tools.test.ts +0 -145
  664. package/src/terminal/tui/tools.ts +0 -142
  665. package/src/terminal/tui/transcript.test.ts +0 -25
  666. package/src/terminal/tui/transcript.ts +0 -124
  667. package/src/terminal/tui/ui.test.ts +0 -313
  668. package/src/terminal/tui/ui.ts +0 -166
  669. package/src/terminal/tui/welcome.ts +0 -102
  670. package/src/tools/askUser.test.ts +0 -69
  671. package/src/tools/askUser.ts +0 -59
  672. package/src/tools/definitions.ts +0 -187
  673. package/src/tools/maintenance.ts +0 -24
  674. package/src/tools/memoryTools.ts +0 -22
  675. package/src/tools/pluginPropose.ts +0 -41
  676. package/src/tools/registryWrite.test.ts +0 -101
  677. package/src/tools/registryWrite.ts +0 -182
  678. package/src/tools/spawnSubagent.ts +0 -92
  679. package/src/tools/types.ts +0 -39
  680. package/src/web/safeRequest.ts +0 -171
  681. package/src/web/text.ts +0 -53
  682. package/src/web/tools.ts +0 -134
  683. package/src/web/web.test.ts +0 -141
@@ -1,549 +0,0 @@
1
- // Connected apps as sessions use them: which connections a session may reach, the two broker
2
- // tools every such session gets, approval of anything that is not a read, and a redacted record
3
- // of what each call returned.
4
- import { createHash, randomUUID } from 'node:crypto'
5
- import { join } from 'node:path'
6
-
7
- import type { SecretStore } from '../accounts/secrets'
8
- import type { Bus } from '../core/bus'
9
- import type { HarnessEnv } from '../core/env'
10
- import { HarnessError, invalid, notFound } from '../core/errors'
11
- import { newId, now, readJson, writeJson } from '../core/fs'
12
- import { charCount, takeChars } from '../core/text'
13
- import type { CapabilitySet } from '../capabilities/types'
14
- import type { CallerContext } from '../memory/caller'
15
- import type { ToolPolicy } from '../sessions/policy'
16
- import type { ActiveRun, RunRegistry } from '../sessions/registry'
17
- import { findRun, runDir } from '../sessions/runStore'
18
- import type { SessionBroker } from '../sessions/sessions'
19
- import type { ToolSession, ToolSpec } from '../tools/types'
20
- import { allowed, Connections, webUrl } from './connections'
21
- import { isSignInRequired, McpManager, signInRequired } from './manager'
22
- import { signIn, type OAuthHost } from './oauth'
23
- import type { Connection, HttpConfig, LaunchConfig, McpSource, McpTrace } from './types'
24
-
25
- /** A session's access to the broker. A terminal session presents `token`; an SDK session holds the object. */
26
- export interface BrokerSession {
27
- token: string
28
- sessionId: string
29
- runId: string | null
30
- caller: CallerContext
31
- /** Only reads are permitted. */
32
- readOnly: boolean
33
- depth: number
34
- /** The run's immutable tool and connector set. */
35
- capabilities?: CapabilitySet
36
- }
37
-
38
- export interface BrokerTool {
39
- name: string
40
- description?: string
41
- inputSchema?: unknown
42
- }
43
-
44
- /** Tools the embedding application offers through the broker, beside connected apps. */
45
- export interface BrokeredTools {
46
- list(session: BrokerSession): Promise<BrokerTool[]>
47
- has(name: string): boolean
48
- /** The tool's result as the application returns it: text, `{ text, image? }`, or structured data. */
49
- call(session: BrokerSession, name: string, args: Record<string, unknown>): Promise<unknown>
50
- /** Changes whenever the offered tools may have changed. */
51
- revision?(session: BrokerSession): Promise<unknown>
52
- /** A sentence added to the discovery tool's description, e.g. where the application lists the rest of its tools. */
53
- discoveryNote?: string
54
- }
55
-
56
- interface ListedTool extends BrokerTool {
57
- connectionId: string
58
- tool: string
59
- origin?: 'app'
60
- }
61
-
62
- const TOOL_SUMMARY_CHARS = 160
63
-
64
- /**
65
- * A tool listing a model can scan: a name and one line each. Input schemas are the bulk of a
66
- * discovery reply, so they come back for one named tool at a time.
67
- */
68
- export function compactTools<T extends BrokerTool>(tools: readonly T[], tool?: string): Array<Omit<T, 'inputSchema'> | T> {
69
- if (tool) return tools.filter((entry) => entry.name === tool)
70
- return tools.map(({ inputSchema: _schema, ...entry }) => ({
71
- ...entry,
72
- ...(entry.description && entry.description.length > TOOL_SUMMARY_CHARS ? { description: `${entry.description.slice(0, TOOL_SUMMARY_CHARS).trimEnd()}…` } : {})
73
- })) as Array<Omit<T, 'inputSchema'>>
74
- }
75
-
76
- /** Most tools one listing returns. A server with hundreds of tools would otherwise make every discovery call a very large input. */
77
- export const TOOL_PAGE = 40
78
-
79
- /**
80
- * One page of a tool listing: names and summaries only, optionally filtered by a
81
- * case-insensitive `query` over name and description. `more` and `nextOffset` appear when
82
- * entries remain.
83
- */
84
- export function pageTools<T extends BrokerTool>(tools: readonly T[], options: { query?: string; offset?: number; limit?: number } = {}) {
85
- const query = options.query?.trim().toLowerCase()
86
- const matching = query ? tools.filter((tool) => tool.name.toLowerCase().includes(query) || (tool.description ?? '').toLowerCase().includes(query)) : tools
87
- const offset = Math.max(0, Math.floor(options.offset ?? 0))
88
- const limit = Math.max(1, Math.min(Math.floor(options.limit ?? TOOL_PAGE), 100))
89
- const page = compactTools(matching.slice(offset, offset + limit))
90
- const next = offset + page.length
91
- return { tools: page, total: matching.length, ...(next < matching.length ? { more: matching.length - next, nextOffset: next } : {}) }
92
- }
93
-
94
- const WORKSPACE_READS = new Set([
95
- 'x_workspace_status', 'x_workspace_context', 'x_workspace_search', 'x_workspace_note_list', 'x_workspace_note_read', 'x_workspace_project_list', 'x_workspace_project_get',
96
- 'x_workspace_task_list', 'x_workspace_task_get', 'x_workspace_milestone_list', 'x_workspace_milestone_get', 'x_workspace_update_list', 'x_workspace_update_get',
97
- 'x_workspace_meeting_list', 'x_workspace_meeting_get', 'x_workspace_resource_list', 'x_workspace_resource_get', 'x_workspace_resource_preview'
98
- ])
99
-
100
- interface Proposal {
101
- runId: string
102
- sessionId: string
103
- connectionId: string
104
- data: unknown
105
- expiresAt: string
106
- }
107
-
108
- interface AuthorizedCall {
109
- session: BrokerSession
110
- connection: Connection
111
- runId: string
112
- }
113
-
114
- export interface ConnectedAppsOptions {
115
- env: HarnessEnv
116
- stateDir: string
117
- secrets: SecretStore
118
- bus: Bus
119
- runs: RunRegistry
120
- policy: ToolPolicy
121
- }
122
-
123
- /** The scope a plugin hook's connections are opened under: they belong to no session. */
124
- const UNATTENDED_SCOPE = 'plugin-hooks'
125
-
126
- export class ConnectedApps implements SessionBroker {
127
- readonly toolNames = ['mcp_list_tools', 'mcp_call_tool'] as const
128
- readonly connections: Connections
129
- private readonly manager: McpManager
130
- private readonly oauth: OAuthHost
131
- private readonly grants = new Map<string, BrokerSession>()
132
- private readonly proposals = new Map<string, Proposal>()
133
- private readonly calls = new Map<string, AuthorizedCall>()
134
- private brokered: BrokeredTools | null = null
135
-
136
- constructor(private readonly options: ConnectedAppsOptions) {
137
- this.connections = new Connections(options.stateDir, options.secrets, options.bus, () => options.env.root)
138
- this.oauth = {
139
- clientName: options.env.productName,
140
- load: (id) => this.connections.oauthLoad(id),
141
- save: (id, state) => this.connections.oauthSave(id, state),
142
- openUrl: (url) => {
143
- if (!webUrl(url)) throw invalid('The sign-in page must be an https:// address.')
144
- // The application shows the page; the harness never opens a browser by itself.
145
- options.bus.emit({ type: 'connections.openUrl', url })
146
- }
147
- }
148
- this.manager = new McpManager(this.oauth)
149
- }
150
-
151
- /** Loads what is needed to redact results. Call once before sessions start. */
152
- start(): Promise<void> {
153
- return this.connections.refreshSecrets()
154
- }
155
-
156
- /** Lets the application offer its own tools through `mcp_list_tools` and `mcp_call_tool`. */
157
- expose(tools: BrokeredTools): void {
158
- this.brokered = tools
159
- }
160
-
161
- // ---- Grants -----------------------------------------------------------------------------
162
-
163
- /** Gives a session access to the broker. The token is what a process outside the harness presents. */
164
- grant(input: Omit<BrokerSession, 'token'>): BrokerSession {
165
- const session: BrokerSession = { ...input, token: `${newId()}${newId()}` }
166
- this.grants.set(session.token, session)
167
- return session
168
- }
169
-
170
- session(token: string): BrokerSession {
171
- const session = this.grants.get(token)
172
- if (!session) throw new HarnessError('mcp_unauthorized', 'This MCP session is no longer authorized.')
173
- return session
174
- }
175
-
176
- revokeSession(sessionId: string): void {
177
- for (const [token, session] of this.grants) if (session.sessionId === sessionId) this.grants.delete(token)
178
- for (const [key, proposal] of this.proposals) if (proposal.sessionId === sessionId) this.proposals.delete(key)
179
- }
180
-
181
- /** A run ended: its grants, previews, and open client sessions go with it. */
182
- revokeRun(runId: string, sessionId: string): void {
183
- for (const [token, session] of this.grants) if (session.runId === runId) this.grants.delete(token)
184
- for (const [key, proposal] of this.proposals) if (proposal.runId === runId) this.proposals.delete(key)
185
- void this.manager.close(undefined, sessionId)
186
- }
187
-
188
- private activeRun(session: BrokerSession): ActiveRun {
189
- const run = (session.runId ? this.options.runs.active(session.runId) : null) ?? this.options.runs.activeForSession(session.sessionId)
190
- if (!run) throw new HarnessError('run_not_active', 'The requesting run has ended.')
191
- return run
192
- }
193
-
194
- private valid(session: BrokerSession): void {
195
- if (this.grants.get(session.token) !== session) throw new HarnessError('mcp_unauthorized', 'This MCP session is no longer authorized.')
196
- }
197
-
198
- // ---- What a session may reach ---------------------------------------------------------------
199
-
200
- private async reachable(session: BrokerSession): Promise<Connection[]> {
201
- const scoped = this.connections.forScope({ agentId: session.caller.agentId, projectId: session.caller.projectId })
202
- const frozen = session.capabilities ? scoped.filter((connection) => session.capabilities!.connectors.includes(connection.id)) : scoped
203
- const policy = this.options.policy.connections
204
- // Nothing to narrow: the application is not asked.
205
- if (!policy || !frozen.length) return frozen
206
- const ids = await policy({ sessionId: session.sessionId, runId: session.runId, caller: session.caller, connectionIds: frozen.map((connection) => connection.id) })
207
- return frozen.filter((connection) => ids.includes(connection.id))
208
- }
209
-
210
- /** The application's tools and every reachable connection's tools, with the connections that could not be read. */
211
- async list(session: BrokerSession): Promise<{ tools: ListedTool[]; errors: { connection: string; message: string }[] }> {
212
- const own = (await this.brokered?.list(session)) ?? []
213
- const discovered = await Promise.all(
214
- (await this.reachable(session)).map(async (connection) => {
215
- const tools: ListedTool[] = []
216
- let config: LaunchConfig | null = null
217
- try {
218
- config = await this.connections.launch(connection)
219
- const client = await this.manager.client(session.sessionId, config)
220
- for (const tool of (await client.listTools({}, { timeout: 15000 })).tools) {
221
- const alias = `mcp_${createHash('sha256').update(`${connection.id}:${tool.name}`).digest('hex').slice(0, 12)}_${tool.name.replace(/[^a-zA-Z0-9_]/g, '_').slice(0, 40)}`
222
- tools.push({ name: alias, description: `${connection.name}: ${tool.description ?? tool.name}`, inputSchema: tool.inputSchema, connectionId: connection.id, tool: tool.name })
223
- }
224
- if (client.getServerCapabilities()?.resources) {
225
- for (const operation of ['list', 'read'] as const) {
226
- tools.push({
227
- name: `mcp_${connection.id.replace(/-/g, '').slice(0, 12)}_resources_${operation}`,
228
- description: `${connection.name}: ${operation} MCP resources`,
229
- inputSchema: { type: 'object', properties: operation === 'read' ? { uri: { type: 'string' } } : {}, ...(operation === 'read' ? { required: ['uri'] } : {}) },
230
- connectionId: connection.id,
231
- tool: `resources/${operation}`
232
- })
233
- }
234
- }
235
- return { tools, errors: [] }
236
- } catch (error) {
237
- const unauthorized = isSignInRequired(error)
238
- const message = unauthorized ? signInRequired(connection).message : `${connection.name} could not load its tools. Check its scope in Capability → Connectors.`
239
- if (unauthorized) await this.manager.close(connection.id, session.sessionId)
240
- this.connectionFailed(connection.id, unauthorized)
241
- return { tools: [], errors: [{ connection: connection.name, message }] }
242
- }
243
- })
244
- )
245
- return {
246
- tools: [...own.map((tool): ListedTool => ({ ...tool, origin: 'app', connectionId: '__app__', tool: tool.name })), ...discovered.flatMap((entry) => entry.tools)],
247
- errors: discovered.flatMap((entry) => entry.errors)
248
- }
249
- }
250
-
251
- private connectionFailed(connectionId: string, unauthorized: boolean): void {
252
- try {
253
- this.connections.update(connectionId, (item) => {
254
- if (item.auth === 'oauth' && unauthorized) {
255
- item.authState = 'expired'
256
- item.error = `${item.name} needs you to sign in again.`
257
- } else if (item.kind === 'remote') {
258
- item.error = `${item.name} could not load its tools. Check its address and sign-in, then test or reconnect.`
259
- } else {
260
- item.error = `${item.name} could not load its tools. Check its executable and arguments, then test or reconnect.`
261
- }
262
- })
263
- this.connections.changed()
264
- } catch {
265
- // The connection was removed while it was being read.
266
- }
267
- }
268
-
269
- // ---- Calling ------------------------------------------------------------------------------
270
-
271
- /** Runs one tool by the name `list` gave it. */
272
- async invoke(session: BrokerSession, alias: string, args: Record<string, unknown>): Promise<unknown> {
273
- if (this.brokered?.has(alias)) {
274
- const result = await this.brokered.call(session, alias, args)
275
- const output = result as { text?: string; image?: { data: string; mimeType: string } } | null
276
- return {
277
- content: [{ type: 'text', text: output?.text ?? (typeof result === 'string' ? result : JSON.stringify(result)) }, ...(output?.image ? [{ type: 'image', ...output.image }] : [])],
278
- ...(!output?.image && result && typeof result === 'object' ? { structuredContent: Array.isArray(result) ? { result } : result } : {})
279
- }
280
- }
281
- const tool = (await this.list(session)).tools.find((candidate) => candidate.name === alias)
282
- if (!tool) throw new HarnessError('mcp_tool_unavailable', 'This MCP tool is unavailable or its connection was disabled.')
283
- const toolCallId = randomUUID()
284
- const config = await this.authorize(session, tool.connectionId, tool.tool, args, toolCallId)
285
- try {
286
- const client = await this.manager.client(session.sessionId, config)
287
- const result = tool.tool === 'resources/list' ? await client.listResources() : tool.tool === 'resources/read' ? await client.readResource({ uri: String(args.uri) }) : await client.callTool({ name: tool.tool, arguments: args }, { timeout: 60000 })
288
- this.completed(toolCallId, tool.tool, { result })
289
- return result
290
- } catch (error) {
291
- const message = error instanceof Error ? error.message : 'MCP call failed'
292
- this.completed(toolCallId, tool.tool, { error: tool.tool === 'x_workspace_mutation_apply' ? 'Workspace apply did not return a confirmed result. Do not retry automatically; read the affected record to verify its state.' : message })
293
- throw error
294
- }
295
- }
296
-
297
- /** Checks scope, asks for approval when the call is not a read, and returns how to reach the connection. */
298
- private async authorize(session: BrokerSession, connectionId: string, tool: string, args: Record<string, unknown>, toolCallId: string): Promise<LaunchConfig> {
299
- const run = this.activeRun(session)
300
- const record = findRun(this.options.env.root, run.runId)
301
- if (record) {
302
- const scope = await this.options.policy.scope?.({ run: record, caller: session.caller, tool: 'connected_app', args })
303
- if (scope && scope.automatic && !scope.allowed) throw new HarnessError('outside_work_scope', scope.reason ?? 'Outside the approved work scope.')
304
- }
305
- const denied = (): HarnessError => new HarnessError('mcp_access_denied', 'This connection is disabled or unavailable to this agent.')
306
- const connection = (await this.reachable(session)).find((item) => item.id === connectionId)
307
- if (!connection) throw denied()
308
- const workspace = connection.kind === 'workspace'
309
- const preview = workspace && tool === 'x_workspace_mutation_preview'
310
- const apply = workspace && tool === 'x_workspace_mutation_apply'
311
- const isRead = (workspace && WORKSPACE_READS.has(tool)) || (!apply && !preview && connection.readTools.includes(tool))
312
- if (session.readOnly && !isRead) throw new HarnessError('mcp_read_only', 'This session only permits reads from connected apps.')
313
- let proposal: unknown
314
- if (apply) {
315
- const approvalToken = typeof args.approvalToken === 'string' ? args.approvalToken : ''
316
- const saved = this.proposals.get(approvalToken)
317
- this.proposals.delete(approvalToken)
318
- if (!saved) throw new HarnessError('mcp_preview_required', 'Create a fresh preview in this run before applying.')
319
- if (saved.sessionId !== session.sessionId || saved.runId !== run.runId || saved.connectionId !== connectionId || saved.expiresAt <= now()) throw new HarnessError('mcp_preview_required', 'This preview belongs to another run or has expired.')
320
- proposal = saved.data
321
- }
322
- run.emit('tool.started', { toolCallId, name: tool, summary: connection.name })
323
- if (!isRead && !preview) {
324
- const action = JSON.stringify(proposal ?? this.connections.scrub(args, connection.id), null, 2)
325
- const decision = await run.requestApproval({ requestId: `mcp-${newId()}`, target: connection.name, action: `${tool}\n${action}`, standing: 'switch', timeoutMs: 300_000 })
326
- if (decision !== 'approved') {
327
- run.emit('tool.completed', { toolCallId, name: tool, ok: false })
328
- throw new HarnessError('mcp_denied', 'The user denied the MCP operation or its approval expired.')
329
- }
330
- }
331
- // Access may have been revoked, or the run ended, while the request was waiting.
332
- const current = (await this.reachable(session)).find((item) => item.id === connectionId)
333
- if (!current) throw new HarnessError('mcp_access_denied', 'Connection access was revoked while waiting.')
334
- this.valid(session)
335
- this.activeRun(session)
336
- this.calls.set(toolCallId, { session, connection: current, runId: run.runId })
337
- return this.connections.launch(current)
338
- }
339
-
340
- /** Records what an authorized call returned: a redacted trace with its sources, and the tool's outcome. */
341
- private completed(toolCallId: string, tool: string, outcome: { result?: unknown; error?: string }): void {
342
- const call = this.calls.get(toolCallId)
343
- if (!call) return
344
- this.calls.delete(toolCallId)
345
- const { connection, session, runId } = call
346
- const result = (outcome.result ?? null) as { structuredContent?: { data?: { approvalToken?: unknown; expiresAt?: unknown }; truncated?: unknown }; isError?: unknown } | null
347
- const structured = result?.structuredContent
348
- const live = this.grants.get(session.token) === session && this.options.runs.active(runId) !== null
349
- if (tool === 'x_workspace_mutation_preview' && live && typeof structured?.data?.approvalToken === 'string') {
350
- this.proposals.set(structured.data.approvalToken, { runId, sessionId: session.sessionId, connectionId: connection.id, data: this.connections.scrub(structured.data, connection.id), expiresAt: typeof structured.data.expiresAt === 'string' ? structured.data.expiresAt : '' })
351
- }
352
- const ok = outcome.error === undefined && result?.isError !== true
353
- const cleaned = this.connections.scrub(result, connection.id) as { structuredContent?: { sources?: unknown } } | null
354
- const raw = outcome.error === undefined ? JSON.stringify(cleaned) : String(this.connections.scrub(outcome.error, connection.id))
355
- const found = cleaned?.structuredContent?.sources
356
- const sources: McpSource[] = (Array.isArray(found) ? found : [])
357
- .flatMap((source: Record<string, unknown> | null) => {
358
- if (!source || typeof source.id !== 'string' || typeof source.title !== 'string' || typeof source.uri !== 'string') return []
359
- const value: McpSource = { id: source.id, title: source.title, uri: source.uri, path: typeof source.path === 'string' ? source.path : null }
360
- for (const field of ['revision', 'excerpt', 'projectId'] as const) if (typeof source[field] === 'string') value[field] = takeChars(source[field] as string, 2000)
361
- return [value]
362
- })
363
- .slice(0, 100)
364
- const trace: McpTrace = { id: toolCallId, connectionId: connection.id, connectionName: connection.name, tool, at: now(), ok, summary: tool, result: takeChars(raw, 24000), sources, truncated: charCount(raw) > 24000 || structured?.truncated === true }
365
- try {
366
- const file = join(runDir(this.options.env.root, runId), 'mcp-context.json')
367
- writeJson(file, [...(readJson<McpTrace[]>(file) ?? []), trace])
368
- } catch {
369
- // The call happened; a trace that cannot be written does not undo it.
370
- }
371
- this.options.runs.active(runId)?.emit('tool.completed', { toolCallId, name: tool, ok })
372
- }
373
-
374
- /** What a run retrieved from connected apps, in order. */
375
- runContext(runId: string): McpTrace[] {
376
- return readJson<McpTrace[]>(join(runDir(this.options.env.root, runId), 'mcp-context.json')) ?? []
377
- }
378
-
379
- /** Changes whenever what a session can discover may have changed. */
380
- async revision(session: BrokerSession): Promise<unknown> {
381
- return { connections: this.connections.revision(), tools: (await this.brokered?.revision?.(session)) ?? null }
382
- }
383
-
384
- // ---- The two tools a session gets -------------------------------------------------------------
385
-
386
- tools(session: ToolSession, options: { readOnly: boolean }): ToolSpec[] {
387
- const granted = this.grant({ sessionId: session.run.sessionId, runId: session.run.runId, caller: session.caller, readOnly: options.readOnly, depth: session.depth, capabilities: session.capabilities })
388
- return this.brokerTools(granted)
389
- }
390
-
391
- /** `mcp_list_tools` and `mcp_call_tool` bound to a granted session. */
392
- brokerTools(session: BrokerSession): ToolSpec[] {
393
- return [
394
- {
395
- name: 'mcp_list_tools',
396
- label: 'App and connector tools',
397
- description: `Discover enabled ${this.options.env.productName} app operations and connector tools by name. Pass tool to get one tool with its input schema.${this.brokered?.discoveryNote ? ` ${this.brokered.discoveryNote}` : ''}`,
398
- parameters: (Type) =>
399
- Type.Object({
400
- tool: Type.Optional(Type.String({ description: 'One tool name, to get its input schema.' })),
401
- query: Type.Optional(Type.String({ description: 'Only tools whose name or description contains this text.' })),
402
- offset: Type.Optional(Type.Integer({ minimum: 0, description: 'Where to continue a long list (nextOffset from the previous page).' }))
403
- }),
404
- execute: async (input) => {
405
- const listed = await this.list(session)
406
- const wanted = typeof input.tool === 'string' && input.tool ? input.tool : undefined
407
- if (wanted) return JSON.stringify({ ...listed, tools: compactTools(listed.tools, wanted) })
408
- const page = pageTools(listed.tools, { query: typeof input.query === 'string' ? input.query : undefined, offset: typeof input.offset === 'number' ? input.offset : undefined })
409
- return JSON.stringify({ ...listed, ...page, note: `Names and summaries only. Call mcp_list_tools with tool for the input schema before the first call to that tool.${page.more ? ' More tools match: pass offset, and query to narrow the list.' : ''}` })
410
- }
411
- },
412
- {
413
- name: 'mcp_call_tool',
414
- label: 'Use connector',
415
- description: 'Invoke an enabled app or connector tool returned by mcp_list_tools. Current settings are checked on every call. Changes require approval.',
416
- parameters: (Type) => Type.Object({ name: Type.String(), arguments: Type.Record(Type.String(), Type.Unknown()) }),
417
- execute: async (input) => JSON.stringify(await this.invoke(session, String(input.name), (input.arguments ?? {}) as Record<string, unknown>))
418
- }
419
- ]
420
- }
421
-
422
- // ---- What a person does on the Connections screen ---------------------------------------------
423
-
424
- async save(input: Parameters<Connections['save']>[0]): Promise<Connection> {
425
- const connection = await this.connections.save(input)
426
- this.cancelConnection(connection.id)
427
- return connection
428
- }
429
-
430
- async remove(connectionId: string): Promise<void> {
431
- await this.connections.remove(connectionId)
432
- this.cancelConnection(connectionId)
433
- }
434
-
435
- private cancelConnection(connectionId: string): void {
436
- for (const [key, proposal] of this.proposals) if (proposal.connectionId === connectionId) this.proposals.delete(key)
437
- void this.manager.close(connectionId)
438
- }
439
-
440
- /** Connects once and records what the server offers, or why it could not be reached. */
441
- async test(connectionId: string): Promise<Connection> {
442
- const connection = this.connections.find(connectionId)
443
- let probed: Awaited<ReturnType<McpManager['probe']>> | null = null
444
- let failure: unknown = null
445
- try {
446
- probed = await this.manager.probe(await this.connections.launch(connection))
447
- } catch (error) {
448
- failure = error
449
- }
450
- if (JSON.stringify(this.connections.find(connectionId)) !== JSON.stringify(connection)) throw new HarnessError('mcp_config_changed', 'Connection changed during its test. Test the saved connection again.')
451
- const updated = this.connections.update(connectionId, (item) => {
452
- item.checkedAt = now()
453
- if (probed) {
454
- item.serverName = probed.serverName
455
- item.tools = probed.tools
456
- item.error = null
457
- if (item.kind === 'workspace' && !item.expectedVaultId) item.expectedVaultId = probed.vaultId
458
- } else {
459
- if (isSignInRequired(failure) && item.auth === 'oauth' && item.authState === 'signed_in') item.authState = 'expired'
460
- item.error = failure instanceof Error ? failure.message : String(failure)
461
- item.tools = []
462
- }
463
- })
464
- this.connections.changed()
465
- return updated
466
- }
467
-
468
- /** Signs in with the provider in a browser. Only a person starts this; a session that finds an expired sign-in reports it. */
469
- async signIn(connectionId: string): Promise<Connection> {
470
- const connection = this.connections.find(connectionId)
471
- if (connection.kind !== 'remote' || connection.auth !== 'oauth') throw invalid('This connection does not use browser sign-in.')
472
- if (connection.oauthClient === 'user' && !(await this.connections.hasOauthClient(connection.id))) throw invalid('Add your OAuth client ID before signing in.')
473
- await signIn(this.oauth, (await this.connections.launch(connection)) as HttpConfig)
474
- const updated = this.connections.update(connectionId, (item) => Object.assign(item, { authState: 'signed_in', error: null }))
475
- await this.manager.close(connectionId)
476
- this.connections.changed()
477
- return updated
478
- }
479
-
480
- async signOut(connectionId: string): Promise<Connection> {
481
- const updated = await this.connections.signOut(connectionId)
482
- this.cancelConnection(connectionId)
483
- return updated
484
- }
485
-
486
- /** Reads one retrieved source again from the Xingular Workspace connection it came from. */
487
- async refreshSource(runId: string, traceId: string, sourceUri: string): Promise<unknown> {
488
- const trace = this.runContext(runId).find((entry) => entry.id === traceId)
489
- if (!trace) throw notFound('Retrieved context')
490
- const source = trace.sources.find((entry) => entry.uri === sourceUri)
491
- if (!source) throw notFound('Source')
492
- const connection = this.connections.list().find((item) => item.enabled && item.kind === 'workspace' && item.id === trace.connectionId)
493
- if (!connection) throw new HarnessError('mcp_access_denied', 'Enable the original Xingular Workspace connection to refresh this source.')
494
- const kind = sourceUri.split('/')[3] ?? ''
495
- const [tool, args]: [string, Record<string, unknown>] = kind.startsWith('note')
496
- ? ['x_workspace_note_read', { path: source.path ?? source.id }]
497
- : kind.startsWith('task')
498
- ? ['x_workspace_task_get', { id: source.id }]
499
- : kind.startsWith('project')
500
- ? ['x_workspace_project_get', { id: source.id }]
501
- : kind.startsWith('resource')
502
- ? ['x_workspace_resource_get', { id: source.id }]
503
- : ['x_workspace_context', { query: source.title || source.id }]
504
- return this.connections.scrub(await this.manager.readSource(await this.connections.launch(connection), tool, args), connection.id)
505
- }
506
-
507
- /** Gives one agent exactly these connections, if its creator may reach each of them. */
508
- setAgentScope(creator: { agentId?: string | null; projectId?: string | null }, agentId: string, ids: readonly string[]): Connection[] {
509
- const all = this.connections.list()
510
- for (const id of ids) {
511
- const connection = all.find((item) => item.id === id)
512
- if (!connection) throw notFound('Connection')
513
- if (!allowed(connection, creator)) throw new HarnessError('required_connections_unavailable', `${connection.name} is disabled or outside your connection scope.`)
514
- }
515
- return this.connections.setAgentScope(agentId, ids)
516
- }
517
-
518
- /**
519
- * A call with no session and nobody to ask, made by a plugin's hook. It reaches a connection
520
- * only when it is on for everyone, and a tool only when a person marked it to run without asking.
521
- */
522
- async callUnattended(reference: string, tool: string, args: Record<string, unknown> = {}): Promise<unknown> {
523
- const connection = this.connections.list().find((item) => item.id === reference || item.name === reference)
524
- if (!connection || !allowed(connection, {})) throw new HarnessError('mcp_access_denied', `There is no connected app called "${reference}" that is on for everyone.`)
525
- // A change to the first-party workspace is previewed and approved by a person, never run from a hook.
526
- if (!connection.readTools.includes(tool) || tool.startsWith('x_workspace_mutation')) {
527
- throw new HarnessError('mcp_denied', `${connection.name} asks before running "${tool}". Mark it to run without asking in the connection's settings to let a plugin use it.`)
528
- }
529
- const client = await this.manager.client(UNATTENDED_SCOPE, await this.connections.launch(connection))
530
- return client.callTool({ name: tool, arguments: args }, { timeout: 60000 })
531
- }
532
-
533
- /** Switches one saved connection on or off for everyone, one agent, or one project. */
534
- attach(connectionId: string, scope: { agentId?: string | null; projectId?: string | null }, on: boolean): void {
535
- const connection = this.connections.find(connectionId)
536
- if (!connection.enabled) throw invalid(`${connection.name} is switched off. Switch it on in its own settings first.`)
537
- this.connections.setScope(connectionId, scope, on)
538
- }
539
-
540
- /** Forgets an agent that no longer exists. */
541
- removeAgentScope(agentId: string): void {
542
- this.connections.removeAgentScope(agentId)
543
- }
544
-
545
- async close(): Promise<void> {
546
- await this.manager.close(undefined, UNATTENDED_SCOPE).catch(() => undefined)
547
- await this.manager.close()
548
- }
549
- }
package/src/mcp/types.ts DELETED
@@ -1,108 +0,0 @@
1
- // Connected apps: MCP servers the user added. A connection is device-local; its secrets
2
- // (environment values, request headers, OAuth tokens and client) are in the secret store,
3
- // never in `connections.json`.
4
- import { z } from 'zod'
5
-
6
- /** Loopback address every OAuth sign-in returns to. Pre-registered clients must list it exactly. */
7
- export const MCP_OAUTH_PORT = 47823
8
- export const MCP_OAUTH_REDIRECT_URL = `http://127.0.0.1:${MCP_OAUTH_PORT}/oauth/callback`
9
-
10
- /** Stable attachment key for a connected app's capability switch. */
11
- export const connectionCapabilityId = (id: string): string => `connected-apps/connection/${id}`
12
-
13
- export const connectionSchema = z.object({
14
- id: z.string().default(''),
15
- name: z.string().default(''),
16
- /** `workspace` (the first-party Xingular Workspace server), `local` (a command), or `remote` (Streamable HTTP). */
17
- kind: z.string().default(''),
18
- command: z.string().default(''),
19
- args: z.array(z.string()).default([]),
20
- cwd: z.string().nullable().default(null),
21
- envKeys: z.array(z.string()).default([]),
22
- enabled: z.boolean().default(false),
23
- /** Available to every agent and project, except those excluded. */
24
- global: z.boolean().default(false),
25
- agentIds: z.array(z.string()).default([]),
26
- projectIds: z.array(z.string()).default([]),
27
- excludedAgentIds: z.array(z.string()).default([]),
28
- excludedProjectIds: z.array(z.string()).default([]),
29
- /** Tools that run without asking. */
30
- readTools: z.array(z.string()).default([]),
31
- expectedVaultId: z.string().nullable().default(null),
32
- checkedAt: z.string().nullable().default(null),
33
- serverName: z.string().nullable().default(null),
34
- tools: z.array(z.unknown()).default([]),
35
- error: z.string().nullable().default(null),
36
- url: z.string().nullable().default(null),
37
- /** `none`, `headers`, or `oauth`. */
38
- auth: z.string().default(''),
39
- headerKeys: z.array(z.string()).default([]),
40
- oauthClient: z.string().nullable().default(null),
41
- oauthScopes: z.array(z.string()).default([]),
42
- authState: z.string().nullable().default(null),
43
- catalogId: z.string().nullable().default(null)
44
- })
45
- export type Connection = z.infer<typeof connectionSchema>
46
-
47
- export const connectionInputSchema = connectionSchema.extend({
48
- env: z.record(z.string(), z.string()).nullish(),
49
- removeEnv: z.array(z.string()).nullish(),
50
- headers: z.record(z.string(), z.string()).nullish(),
51
- removeHeaders: z.array(z.string()).nullish(),
52
- /** A client registered by the user with the provider; replaces any saved sign-in. */
53
- oauthCredentials: z.object({ clientId: z.string(), clientSecret: z.string() }).nullish()
54
- })
55
- export type ConnectionInput = z.input<typeof connectionInputSchema>
56
-
57
- export interface StdioConfig {
58
- id: string
59
- name: string
60
- transport: 'stdio'
61
- command: string
62
- args: string[]
63
- cwd: string | null
64
- env: Record<string, string>
65
- }
66
-
67
- export interface HttpConfig {
68
- id: string
69
- name: string
70
- transport: 'http'
71
- url: string
72
- headers: Record<string, string>
73
- auth: 'none' | 'headers' | 'oauth'
74
- scopes: string[]
75
- }
76
-
77
- /** What it takes to reach a server: a process to start, or an address and its credentials. */
78
- export type LaunchConfig = StdioConfig | HttpConfig
79
-
80
- /** Who a session is, for deciding which connections it may reach. */
81
- export interface Scope {
82
- agentId?: string | null
83
- projectId?: string | null
84
- }
85
-
86
- export interface McpSource {
87
- id: string
88
- title: string
89
- uri: string
90
- path?: string | null
91
- revision?: string
92
- excerpt?: string
93
- projectId?: string
94
- }
95
-
96
- /** One connected-app call a run made, kept in `runs/<id>/mcp-context.json`. */
97
- export interface McpTrace {
98
- id: string
99
- connectionId: string
100
- connectionName: string
101
- tool: string
102
- at: string
103
- ok: boolean
104
- summary: string
105
- result: string
106
- sources: McpSource[]
107
- truncated: boolean
108
- }