@xingular/harness 0.1.6 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (593) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE.md +60 -0
  4. package/README.md +265 -71
  5. package/THIRD_PARTY_LICENSES.md +942 -0
  6. package/dist/cli.js +14842 -9445
  7. package/dist/sdk/accounts/accounts.d.ts +165 -0
  8. package/dist/sdk/accounts/accounts.js +730 -0
  9. package/dist/sdk/accounts/choices.d.ts +23 -0
  10. package/dist/sdk/accounts/choices.js +62 -0
  11. package/dist/sdk/accounts/env.d.ts +78 -0
  12. package/dist/sdk/accounts/env.js +294 -0
  13. package/dist/sdk/accounts/secrets.d.ts +16 -0
  14. package/dist/sdk/accounts/secrets.js +40 -0
  15. package/dist/sdk/accounts/store.d.ts +114 -0
  16. package/dist/sdk/accounts/store.js +255 -0
  17. package/dist/sdk/browser/config.d.ts +16 -0
  18. package/dist/sdk/browser/config.js +22 -0
  19. package/dist/sdk/browser/diagnostics.d.ts +4 -0
  20. package/dist/sdk/browser/diagnostics.js +38 -0
  21. package/dist/sdk/browser/index.d.ts +17 -0
  22. package/dist/sdk/browser/index.js +65 -0
  23. package/dist/sdk/browser/network.d.ts +10 -0
  24. package/dist/sdk/browser/network.js +59 -0
  25. package/dist/sdk/browser/session.d.ts +84 -0
  26. package/dist/sdk/browser/session.js +192 -0
  27. package/dist/sdk/browser/tools.d.ts +8 -0
  28. package/dist/sdk/browser/tools.js +329 -0
  29. package/dist/sdk/capabilities/api.d.ts +22 -0
  30. package/dist/sdk/capabilities/api.js +54 -0
  31. package/dist/sdk/capabilities/runSnapshot.d.ts +18 -0
  32. package/dist/sdk/capabilities/runSnapshot.js +47 -0
  33. package/dist/sdk/capabilities/types.d.ts +29 -0
  34. package/dist/sdk/capabilities/types.js +1 -0
  35. package/dist/sdk/cli.d.ts +2 -0
  36. package/dist/sdk/cli.js +142 -0
  37. package/dist/sdk/core/bus.d.ts +23 -0
  38. package/dist/sdk/core/bus.js +76 -0
  39. package/dist/sdk/core/caller.d.ts +22 -0
  40. package/dist/sdk/core/caller.js +16 -0
  41. package/dist/sdk/core/changes.d.ts +15 -0
  42. package/dist/sdk/core/changes.js +15 -0
  43. package/dist/sdk/core/effort.d.ts +2 -0
  44. package/dist/sdk/core/effort.js +1 -0
  45. package/dist/sdk/core/env.d.ts +18 -0
  46. package/dist/sdk/core/env.js +8 -0
  47. package/dist/sdk/core/errors.d.ts +15 -0
  48. package/dist/sdk/core/errors.js +24 -0
  49. package/dist/sdk/core/frontmatter.d.ts +12 -0
  50. package/dist/sdk/core/frontmatter.js +50 -0
  51. package/dist/sdk/core/fs.d.ts +18 -0
  52. package/dist/sdk/core/fs.js +106 -0
  53. package/dist/sdk/core/index.d.ts +24 -0
  54. package/dist/sdk/core/index.js +187 -0
  55. package/dist/sdk/core/path.d.ts +7 -0
  56. package/dist/sdk/core/path.js +79 -0
  57. package/dist/sdk/core/projects.d.ts +18 -0
  58. package/dist/sdk/core/projects.js +67 -0
  59. package/dist/sdk/core/secrets.d.ts +2 -0
  60. package/dist/sdk/core/secrets.js +5 -0
  61. package/dist/sdk/core/text.d.ts +7 -0
  62. package/dist/sdk/core/text.js +40 -0
  63. package/dist/sdk/doctor/checks.d.ts +5 -0
  64. package/dist/sdk/doctor/checks.js +208 -0
  65. package/dist/sdk/doctor/probe.d.ts +4 -0
  66. package/dist/sdk/doctor/probe.js +92 -0
  67. package/dist/sdk/doctor/service.d.ts +23 -0
  68. package/dist/sdk/doctor/service.js +144 -0
  69. package/dist/sdk/doctor/types.d.ts +141 -0
  70. package/dist/sdk/doctor/types.js +29 -0
  71. package/dist/sdk/harness.d.ts +133 -0
  72. package/dist/sdk/harness.js +299 -0
  73. package/dist/sdk/history/lessonPrompt.d.ts +2 -0
  74. package/dist/sdk/history/lessonPrompt.js +15 -0
  75. package/dist/sdk/history/lessons.d.ts +52 -0
  76. package/dist/sdk/history/lessons.js +173 -0
  77. package/dist/sdk/history/recall.d.ts +68 -0
  78. package/dist/sdk/history/recall.js +199 -0
  79. package/dist/sdk/history/trajectory.d.ts +7 -0
  80. package/dist/sdk/history/trajectory.js +216 -0
  81. package/dist/sdk/hub/catalog.json +123 -0
  82. package/dist/sdk/hub/cli.d.ts +7 -0
  83. package/dist/sdk/hub/cli.js +81 -0
  84. package/dist/sdk/hub/hub.d.ts +74 -0
  85. package/dist/sdk/hub/hub.js +474 -0
  86. package/dist/sdk/hub/schema.d.ts +280 -0
  87. package/dist/sdk/hub/schema.js +78 -0
  88. package/dist/sdk/index.d.ts +63 -0
  89. package/dist/sdk/index.js +48 -0
  90. package/dist/sdk/mcp/connections.d.ts +83 -0
  91. package/dist/sdk/mcp/connections.js +669 -0
  92. package/dist/sdk/mcp/manager.d.ts +26 -0
  93. package/dist/sdk/mcp/manager.js +124 -0
  94. package/dist/sdk/mcp/oauth.d.ts +35 -0
  95. package/dist/sdk/mcp/oauth.js +171 -0
  96. package/dist/sdk/mcp/scopeMigration.d.ts +19 -0
  97. package/dist/sdk/mcp/scopeMigration.js +198 -0
  98. package/dist/sdk/mcp/service.d.ts +160 -0
  99. package/dist/sdk/mcp/service.js +510 -0
  100. package/dist/sdk/mcp/types.d.ts +131 -0
  101. package/dist/sdk/mcp/types.js +49 -0
  102. package/dist/sdk/pi/runtime.d.ts +13 -0
  103. package/dist/sdk/pi/runtime.js +31 -0
  104. package/dist/sdk/plugins/api.d.ts +66 -0
  105. package/dist/sdk/plugins/api.js +155 -0
  106. package/dist/sdk/plugins/attachments.d.ts +46 -0
  107. package/dist/sdk/plugins/attachments.js +111 -0
  108. package/dist/sdk/plugins/builtin.d.ts +6 -0
  109. package/dist/sdk/plugins/builtin.js +68 -0
  110. package/dist/sdk/plugins/catalogue.d.ts +29 -0
  111. package/dist/sdk/plugins/catalogue.js +196 -0
  112. package/dist/sdk/plugins/cli.d.ts +13 -0
  113. package/dist/sdk/plugins/cli.js +187 -0
  114. package/dist/sdk/plugins/discover.d.ts +42 -0
  115. package/dist/sdk/plugins/discover.js +115 -0
  116. package/dist/sdk/plugins/firstParty.d.ts +50 -0
  117. package/dist/sdk/plugins/firstParty.js +113 -0
  118. package/dist/sdk/plugins/hooks.d.ts +94 -0
  119. package/dist/sdk/plugins/hooks.js +162 -0
  120. package/dist/sdk/plugins/identity.d.ts +19 -0
  121. package/dist/sdk/plugins/identity.js +48 -0
  122. package/dist/sdk/plugins/install.d.ts +20 -0
  123. package/dist/sdk/plugins/install.js +110 -0
  124. package/dist/sdk/plugins/inventory.d.ts +22 -0
  125. package/dist/sdk/plugins/inventory.js +110 -0
  126. package/dist/sdk/plugins/manifest.d.ts +13 -0
  127. package/dist/sdk/plugins/manifest.js +56 -0
  128. package/dist/sdk/plugins/plugins.d.ts +104 -0
  129. package/dist/sdk/plugins/plugins.js +164 -0
  130. package/dist/sdk/plugins/runtime.d.ts +9 -0
  131. package/dist/sdk/plugins/runtime.js +95 -0
  132. package/dist/sdk/plugins/trust.d.ts +44 -0
  133. package/dist/sdk/plugins/trust.js +120 -0
  134. package/dist/sdk/plugins/types.d.ts +159 -0
  135. package/dist/sdk/plugins/types.js +7 -0
  136. package/dist/sdk/prompt/compile.d.ts +174 -0
  137. package/dist/sdk/prompt/compile.js +396 -0
  138. package/dist/sdk/refine/cli.d.ts +4 -0
  139. package/dist/sdk/refine/cli.js +186 -0
  140. package/dist/sdk/refine/demo.d.ts +21 -0
  141. package/dist/sdk/refine/demo.js +114 -0
  142. package/dist/sdk/refine/evidence.d.ts +55 -0
  143. package/dist/sdk/refine/evidence.js +330 -0
  144. package/dist/sdk/refine/host.d.ts +51 -0
  145. package/dist/sdk/refine/host.js +76 -0
  146. package/dist/sdk/refine/ledger.d.ts +48 -0
  147. package/dist/sdk/refine/ledger.js +76 -0
  148. package/dist/sdk/refine/library.d.ts +55 -0
  149. package/dist/sdk/refine/library.js +177 -0
  150. package/dist/sdk/refine/pi.d.ts +72 -0
  151. package/dist/sdk/refine/pi.js +248 -0
  152. package/dist/sdk/refine/prompts.d.ts +45 -0
  153. package/dist/sdk/refine/prompts.js +390 -0
  154. package/dist/sdk/refine/recursion.d.ts +113 -0
  155. package/dist/sdk/refine/recursion.js +258 -0
  156. package/dist/sdk/refine/runner.d.ts +81 -0
  157. package/dist/sdk/refine/runner.js +150 -0
  158. package/dist/sdk/refine/selection.d.ts +57 -0
  159. package/dist/sdk/refine/selection.js +251 -0
  160. package/dist/sdk/refine/service.d.ts +84 -0
  161. package/dist/sdk/refine/service.js +165 -0
  162. package/dist/sdk/refine/suite.d.ts +67 -0
  163. package/dist/sdk/refine/suite.js +174 -0
  164. package/dist/sdk/refine/trajectory.d.ts +9 -0
  165. package/dist/sdk/refine/trajectory.js +68 -0
  166. package/dist/sdk/refine/types.d.ts +77 -0
  167. package/dist/sdk/refine/types.js +10 -0
  168. package/dist/sdk/server/methods.d.ts +3 -0
  169. package/dist/sdk/server/methods.js +370 -0
  170. package/dist/sdk/server/remote.d.ts +19 -0
  171. package/dist/sdk/server/remote.js +84 -0
  172. package/dist/sdk/server/rpc.d.ts +20 -0
  173. package/dist/sdk/server/rpc.js +102 -0
  174. package/dist/sdk/server/serve.d.ts +10 -0
  175. package/dist/sdk/server/serve.js +18 -0
  176. package/dist/sdk/sessions/approvals.d.ts +47 -0
  177. package/dist/sdk/sessions/approvals.js +119 -0
  178. package/dist/sdk/sessions/continuation.d.ts +48 -0
  179. package/dist/sdk/sessions/continuation.js +85 -0
  180. package/dist/sdk/sessions/contracts.d.ts +534 -0
  181. package/dist/sdk/sessions/contracts.js +299 -0
  182. package/dist/sdk/sessions/extensionUi.d.ts +19 -0
  183. package/dist/sdk/sessions/extensionUi.js +64 -0
  184. package/dist/sdk/sessions/history.d.ts +16 -0
  185. package/dist/sdk/sessions/history.js +68 -0
  186. package/dist/sdk/sessions/lineageJoin.d.ts +2 -0
  187. package/dist/sdk/sessions/lineageJoin.js +61 -0
  188. package/dist/sdk/sessions/planMode.d.ts +36 -0
  189. package/dist/sdk/sessions/planMode.js +84 -0
  190. package/dist/sdk/sessions/policy.d.ts +43 -0
  191. package/dist/sdk/sessions/policy.js +1 -0
  192. package/dist/sdk/sessions/pricing.d.ts +34 -0
  193. package/dist/sdk/sessions/pricing.js +40 -0
  194. package/dist/sdk/sessions/reasoningSummaries.d.ts +11 -0
  195. package/dist/sdk/sessions/reasoningSummaries.js +61 -0
  196. package/dist/sdk/sessions/registry.d.ts +102 -0
  197. package/dist/sdk/sessions/registry.js +383 -0
  198. package/dist/sdk/sessions/runIndex.d.ts +21 -0
  199. package/dist/sdk/sessions/runIndex.js +65 -0
  200. package/dist/sdk/sessions/runStore.d.ts +66 -0
  201. package/dist/sdk/sessions/runStore.js +335 -0
  202. package/dist/sdk/sessions/runner.d.ts +213 -0
  203. package/dist/sdk/sessions/runner.js +589 -0
  204. package/dist/sdk/sessions/sessions.d.ts +140 -0
  205. package/dist/sdk/sessions/sessions.js +394 -0
  206. package/dist/sdk/sessions/subagentService.d.ts +41 -0
  207. package/dist/sdk/sessions/subagentService.js +247 -0
  208. package/dist/sdk/sessions/subagents.d.ts +50 -0
  209. package/dist/sdk/sessions/subagents.js +68 -0
  210. package/dist/sdk/terminal/accountsMenu.d.ts +46 -0
  211. package/dist/sdk/terminal/accountsMenu.js +392 -0
  212. package/dist/sdk/terminal/cli.d.ts +20 -0
  213. package/dist/sdk/terminal/cli.js +121 -0
  214. package/dist/sdk/terminal/client.d.ts +15 -0
  215. package/dist/sdk/terminal/client.js +126 -0
  216. package/dist/sdk/terminal/control.d.ts +4 -0
  217. package/dist/sdk/terminal/control.js +25 -0
  218. package/dist/sdk/terminal/controller.d.ts +72 -0
  219. package/dist/sdk/terminal/controller.js +351 -0
  220. package/dist/sdk/terminal/hubMenu.d.ts +10 -0
  221. package/dist/sdk/terminal/hubMenu.js +34 -0
  222. package/dist/sdk/terminal/launch.d.ts +5 -0
  223. package/dist/sdk/terminal/launch.js +27 -0
  224. package/dist/sdk/terminal/logs.d.ts +14 -0
  225. package/dist/sdk/terminal/logs.js +59 -0
  226. package/dist/sdk/terminal/piExtension.d.ts +6 -0
  227. package/dist/sdk/terminal/piExtension.js +392 -0
  228. package/dist/sdk/terminal/pluginMenu.d.ts +34 -0
  229. package/dist/sdk/terminal/pluginMenu.js +101 -0
  230. package/dist/sdk/terminal/socket.d.ts +70 -0
  231. package/dist/sdk/terminal/socket.js +256 -0
  232. package/dist/sdk/terminal/standalone.d.ts +18 -0
  233. package/dist/sdk/terminal/standalone.js +146 -0
  234. package/dist/sdk/terminal/terminals.d.ts +176 -0
  235. package/dist/sdk/terminal/terminals.js +767 -0
  236. package/dist/sdk/terminal/trajectory.d.ts +10 -0
  237. package/dist/sdk/terminal/trajectory.js +30 -0
  238. package/dist/sdk/terminal/tui/chrome.d.ts +64 -0
  239. package/dist/sdk/terminal/tui/chrome.js +169 -0
  240. package/dist/sdk/terminal/tui/clipboardFiles.d.ts +11 -0
  241. package/dist/sdk/terminal/tui/clipboardFiles.js +74 -0
  242. package/dist/sdk/terminal/tui/commandPages.d.ts +7 -0
  243. package/dist/sdk/terminal/tui/commandPages.js +63 -0
  244. package/dist/sdk/terminal/tui/commands.d.ts +42 -0
  245. package/dist/sdk/terminal/tui/commands.js +276 -0
  246. package/dist/sdk/terminal/tui/dialogGeometry.d.ts +27 -0
  247. package/dist/sdk/terminal/tui/dialogGeometry.js +50 -0
  248. package/dist/sdk/terminal/tui/dialogs.d.ts +75 -0
  249. package/dist/sdk/terminal/tui/dialogs.js +363 -0
  250. package/dist/sdk/terminal/tui/keybindings.d.ts +11 -0
  251. package/dist/sdk/terminal/tui/keybindings.js +49 -0
  252. package/dist/sdk/terminal/tui/list.d.ts +73 -0
  253. package/dist/sdk/terminal/tui/list.js +196 -0
  254. package/dist/sdk/terminal/tui/modeChoices.d.ts +42 -0
  255. package/dist/sdk/terminal/tui/modeChoices.js +70 -0
  256. package/dist/sdk/terminal/tui/modelPicker.d.ts +55 -0
  257. package/dist/sdk/terminal/tui/modelPicker.js +155 -0
  258. package/dist/sdk/terminal/tui/mouse.d.ts +3 -0
  259. package/dist/sdk/terminal/tui/mouse.js +3 -0
  260. package/dist/sdk/terminal/tui/page.d.ts +14 -0
  261. package/dist/sdk/terminal/tui/page.js +1 -0
  262. package/dist/sdk/terminal/tui/pageOverlay.d.ts +27 -0
  263. package/dist/sdk/terminal/tui/pageOverlay.js +145 -0
  264. package/dist/sdk/terminal/tui/pages/accountsPage.d.ts +54 -0
  265. package/dist/sdk/terminal/tui/pages/accountsPage.js +181 -0
  266. package/dist/sdk/terminal/tui/pages/componentsPage.d.ts +47 -0
  267. package/dist/sdk/terminal/tui/pages/componentsPage.js +119 -0
  268. package/dist/sdk/terminal/tui/pages/doctorPage.d.ts +37 -0
  269. package/dist/sdk/terminal/tui/pages/doctorPage.js +145 -0
  270. package/dist/sdk/terminal/tui/pages/hubPage.d.ts +39 -0
  271. package/dist/sdk/terminal/tui/pages/hubPage.js +128 -0
  272. package/dist/sdk/terminal/tui/pages/logPage.d.ts +38 -0
  273. package/dist/sdk/terminal/tui/pages/logPage.js +189 -0
  274. package/dist/sdk/terminal/tui/pages/permissionsPage.d.ts +44 -0
  275. package/dist/sdk/terminal/tui/pages/permissionsPage.js +124 -0
  276. package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +57 -0
  277. package/dist/sdk/terminal/tui/pages/pluginsPage.js +243 -0
  278. package/dist/sdk/terminal/tui/pages/settingsPage.d.ts +55 -0
  279. package/dist/sdk/terminal/tui/pages/settingsPage.js +88 -0
  280. package/dist/sdk/terminal/tui/pages/trajectoryPage.d.ts +58 -0
  281. package/dist/sdk/terminal/tui/pages/trajectoryPage.js +377 -0
  282. package/dist/sdk/terminal/tui/piAdapter.d.ts +18 -0
  283. package/dist/sdk/terminal/tui/piAdapter.js +48 -0
  284. package/dist/sdk/terminal/tui/planMode.d.ts +2 -0
  285. package/dist/sdk/terminal/tui/planMode.js +2 -0
  286. package/dist/sdk/terminal/tui/questionPicker.d.ts +20 -0
  287. package/dist/sdk/terminal/tui/questionPicker.js +150 -0
  288. package/dist/sdk/terminal/tui/questions.d.ts +19 -0
  289. package/dist/sdk/terminal/tui/questions.js +42 -0
  290. package/dist/sdk/terminal/tui/runtime.d.ts +114 -0
  291. package/dist/sdk/terminal/tui/runtime.js +441 -0
  292. package/dist/sdk/terminal/tui/search.d.ts +22 -0
  293. package/dist/sdk/terminal/tui/search.js +60 -0
  294. package/dist/sdk/terminal/tui/selection.d.ts +16 -0
  295. package/dist/sdk/terminal/tui/selection.js +16 -0
  296. package/dist/sdk/terminal/tui/sessionUi.d.ts +3 -0
  297. package/dist/sdk/terminal/tui/sessionUi.js +30 -0
  298. package/dist/sdk/terminal/tui/settingsModel.d.ts +12 -0
  299. package/dist/sdk/terminal/tui/settingsModel.js +84 -0
  300. package/dist/sdk/terminal/tui/sideQuestion.d.ts +53 -0
  301. package/dist/sdk/terminal/tui/sideQuestion.js +197 -0
  302. package/dist/sdk/terminal/tui/skillInvocation.d.ts +9 -0
  303. package/dist/sdk/terminal/tui/skillInvocation.js +43 -0
  304. package/dist/sdk/terminal/tui/status.d.ts +18 -0
  305. package/dist/sdk/terminal/tui/status.js +67 -0
  306. package/dist/sdk/terminal/tui/theme.d.ts +45 -0
  307. package/dist/sdk/terminal/tui/theme.js +176 -0
  308. package/dist/sdk/terminal/tui/treeModel.d.ts +79 -0
  309. package/dist/sdk/terminal/tui/treeModel.js +483 -0
  310. package/dist/sdk/terminal/tui/treePicker.d.ts +49 -0
  311. package/dist/sdk/terminal/tui/treePicker.js +251 -0
  312. package/dist/sdk/terminal/tui/ui.d.ts +47 -0
  313. package/dist/sdk/terminal/tui/ui.js +148 -0
  314. package/dist/sdk/terminal/tui/workingStatus.d.ts +9 -0
  315. package/dist/sdk/terminal/tui/workingStatus.js +229 -0
  316. package/dist/sdk/tools/askUser.d.ts +6 -0
  317. package/dist/sdk/tools/askUser.js +74 -0
  318. package/dist/sdk/tools/checklist.d.ts +9 -0
  319. package/dist/sdk/tools/checklist.js +54 -0
  320. package/dist/sdk/tools/definitions.d.ts +30 -0
  321. package/dist/sdk/tools/definitions.js +117 -0
  322. package/dist/sdk/tools/dispatch.d.ts +16 -0
  323. package/dist/sdk/tools/dispatch.js +67 -0
  324. package/dist/sdk/tools/harnessTools.d.ts +6 -0
  325. package/dist/sdk/tools/harnessTools.js +20 -0
  326. package/dist/sdk/tools/sessionName.d.ts +7 -0
  327. package/dist/sdk/tools/sessionName.js +31 -0
  328. package/dist/sdk/tools/spawnSubagent.d.ts +4 -0
  329. package/dist/sdk/tools/spawnSubagent.js +49 -0
  330. package/dist/sdk/tools/types.d.ts +48 -0
  331. package/dist/sdk/tools/types.js +1 -0
  332. package/dist/sdk/variant/components.d.ts +34 -0
  333. package/dist/sdk/variant/components.js +230 -0
  334. package/dist/sdk/variant/materialise.d.ts +66 -0
  335. package/dist/sdk/variant/materialise.js +81 -0
  336. package/dist/sdk/variant/migrate.d.ts +4 -0
  337. package/dist/sdk/variant/migrate.js +41 -0
  338. package/dist/sdk/variant/seed.d.ts +20 -0
  339. package/dist/sdk/variant/seed.js +116 -0
  340. package/dist/sdk/variant/store.d.ts +82 -0
  341. package/dist/sdk/variant/store.js +151 -0
  342. package/dist/sdk/variant/surface.d.ts +56 -0
  343. package/dist/sdk/variant/surface.js +81 -0
  344. package/dist/sdk/variant/trust.d.ts +27 -0
  345. package/dist/sdk/variant/trust.js +64 -0
  346. package/dist/sdk/variant/variant.d.ts +71 -0
  347. package/dist/sdk/variant/variant.js +331 -0
  348. package/dist/sdk/web/markdown.d.ts +10 -0
  349. package/dist/sdk/web/markdown.js +66 -0
  350. package/dist/sdk/web/safeRequest.d.ts +34 -0
  351. package/dist/sdk/web/safeRequest.js +175 -0
  352. package/dist/sdk/web/search.d.ts +53 -0
  353. package/dist/sdk/web/search.js +168 -0
  354. package/dist/sdk/web/text.d.ts +2 -0
  355. package/dist/sdk/web/text.js +7 -0
  356. package/dist/sdk/web/tools.d.ts +22 -0
  357. package/dist/sdk/web/tools.js +195 -0
  358. package/dist/sdk/web/turndown-plugin-gfm.d.ts +4 -0
  359. package/dist/sdk/wiki/notes.d.ts +68 -0
  360. package/dist/sdk/wiki/notes.js +297 -0
  361. package/dist/sdk/world/actions.d.ts +23 -0
  362. package/dist/sdk/world/actions.js +31 -0
  363. package/dist/sdk/world/cli.d.ts +12 -0
  364. package/dist/sdk/world/cli.js +166 -0
  365. package/dist/sdk/world/images.d.ts +20 -0
  366. package/dist/sdk/world/images.js +48 -0
  367. package/dist/sdk/world/untrusted.d.ts +12 -0
  368. package/dist/sdk/world/untrusted.js +20 -0
  369. package/dist/sdk/world/world.d.ts +65 -0
  370. package/dist/sdk/world/world.js +80 -0
  371. package/dist/terminal-opentui.js +13612 -0
  372. package/dist/terminal-pi.js +1170 -62
  373. package/docs/README.md +34 -0
  374. package/docs/architecture/00-overview.md +159 -0
  375. package/docs/architecture/01-extension-points.md +78 -0
  376. package/docs/architecture/02-sessions-and-runs.md +146 -0
  377. package/docs/architecture/03-variants.md +95 -0
  378. package/docs/architecture/04-prompt.md +102 -0
  379. package/docs/architecture/05-refinement.md +107 -0
  380. package/docs/architecture/06-plugins-and-capabilities.md +93 -0
  381. package/docs/architecture/07-tools-and-gate.md +88 -0
  382. package/docs/architecture/08-memory-and-history.md +94 -0
  383. package/docs/architecture/09-accounts-and-connectors.md +90 -0
  384. package/docs/architecture/10-server-protocol.md +84 -0
  385. package/docs/architecture/11-terminal.md +81 -0
  386. package/docs/architecture/12-storage.md +61 -0
  387. package/docs/architecture/13-world-tools.md +23 -0
  388. package/docs/architecture/README.md +114 -0
  389. package/docs/architecture/proposals/PROP-0001-reporting-section.md +106 -0
  390. package/docs/architecture/proposals/PROP-0002-retain-rollout-workspaces.md +104 -0
  391. package/docs/architecture/proposals/PROP-0003-executor-settings.md +81 -0
  392. package/docs/architecture/proposals/PROP-0004-flexible-reporting-guidance.md +71 -0
  393. package/docs/architecture/proposals/PROP-0005-xharness-cli-name.md +78 -0
  394. package/docs/architecture/proposals/PROP-0006-run-checklist.md +68 -0
  395. package/docs/architecture/proposals/PROP-0007-run-continuation.md +80 -0
  396. package/docs/architecture/proposals/PROP-0008-lessons-from-runs.md +80 -0
  397. package/docs/architecture/proposals/PROP-0009-foundation-and-variants.md +78 -0
  398. package/docs/architecture/proposals/PROP-0010-session-names.md +73 -0
  399. package/docs/architecture/proposals/PROP-0011-doctor.md +63 -0
  400. package/docs/architecture/proposals/PROP-0012-release-baseline.md +56 -0
  401. package/docs/architecture/proposals/README.md +76 -0
  402. package/docs/decisions/ADR-0001-owned-terminal.md +87 -0
  403. package/docs/decisions/ADR-0002-native-subagent-lifecycle.md +49 -0
  404. package/docs/decisions/ADR-0003-shared-asynchronous-subagents.md +70 -0
  405. package/docs/decisions/ADR-0004-fullscreen-terminal-layout.md +50 -0
  406. package/docs/decisions/ADR-0005-app-provided-oauth-clients.md +54 -0
  407. package/docs/decisions/ADR-0006-opentui-only-terminal.md +47 -0
  408. package/docs/decisions/ADR-0007-reporting-section.md +33 -0
  409. package/docs/decisions/ADR-0008-flexible-reporting-guidance.md +38 -0
  410. package/docs/decisions/ADR-0009-xharness-command.md +38 -0
  411. package/docs/decisions/ADR-0010-lessons-in-the-wiki.md +31 -0
  412. package/docs/decisions/ADR-0011-foundation-and-variants.md +28 -0
  413. package/docs/decisions/ADR-0012-native-session-names.md +34 -0
  414. package/docs/decisions/ADR-0013-doctor.md +27 -0
  415. package/docs/decisions/ADR-0014-public-release-baseline.md +21 -0
  416. package/docs/doctor.md +74 -0
  417. package/docs/experiments/EXP-0001-terminal-input-latency/plan.md +81 -0
  418. package/docs/experiments/EXP-0001-terminal-input-latency/results.md +46 -0
  419. package/docs/experiments/EXP-0002-opentui-typing-latency/plan.md +70 -0
  420. package/docs/experiments/EXP-0002-opentui-typing-latency/results.md +92 -0
  421. package/docs/features/README.md +20 -0
  422. package/docs/features/automations/README.md +41 -0
  423. package/docs/features/cores/README.md +39 -0
  424. package/docs/features/google-harness2/README.md +52 -0
  425. package/docs/features/integrations/README.md +40 -0
  426. package/docs/features/interfaces/README.md +29 -0
  427. package/docs/features/memory/README.md +28 -0
  428. package/docs/releases/1.0.0.md +40 -0
  429. package/docs/releases/README.md +36 -0
  430. package/docs/study/00-index.md +78 -0
  431. package/docs/study/arms/00-matrix.md +20 -0
  432. package/docs/study/arms/01-system-prompt.md +211 -0
  433. package/docs/study/arms/02-tools.md +79 -0
  434. package/docs/study/arms/03-subagents.md +90 -0
  435. package/docs/study/arms/04-skills.md +75 -0
  436. package/docs/study/arms/05-context-management.md +90 -0
  437. package/docs/study/arms/06-memory.md +90 -0
  438. package/docs/study/arms/07-governance.md +71 -0
  439. package/docs/study/arms/08-execution.md +69 -0
  440. package/docs/study/arms/09-observability.md +60 -0
  441. package/docs/study/arms/10-refinement.md +110 -0
  442. package/docs/study/btw-comparison.md +37 -0
  443. package/docs/study/feature-gap-review.md +42 -0
  444. package/docs/study/insights.md +123 -0
  445. package/docs/study/roadmap.md +72 -0
  446. package/docs/study/sources/claude-code.md +44 -0
  447. package/docs/study/sources/deepseek-harness.md +102 -0
  448. package/docs/study/sources/harness2.md +50 -0
  449. package/docs/study/sources/kimi-cli.md +42 -0
  450. package/docs/study/sources/omp.md +93 -0
  451. package/docs/study/sources/opencode.md +43 -0
  452. package/docs/study/sources/openhands.md +46 -0
  453. package/docs/study/sources/smolagents.md +40 -0
  454. package/docs/study/sources/swe-agent.md +34 -0
  455. package/docs/system-prompt-design.md +196 -0
  456. package/docs/terminal-tui.md +671 -0
  457. package/package.json +48 -12
  458. package/src/accounts/accounts.test.ts +0 -223
  459. package/src/accounts/accounts.ts +0 -522
  460. package/src/accounts/env.test.ts +0 -95
  461. package/src/accounts/env.ts +0 -338
  462. package/src/accounts/secrets.ts +0 -50
  463. package/src/accounts/store.ts +0 -338
  464. package/src/capabilities/api.ts +0 -75
  465. package/src/capabilities/runSnapshot.ts +0 -59
  466. package/src/capabilities/types.ts +0 -34
  467. package/src/cli.ts +0 -114
  468. package/src/core/bus.ts +0 -34
  469. package/src/core/changes.ts +0 -33
  470. package/src/core/env.ts +0 -27
  471. package/src/core/errors.ts +0 -32
  472. package/src/core/frontmatter.ts +0 -47
  473. package/src/core/fs.test.ts +0 -38
  474. package/src/core/fs.ts +0 -92
  475. package/src/core/index.ts +0 -193
  476. package/src/core/path.test.ts +0 -14
  477. package/src/core/path.ts +0 -79
  478. package/src/core/projects.ts +0 -90
  479. package/src/core/text.ts +0 -39
  480. package/src/harness.ts +0 -299
  481. package/src/index.ts +0 -70
  482. package/src/mcp/connections.ts +0 -614
  483. package/src/mcp/manager.ts +0 -130
  484. package/src/mcp/oauth.ts +0 -195
  485. package/src/mcp/scopeMigration.test.ts +0 -79
  486. package/src/mcp/scopeMigration.ts +0 -204
  487. package/src/mcp/service.test.ts +0 -376
  488. package/src/mcp/service.ts +0 -549
  489. package/src/mcp/types.ts +0 -108
  490. package/src/memory/api.test.ts +0 -82
  491. package/src/memory/api.ts +0 -289
  492. package/src/memory/blocks.test.ts +0 -78
  493. package/src/memory/blocks.ts +0 -406
  494. package/src/memory/caller.ts +0 -57
  495. package/src/memory/dispatch.ts +0 -59
  496. package/src/memory/facts.test.ts +0 -41
  497. package/src/memory/facts.ts +0 -248
  498. package/src/memory/graph.ts +0 -103
  499. package/src/memory/health.test.ts +0 -130
  500. package/src/memory/health.ts +0 -74
  501. package/src/memory/maintainer.ts +0 -272
  502. package/src/memory/maintenance.test.ts +0 -176
  503. package/src/memory/maintenance.ts +0 -330
  504. package/src/memory/migrate.ts +0 -79
  505. package/src/memory/operations.ts +0 -138
  506. package/src/memory/proposals.test.ts +0 -168
  507. package/src/memory/proposals.ts +0 -576
  508. package/src/memory/recall.test.ts +0 -104
  509. package/src/memory/recall.ts +0 -271
  510. package/src/memory/references.ts +0 -77
  511. package/src/memory/runContext.ts +0 -93
  512. package/src/memory/secrets.ts +0 -6
  513. package/src/memory/store.test.ts +0 -66
  514. package/src/memory/store.ts +0 -385
  515. package/src/memory/wiki.test.ts +0 -47
  516. package/src/memory/wiki.ts +0 -422
  517. package/src/memory/wikiIndex.test.ts +0 -88
  518. package/src/memory/wikiIndex.ts +0 -116
  519. package/src/plugins/api.ts +0 -181
  520. package/src/plugins/attachments.test.ts +0 -84
  521. package/src/plugins/attachments.ts +0 -141
  522. package/src/plugins/builtin.ts +0 -82
  523. package/src/plugins/catalogue.test.ts +0 -254
  524. package/src/plugins/catalogue.ts +0 -251
  525. package/src/plugins/cli.ts +0 -184
  526. package/src/plugins/discover.ts +0 -151
  527. package/src/plugins/firstParty.test.ts +0 -143
  528. package/src/plugins/firstParty.ts +0 -129
  529. package/src/plugins/hooks.test.ts +0 -250
  530. package/src/plugins/hooks.ts +0 -239
  531. package/src/plugins/identity.ts +0 -37
  532. package/src/plugins/install.test.ts +0 -107
  533. package/src/plugins/install.ts +0 -106
  534. package/src/plugins/inventory.ts +0 -123
  535. package/src/plugins/manifest.ts +0 -76
  536. package/src/plugins/plugins.test.ts +0 -205
  537. package/src/plugins/plugins.ts +0 -189
  538. package/src/plugins/proposal.ts +0 -121
  539. package/src/plugins/runtime.test.ts +0 -40
  540. package/src/plugins/runtime.ts +0 -82
  541. package/src/plugins/trust.ts +0 -142
  542. package/src/plugins/types.ts +0 -149
  543. package/src/prompt/compile.test.ts +0 -261
  544. package/src/prompt/compile.ts +0 -732
  545. package/src/server/methods.ts +0 -314
  546. package/src/server/remote.ts +0 -77
  547. package/src/server/rpc.ts +0 -116
  548. package/src/server/serve.ts +0 -28
  549. package/src/server/server.test.ts +0 -174
  550. package/src/sessions/approvals.ts +0 -118
  551. package/src/sessions/contracts.ts +0 -310
  552. package/src/sessions/conversation.test.ts +0 -150
  553. package/src/sessions/extensionSession.test.ts +0 -74
  554. package/src/sessions/extensionUi.test.ts +0 -65
  555. package/src/sessions/extensionUi.ts +0 -102
  556. package/src/sessions/history.ts +0 -51
  557. package/src/sessions/lineageJoin.ts +0 -75
  558. package/src/sessions/policy.ts +0 -32
  559. package/src/sessions/pricing.ts +0 -60
  560. package/src/sessions/reasoningSummaries.ts +0 -59
  561. package/src/sessions/registry.ts +0 -294
  562. package/src/sessions/runIndex.ts +0 -99
  563. package/src/sessions/runStore.test.ts +0 -152
  564. package/src/sessions/runStore.ts +0 -332
  565. package/src/sessions/runner.ts +0 -569
  566. package/src/sessions/runtimeResources.test.ts +0 -61
  567. package/src/sessions/sessions.test.ts +0 -455
  568. package/src/sessions/sessions.ts +0 -295
  569. package/src/skills/registry.test.ts +0 -104
  570. package/src/skills/registry.ts +0 -407
  571. package/src/terminal/cli.ts +0 -149
  572. package/src/terminal/client.ts +0 -74
  573. package/src/terminal/controller.ts +0 -227
  574. package/src/terminal/launch.test.ts +0 -34
  575. package/src/terminal/launch.ts +0 -88
  576. package/src/terminal/piExtension.ts +0 -210
  577. package/src/terminal/pluginControl.test.ts +0 -146
  578. package/src/terminal/pluginMenu.ts +0 -112
  579. package/src/terminal/socket.test.ts +0 -71
  580. package/src/terminal/socket.ts +0 -221
  581. package/src/terminal/standalone.test.ts +0 -130
  582. package/src/terminal/standalone.ts +0 -144
  583. package/src/terminal/terminal.test.ts +0 -330
  584. package/src/terminal/terminals.ts +0 -443
  585. package/src/tools/askUser.ts +0 -45
  586. package/src/tools/definitions.ts +0 -187
  587. package/src/tools/memoryTools.ts +0 -22
  588. package/src/tools/pluginPropose.ts +0 -41
  589. package/src/tools/types.ts +0 -39
  590. package/src/web/safeRequest.ts +0 -171
  591. package/src/web/text.ts +0 -53
  592. package/src/web/tools.ts +0 -134
  593. package/src/web/web.test.ts +0 -141
@@ -0,0 +1,26 @@
1
+ import { Client } from '@modelcontextprotocol/client';
2
+ import { HarnessError } from "../core/errors.js";
3
+ import { type OAuthHost } from "./oauth.js";
4
+ import type { LaunchConfig } from "./types.js";
5
+ export declare const signInRequired: (config: Pick<LaunchConfig, "name">) => HarnessError;
6
+ export declare const isSignInRequired: (error: unknown) => boolean;
7
+ export declare class McpManager {
8
+ private readonly oauth;
9
+ private readonly sessions;
10
+ constructor(oauth: OAuthHost);
11
+ close(connectionId?: string, sessionId?: string): Promise<void>;
12
+ /** The client for a connection in one scope, reconnecting when the connection's configuration changed. */
13
+ client(scope: string, config: LaunchConfig): Promise<Client>;
14
+ private connectStdio;
15
+ private connectHttp;
16
+ /** Runs `work` on a connection opened only for it. */
17
+ private once;
18
+ /** What a connection offers, read on a connection of its own. */
19
+ probe(config: LaunchConfig): Promise<{
20
+ serverName: string;
21
+ tools: unknown[];
22
+ vaultId: string | null;
23
+ }>;
24
+ /** One read on a connection of its own, outside any session. */
25
+ readSource(config: LaunchConfig, tool: string, args: Record<string, unknown>): Promise<unknown>;
26
+ }
@@ -0,0 +1,124 @@
1
+ // Live MCP client sessions: one per (session, connection), opened on first use and closed when
2
+ // the session's run ends or the connection changes.
3
+ import { Client, SSEClientTransport, StreamableHTTPClientTransport, UnauthorizedError } from '@modelcontextprotocol/client';
4
+ import { StdioClientTransport } from '@modelcontextprotocol/client/stdio';
5
+ import { randomUUID } from 'node:crypto';
6
+ import { HarnessError } from "../core/errors.js";
7
+ import { StoredOAuthProvider } from "./oauth.js";
8
+ export const signInRequired = (config) => new HarnessError('mcp_unauthorized', `${config.name} needs you to sign in again in Connections.`);
9
+ export const isSignInRequired = (error) => error instanceof UnauthorizedError || (error instanceof HarnessError && error.code === 'mcp_unauthorized');
10
+ export class McpManager {
11
+ oauth;
12
+ sessions = new Map();
13
+ constructor(oauth) {
14
+ this.oauth = oauth;
15
+ }
16
+ async close(connectionId, sessionId) {
17
+ const closing = [...this.sessions].filter(([key]) => (!connectionId || key.endsWith(`:${connectionId}`)) && (!sessionId || key.startsWith(`${sessionId}:`)));
18
+ for (const [key] of closing)
19
+ this.sessions.delete(key);
20
+ await Promise.allSettled(closing.map(async ([, session]) => {
21
+ const live = await session;
22
+ await live.client.close();
23
+ await live.transport.close();
24
+ }));
25
+ }
26
+ /** The client for a connection in one scope, reconnecting when the connection's configuration changed. */
27
+ async client(scope, config) {
28
+ const key = `${scope}:${config.id}`;
29
+ const fingerprint = JSON.stringify(config);
30
+ const existing = this.sessions.get(key);
31
+ if (existing) {
32
+ const live = await existing.catch(() => null);
33
+ if (live?.config === fingerprint)
34
+ return live.client;
35
+ await live?.client.close().catch(() => undefined);
36
+ this.sessions.delete(key);
37
+ }
38
+ const pending = (async () => {
39
+ const { client, transport } = config.transport === 'http' ? await this.connectHttp(config) : await this.connectStdio(config);
40
+ client.onclose = () => {
41
+ if (this.sessions.get(key) === pending)
42
+ this.sessions.delete(key);
43
+ };
44
+ return { client, transport, config: fingerprint };
45
+ })();
46
+ this.sessions.set(key, pending);
47
+ try {
48
+ return (await pending).client;
49
+ }
50
+ catch (error) {
51
+ this.sessions.delete(key);
52
+ throw error;
53
+ }
54
+ }
55
+ async connectStdio(config) {
56
+ const client = new Client({ name: 'xagent', version: '0.1.0' });
57
+ const transport = new StdioClientTransport({ command: config.command, args: config.args, cwd: config.cwd ?? undefined, env: config.env, stderr: 'pipe' });
58
+ try {
59
+ await client.connect(transport, { timeout: 30000 });
60
+ }
61
+ catch {
62
+ await transport.close();
63
+ throw new HarnessError('mcp_unavailable', `${config.name} could not start or initialize. Check its executable and arguments.`);
64
+ }
65
+ // Servers' diagnostics may contain secrets; do not persist or forward stderr.
66
+ transport.stderr?.on('data', () => undefined);
67
+ return { client, transport };
68
+ }
69
+ async connectHttp(config) {
70
+ const authProvider = config.auth === 'oauth' ? new StoredOAuthProvider(this.oauth, config, false) : undefined;
71
+ // Without saved tokens the only way forward is the browser, which a session may not open.
72
+ if (authProvider && !(await authProvider.tokens()))
73
+ throw signInRequired(config);
74
+ const options = { authProvider, requestInit: { headers: config.headers } };
75
+ // Servers that predate Streamable HTTP only answer on SSE.
76
+ for (const Transport of [StreamableHTTPClientTransport, SSEClientTransport]) {
77
+ const client = new Client({ name: 'xagent', version: '0.1.0' });
78
+ const transport = new Transport(new URL(config.url), options);
79
+ try {
80
+ await client.connect(transport, { timeout: 30000 });
81
+ return { client, transport };
82
+ }
83
+ catch (error) {
84
+ await transport.close().catch(() => undefined);
85
+ if (isSignInRequired(error))
86
+ throw signInRequired(config);
87
+ }
88
+ }
89
+ throw new HarnessError('mcp_unavailable', `${config.name} could not be reached. Check its address and credentials.`);
90
+ }
91
+ /** Runs `work` on a connection opened only for it. */
92
+ async once(prefix, config, work) {
93
+ const scope = `${prefix}-${randomUUID()}`;
94
+ try {
95
+ return await work(await this.client(scope, config));
96
+ }
97
+ finally {
98
+ const key = `${scope}:${config.id}`;
99
+ const session = this.sessions.get(key);
100
+ this.sessions.delete(key);
101
+ if (session)
102
+ await (await session).client.close().catch(() => undefined);
103
+ }
104
+ }
105
+ /** What a connection offers, read on a connection of its own. */
106
+ probe(config) {
107
+ return this.once('probe', config, async (client) => {
108
+ const tools = (await client.listTools()).tools;
109
+ let vaultId = null;
110
+ if (tools.some((tool) => tool.name === 'x_workspace_status')) {
111
+ const status = await client.callTool({ name: 'x_workspace_status', arguments: {} });
112
+ const envelope = status.structuredContent;
113
+ if (!envelope?.ok)
114
+ throw new HarnessError('mcp_unavailable', envelope?.error?.message ?? 'Workspace vault is not bound.');
115
+ vaultId = envelope.vaultId ?? null;
116
+ }
117
+ return { serverName: client.getServerVersion()?.name ?? config.name, tools, vaultId };
118
+ });
119
+ }
120
+ /** One read on a connection of its own, outside any session. */
121
+ readSource(config, tool, args) {
122
+ return this.once('source', config, (client) => client.callTool({ name: tool, arguments: args }, { timeout: 60000 }));
123
+ }
124
+ }
@@ -0,0 +1,35 @@
1
+ import type { OAuthClientInformationContext, OAuthClientMetadata, OAuthClientProvider, OAuthDiscoveryState, StoredOAuthClientInformation, StoredOAuthTokens } from '@modelcontextprotocol/client';
2
+ import { type HttpConfig } from "./types.js";
3
+ /** Where a connection's OAuth state is read and written, and how a sign-in page is shown. */
4
+ export interface OAuthHost {
5
+ load(connectionId: string): Promise<Record<string, unknown>>;
6
+ save(connectionId: string, state: Record<string, unknown>): Promise<void>;
7
+ openUrl(url: string): Promise<void> | void;
8
+ /** The name shown on the provider's consent page. */
9
+ clientName: string;
10
+ }
11
+ export declare class StoredOAuthProvider implements OAuthClientProvider {
12
+ private readonly host;
13
+ private readonly config;
14
+ private readonly interactive;
15
+ readonly expectedState: `${string}-${string}-${string}-${string}-${string}`;
16
+ private verifier;
17
+ constructor(host: OAuthHost, config: Pick<HttpConfig, 'id' | 'scopes'>, interactive: boolean);
18
+ get redirectUrl(): string;
19
+ get clientMetadata(): OAuthClientMetadata;
20
+ state(): string;
21
+ private load;
22
+ private change;
23
+ clientInformation(context?: OAuthClientInformationContext): Promise<StoredOAuthClientInformation | undefined>;
24
+ saveClientInformation(client: StoredOAuthClientInformation): Promise<void>;
25
+ tokens(): Promise<StoredOAuthTokens | undefined>;
26
+ saveTokens(tokens: StoredOAuthTokens): Promise<void>;
27
+ discoveryState(): Promise<OAuthDiscoveryState | undefined>;
28
+ saveDiscoveryState(discovery: OAuthDiscoveryState): Promise<void>;
29
+ saveCodeVerifier(verifier: string): void;
30
+ codeVerifier(): string;
31
+ invalidateCredentials(scope: 'all' | 'client' | 'tokens' | 'verifier' | 'discovery'): Promise<void>;
32
+ redirectToAuthorization(url: URL): Promise<void>;
33
+ }
34
+ /** Opens the provider's sign-in page and waits for the browser to return to the loopback address. */
35
+ export declare function signIn(host: OAuthHost, config: HttpConfig): Promise<void>;
@@ -0,0 +1,171 @@
1
+ // OAuth sign-in for a remote connection. State is kept with the connection's other secrets.
2
+ // Only an interactive provider (a sign-in a person started) may open a browser; a session that
3
+ // needs a new sign-in fails instead.
4
+ import { auth, UnauthorizedError } from '@modelcontextprotocol/client';
5
+ import { randomUUID } from 'node:crypto';
6
+ import { createServer } from 'node:http';
7
+ import { HarnessError } from "../core/errors.js";
8
+ import { MCP_OAUTH_PORT, MCP_OAUTH_REDIRECT_URL } from "./types.js";
9
+ export class StoredOAuthProvider {
10
+ host;
11
+ config;
12
+ interactive;
13
+ expectedState = randomUUID();
14
+ verifier = null;
15
+ constructor(host, config, interactive) {
16
+ this.host = host;
17
+ this.config = config;
18
+ this.interactive = interactive;
19
+ }
20
+ get redirectUrl() {
21
+ return MCP_OAUTH_REDIRECT_URL;
22
+ }
23
+ get clientMetadata() {
24
+ return {
25
+ client_name: this.host.clientName,
26
+ redirect_uris: [MCP_OAUTH_REDIRECT_URL],
27
+ grant_types: ['authorization_code', 'refresh_token'],
28
+ response_types: ['code'],
29
+ token_endpoint_auth_method: 'none',
30
+ ...(this.config.scopes.length ? { scope: this.config.scopes.join(' ') } : {})
31
+ };
32
+ }
33
+ state() {
34
+ return this.expectedState;
35
+ }
36
+ load() {
37
+ return this.host.load(this.config.id);
38
+ }
39
+ async change(edit) {
40
+ await this.host.save(this.config.id, edit(await this.load()));
41
+ }
42
+ async clientInformation(context) {
43
+ const saved = await this.load();
44
+ if (!saved.staticClient)
45
+ return saved.client;
46
+ // A client the user registered themselves (providers without dynamic registration) wins. It is
47
+ // tied to the authorization server seen at sign-in, so a session never offers it to another one.
48
+ if (this.interactive && context && saved.staticIssuer !== context.issuer)
49
+ await this.change((current) => ({ ...current, staticIssuer: context.issuer }));
50
+ const issuer = this.interactive ? context?.issuer : saved.staticIssuer;
51
+ return issuer ? { ...saved.staticClient, issuer } : saved.staticClient;
52
+ }
53
+ async saveClientInformation(client) {
54
+ await this.change((saved) => ({ ...saved, client }));
55
+ }
56
+ async tokens() {
57
+ return (await this.load()).tokens;
58
+ }
59
+ async saveTokens(tokens) {
60
+ await this.change((saved) => ({ ...saved, tokens }));
61
+ }
62
+ async discoveryState() {
63
+ return (await this.load()).discovery;
64
+ }
65
+ async saveDiscoveryState(discovery) {
66
+ await this.change((saved) => ({ ...saved, discovery }));
67
+ }
68
+ saveCodeVerifier(verifier) {
69
+ this.verifier = verifier;
70
+ }
71
+ codeVerifier() {
72
+ if (!this.verifier)
73
+ throw new UnauthorizedError('Sign-in was not started from this app.');
74
+ return this.verifier;
75
+ }
76
+ async invalidateCredentials(scope) {
77
+ if (scope === 'verifier' || scope === 'all')
78
+ this.verifier = null;
79
+ if (scope === 'verifier')
80
+ return;
81
+ await this.change((saved) => (scope === 'all' ? {} : { ...saved, [scope]: undefined }));
82
+ }
83
+ async redirectToAuthorization(url) {
84
+ if (!this.interactive)
85
+ throw new UnauthorizedError('Sign in again in Connections.');
86
+ // Google only returns a refresh token when offline access is requested with a consent prompt.
87
+ if (url.hostname === 'accounts.google.com') {
88
+ url.searchParams.set('access_type', 'offline');
89
+ url.searchParams.set('prompt', 'consent');
90
+ }
91
+ await this.host.openUrl(url.toString());
92
+ }
93
+ }
94
+ const page = (title, message) => `<!doctype html><meta charset="utf-8"><title>${title}</title><body style="font:16px system-ui;margin:20vh auto;max-width:28rem;text-align:center"><p>${message}</p></body>`;
95
+ // One sign-in owns the loopback port. Starting another ends the one still waiting, so a closed
96
+ // browser tab never blocks a retry.
97
+ let cancelActive = null;
98
+ /** Waits on the fixed loopback address for the provider to send the browser back. */
99
+ function listenForCallback(expectedState, clientName) {
100
+ return new Promise((ready, failed) => {
101
+ let settle;
102
+ const result = new Promise((resolve, reject) => {
103
+ settle = { resolve, reject };
104
+ });
105
+ result.catch(() => undefined);
106
+ const server = createServer((request, response) => {
107
+ const url = new URL(request.url ?? '/', MCP_OAUTH_REDIRECT_URL);
108
+ const reply = (status, message) => {
109
+ response.writeHead(status, { 'content-type': 'text/html; charset=utf-8' });
110
+ response.end(page(clientName, message));
111
+ };
112
+ if (url.pathname !== new URL(MCP_OAUTH_REDIRECT_URL).pathname)
113
+ return reply(404, 'Not found.');
114
+ // Anything on this machine can reach the port; only the request carrying this sign-in's state counts.
115
+ if (url.searchParams.get('state') !== expectedState)
116
+ return reply(400, `This sign-in link is not the one ${clientName} is waiting for.`);
117
+ const code = url.searchParams.get('code');
118
+ if (!code) {
119
+ reply(400, 'Sign-in was not completed. You can close this window.');
120
+ return settle.reject(new HarnessError('mcp_unauthorized', url.searchParams.get('error') === 'access_denied' ? 'Sign-in was cancelled.' : 'The provider did not complete the sign-in.'));
121
+ }
122
+ reply(200, `Signed in. You can close this window and return to ${clientName}.`);
123
+ settle.resolve({ code, iss: url.searchParams.get('iss') ?? undefined });
124
+ });
125
+ const timer = setTimeout(() => settle.reject(new HarnessError('mcp_unauthorized', 'Sign-in timed out. Try again.')), 300000);
126
+ server.once('error', (error) => {
127
+ clearTimeout(timer);
128
+ failed(new HarnessError('invalid_request', error.code === 'EADDRINUSE' ? `Port ${MCP_OAUTH_PORT} is in use. Finish or cancel the other sign-in, or quit the program using that port, then try again.` : 'The sign-in listener could not start.'));
129
+ });
130
+ const closed = new Promise((resolve) => server.once('close', resolve));
131
+ const close = () => {
132
+ clearTimeout(timer);
133
+ if (cancelActive === cancel)
134
+ cancelActive = null;
135
+ server.close();
136
+ server.closeAllConnections();
137
+ return closed;
138
+ };
139
+ const cancel = () => {
140
+ settle.reject(new HarnessError('mcp_unauthorized', 'Sign-in was cancelled.'));
141
+ return close();
142
+ };
143
+ server.listen(MCP_OAUTH_PORT, '127.0.0.1', () => {
144
+ cancelActive = cancel;
145
+ ready({ result, close });
146
+ });
147
+ });
148
+ }
149
+ /** Opens the provider's sign-in page and waits for the browser to return to the loopback address. */
150
+ export async function signIn(host, config) {
151
+ const provider = new StoredOAuthProvider(host, config, true);
152
+ const scope = config.scopes.join(' ') || undefined;
153
+ await cancelActive?.();
154
+ const callback = await listenForCallback(provider.expectedState, host.clientName);
155
+ try {
156
+ if ((await auth(provider, { serverUrl: config.url, scope, forceReauthorization: true })) === 'REDIRECT') {
157
+ const { code, iss } = await callback.result;
158
+ if ((await auth(provider, { serverUrl: config.url, scope, authorizationCode: code, iss })) !== 'AUTHORIZED')
159
+ throw new HarnessError('mcp_unauthorized', 'The provider did not complete the sign-in.');
160
+ }
161
+ }
162
+ catch (error) {
163
+ if (error instanceof HarnessError)
164
+ throw error;
165
+ // Provider responses can quote credentials; report only that it failed.
166
+ throw new HarnessError('mcp_unauthorized', `${config.name} sign-in failed. Check the connection's address and OAuth client, then try again.`);
167
+ }
168
+ finally {
169
+ await callback.close();
170
+ }
171
+ }
@@ -0,0 +1,19 @@
1
+ interface MigrationRecord {
2
+ version: 1;
3
+ status: 'attachments-written' | 'complete';
4
+ connectionCount: number;
5
+ scopeAssignmentCount: number;
6
+ connectionsBackup: string | null;
7
+ attachmentsBackup: string | null;
8
+ hadAttachments: boolean;
9
+ }
10
+ /** Scope writes are safe only after the legacy records have been copied and stripped. */
11
+ export declare function connectionScopeMigrationComplete(root: string): boolean;
12
+ /**
13
+ * Runs once when a data root opens. Both source files are backed up before either is changed;
14
+ * a stage marker makes an interrupted migration safe to finish on the next open.
15
+ */
16
+ export declare function migrateConnectionScopes(root: string, stateDir: string): MigrationRecord;
17
+ /** Restores the byte-identical pre-migration files from the backups if an operator rolls back. */
18
+ export declare function rollbackConnectionScopeMigration(root: string, stateDir: string): void;
19
+ export {};
@@ -0,0 +1,198 @@
1
+ // Moves who can reach each connected app out of the device-local connection records and into
2
+ // the data root's shared capability attachment store. The originals remain as owner-only backups.
3
+ import { chmodSync, existsSync, readFileSync, unlinkSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { atomicWrite, readJson, writeJson } from "../core/fs.js";
6
+ import * as attachments from "../plugins/attachments.js";
7
+ import { connectionCapabilityId, connectionSchema } from "./types.js";
8
+ const recordPath = (root) => join(root, 'config/capability-scope-migration.json');
9
+ const attachmentsPath = (root) => join(root, 'config/plugin-attachments.json');
10
+ const connectionPath = (stateDir) => join(stateDir, 'connections.json');
11
+ const connectionsBackupPath = (stateDir) => join(stateDir, 'connections.pre-capability-scope.json');
12
+ const attachmentsBackupPath = (root) => join(root, 'config/plugin-attachments.pre-capability-scope.json');
13
+ /** Scope writes are safe only after the legacy records have been copied and stripped. */
14
+ export function connectionScopeMigrationComplete(root) {
15
+ try {
16
+ const marker = readJson(recordPath(root));
17
+ return marker?.version === 1 && marker.status === 'complete';
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ function unique(values) {
24
+ return [...new Set(values)];
25
+ }
26
+ function scopeRows(connection) {
27
+ const agents = new Map();
28
+ const projects = new Map();
29
+ for (const id of unique([...connection.agentIds, ...connection.excludedAgentIds])) {
30
+ agents.set(id, !connection.excludedAgentIds.includes(id));
31
+ }
32
+ for (const id of unique([...connection.projectIds, ...connection.excludedProjectIds])) {
33
+ projects.set(id, !connection.excludedProjectIds.includes(id));
34
+ }
35
+ return { global: connection.global, agents, projects };
36
+ }
37
+ function assignmentCount(rows) {
38
+ return 1 + rows.agents.size + rows.projects.size;
39
+ }
40
+ function removeId(choices, id) {
41
+ attachments.forgetId(choices, id);
42
+ }
43
+ function put(map, id, value) {
44
+ map.on = map.on.filter((item) => item !== id);
45
+ map.off = map.off.filter((item) => item !== id);
46
+ map[value ? 'on' : 'off'].push(id);
47
+ }
48
+ function writeRows(choices, id, rows) {
49
+ removeId(choices, id);
50
+ put(choices.global, id, rows.global);
51
+ for (const [scopeId, on] of rows.agents) {
52
+ const target = (choices.agents[scopeId] ??= { on: [], off: [] });
53
+ put(target, id, on);
54
+ }
55
+ for (const [scopeId, on] of rows.projects) {
56
+ const target = (choices.projects[scopeId] ??= { on: [], off: [] });
57
+ put(target, id, on);
58
+ }
59
+ }
60
+ function readValue(item, id) {
61
+ if (item?.off.includes(id))
62
+ return false;
63
+ if (item?.on.includes(id))
64
+ return true;
65
+ return null;
66
+ }
67
+ function verifyRows(choices, id, expected) {
68
+ if (readValue(choices.global, id) !== expected.global)
69
+ return false;
70
+ for (const [scopeId, on] of expected.agents) {
71
+ if (readValue(choices.agents[scopeId], id) !== on)
72
+ return false;
73
+ }
74
+ for (const [scopeId, on] of expected.projects) {
75
+ if (readValue(choices.projects[scopeId], id) !== on)
76
+ return false;
77
+ }
78
+ return true;
79
+ }
80
+ function backup(source, target) {
81
+ if (!existsSync(source))
82
+ return false;
83
+ if (!existsSync(target))
84
+ atomicWrite(target, readFileSync(source));
85
+ chmodSync(target, 0o600);
86
+ return true;
87
+ }
88
+ function setPrivate(path) {
89
+ try {
90
+ chmodSync(path, 0o600);
91
+ }
92
+ catch { /* The atomic write remains usable if chmod is unavailable. */ }
93
+ }
94
+ function stripScopes(stateDir) {
95
+ const path = connectionPath(stateDir);
96
+ if (!existsSync(path))
97
+ return;
98
+ const stored = readJson(path);
99
+ if (!Array.isArray(stored))
100
+ throw new Error('Stored connector data must be a list before its scopes can be migrated.');
101
+ const records = stored.map((item) => {
102
+ if (!item || typeof item !== 'object' || Array.isArray(item))
103
+ throw new Error('A stored connector record is invalid; no scope data was removed.');
104
+ const { global: _global, agentIds: _agentIds, projectIds: _projectIds, excludedAgentIds: _excludedAgentIds, excludedProjectIds: _excludedProjectIds, ...connection } = item;
105
+ return connection;
106
+ });
107
+ writeJson(path, records);
108
+ setPrivate(path);
109
+ }
110
+ /**
111
+ * Runs once when a data root opens. Both source files are backed up before either is changed;
112
+ * a stage marker makes an interrupted migration safe to finish on the next open.
113
+ */
114
+ export function migrateConnectionScopes(root, stateDir) {
115
+ const marker = readJson(recordPath(root));
116
+ if (marker?.version === 1 && marker.status === 'complete')
117
+ return marker;
118
+ if (marker?.version === 1 && marker.status === 'attachments-written') {
119
+ stripScopes(stateDir);
120
+ const complete = { ...marker, status: 'complete' };
121
+ writeJson(recordPath(root), complete);
122
+ return complete;
123
+ }
124
+ const connectionsFile = connectionPath(stateDir);
125
+ const hadConnections = existsSync(connectionsFile);
126
+ const raw = hadConnections ? readJson(connectionsFile) : [];
127
+ if (!Array.isArray(raw))
128
+ throw new Error('Stored connector data must be a list before its scopes can be migrated.');
129
+ const parsed = raw.map((item) => {
130
+ const result = connectionSchema.safeParse(item);
131
+ if (!result.success)
132
+ throw new Error('A stored connector record is invalid; no scope data was removed.');
133
+ return result.data;
134
+ });
135
+ const connectionBackup = hadConnections ? connectionsBackupPath(stateDir) : null;
136
+ const hadAttachments = existsSync(attachmentsPath(root));
137
+ const attachmentBackup = hadAttachments ? attachmentsBackupPath(root) : null;
138
+ const migration = {
139
+ version: 1,
140
+ status: 'attachments-written',
141
+ connectionCount: parsed.length,
142
+ scopeAssignmentCount: parsed.reduce((count, connection) => count + assignmentCount(scopeRows(connection)), 0),
143
+ connectionsBackup: connectionBackup,
144
+ attachmentsBackup: attachmentBackup,
145
+ hadAttachments
146
+ };
147
+ backup(connectionsFile, connectionBackup ?? '');
148
+ backup(attachmentsPath(root), attachmentBackup ?? '');
149
+ try {
150
+ const choices = attachments.load(root);
151
+ const expected = new Map();
152
+ for (const connection of parsed) {
153
+ const id = connectionCapabilityId(connection.id);
154
+ const rows = scopeRows(connection);
155
+ expected.set(id, rows);
156
+ writeRows(choices, id, rows);
157
+ }
158
+ const migratedAssignments = [...expected.values()].reduce((count, rows) => count + assignmentCount(rows), 0);
159
+ if (migratedAssignments !== migration.scopeAssignmentCount || [...expected].some(([id, rows]) => !verifyRows(choices, id, rows))) {
160
+ throw new Error('Connector scope count check failed; the original files were restored.');
161
+ }
162
+ attachments.save(root, choices);
163
+ const saved = attachments.load(root);
164
+ if ([...expected].some(([id, rows]) => !verifyRows(saved, id, rows)))
165
+ throw new Error('Connector scope count check failed after saving; the original files were restored.');
166
+ writeJson(recordPath(root), migration);
167
+ stripScopes(stateDir);
168
+ const complete = { ...migration, status: 'complete' };
169
+ writeJson(recordPath(root), complete);
170
+ return complete;
171
+ }
172
+ catch (error) {
173
+ if (attachmentBackup && existsSync(attachmentBackup))
174
+ atomicWrite(attachmentsPath(root), readFileSync(attachmentBackup));
175
+ else if (!hadAttachments && existsSync(attachmentsPath(root)))
176
+ unlinkSync(attachmentsPath(root));
177
+ if (connectionBackup && existsSync(connectionBackup))
178
+ atomicWrite(connectionsFile, readFileSync(connectionBackup));
179
+ try {
180
+ unlinkSync(recordPath(root));
181
+ }
182
+ catch { /* No marker is also a valid retry state. */ }
183
+ throw error;
184
+ }
185
+ }
186
+ /** Restores the byte-identical pre-migration files from the backups if an operator rolls back. */
187
+ export function rollbackConnectionScopeMigration(root, stateDir) {
188
+ const marker = readJson(recordPath(root));
189
+ if (!marker || marker.version !== 1)
190
+ return;
191
+ if (marker.attachmentsBackup && existsSync(marker.attachmentsBackup))
192
+ atomicWrite(attachmentsPath(root), readFileSync(marker.attachmentsBackup));
193
+ else if (!marker.hadAttachments && existsSync(attachmentsPath(root)))
194
+ unlinkSync(attachmentsPath(root));
195
+ if (marker.connectionsBackup && existsSync(marker.connectionsBackup))
196
+ atomicWrite(connectionPath(stateDir), readFileSync(marker.connectionsBackup));
197
+ unlinkSync(recordPath(root));
198
+ }