@xingular/harness 0.1.7 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (683) hide show
  1. package/CHANGELOG.md +97 -1
  2. package/LICENSE +202 -0
  3. package/NOTICE.md +22 -0
  4. package/README.md +187 -85
  5. package/THIRD_PARTY_LICENSES.md +942 -0
  6. package/dist/cli.js +13701 -13498
  7. package/dist/sdk/accounts/accounts.d.ts +165 -0
  8. package/dist/sdk/accounts/accounts.js +730 -0
  9. package/dist/sdk/accounts/choices.d.ts +23 -0
  10. package/dist/sdk/accounts/choices.js +62 -0
  11. package/dist/sdk/accounts/env.d.ts +78 -0
  12. package/dist/sdk/accounts/env.js +294 -0
  13. package/dist/sdk/accounts/secrets.d.ts +16 -0
  14. package/dist/sdk/accounts/secrets.js +40 -0
  15. package/dist/sdk/accounts/store.d.ts +114 -0
  16. package/dist/sdk/accounts/store.js +255 -0
  17. package/dist/sdk/browser/config.d.ts +16 -0
  18. package/dist/sdk/browser/config.js +22 -0
  19. package/dist/sdk/browser/diagnostics.d.ts +4 -0
  20. package/dist/sdk/browser/diagnostics.js +38 -0
  21. package/dist/sdk/browser/index.d.ts +17 -0
  22. package/dist/sdk/browser/index.js +65 -0
  23. package/dist/sdk/browser/network.d.ts +10 -0
  24. package/dist/sdk/browser/network.js +59 -0
  25. package/dist/sdk/browser/session.d.ts +84 -0
  26. package/dist/sdk/browser/session.js +192 -0
  27. package/dist/sdk/browser/tools.d.ts +8 -0
  28. package/dist/sdk/browser/tools.js +329 -0
  29. package/dist/sdk/capabilities/api.d.ts +22 -0
  30. package/dist/sdk/capabilities/api.js +54 -0
  31. package/dist/sdk/capabilities/runSnapshot.d.ts +18 -0
  32. package/dist/sdk/capabilities/runSnapshot.js +47 -0
  33. package/dist/sdk/capabilities/types.d.ts +29 -0
  34. package/dist/sdk/capabilities/types.js +1 -0
  35. package/dist/sdk/cli.d.ts +2 -0
  36. package/dist/sdk/cli.js +142 -0
  37. package/dist/sdk/core/bus.d.ts +23 -0
  38. package/dist/sdk/core/bus.js +76 -0
  39. package/dist/sdk/core/caller.d.ts +22 -0
  40. package/dist/sdk/core/caller.js +16 -0
  41. package/dist/sdk/core/changes.d.ts +15 -0
  42. package/dist/sdk/core/changes.js +15 -0
  43. package/dist/sdk/core/effort.d.ts +2 -0
  44. package/dist/sdk/core/effort.js +1 -0
  45. package/dist/sdk/core/env.d.ts +18 -0
  46. package/dist/sdk/core/env.js +8 -0
  47. package/dist/sdk/core/errors.d.ts +15 -0
  48. package/dist/sdk/core/errors.js +24 -0
  49. package/dist/sdk/core/frontmatter.d.ts +12 -0
  50. package/dist/sdk/core/frontmatter.js +50 -0
  51. package/dist/sdk/core/fs.d.ts +18 -0
  52. package/dist/sdk/core/fs.js +106 -0
  53. package/dist/sdk/core/index.d.ts +24 -0
  54. package/dist/sdk/core/index.js +187 -0
  55. package/dist/sdk/core/path.d.ts +7 -0
  56. package/dist/sdk/core/path.js +79 -0
  57. package/dist/sdk/core/projects.d.ts +18 -0
  58. package/dist/sdk/core/projects.js +67 -0
  59. package/dist/sdk/core/secrets.d.ts +2 -0
  60. package/dist/sdk/core/secrets.js +5 -0
  61. package/dist/sdk/core/text.d.ts +7 -0
  62. package/dist/sdk/core/text.js +40 -0
  63. package/dist/sdk/doctor/checks.d.ts +5 -0
  64. package/dist/sdk/doctor/checks.js +208 -0
  65. package/dist/sdk/doctor/probe.d.ts +4 -0
  66. package/dist/sdk/doctor/probe.js +92 -0
  67. package/dist/sdk/doctor/service.d.ts +23 -0
  68. package/dist/sdk/doctor/service.js +144 -0
  69. package/dist/sdk/doctor/types.d.ts +141 -0
  70. package/dist/sdk/doctor/types.js +29 -0
  71. package/dist/sdk/harness.d.ts +133 -0
  72. package/dist/sdk/harness.js +299 -0
  73. package/dist/sdk/history/lessonPrompt.d.ts +2 -0
  74. package/dist/sdk/history/lessonPrompt.js +15 -0
  75. package/dist/sdk/history/lessons.d.ts +52 -0
  76. package/dist/sdk/history/lessons.js +173 -0
  77. package/dist/sdk/history/recall.d.ts +68 -0
  78. package/dist/sdk/history/recall.js +199 -0
  79. package/dist/sdk/history/trajectory.d.ts +7 -0
  80. package/dist/sdk/history/trajectory.js +216 -0
  81. package/dist/sdk/hub/catalog.json +123 -0
  82. package/dist/sdk/hub/cli.d.ts +7 -0
  83. package/dist/sdk/hub/cli.js +81 -0
  84. package/dist/sdk/hub/hub.d.ts +74 -0
  85. package/dist/sdk/hub/hub.js +474 -0
  86. package/dist/sdk/hub/schema.d.ts +280 -0
  87. package/dist/sdk/hub/schema.js +78 -0
  88. package/dist/sdk/index.d.ts +63 -0
  89. package/dist/sdk/index.js +48 -0
  90. package/dist/sdk/mcp/connections.d.ts +83 -0
  91. package/dist/sdk/mcp/connections.js +669 -0
  92. package/dist/sdk/mcp/manager.d.ts +26 -0
  93. package/dist/sdk/mcp/manager.js +124 -0
  94. package/dist/sdk/mcp/oauth.d.ts +35 -0
  95. package/dist/sdk/mcp/oauth.js +171 -0
  96. package/dist/sdk/mcp/scopeMigration.d.ts +19 -0
  97. package/dist/sdk/mcp/scopeMigration.js +198 -0
  98. package/dist/sdk/mcp/service.d.ts +160 -0
  99. package/dist/sdk/mcp/service.js +510 -0
  100. package/dist/sdk/mcp/types.d.ts +131 -0
  101. package/dist/sdk/mcp/types.js +49 -0
  102. package/dist/sdk/pi/runtime.d.ts +13 -0
  103. package/dist/sdk/pi/runtime.js +31 -0
  104. package/dist/sdk/plugins/api.d.ts +66 -0
  105. package/dist/sdk/plugins/api.js +155 -0
  106. package/dist/sdk/plugins/attachments.d.ts +46 -0
  107. package/dist/sdk/plugins/attachments.js +111 -0
  108. package/dist/sdk/plugins/builtin.d.ts +6 -0
  109. package/dist/sdk/plugins/builtin.js +68 -0
  110. package/dist/sdk/plugins/catalogue.d.ts +29 -0
  111. package/dist/sdk/plugins/catalogue.js +196 -0
  112. package/dist/sdk/plugins/cli.d.ts +13 -0
  113. package/dist/sdk/plugins/cli.js +187 -0
  114. package/dist/sdk/plugins/discover.d.ts +42 -0
  115. package/dist/sdk/plugins/discover.js +115 -0
  116. package/dist/sdk/plugins/firstParty.d.ts +50 -0
  117. package/dist/sdk/plugins/firstParty.js +113 -0
  118. package/dist/sdk/plugins/hooks.d.ts +94 -0
  119. package/dist/sdk/plugins/hooks.js +162 -0
  120. package/dist/sdk/plugins/identity.d.ts +19 -0
  121. package/dist/sdk/plugins/identity.js +48 -0
  122. package/dist/sdk/plugins/install.d.ts +20 -0
  123. package/dist/sdk/plugins/install.js +110 -0
  124. package/dist/sdk/plugins/inventory.d.ts +22 -0
  125. package/dist/sdk/plugins/inventory.js +110 -0
  126. package/dist/sdk/plugins/manifest.d.ts +13 -0
  127. package/dist/sdk/plugins/manifest.js +56 -0
  128. package/dist/sdk/plugins/plugins.d.ts +104 -0
  129. package/dist/sdk/plugins/plugins.js +164 -0
  130. package/dist/sdk/plugins/runtime.d.ts +9 -0
  131. package/dist/sdk/plugins/runtime.js +95 -0
  132. package/dist/sdk/plugins/trust.d.ts +44 -0
  133. package/dist/sdk/plugins/trust.js +120 -0
  134. package/dist/sdk/plugins/types.d.ts +159 -0
  135. package/dist/sdk/plugins/types.js +7 -0
  136. package/dist/sdk/prompt/compile.d.ts +174 -0
  137. package/dist/sdk/prompt/compile.js +396 -0
  138. package/dist/sdk/refine/cli.d.ts +4 -0
  139. package/dist/sdk/refine/cli.js +186 -0
  140. package/dist/sdk/refine/demo.d.ts +21 -0
  141. package/dist/sdk/refine/demo.js +114 -0
  142. package/dist/sdk/refine/evidence.d.ts +55 -0
  143. package/dist/sdk/refine/evidence.js +330 -0
  144. package/dist/sdk/refine/host.d.ts +51 -0
  145. package/dist/sdk/refine/host.js +76 -0
  146. package/dist/sdk/refine/ledger.d.ts +48 -0
  147. package/dist/sdk/refine/ledger.js +76 -0
  148. package/dist/sdk/refine/library.d.ts +55 -0
  149. package/dist/sdk/refine/library.js +177 -0
  150. package/dist/sdk/refine/pi.d.ts +72 -0
  151. package/dist/sdk/refine/pi.js +248 -0
  152. package/dist/sdk/refine/prompts.d.ts +45 -0
  153. package/dist/sdk/refine/prompts.js +390 -0
  154. package/dist/sdk/refine/recursion.d.ts +113 -0
  155. package/dist/sdk/refine/recursion.js +258 -0
  156. package/dist/sdk/refine/runner.d.ts +81 -0
  157. package/dist/sdk/refine/runner.js +150 -0
  158. package/dist/sdk/refine/selection.d.ts +57 -0
  159. package/dist/sdk/refine/selection.js +251 -0
  160. package/dist/sdk/refine/service.d.ts +84 -0
  161. package/dist/sdk/refine/service.js +165 -0
  162. package/dist/sdk/refine/suite.d.ts +67 -0
  163. package/dist/sdk/refine/suite.js +174 -0
  164. package/dist/sdk/refine/trajectory.d.ts +9 -0
  165. package/dist/sdk/refine/trajectory.js +68 -0
  166. package/dist/sdk/refine/types.d.ts +77 -0
  167. package/dist/sdk/refine/types.js +10 -0
  168. package/dist/sdk/server/methods.d.ts +3 -0
  169. package/dist/sdk/server/methods.js +370 -0
  170. package/dist/sdk/server/remote.d.ts +19 -0
  171. package/dist/sdk/server/remote.js +84 -0
  172. package/dist/sdk/server/rpc.d.ts +20 -0
  173. package/dist/sdk/server/rpc.js +102 -0
  174. package/dist/sdk/server/serve.d.ts +10 -0
  175. package/dist/sdk/server/serve.js +18 -0
  176. package/dist/sdk/sessions/approvals.d.ts +47 -0
  177. package/dist/sdk/sessions/approvals.js +119 -0
  178. package/dist/sdk/sessions/continuation.d.ts +48 -0
  179. package/dist/sdk/sessions/continuation.js +85 -0
  180. package/dist/sdk/sessions/contracts.d.ts +534 -0
  181. package/dist/sdk/sessions/contracts.js +299 -0
  182. package/dist/sdk/sessions/extensionUi.d.ts +19 -0
  183. package/dist/sdk/sessions/extensionUi.js +64 -0
  184. package/dist/sdk/sessions/history.d.ts +16 -0
  185. package/dist/sdk/sessions/history.js +68 -0
  186. package/dist/sdk/sessions/lineageJoin.d.ts +2 -0
  187. package/dist/sdk/sessions/lineageJoin.js +61 -0
  188. package/dist/sdk/sessions/planMode.d.ts +36 -0
  189. package/dist/sdk/sessions/planMode.js +84 -0
  190. package/dist/sdk/sessions/policy.d.ts +43 -0
  191. package/dist/sdk/sessions/policy.js +1 -0
  192. package/dist/sdk/sessions/pricing.d.ts +34 -0
  193. package/dist/sdk/sessions/pricing.js +40 -0
  194. package/dist/sdk/sessions/reasoningSummaries.d.ts +11 -0
  195. package/dist/sdk/sessions/reasoningSummaries.js +61 -0
  196. package/dist/sdk/sessions/registry.d.ts +102 -0
  197. package/dist/sdk/sessions/registry.js +383 -0
  198. package/dist/sdk/sessions/runIndex.d.ts +21 -0
  199. package/dist/sdk/sessions/runIndex.js +65 -0
  200. package/dist/sdk/sessions/runStore.d.ts +66 -0
  201. package/dist/sdk/sessions/runStore.js +335 -0
  202. package/dist/sdk/sessions/runner.d.ts +213 -0
  203. package/dist/sdk/sessions/runner.js +589 -0
  204. package/dist/sdk/sessions/sessions.d.ts +140 -0
  205. package/dist/sdk/sessions/sessions.js +394 -0
  206. package/dist/sdk/sessions/subagentService.d.ts +41 -0
  207. package/dist/sdk/sessions/subagentService.js +247 -0
  208. package/dist/sdk/sessions/subagents.d.ts +50 -0
  209. package/dist/sdk/sessions/subagents.js +68 -0
  210. package/dist/sdk/terminal/accountsMenu.d.ts +46 -0
  211. package/dist/sdk/terminal/accountsMenu.js +392 -0
  212. package/dist/sdk/terminal/cli.d.ts +20 -0
  213. package/dist/sdk/terminal/cli.js +121 -0
  214. package/dist/sdk/terminal/client.d.ts +15 -0
  215. package/dist/sdk/terminal/client.js +126 -0
  216. package/dist/sdk/terminal/control.d.ts +4 -0
  217. package/dist/sdk/terminal/control.js +25 -0
  218. package/dist/sdk/terminal/controller.d.ts +72 -0
  219. package/dist/sdk/terminal/controller.js +351 -0
  220. package/dist/sdk/terminal/hubMenu.d.ts +10 -0
  221. package/dist/sdk/terminal/hubMenu.js +34 -0
  222. package/dist/sdk/terminal/launch.d.ts +5 -0
  223. package/dist/sdk/terminal/launch.js +27 -0
  224. package/dist/sdk/terminal/logs.d.ts +14 -0
  225. package/dist/sdk/terminal/logs.js +59 -0
  226. package/dist/sdk/terminal/piExtension.d.ts +6 -0
  227. package/dist/sdk/terminal/piExtension.js +392 -0
  228. package/dist/sdk/terminal/pluginMenu.d.ts +34 -0
  229. package/dist/sdk/terminal/pluginMenu.js +101 -0
  230. package/dist/sdk/terminal/socket.d.ts +70 -0
  231. package/dist/sdk/terminal/socket.js +256 -0
  232. package/dist/sdk/terminal/standalone.d.ts +18 -0
  233. package/dist/sdk/terminal/standalone.js +146 -0
  234. package/dist/sdk/terminal/terminals.d.ts +176 -0
  235. package/dist/sdk/terminal/terminals.js +767 -0
  236. package/dist/sdk/terminal/trajectory.d.ts +10 -0
  237. package/dist/sdk/terminal/trajectory.js +30 -0
  238. package/dist/sdk/terminal/tui/chrome.d.ts +64 -0
  239. package/dist/sdk/terminal/tui/chrome.js +169 -0
  240. package/dist/sdk/terminal/tui/clipboardFiles.d.ts +11 -0
  241. package/dist/sdk/terminal/tui/clipboardFiles.js +74 -0
  242. package/dist/sdk/terminal/tui/commandPages.d.ts +7 -0
  243. package/dist/sdk/terminal/tui/commandPages.js +63 -0
  244. package/dist/sdk/terminal/tui/commands.d.ts +42 -0
  245. package/dist/sdk/terminal/tui/commands.js +276 -0
  246. package/dist/sdk/terminal/tui/dialogGeometry.d.ts +27 -0
  247. package/dist/sdk/terminal/tui/dialogGeometry.js +50 -0
  248. package/dist/sdk/terminal/tui/dialogs.d.ts +75 -0
  249. package/dist/sdk/terminal/tui/dialogs.js +363 -0
  250. package/dist/sdk/terminal/tui/keybindings.d.ts +11 -0
  251. package/dist/sdk/terminal/tui/keybindings.js +49 -0
  252. package/dist/sdk/terminal/tui/list.d.ts +73 -0
  253. package/dist/sdk/terminal/tui/list.js +196 -0
  254. package/dist/sdk/terminal/tui/modeChoices.d.ts +42 -0
  255. package/dist/sdk/terminal/tui/modeChoices.js +70 -0
  256. package/dist/sdk/terminal/tui/modelPicker.d.ts +55 -0
  257. package/dist/sdk/terminal/tui/modelPicker.js +155 -0
  258. package/dist/sdk/terminal/tui/mouse.d.ts +3 -0
  259. package/dist/sdk/terminal/tui/mouse.js +3 -0
  260. package/dist/sdk/terminal/tui/page.d.ts +14 -0
  261. package/dist/sdk/terminal/tui/page.js +1 -0
  262. package/dist/sdk/terminal/tui/pageOverlay.d.ts +27 -0
  263. package/dist/sdk/terminal/tui/pageOverlay.js +145 -0
  264. package/dist/sdk/terminal/tui/pages/accountsPage.d.ts +54 -0
  265. package/dist/sdk/terminal/tui/pages/accountsPage.js +181 -0
  266. package/dist/sdk/terminal/tui/pages/componentsPage.d.ts +47 -0
  267. package/dist/sdk/terminal/tui/pages/componentsPage.js +119 -0
  268. package/dist/sdk/terminal/tui/pages/doctorPage.d.ts +37 -0
  269. package/dist/sdk/terminal/tui/pages/doctorPage.js +145 -0
  270. package/dist/sdk/terminal/tui/pages/hubPage.d.ts +39 -0
  271. package/dist/sdk/terminal/tui/pages/hubPage.js +128 -0
  272. package/dist/sdk/terminal/tui/pages/logPage.d.ts +38 -0
  273. package/dist/sdk/terminal/tui/pages/logPage.js +189 -0
  274. package/dist/sdk/terminal/tui/pages/permissionsPage.d.ts +44 -0
  275. package/dist/sdk/terminal/tui/pages/permissionsPage.js +124 -0
  276. package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +57 -0
  277. package/dist/sdk/terminal/tui/pages/pluginsPage.js +243 -0
  278. package/dist/sdk/terminal/tui/pages/settingsPage.d.ts +55 -0
  279. package/dist/sdk/terminal/tui/pages/settingsPage.js +88 -0
  280. package/dist/sdk/terminal/tui/pages/trajectoryPage.d.ts +58 -0
  281. package/dist/sdk/terminal/tui/pages/trajectoryPage.js +377 -0
  282. package/dist/sdk/terminal/tui/piAdapter.d.ts +18 -0
  283. package/dist/sdk/terminal/tui/piAdapter.js +48 -0
  284. package/dist/sdk/terminal/tui/planMode.d.ts +2 -0
  285. package/dist/sdk/terminal/tui/planMode.js +2 -0
  286. package/dist/sdk/terminal/tui/questionPicker.d.ts +20 -0
  287. package/dist/sdk/terminal/tui/questionPicker.js +150 -0
  288. package/dist/sdk/terminal/tui/questions.d.ts +19 -0
  289. package/dist/sdk/terminal/tui/questions.js +42 -0
  290. package/dist/sdk/terminal/tui/runtime.d.ts +114 -0
  291. package/dist/sdk/terminal/tui/runtime.js +441 -0
  292. package/dist/sdk/terminal/tui/search.d.ts +22 -0
  293. package/dist/sdk/terminal/tui/search.js +60 -0
  294. package/dist/sdk/terminal/tui/selection.d.ts +16 -0
  295. package/dist/sdk/terminal/tui/selection.js +16 -0
  296. package/dist/sdk/terminal/tui/sessionUi.d.ts +3 -0
  297. package/dist/sdk/terminal/tui/sessionUi.js +30 -0
  298. package/dist/sdk/terminal/tui/settingsModel.d.ts +12 -0
  299. package/dist/sdk/terminal/tui/settingsModel.js +84 -0
  300. package/dist/sdk/terminal/tui/sideQuestion.d.ts +53 -0
  301. package/dist/sdk/terminal/tui/sideQuestion.js +197 -0
  302. package/dist/sdk/terminal/tui/skillInvocation.d.ts +9 -0
  303. package/dist/sdk/terminal/tui/skillInvocation.js +43 -0
  304. package/dist/sdk/terminal/tui/status.d.ts +18 -0
  305. package/dist/sdk/terminal/tui/status.js +67 -0
  306. package/dist/sdk/terminal/tui/theme.d.ts +45 -0
  307. package/dist/sdk/terminal/tui/theme.js +176 -0
  308. package/dist/sdk/terminal/tui/treeModel.d.ts +79 -0
  309. package/dist/sdk/terminal/tui/treeModel.js +483 -0
  310. package/dist/sdk/terminal/tui/treePicker.d.ts +49 -0
  311. package/dist/sdk/terminal/tui/treePicker.js +251 -0
  312. package/dist/sdk/terminal/tui/ui.d.ts +47 -0
  313. package/dist/sdk/terminal/tui/ui.js +148 -0
  314. package/dist/sdk/terminal/tui/workingStatus.d.ts +9 -0
  315. package/dist/sdk/terminal/tui/workingStatus.js +229 -0
  316. package/dist/sdk/tools/askUser.d.ts +6 -0
  317. package/dist/sdk/tools/askUser.js +74 -0
  318. package/dist/sdk/tools/checklist.d.ts +9 -0
  319. package/dist/sdk/tools/checklist.js +54 -0
  320. package/dist/sdk/tools/definitions.d.ts +30 -0
  321. package/dist/sdk/tools/definitions.js +117 -0
  322. package/dist/sdk/tools/dispatch.d.ts +16 -0
  323. package/dist/sdk/tools/dispatch.js +67 -0
  324. package/dist/sdk/tools/harnessTools.d.ts +6 -0
  325. package/dist/sdk/tools/harnessTools.js +20 -0
  326. package/dist/sdk/tools/sessionName.d.ts +7 -0
  327. package/dist/sdk/tools/sessionName.js +31 -0
  328. package/dist/sdk/tools/spawnSubagent.d.ts +4 -0
  329. package/dist/sdk/tools/spawnSubagent.js +49 -0
  330. package/dist/sdk/tools/types.d.ts +48 -0
  331. package/dist/sdk/tools/types.js +1 -0
  332. package/dist/sdk/variant/components.d.ts +34 -0
  333. package/dist/sdk/variant/components.js +230 -0
  334. package/dist/sdk/variant/materialise.d.ts +66 -0
  335. package/dist/sdk/variant/materialise.js +81 -0
  336. package/dist/sdk/variant/migrate.d.ts +4 -0
  337. package/dist/sdk/variant/migrate.js +41 -0
  338. package/dist/sdk/variant/seed.d.ts +20 -0
  339. package/dist/sdk/variant/seed.js +116 -0
  340. package/dist/sdk/variant/store.d.ts +82 -0
  341. package/dist/sdk/variant/store.js +151 -0
  342. package/dist/sdk/variant/surface.d.ts +56 -0
  343. package/dist/sdk/variant/surface.js +81 -0
  344. package/dist/sdk/variant/trust.d.ts +27 -0
  345. package/dist/sdk/variant/trust.js +64 -0
  346. package/dist/sdk/variant/variant.d.ts +71 -0
  347. package/dist/sdk/variant/variant.js +331 -0
  348. package/dist/sdk/web/markdown.d.ts +10 -0
  349. package/dist/sdk/web/markdown.js +66 -0
  350. package/dist/sdk/web/safeRequest.d.ts +34 -0
  351. package/dist/sdk/web/safeRequest.js +175 -0
  352. package/dist/sdk/web/search.d.ts +53 -0
  353. package/dist/sdk/web/search.js +168 -0
  354. package/dist/sdk/web/text.d.ts +2 -0
  355. package/dist/sdk/web/text.js +7 -0
  356. package/dist/sdk/web/tools.d.ts +22 -0
  357. package/dist/sdk/web/tools.js +195 -0
  358. package/dist/sdk/web/turndown-plugin-gfm.d.ts +4 -0
  359. package/dist/sdk/wiki/notes.d.ts +68 -0
  360. package/dist/sdk/wiki/notes.js +297 -0
  361. package/dist/sdk/world/actions.d.ts +23 -0
  362. package/dist/sdk/world/actions.js +31 -0
  363. package/dist/sdk/world/cli.d.ts +12 -0
  364. package/dist/sdk/world/cli.js +166 -0
  365. package/dist/sdk/world/images.d.ts +20 -0
  366. package/dist/sdk/world/images.js +48 -0
  367. package/dist/sdk/world/untrusted.d.ts +12 -0
  368. package/dist/sdk/world/untrusted.js +20 -0
  369. package/dist/sdk/world/world.d.ts +65 -0
  370. package/dist/sdk/world/world.js +80 -0
  371. package/dist/terminal-opentui.js +13612 -0
  372. package/dist/terminal-pi.js +808 -151
  373. package/docs/README.md +22 -0
  374. package/docs/architecture/00-overview.md +159 -0
  375. package/docs/architecture/01-extension-points.md +78 -0
  376. package/docs/architecture/02-sessions-and-runs.md +146 -0
  377. package/docs/architecture/03-variants.md +95 -0
  378. package/docs/architecture/04-prompt.md +102 -0
  379. package/docs/architecture/05-refinement.md +107 -0
  380. package/docs/architecture/06-plugins-and-capabilities.md +93 -0
  381. package/docs/architecture/07-tools-and-gate.md +88 -0
  382. package/docs/architecture/08-memory-and-history.md +94 -0
  383. package/docs/architecture/09-accounts-and-connectors.md +90 -0
  384. package/docs/architecture/10-server-protocol.md +84 -0
  385. package/docs/architecture/11-terminal.md +81 -0
  386. package/docs/architecture/12-storage.md +61 -0
  387. package/docs/architecture/13-world-tools.md +23 -0
  388. package/docs/architecture/README.md +114 -0
  389. package/docs/architecture/proposals/PROP-0001-reporting-section.md +106 -0
  390. package/docs/architecture/proposals/PROP-0002-retain-rollout-workspaces.md +104 -0
  391. package/docs/architecture/proposals/PROP-0003-executor-settings.md +81 -0
  392. package/docs/architecture/proposals/PROP-0004-flexible-reporting-guidance.md +71 -0
  393. package/docs/architecture/proposals/PROP-0005-xharness-cli-name.md +78 -0
  394. package/docs/architecture/proposals/PROP-0006-run-checklist.md +68 -0
  395. package/docs/architecture/proposals/PROP-0007-run-continuation.md +80 -0
  396. package/docs/architecture/proposals/PROP-0008-lessons-from-runs.md +80 -0
  397. package/docs/architecture/proposals/PROP-0009-foundation-and-variants.md +78 -0
  398. package/docs/architecture/proposals/PROP-0010-session-names.md +73 -0
  399. package/docs/architecture/proposals/PROP-0011-doctor.md +63 -0
  400. package/docs/architecture/proposals/PROP-0012-release-baseline.md +56 -0
  401. package/docs/architecture/proposals/README.md +76 -0
  402. package/docs/decisions/ADR-0002-native-subagent-lifecycle.md +49 -0
  403. package/docs/decisions/ADR-0003-shared-asynchronous-subagents.md +70 -0
  404. package/docs/decisions/ADR-0004-fullscreen-terminal-layout.md +50 -0
  405. package/docs/decisions/ADR-0005-app-provided-oauth-clients.md +54 -0
  406. package/docs/decisions/ADR-0006-opentui-only-terminal.md +47 -0
  407. package/docs/decisions/ADR-0007-reporting-section.md +33 -0
  408. package/docs/decisions/ADR-0008-flexible-reporting-guidance.md +38 -0
  409. package/docs/decisions/ADR-0009-xharness-command.md +38 -0
  410. package/docs/decisions/ADR-0010-lessons-in-the-wiki.md +31 -0
  411. package/docs/decisions/ADR-0011-foundation-and-variants.md +28 -0
  412. package/docs/decisions/ADR-0012-native-session-names.md +34 -0
  413. package/docs/decisions/ADR-0013-doctor.md +27 -0
  414. package/docs/decisions/ADR-0014-public-release-baseline.md +21 -0
  415. package/docs/doctor.md +74 -0
  416. package/docs/experiments/EXP-0001-terminal-input-latency/plan.md +81 -0
  417. package/docs/experiments/EXP-0001-terminal-input-latency/results.md +46 -0
  418. package/docs/experiments/EXP-0002-opentui-typing-latency/plan.md +70 -0
  419. package/docs/experiments/EXP-0002-opentui-typing-latency/results.md +92 -0
  420. package/docs/features/README.md +20 -0
  421. package/docs/features/automations/README.md +41 -0
  422. package/docs/features/cores/README.md +39 -0
  423. package/docs/features/google-harness2/README.md +52 -0
  424. package/docs/features/integrations/README.md +40 -0
  425. package/docs/features/interfaces/README.md +29 -0
  426. package/docs/features/memory/README.md +28 -0
  427. package/docs/releases/1.0.0.md +40 -0
  428. package/docs/releases/README.md +36 -0
  429. package/docs/study/00-index.md +78 -0
  430. package/docs/study/arms/00-matrix.md +20 -0
  431. package/docs/study/arms/01-system-prompt.md +211 -0
  432. package/docs/study/arms/02-tools.md +79 -0
  433. package/docs/study/arms/03-subagents.md +90 -0
  434. package/docs/study/arms/04-skills.md +75 -0
  435. package/docs/study/arms/05-context-management.md +90 -0
  436. package/docs/study/arms/06-memory.md +90 -0
  437. package/docs/study/arms/07-governance.md +71 -0
  438. package/docs/study/arms/08-execution.md +69 -0
  439. package/docs/study/arms/09-observability.md +60 -0
  440. package/docs/study/arms/10-refinement.md +110 -0
  441. package/docs/study/btw-comparison.md +37 -0
  442. package/docs/study/feature-gap-review.md +42 -0
  443. package/docs/study/insights.md +123 -0
  444. package/docs/study/roadmap.md +72 -0
  445. package/docs/study/sources/claude-code.md +44 -0
  446. package/docs/study/sources/deepseek-harness.md +102 -0
  447. package/docs/study/sources/harness2.md +50 -0
  448. package/docs/study/sources/kimi-cli.md +42 -0
  449. package/docs/study/sources/omp.md +93 -0
  450. package/docs/study/sources/opencode.md +43 -0
  451. package/docs/study/sources/openhands.md +46 -0
  452. package/docs/study/sources/smolagents.md +40 -0
  453. package/docs/study/sources/swe-agent.md +34 -0
  454. package/docs/system-prompt-design.md +196 -0
  455. package/docs/terminal-tui.md +473 -56
  456. package/package.json +43 -13
  457. package/docs/evidence/terminal-2026-10-17/120x40-completed-transcript.ansi.gz +0 -0
  458. package/docs/evidence/terminal-2026-10-17/40x20-settings-interaction.ansi.gz +0 -0
  459. package/docs/evidence/terminal-2026-10-17/40x20-settings-keyboard.ansi.gz +0 -0
  460. package/docs/evidence/terminal-2026-10-17/40x20-welcome.ansi.gz +0 -0
  461. package/docs/evidence/terminal-2026-10-17/80x24-approval-0.ansi.gz +0 -0
  462. package/docs/evidence/terminal-2026-10-17/80x24-question.ansi.gz +0 -0
  463. package/docs/evidence/terminal-2026-10-17/verification.json +0 -130
  464. package/docs/evidence/terminal-2026-10-17-followup/120x40-completed-transcript.ansi.gz +0 -0
  465. package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-interaction.ansi.gz +0 -0
  466. package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-keyboard.ansi.gz +0 -0
  467. package/docs/evidence/terminal-2026-10-17-followup/40x20-welcome.ansi.gz +0 -0
  468. package/docs/evidence/terminal-2026-10-17-followup/80x24-approval-0.ansi.gz +0 -0
  469. package/docs/evidence/terminal-2026-10-17-followup/80x24-plugin-light.ansi.gz +0 -0
  470. package/docs/evidence/terminal-2026-10-17-followup/80x24-question-batch.ansi.gz +0 -0
  471. package/docs/evidence/terminal-2026-10-17-followup/80x24-question.ansi.gz +0 -0
  472. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-approval-0.ansi.gz +0 -0
  473. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-plugin-light.ansi.gz +0 -0
  474. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question-batch.ansi.gz +0 -0
  475. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question.ansi.gz +0 -0
  476. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/verification.json +0 -95
  477. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-approval-0.ansi.gz +0 -0
  478. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-plugin-light.ansi.gz +0 -0
  479. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question-batch.ansi.gz +0 -0
  480. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question.ansi.gz +0 -0
  481. package/docs/evidence/terminal-2026-10-17-followup/global-install/README.md +0 -27
  482. package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command-80x24.ansi.gz +0 -0
  483. package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command.json +0 -18
  484. package/docs/evidence/terminal-2026-10-17-followup/global-install/verification.json +0 -95
  485. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-80x24.json.gz +0 -0
  486. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-final-80x24.json.gz +0 -0
  487. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-scenario.json +0 -60
  488. package/docs/evidence/terminal-2026-10-17-followup/live-codex/README.md +0 -24
  489. package/docs/evidence/terminal-2026-10-17-followup/live-codex/complete-80x24.ansi.gz +0 -0
  490. package/docs/evidence/terminal-2026-10-17-followup/live-codex/verification.json +0 -57
  491. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24-early.json.gz +0 -0
  492. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24.json.gz +0 -0
  493. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-scenario.json +0 -58
  494. package/docs/evidence/terminal-2026-10-17-followup/omp-supplemental-static.json.gz +0 -0
  495. package/docs/evidence/terminal-2026-10-17-followup/rea-artifacts.json +0 -320
  496. package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.json +0 -30
  497. package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.md +0 -133
  498. package/docs/evidence/terminal-2026-10-17-followup/reference-source-observations.json +0 -20
  499. package/docs/evidence/terminal-2026-10-17-followup/verification.json +0 -207
  500. package/src/accounts/accounts.test.ts +0 -333
  501. package/src/accounts/accounts.ts +0 -658
  502. package/src/accounts/env.test.ts +0 -95
  503. package/src/accounts/env.ts +0 -338
  504. package/src/accounts/secrets.ts +0 -50
  505. package/src/accounts/store.ts +0 -338
  506. package/src/capabilities/api.ts +0 -75
  507. package/src/capabilities/runSnapshot.ts +0 -59
  508. package/src/capabilities/types.ts +0 -34
  509. package/src/cli.ts +0 -118
  510. package/src/core/bus.ts +0 -34
  511. package/src/core/changes.ts +0 -33
  512. package/src/core/env.ts +0 -27
  513. package/src/core/errors.ts +0 -32
  514. package/src/core/frontmatter.ts +0 -47
  515. package/src/core/fs.test.ts +0 -38
  516. package/src/core/fs.ts +0 -92
  517. package/src/core/index.ts +0 -193
  518. package/src/core/path.test.ts +0 -14
  519. package/src/core/path.ts +0 -79
  520. package/src/core/projects.ts +0 -90
  521. package/src/core/text.ts +0 -39
  522. package/src/harness.ts +0 -312
  523. package/src/hub/catalog.json +0 -123
  524. package/src/hub/cli.ts +0 -59
  525. package/src/hub/hub.test.ts +0 -205
  526. package/src/hub/hub.ts +0 -256
  527. package/src/hub/schema.ts +0 -81
  528. package/src/index.ts +0 -75
  529. package/src/mcp/connections.ts +0 -614
  530. package/src/mcp/manager.ts +0 -130
  531. package/src/mcp/oauth.ts +0 -195
  532. package/src/mcp/scopeMigration.test.ts +0 -79
  533. package/src/mcp/scopeMigration.ts +0 -204
  534. package/src/mcp/service.test.ts +0 -376
  535. package/src/mcp/service.ts +0 -549
  536. package/src/mcp/types.ts +0 -108
  537. package/src/memory/api.test.ts +0 -82
  538. package/src/memory/api.ts +0 -303
  539. package/src/memory/blocks.test.ts +0 -78
  540. package/src/memory/blocks.ts +0 -408
  541. package/src/memory/caller.ts +0 -69
  542. package/src/memory/curation.test.ts +0 -163
  543. package/src/memory/curation.ts +0 -64
  544. package/src/memory/dispatch.ts +0 -59
  545. package/src/memory/facts.test.ts +0 -41
  546. package/src/memory/facts.ts +0 -248
  547. package/src/memory/graph.ts +0 -103
  548. package/src/memory/health.test.ts +0 -130
  549. package/src/memory/health.ts +0 -74
  550. package/src/memory/maintainer.ts +0 -272
  551. package/src/memory/maintenance.test.ts +0 -176
  552. package/src/memory/maintenance.ts +0 -518
  553. package/src/memory/migrate.ts +0 -79
  554. package/src/memory/operations.ts +0 -150
  555. package/src/memory/proposals.test.ts +0 -168
  556. package/src/memory/proposals.ts +0 -584
  557. package/src/memory/recall.test.ts +0 -115
  558. package/src/memory/recall.ts +0 -278
  559. package/src/memory/references.ts +0 -77
  560. package/src/memory/runContext.ts +0 -93
  561. package/src/memory/secrets.ts +0 -6
  562. package/src/memory/store.test.ts +0 -66
  563. package/src/memory/store.ts +0 -385
  564. package/src/memory/wiki.test.ts +0 -47
  565. package/src/memory/wiki.ts +0 -422
  566. package/src/memory/wikiIndex.test.ts +0 -88
  567. package/src/memory/wikiIndex.ts +0 -116
  568. package/src/plugins/api.ts +0 -181
  569. package/src/plugins/attachments.test.ts +0 -84
  570. package/src/plugins/attachments.ts +0 -141
  571. package/src/plugins/builtin.ts +0 -82
  572. package/src/plugins/catalogue.test.ts +0 -254
  573. package/src/plugins/catalogue.ts +0 -251
  574. package/src/plugins/cli.ts +0 -184
  575. package/src/plugins/discover.ts +0 -151
  576. package/src/plugins/firstParty.test.ts +0 -143
  577. package/src/plugins/firstParty.ts +0 -129
  578. package/src/plugins/hooks.test.ts +0 -250
  579. package/src/plugins/hooks.ts +0 -239
  580. package/src/plugins/identity.ts +0 -37
  581. package/src/plugins/install.test.ts +0 -107
  582. package/src/plugins/install.ts +0 -106
  583. package/src/plugins/inventory.ts +0 -123
  584. package/src/plugins/manifest.ts +0 -76
  585. package/src/plugins/plugins.test.ts +0 -205
  586. package/src/plugins/plugins.ts +0 -189
  587. package/src/plugins/proposal.ts +0 -121
  588. package/src/plugins/runtime.test.ts +0 -40
  589. package/src/plugins/runtime.ts +0 -82
  590. package/src/plugins/trust.ts +0 -142
  591. package/src/plugins/types.ts +0 -149
  592. package/src/prompt/compile.test.ts +0 -261
  593. package/src/prompt/compile.ts +0 -732
  594. package/src/server/methods.ts +0 -349
  595. package/src/server/remote.ts +0 -77
  596. package/src/server/rpc.ts +0 -116
  597. package/src/server/serve.ts +0 -28
  598. package/src/server/server.test.ts +0 -174
  599. package/src/sessions/approvals.ts +0 -118
  600. package/src/sessions/contracts.ts +0 -336
  601. package/src/sessions/conversation.test.ts +0 -177
  602. package/src/sessions/extensionSession.test.ts +0 -74
  603. package/src/sessions/extensionUi.test.ts +0 -65
  604. package/src/sessions/extensionUi.ts +0 -102
  605. package/src/sessions/history.ts +0 -51
  606. package/src/sessions/lineageJoin.ts +0 -75
  607. package/src/sessions/policy.ts +0 -36
  608. package/src/sessions/pricing.ts +0 -60
  609. package/src/sessions/questionBatches.test.ts +0 -110
  610. package/src/sessions/reasoningSummaries.ts +0 -59
  611. package/src/sessions/registry.ts +0 -381
  612. package/src/sessions/runIndex.ts +0 -99
  613. package/src/sessions/runStore.test.ts +0 -152
  614. package/src/sessions/runStore.ts +0 -332
  615. package/src/sessions/runner.ts +0 -604
  616. package/src/sessions/runtimeResources.test.ts +0 -61
  617. package/src/sessions/sessions.test.ts +0 -549
  618. package/src/sessions/sessions.ts +0 -339
  619. package/src/skills/registry.test.ts +0 -104
  620. package/src/skills/registry.ts +0 -413
  621. package/src/terminal/accountsMenu.test.ts +0 -225
  622. package/src/terminal/accountsMenu.ts +0 -382
  623. package/src/terminal/cli.ts +0 -149
  624. package/src/terminal/client.ts +0 -74
  625. package/src/terminal/control.test.ts +0 -23
  626. package/src/terminal/control.ts +0 -23
  627. package/src/terminal/controller.ts +0 -291
  628. package/src/terminal/hubMenu.ts +0 -24
  629. package/src/terminal/launch.test.ts +0 -25
  630. package/src/terminal/launch.ts +0 -48
  631. package/src/terminal/piExtension.lifecycle.test.ts +0 -55
  632. package/src/terminal/piExtension.ts +0 -259
  633. package/src/terminal/pluginControl.test.ts +0 -146
  634. package/src/terminal/pluginMenu.ts +0 -112
  635. package/src/terminal/socket.test.ts +0 -71
  636. package/src/terminal/socket.ts +0 -232
  637. package/src/terminal/standalone.test.ts +0 -167
  638. package/src/terminal/standalone.ts +0 -153
  639. package/src/terminal/terminal.test.ts +0 -399
  640. package/src/terminal/terminals.ts +0 -553
  641. package/src/terminal/tui/application.test.ts +0 -114
  642. package/src/terminal/tui/application.ts +0 -491
  643. package/src/terminal/tui/commands.test.ts +0 -218
  644. package/src/terminal/tui/commands.ts +0 -361
  645. package/src/terminal/tui/dialogs.ts +0 -301
  646. package/src/terminal/tui/editor.test.ts +0 -84
  647. package/src/terminal/tui/editor.ts +0 -79
  648. package/src/terminal/tui/keybindings.test.ts +0 -22
  649. package/src/terminal/tui/keybindings.ts +0 -50
  650. package/src/terminal/tui/piAdapter.ts +0 -62
  651. package/src/terminal/tui/presentation.test.ts +0 -79
  652. package/src/terminal/tui/questions.test.ts +0 -41
  653. package/src/terminal/tui/questions.ts +0 -47
  654. package/src/terminal/tui/runtime.socket.test.ts +0 -104
  655. package/src/terminal/tui/runtime.test.ts +0 -215
  656. package/src/terminal/tui/runtime.ts +0 -388
  657. package/src/terminal/tui/sessionUi.ts +0 -24
  658. package/src/terminal/tui/settings.test.ts +0 -150
  659. package/src/terminal/tui/settings.ts +0 -188
  660. package/src/terminal/tui/status.test.ts +0 -70
  661. package/src/terminal/tui/status.ts +0 -109
  662. package/src/terminal/tui/theme.ts +0 -174
  663. package/src/terminal/tui/tools.test.ts +0 -145
  664. package/src/terminal/tui/tools.ts +0 -142
  665. package/src/terminal/tui/transcript.test.ts +0 -25
  666. package/src/terminal/tui/transcript.ts +0 -124
  667. package/src/terminal/tui/ui.test.ts +0 -313
  668. package/src/terminal/tui/ui.ts +0 -166
  669. package/src/terminal/tui/welcome.ts +0 -102
  670. package/src/tools/askUser.test.ts +0 -69
  671. package/src/tools/askUser.ts +0 -59
  672. package/src/tools/definitions.ts +0 -187
  673. package/src/tools/maintenance.ts +0 -24
  674. package/src/tools/memoryTools.ts +0 -22
  675. package/src/tools/pluginPropose.ts +0 -41
  676. package/src/tools/registryWrite.test.ts +0 -101
  677. package/src/tools/registryWrite.ts +0 -182
  678. package/src/tools/spawnSubagent.ts +0 -92
  679. package/src/tools/types.ts +0 -39
  680. package/src/web/safeRequest.ts +0 -171
  681. package/src/web/text.ts +0 -53
  682. package/src/web/tools.ts +0 -134
  683. package/src/web/web.test.ts +0 -141
@@ -1,614 +0,0 @@
1
- // Device-local connected apps: the saved connections, who may reach each one, how each is
2
- // launched, and what must never be persisted from their results.
3
- import { chmodSync } from 'node:fs'
4
- import { isAbsolute, join } from 'node:path'
5
-
6
- import { secretKey, type SecretStore } from '../accounts/secrets'
7
- import type { Bus } from '../core/bus'
8
- import { HarnessError, invalid, notFound } from '../core/errors'
9
- import { newId, readJson, safeId, writeJson } from '../core/fs'
10
- import { findBinary, pathVariableName, searchPath } from '../core/path'
11
- import { isDir } from '../memory/store'
12
- import type { RunEvent } from '../sessions/contracts'
13
- import * as attachments from '../plugins/attachments'
14
- import { connectionScopeMigrationComplete } from './scopeMigration'
15
- import { connectionCapabilityId, connectionInputSchema, connectionSchema, type Connection, type ConnectionInput, type LaunchConfig, type Scope } from './types'
16
-
17
- const OAUTH_STATE = 'oauth'
18
- const OAUTH_CLIENT_ID = 'oauth_client_id'
19
- const OAUTH_CLIENT_SECRET = 'oauth_client_secret'
20
- const headerItem = (name: string): string => `header:${name}`
21
-
22
- /** Remote servers and sign-in pages must use TLS; plain HTTP is only for servers on this machine. */
23
- export function webUrl(text: string | null | undefined): URL | null {
24
- try {
25
- const url = new URL(text ?? '')
26
- const loopback = ['127.0.0.1', 'localhost', '[::1]'].includes(url.hostname)
27
- return url.protocol === 'https:' || (url.protocol === 'http:' && loopback) ? url : null
28
- } catch {
29
- return null
30
- }
31
- }
32
-
33
- /** Whether a session with this scope may reach the connection. */
34
- export function allowed(connection: Connection, scope: Scope): boolean {
35
- if (!connection.enabled) return false
36
- if (scope.agentId && connection.excludedAgentIds.includes(scope.agentId)) return false
37
- if (scope.projectId && connection.excludedProjectIds.includes(scope.projectId)) return false
38
- return connection.global || Boolean(scope.agentId && connection.agentIds.includes(scope.agentId)) || Boolean(scope.projectId && connection.projectIds.includes(scope.projectId))
39
- }
40
-
41
- /** Gives one agent exactly these connections, leaving every other agent's access as it was. */
42
- export function setAgentScope(all: Connection[], agentId: string, ids: readonly string[]): void {
43
- for (const connection of all) {
44
- connection.agentIds = connection.agentIds.filter((id) => id !== agentId)
45
- connection.excludedAgentIds = connection.excludedAgentIds.filter((id) => id !== agentId)
46
- if (ids.includes(connection.id)) {
47
- if (!connection.global) connection.agentIds.push(agentId)
48
- } else if (connection.global) {
49
- connection.excludedAgentIds.push(agentId)
50
- }
51
- }
52
- }
53
-
54
- /**
55
- * Switches one connection on or off for everyone, for one agent, or for one project, leaving
56
- * every other agent's and project's access as it was.
57
- */
58
- export function setScope(connection: Connection, scope: Scope, on: boolean): void {
59
- const without = (ids: string[], id: string): string[] => ids.filter((item) => item !== id)
60
- if (scope.agentId) {
61
- connection.agentIds = without(connection.agentIds, scope.agentId)
62
- connection.excludedAgentIds = without(connection.excludedAgentIds, scope.agentId)
63
- if (on && !connection.global) connection.agentIds.push(scope.agentId)
64
- // Off must hold in a project that has the connection too.
65
- else if (!on && (connection.global || connection.projectIds.length)) connection.excludedAgentIds.push(scope.agentId)
66
- } else if (scope.projectId) {
67
- connection.projectIds = without(connection.projectIds, scope.projectId)
68
- connection.excludedProjectIds = without(connection.excludedProjectIds, scope.projectId)
69
- if (on && !connection.global) connection.projectIds.push(scope.projectId)
70
- else if (!on && connection.global) connection.excludedProjectIds.push(scope.projectId)
71
- } else {
72
- connection.global = on
73
- }
74
- }
75
-
76
- /** Why these connections cannot be given to a session with this scope, or nothing. */
77
- export function validateScopeIds(all: readonly Connection[], scope: Scope, ids: readonly string[]): void {
78
- for (const id of ids) {
79
- const connection = all.find((item) => item.id === id)
80
- if (!connection) throw notFound('Connection')
81
- if (!allowed(connection, scope)) throw new HarnessError('required_connections_unavailable', `${connection.name} is disabled or outside your connection scope.`)
82
- }
83
- }
84
-
85
- // ---- Redaction ----------------------------------------------------------------------------------
86
-
87
- const SENSITIVE_FIELDS = new Set(['approvaltoken', 'token', 'apikey', 'accesstoken', 'refreshtoken', 'idtoken', 'clientsecret', 'secret', 'password', 'passwd', 'authorization', 'cookie', 'setcookie', 'env', 'credentials', 'locators'])
88
- const SENSITIVE_KEYS = ['approvalToken', 'token', 'apiKey', 'api_key', 'accessToken', 'access_token', 'refreshToken', 'refresh_token', 'clientSecret', 'client_secret', 'password', 'authorization', 'cookie']
89
-
90
- function sensitiveField(key: string): boolean {
91
- return SENSITIVE_FIELDS.has(key.replace(/[^A-Za-z0-9]/g, '').toLowerCase())
92
- }
93
-
94
- /** Replaces the value of every `"key": "…"` in text that is not valid JSON (a truncated summary). */
95
- export function redactJsonField(text: string, key: string): string {
96
- const marker = `"${key}"`
97
- let output = text
98
- let offset = 0
99
- for (;;) {
100
- const found = output.indexOf(marker, offset)
101
- if (found < 0) return output
102
- const start = found + marker.length
103
- const match = /^\s*:\s*"/.exec(output.slice(start))
104
- if (!match) {
105
- offset = start
106
- continue
107
- }
108
- const valueStart = start + match[0].length
109
- const quote = output.indexOf('"', valueStart)
110
- const end = quote < 0 ? output.length : quote
111
- output = `${output.slice(0, valueStart)}[redacted]${output.slice(end)}`
112
- offset = valueStart + '[redacted]'.length
113
- }
114
- }
115
-
116
- function parsedContainer(text: string): unknown {
117
- try {
118
- const parsed = JSON.parse(text) as unknown
119
- return parsed && typeof parsed === 'object' ? parsed : undefined
120
- } catch {
121
- return undefined
122
- }
123
- }
124
-
125
- /** Drops credential-like fields from a value, including from JSON carried as text. */
126
- export function scrubSensitive(value: unknown): unknown {
127
- return scrubWith(value, [])
128
- }
129
-
130
- /** `scrubSensitive`, and every one of `secrets` replaced wherever it appears in text. */
131
- export function scrubWith(value: unknown, secrets: readonly string[]): unknown {
132
- if (Array.isArray(value)) return value.map((item) => scrubWith(item, secrets))
133
- if (value && typeof value === 'object') return Object.fromEntries(Object.entries(value).filter(([key]) => !sensitiveField(key)).map(([key, item]) => [key, scrubWith(item, secrets)]))
134
- if (typeof value !== 'string') return value
135
- let output = value
136
- for (const secret of secrets) if (secret) output = output.replaceAll(secret, '[redacted]')
137
- // Text representations of structured previews must not persist approval tokens.
138
- const parsed = parsedContainer(output)
139
- if (parsed !== undefined) return JSON.stringify(scrubWith(parsed, secrets))
140
- // Summaries can contain truncated JSON, which cannot be parsed above.
141
- for (const key of SENSITIVE_KEYS) output = redactJsonField(output, key)
142
- return output
143
- }
144
-
145
- export function revisionOf(all: readonly Connection[]): unknown[] {
146
- return all.map((item) => ({ id: item.id, enabled: item.enabled, global: item.global, agents: item.agentIds, projects: item.projectIds, excludedAgents: item.excludedAgentIds, excludedProjects: item.excludedProjectIds, checkedAt: item.checkedAt, error: item.error }))
147
- }
148
-
149
- function sameScope(left: Connection, right: Connection): boolean {
150
- const ids = (values: string[]): string[] => [...values].sort()
151
- return left.global === right.global
152
- && JSON.stringify(ids(left.agentIds)) === JSON.stringify(ids(right.agentIds))
153
- && JSON.stringify(ids(left.projectIds)) === JSON.stringify(ids(right.projectIds))
154
- && JSON.stringify(ids(left.excludedAgentIds)) === JSON.stringify(ids(right.excludedAgentIds))
155
- && JSON.stringify(ids(left.excludedProjectIds)) === JSON.stringify(ids(right.excludedProjectIds))
156
- }
157
-
158
- function hasScope(connection: Connection): boolean {
159
- return connection.global || connection.agentIds.length > 0 || connection.projectIds.length > 0
160
- || connection.excludedAgentIds.length > 0 || connection.excludedProjectIds.length > 0
161
- }
162
-
163
- function scopeMigrationError(): HarnessError {
164
- return new HarnessError('connection_scope_migration_pending', 'Connector access settings cannot be changed until their scope migration succeeds. Reopen the data root to retry it.')
165
- }
166
-
167
- // ---- The store --------------------------------------------------------------------------------
168
-
169
- export class Connections {
170
- private readonly path: string
171
- /** Every secret value a connection holds, so results can be redacted without waiting on the store. */
172
- private readonly known = new Map<string, string[]>()
173
-
174
- constructor(
175
- stateDir: string,
176
- private readonly secrets: SecretStore,
177
- private readonly bus: Bus,
178
- private readonly attachmentRoot: () => string | null = () => null
179
- ) {
180
- this.path = join(stateDir, 'connections.json')
181
- }
182
-
183
- list(): Connection[] {
184
- const stored = readJson<unknown[]>(this.path) ?? []
185
- const root = this.attachmentRoot()
186
- const choices = root ? attachments.load(root) : null
187
- return stored.flatMap((item) => {
188
- const parsed = connectionSchema.safeParse(item)
189
- if (!parsed.success) return []
190
- const connection = parsed.data
191
- // Records saved before remote servers existed have no `auth`.
192
- if (!connection.auth) connection.auth = 'none'
193
- // The preset was saved as "X Workspace" before the product was renamed.
194
- if (connection.kind === 'workspace' && connection.name === 'X Workspace') connection.name = 'Xingular Workspace'
195
- if (choices) {
196
- const id = connectionCapabilityId(connection.id)
197
- const hasChoice = choices.global.on.includes(id) || choices.global.off.includes(id)
198
- || Object.values(choices.agents).some((entry) => entry.on.includes(id) || entry.off.includes(id))
199
- || Object.values(choices.projects).some((entry) => entry.on.includes(id) || entry.off.includes(id))
200
- // Before the first successful root open, keep old records readable. After migration the
201
- // returned fields are a view over attachments; they are never written back to connections.json.
202
- if (hasChoice || !(connection.global || connection.agentIds.length || connection.projectIds.length || connection.excludedAgentIds.length || connection.excludedProjectIds.length)) {
203
- const attachment = attachments.describe(choices, id, connection.global)
204
- connection.global = attachment.global
205
- connection.agentIds = attachment.on.agentIds
206
- connection.projectIds = attachment.on.projectIds
207
- connection.excludedAgentIds = attachment.off.agentIds
208
- connection.excludedProjectIds = attachment.off.projectIds
209
- }
210
- }
211
- return [connection]
212
- })
213
- }
214
-
215
- find(id: string): Connection {
216
- const connection = this.list().find((item) => item.id === id)
217
- if (!connection) throw notFound('Connection')
218
- return connection
219
- }
220
-
221
- forScope(scope: Scope): Connection[] {
222
- return this.list().filter((connection) => allowed(connection, scope))
223
- }
224
-
225
- revision(): unknown[] {
226
- return revisionOf(this.list())
227
- }
228
-
229
- private write(all: Connection[]): void {
230
- const root = this.attachmentRoot()
231
- let stored: Connection[] | Omit<Connection, 'global' | 'agentIds' | 'projectIds' | 'excludedAgentIds' | 'excludedProjectIds'>[] = all
232
- if (root && connectionScopeMigrationComplete(root)) {
233
- stored = all.map(({ global: _global, agentIds: _agentIds, projectIds: _projectIds, excludedAgentIds: _excludedAgentIds, excludedProjectIds: _excludedProjectIds, ...connection }) => connection)
234
- } else if (root) {
235
- // A non-scope edit is allowed while migration is pending, but its legacy scopes must stay
236
- // in connections.json until the attachment store has been verified.
237
- const previous = new Map<string, Connection>()
238
- for (const item of readJson<unknown[]>(this.path) ?? []) {
239
- const parsed = connectionSchema.safeParse(item)
240
- if (parsed.success) previous.set(parsed.data.id, parsed.data)
241
- }
242
- stored = all.map((connection) => {
243
- const legacy = previous.get(connection.id)
244
- return legacy ? {
245
- ...connection,
246
- global: legacy.global,
247
- agentIds: legacy.agentIds,
248
- projectIds: legacy.projectIds,
249
- excludedAgentIds: legacy.excludedAgentIds,
250
- excludedProjectIds: legacy.excludedProjectIds
251
- } : connection
252
- })
253
- }
254
- writeJson(this.path, stored)
255
- try {
256
- chmodSync(this.path, 0o600)
257
- } catch {
258
- // The file was written; a mode that cannot be set is not worth failing the change.
259
- }
260
- }
261
-
262
- private writeScope(root: string, connection: Connection): void {
263
- const choices = attachments.load(root)
264
- const id = connectionCapabilityId(connection.id)
265
- attachments.forgetId(choices, id)
266
- attachments.set(choices, [id], {}, connection.global, false)
267
- for (const agentId of new Set([...connection.agentIds, ...connection.excludedAgentIds])) {
268
- const on = connection.agentIds.includes(agentId) && !connection.excludedAgentIds.includes(agentId)
269
- attachments.set(choices, [id], { agentId }, on, connection.global)
270
- }
271
- for (const projectId of new Set([...connection.projectIds, ...connection.excludedProjectIds])) {
272
- const on = connection.projectIds.includes(projectId) && !connection.excludedProjectIds.includes(projectId)
273
- attachments.set(choices, [id], { projectId }, on, connection.global)
274
- }
275
- attachments.save(root, choices)
276
- }
277
-
278
- changed(): void {
279
- this.bus.emit({ type: 'connections.changed' })
280
- }
281
-
282
- /** Read-modify-write of one connection. */
283
- update(id: string, change: (connection: Connection) => void): Connection {
284
- const all = this.list()
285
- const connection = all.find((item) => item.id === id)
286
- if (!connection) throw notFound('Connection')
287
- const before = { ...connection, agentIds: [...connection.agentIds], projectIds: [...connection.projectIds], excludedAgentIds: [...connection.excludedAgentIds], excludedProjectIds: [...connection.excludedProjectIds] }
288
- change(connection)
289
- const root = this.attachmentRoot()
290
- if (root && !connectionScopeMigrationComplete(root) && !sameScope(before, connection)) throw scopeMigrationError()
291
- this.write(all)
292
- return connection
293
- }
294
-
295
- /** Read-modify-write of every connection. */
296
- updateAll(change: (all: Connection[]) => void): void {
297
- const all = this.list()
298
- const before = new Map<string, Connection>(all.map((connection): [string, Connection] => [connection.id, {
299
- ...connection,
300
- agentIds: [...connection.agentIds],
301
- projectIds: [...connection.projectIds],
302
- excludedAgentIds: [...connection.excludedAgentIds],
303
- excludedProjectIds: [...connection.excludedProjectIds]
304
- }]))
305
- change(all)
306
- const root = this.attachmentRoot()
307
- if (root && !connectionScopeMigrationComplete(root)) {
308
- const remainingIds = new Set(all.map((connection) => connection.id))
309
- const scopeChanged = all.some((connection) => {
310
- const previous = before.get(connection.id)
311
- return previous ? !sameScope(previous, connection) : hasScope(connection)
312
- }) || [...before].some(([id, connection]) => !remainingIds.has(id) && hasScope(connection))
313
- if (scopeChanged) throw scopeMigrationError()
314
- }
315
- this.write(all)
316
- this.changed()
317
- }
318
-
319
- /** Switches one connector in the shared attachment store, preserving all other scopes. */
320
- setScope(connectionId: string, scope: Scope, on: boolean): Connection[] {
321
- const connection = this.find(connectionId)
322
- const root = this.attachmentRoot()
323
- if (root && !connectionScopeMigrationComplete(root)) throw scopeMigrationError()
324
- if (!root) {
325
- this.update(connectionId, (item) => setScope(item, scope, on))
326
- this.changed()
327
- return this.forScope(scope)
328
- }
329
- const choices = attachments.load(root)
330
- const fallback = connection.global
331
- attachments.set(choices, [connectionCapabilityId(connectionId)], scope, on, fallback)
332
- attachments.save(root, choices)
333
- this.changed()
334
- return this.forScope(scope)
335
- }
336
-
337
- /** Gives one agent an exact connector set without changing project or global choices. */
338
- setAgentScope(agentId: string, ids: readonly string[]): Connection[] {
339
- const all = this.list()
340
- const root = this.attachmentRoot()
341
- if (root && !connectionScopeMigrationComplete(root)) throw scopeMigrationError()
342
- if (!root) {
343
- setAgentScope(all, agentId, ids)
344
- this.write(all)
345
- this.changed()
346
- return this.forScope({ agentId })
347
- }
348
- const choices = attachments.load(root)
349
- for (const connection of all) {
350
- attachments.set(choices, [connectionCapabilityId(connection.id)], { agentId }, ids.includes(connection.id), connection.global)
351
- }
352
- attachments.save(root, choices)
353
- this.changed()
354
- return this.forScope({ agentId })
355
- }
356
-
357
- /** Removes only connector choices when an agent is deleted; other capability choices are separate. */
358
- removeAgentScope(agentId: string): void {
359
- const root = this.attachmentRoot()
360
- // This is cleanup for a deleted caller. Leave stale ids inert until migration can safely
361
- // move the remaining scopes; failing helper cleanup must not leave an orphan agent behind.
362
- if (root && !connectionScopeMigrationComplete(root)) return
363
- if (!root) {
364
- this.updateAll((all) => {
365
- for (const connection of all) {
366
- connection.agentIds = connection.agentIds.filter((id) => id !== agentId)
367
- connection.excludedAgentIds = connection.excludedAgentIds.filter((id) => id !== agentId)
368
- }
369
- })
370
- return
371
- }
372
- const choices = attachments.load(root)
373
- const entry = choices.agents[agentId]
374
- if (!entry) return
375
- const isConnector = (id: string): boolean => id.startsWith('connected-apps/connection/')
376
- entry.on = entry.on.filter((id) => !isConnector(id))
377
- entry.off = entry.off.filter((id) => !isConnector(id))
378
- if (!entry.on.length && !entry.off.length) delete choices.agents[agentId]
379
- attachments.save(root, choices)
380
- this.changed()
381
- }
382
-
383
- private secret(connectionId: string, name: string): Promise<string | null> {
384
- return this.secrets.get(secretKey(`mcp--${connectionId}`, name))
385
- }
386
-
387
- private setSecret(connectionId: string, name: string, value: string): Promise<void> {
388
- return this.secrets.set(secretKey(`mcp--${connectionId}`, name), value)
389
- }
390
-
391
- private deleteSecret(connectionId: string, name: string): Promise<void> {
392
- return this.secrets.delete(secretKey(`mcp--${connectionId}`, name))
393
- }
394
-
395
- /** Everything the secret store holds for a connection: environment and header values, and OAuth credentials. */
396
- private async secretValues(connection: Connection): Promise<string[]> {
397
- const values: string[] = []
398
- for (const key of connection.envKeys) {
399
- const value = await this.secret(connection.id, key)
400
- if (value) values.push(value)
401
- }
402
- for (const key of connection.headerKeys) {
403
- const value = await this.secret(connection.id, headerItem(key))
404
- if (!value) continue
405
- // "Authorization: Bearer <key>" must not leak the key on its own either.
406
- const space = value.indexOf(' ')
407
- if (space >= 0) values.push(value.slice(space + 1).trim())
408
- values.push(value)
409
- }
410
- if (connection.auth === 'oauth') {
411
- const client = await this.secret(connection.id, OAUTH_CLIENT_SECRET)
412
- if (client) values.push(client)
413
- const saved = (parsedContainer((await this.secret(connection.id, OAUTH_STATE)) ?? '') ?? {}) as { tokens?: Record<string, unknown> }
414
- for (const field of ['access_token', 'refresh_token', 'id_token']) if (typeof saved.tokens?.[field] === 'string') values.push(saved.tokens[field] as string)
415
- }
416
- return values.filter(Boolean)
417
- }
418
-
419
- /** Reloads the secret values used for redaction. Called at start and whenever a connection's secrets change. */
420
- async refreshSecrets(): Promise<void> {
421
- const next = new Map<string, string[]>()
422
- for (const connection of this.list()) next.set(connection.id, await this.secretValues(connection).catch(() => []))
423
- this.known.clear()
424
- for (const [id, values] of next) this.known.set(id, values)
425
- }
426
-
427
- /** A connection's result, safe to persist. */
428
- scrub(value: unknown, connectionId: string): unknown {
429
- return scrubWith(value, this.known.get(connectionId) ?? [])
430
- }
431
-
432
- /** Removes credentials from the evidence a run event carries. */
433
- redactEvent(event: RunEvent): void {
434
- if (!event.type.startsWith('tool.') && !['context.snapshot', 'retry.started', 'retry.ended', 'compaction.started', 'compaction.ended'].includes(event.type)) return
435
- const secrets = [...this.known.values()].flat()
436
- event.payload = scrubWith(event.payload, secrets)
437
- if (event.native !== undefined) event.native = scrubWith(event.native, secrets)
438
- }
439
-
440
- // ---- Launching ----------------------------------------------------------------------------
441
-
442
- async launch(connection: Connection): Promise<LaunchConfig> {
443
- if (connection.kind === 'remote') {
444
- const headers: Record<string, string> = {}
445
- for (const key of connection.headerKeys) {
446
- const value = await this.secret(connection.id, headerItem(key))
447
- if (value !== null) headers[key] = value
448
- }
449
- return { id: connection.id, name: connection.name, transport: 'http', url: connection.url ?? '', headers, auth: connection.auth as 'none' | 'headers' | 'oauth', scopes: connection.oauthScopes }
450
- }
451
- let command = findBinary(connection.command) ?? (isAbsolute(connection.command) ? connection.command : null)
452
- if (!command) throw new HarnessError('mcp_unavailable', 'MCP executable was not found. Select its absolute path.')
453
- const env: Record<string, string> = { [pathVariableName(process.env)]: searchPath() }
454
- for (const key of ['HOME', 'TMPDIR', 'LANG']) if (process.env[key]) env[key] = process.env[key]!
455
- for (const key of connection.envKeys) {
456
- const value = await this.secret(connection.id, key)
457
- if (value !== null) env[key] = value
458
- }
459
- const args = [...connection.args]
460
- if (connection.kind === 'workspace') {
461
- // The first-party launcher is JavaScript; run it on this process's Node even where none is on PATH.
462
- args.unshift(command)
463
- command = process.execPath
464
- if (connection.expectedVaultId && !args.includes('--expected-vault-id')) args.push('--expected-vault-id', connection.expectedVaultId)
465
- }
466
- return { id: connection.id, name: connection.name, transport: 'stdio', command, args, cwd: connection.cwd, env }
467
- }
468
-
469
- // ---- OAuth state --------------------------------------------------------------------------
470
-
471
- private requireOauth(id: string): void {
472
- if (!this.list().some((item) => item.id === id && item.kind === 'remote' && item.auth === 'oauth')) throw notFound('Connection')
473
- }
474
-
475
- /** The saved sign-in of a connection, with the client the user registered, if any. */
476
- async oauthLoad(id: string): Promise<Record<string, unknown>> {
477
- this.requireOauth(id)
478
- const saved = (parsedContainer((await this.secret(id, OAUTH_STATE)) ?? '') ?? {}) as Record<string, unknown>
479
- const state = Array.isArray(saved) ? {} : saved
480
- const clientId = await this.secret(id, OAUTH_CLIENT_ID)
481
- if (clientId) {
482
- const clientSecret = await this.secret(id, OAUTH_CLIENT_SECRET)
483
- state.staticClient = { client_id: clientId, ...(clientSecret ? { client_secret: clientSecret } : {}) }
484
- }
485
- return state
486
- }
487
-
488
- async oauthSave(id: string, state: Record<string, unknown>): Promise<void> {
489
- this.requireOauth(id)
490
- const { staticClient: _static, ...saved } = state ?? {}
491
- await this.setSecret(id, OAUTH_STATE, JSON.stringify(saved))
492
- await this.refreshSecrets()
493
- }
494
-
495
- async hasOauthClient(id: string): Promise<boolean> {
496
- return (await this.secret(id, OAUTH_CLIENT_ID)) !== null
497
- }
498
-
499
- private forgetSignIn(id: string): Promise<void> {
500
- return this.deleteSecret(id, OAUTH_STATE)
501
- }
502
-
503
- // ---- Changes ------------------------------------------------------------------------------
504
-
505
- async save(input: ConnectionInput): Promise<Connection> {
506
- const parsed = connectionInputSchema.safeParse(input)
507
- if (!parsed.success) throw invalid('A name, executable, and supported connection kind are required.')
508
- const { env, removeEnv, headers, removeHeaders, oauthCredentials, ...connection } = parsed.data
509
- if (!connection.id) connection.id = newId()
510
- safeId(connection.id)
511
- const remote = connection.kind === 'remote'
512
- if (!connection.name.trim() || !['workspace', 'local', 'remote'].includes(connection.kind) || (!remote && !connection.command.trim())) {
513
- throw invalid('A name, executable, and supported connection kind are required.')
514
- }
515
- if (remote) {
516
- if (!webUrl(connection.url)) throw invalid('Server URL must be an https:// address.')
517
- if (!['none', 'headers', 'oauth'].includes(connection.auth)) throw invalid('Unsupported sign-in method.')
518
- if (connection.oauthClient && !['dynamic', 'user'].includes(connection.oauthClient)) throw invalid('Unsupported OAuth client.')
519
- Object.assign(connection, { command: '', args: [], cwd: null })
520
- if (connection.auth !== 'oauth') Object.assign(connection, { oauthClient: null, oauthScopes: [] })
521
- } else {
522
- Object.assign(connection, { url: null, auth: 'none', oauthClient: null, oauthScopes: [] })
523
- }
524
- if (connection.args.some((value) => value.includes('\0')) || connection.command.includes('\0')) throw invalid('Invalid executable or argument.')
525
- if (connection.cwd && (!isAbsolute(connection.cwd) || !isDir(connection.cwd))) throw invalid('Working directory must be an existing absolute directory.')
526
-
527
- const all = this.list()
528
- const existing = all.find((item) => item.id === connection.id)
529
- const root = this.attachmentRoot()
530
- if (root && !connectionScopeMigrationComplete(root) && (existing ? !sameScope(existing, connection) : hasScope(connection))) {
531
- throw scopeMigrationError()
532
- }
533
- connection.envKeys = [...(existing?.envKeys ?? [])]
534
- connection.headerKeys = [...(existing?.headerKeys ?? [])]
535
- // A sign-in belongs to one server and one client; never carry it to another.
536
- const sameServer = (existing?.url ?? null) === connection.url && (existing?.auth ?? '') === connection.auth && !oauthCredentials
537
- if (!sameServer || connection.auth !== 'oauth') await this.forgetSignIn(connection.id)
538
- connection.authState = connection.auth === 'oauth' ? (sameServer ? (existing?.authState ?? 'signed_out') : 'signed_out') : null
539
- if (oauthCredentials) {
540
- if (!oauthCredentials.clientId.trim()) throw invalid('An OAuth client ID is required.')
541
- await this.setSecret(connection.id, OAUTH_CLIENT_ID, oauthCredentials.clientId.trim())
542
- if (oauthCredentials.clientSecret) await this.setSecret(connection.id, OAUTH_CLIENT_SECRET, oauthCredentials.clientSecret)
543
- else await this.deleteSecret(connection.id, OAUTH_CLIENT_SECRET)
544
- }
545
- for (const [key, value] of Object.entries(headers ?? {})) {
546
- if (!/^[A-Za-z0-9_-]+$/.test(key) || /[\r\n\0]/.test(value)) throw invalid('Invalid header name or value.')
547
- await this.setSecret(connection.id, headerItem(key), value)
548
- if (!connection.headerKeys.includes(key)) connection.headerKeys.push(key)
549
- }
550
- for (const key of removeHeaders ?? []) {
551
- await this.deleteSecret(connection.id, headerItem(key))
552
- connection.headerKeys = connection.headerKeys.filter((value) => value !== key)
553
- }
554
- for (const [key, value] of Object.entries(env ?? {})) {
555
- if (!/^[A-Za-z0-9_]+$/.test(key)) throw invalid('Invalid environment variable name.')
556
- await this.setSecret(connection.id, key, value)
557
- if (!connection.envKeys.includes(key)) connection.envKeys.push(key)
558
- }
559
- for (const key of removeEnv ?? []) {
560
- await this.deleteSecret(connection.id, key)
561
- connection.envKeys = connection.envKeys.filter((value) => value !== key)
562
- }
563
- Object.assign(connection, { checkedAt: null, tools: [], serverName: null, error: null })
564
- if (root && connectionScopeMigrationComplete(root)) this.writeScope(root, connection as Connection)
565
- this.write([...all.filter((item) => item.id !== connection.id), connection])
566
- await this.refreshSecrets()
567
- this.changed()
568
- return connection
569
- }
570
-
571
- /**
572
- * Adds one tool to a connection's no-approval list. Unlike a full save this keeps the
573
- * connection's pending approvals, so the request the user is answering can still be approved.
574
- */
575
- allowTool(connectionId: string, tool: string): Connection {
576
- if (!tool.trim()) throw invalid('A tool is required.')
577
- if (this.list().some((item) => item.id === connectionId && item.kind === 'workspace')) throw invalid('Changes to Xingular Workspace are approved one at a time.')
578
- const connection = this.update(connectionId, (item) => {
579
- if (!item.readTools.includes(tool)) item.readTools.push(tool)
580
- })
581
- this.changed()
582
- return connection
583
- }
584
-
585
- async remove(connectionId: string): Promise<void> {
586
- const all = this.list()
587
- const connection = all.find((item) => item.id === connectionId)
588
- if (connection) {
589
- for (const key of connection.envKeys) await this.deleteSecret(connection.id, key)
590
- for (const key of connection.headerKeys) await this.deleteSecret(connection.id, headerItem(key))
591
- for (const name of [OAUTH_STATE, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET]) await this.deleteSecret(connection.id, name)
592
- }
593
- this.write(all.filter((item) => item.id !== connectionId))
594
- const root = this.attachmentRoot()
595
- if (root) {
596
- const choices = attachments.load(root)
597
- attachments.forgetId(choices, connectionCapabilityId(connectionId))
598
- attachments.save(root, choices)
599
- }
600
- this.known.delete(connectionId)
601
- this.changed()
602
- }
603
-
604
- async signOut(connectionId: string): Promise<Connection> {
605
- await this.forgetSignIn(connectionId)
606
- const connection = this.update(connectionId, (item) => {
607
- if (item.auth === 'oauth') item.authState = 'signed_out'
608
- Object.assign(item, { checkedAt: null, tools: [], error: null })
609
- })
610
- await this.refreshSecrets()
611
- this.changed()
612
- return connection
613
- }
614
- }