@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
@@ -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
- }