@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
@@ -0,0 +1,208 @@
1
+ import { accessSync, constants, existsSync, readFileSync, statSync } from 'node:fs';
2
+ import { delimiter, isAbsolute, join } from 'node:path';
3
+ import { defaultAssets } from "../terminal/terminals.js";
4
+ import { loadPi, PINNED_PI_VERSION } from "../pi/runtime.js";
5
+ import { list as listPlugins } from "../plugins/api.js";
6
+ import { compile } from "../prompt/compile.js";
7
+ import { materialise } from "../variant/materialise.js";
8
+ import { validate } from "../variant/variant.js";
9
+ import { PI_SURFACE } from "../variant/surface.js";
10
+ import { allowed } from "../mcp/connections.js";
11
+ import { BRAVE, TAVILY, EXA } from "../web/search.js";
12
+ import { KEYLESS_SEARCH, WEB_PLUGIN } from "../web/tools.js";
13
+ const pass = (evidence) => ({ status: 'pass', evidence });
14
+ const fail = (evidence, remedy) => ({ status: 'fail', evidence, remedy });
15
+ function executable(name) {
16
+ const paths = isAbsolute(name) ? [name] : (process.env.PATH ?? '').split(delimiter).filter(Boolean).map(dir => join(dir, name));
17
+ return paths.some(path => {
18
+ try {
19
+ accessSync(path, constants.X_OK);
20
+ return statSync(path).isFile();
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ });
26
+ }
27
+ export async function builtinChecks(harness, context, secrets, assets = defaultAssets()) {
28
+ const check = (id, category, title, local) => ({ id, category, title, local });
29
+ const account = () => context.accountId ? harness.accounts.find(context.accountId) : null;
30
+ const checks = [
31
+ check('account', 'account', 'Selected account', async (signal) => {
32
+ const selected = account();
33
+ if (!selected)
34
+ return fail('No account is selected.', 'Choose an account with /accounts.');
35
+ const saved = harness.accounts.overview().accounts.find(item => item.id === selected.id);
36
+ const inspected = await harness.accounts.inspect(selected.id, signal);
37
+ if (!inspected.credentials)
38
+ return fail('The pinned account has no saved provider credentials.', 'Sign in or add a key in /accounts.');
39
+ return { status: saved.state.health === 'ok' || saved.state.health === 'unknown' ? 'pass' : 'warning', evidence: `Credentials are configured. Saved health: ${saved.state.health}; checked ${saved.state.lastCheckedAt ?? 'never'}. ${saved.state.limits.map(limit => `${limit.label || limit.id}: ${limit.usedPercent}% used; resets ${limit.resetsAt ?? 'unknown'}`).join('; ')} ${saved.state.lastError ? `Saved issue: ${saved.state.lastError.category}.` : ''} This does not verify authentication with the provider.`, remedy: saved.state.health === 'ok' ? undefined : 'Use the model live probe to verify current provider access.' };
40
+ }),
41
+ check('accounts.inventory', 'account', 'Other saved accounts', async () => {
42
+ const others = harness.accounts.overview().accounts.filter(item => item.id !== context.accountId);
43
+ return pass(others.length ? others.map(item => `${item.label}: ${item.state.health}; checked ${item.state.lastCheckedAt ?? 'never'}`).join('\n') : 'No other saved accounts.');
44
+ }),
45
+ {
46
+ ...check('model', 'account', 'Selected model', async (signal) => {
47
+ if (!context.accountId || !context.model)
48
+ return fail('No account/model is selected.', 'Choose an account and /model.');
49
+ const model = (await harness.accounts.inspect(context.accountId, signal)).models.find(item => item.id === context.model);
50
+ return model ? pass(`${model.id} is available locally; images: ${model.supportsImages}; reasoning: ${model.reasoning}. Provider access is unverified.`) : fail('The selected model is absent from the account model catalogue.', 'Choose an available model with /model.');
51
+ }),
52
+ live: {
53
+ notice: 'One provider request on the selected account/model, up to 64 output tokens; charges may apply. Only synthetic diagnostic content is sent.',
54
+ run: async ({ signal, run }) => {
55
+ const selected = account();
56
+ if (!selected || !context.model)
57
+ return fail('No account/model is selected.', 'Choose an account and /model.');
58
+ const runtime = await harness.accounts.runtime(selected);
59
+ const model = (await runtime.getAvailable()).find(item => `${item.provider}/${item.id}` === context.model);
60
+ if (!model)
61
+ return fail('The selected model is unavailable.', 'Choose an available model with /model.');
62
+ signal.throwIfAborted();
63
+ const result = await runtime.completeSimple(model, { messages: [{ role: 'user', content: 'Reply with OK.', timestamp: Date.now() }] }, { maxTokens: 64, signal });
64
+ const usage = result.usage;
65
+ run.emit('usage.updated', {
66
+ inputTokens: usage.input, outputTokens: usage.output, cacheReadTokens: usage.cacheRead, cacheWriteTokens: usage.cacheWrite,
67
+ costUsd: usage.cost.total, costSource: 'harness', requests: 1, model: result.model, provider: result.provider,
68
+ request: { index: 1, model: result.model, provider: result.provider, stopReason: result.stopReason }
69
+ });
70
+ return result.stopReason === 'error' || result.stopReason === 'aborted'
71
+ ? fail(`The provider request ended with ${result.stopReason}.`, 'Review account authentication, limits, and model configuration.')
72
+ : pass('The selected provider/model completed a real request. Usage is recorded on the diagnostic run.');
73
+ }
74
+ }
75
+ },
76
+ check('runtime.pi', 'runtime', 'Pi runtime', async () => { await loadPi(); return pass(`Pi ${PINNED_PI_VERSION} loaded with its required dispatcher.`); }),
77
+ check('runtime.launcher', 'runtime', 'Terminal launcher', async () => {
78
+ if (!executable(assets.node))
79
+ return fail('The configured Node executable cannot be accessed.', 'Check the host launch configuration.');
80
+ return executable(process.env.XINGULAR_HARNESS_BUN || 'bun')
81
+ ? pass('Node and Bun executables are accessible. No process was launched for this check.')
82
+ : { status: 'warning', evidence: 'Bun was not found on the inherited PATH or at XINGULAR_HARNESS_BUN. The terminal launcher may resolve an additional login-shell path.', remedy: 'Verify the terminal Bun launch path.' };
83
+ }),
84
+ {
85
+ ...check('native.files', 'tools', 'Native file tools', async () => {
86
+ accessSync(context.cwd, constants.R_OK);
87
+ if (context.tools.some(name => name === 'write' || name === 'edit')) {
88
+ try {
89
+ accessSync(context.cwd, constants.W_OK);
90
+ }
91
+ catch {
92
+ return { status: 'blocked', evidence: 'The working directory is readable but not writable.', remedy: 'Choose a writable working directory for edits.' };
93
+ }
94
+ }
95
+ return pass('The working directory is accessible for enabled native file tools. Per-call policy and actual file operations are unverified.');
96
+ }), tools: ['read', 'grep', 'find', 'ls', 'write', 'edit']
97
+ },
98
+ {
99
+ ...check('native.bash', 'tools', 'Native shell tool', async () => process.platform === 'win32'
100
+ ? { status: 'unverified', evidence: 'Windows shell resolution is delegated to Pi; no shell was launched.' }
101
+ : executable('bash') ? pass('Bash is executable on the inherited PATH. No shell command was run.') : fail('Bash was not found on the inherited PATH.', 'Verify the shell executable used by Pi.')),
102
+ tools: ['bash']
103
+ },
104
+ check('runtime.storage', 'runtime', 'State and data storage', async () => {
105
+ accessSync(harness.stateDir, constants.R_OK | constants.W_OK);
106
+ if (!harness.dataRoot)
107
+ return fail('No data root is open.', 'Open a data location before starting runs.');
108
+ accessSync(harness.dataRoot, constants.R_OK | constants.W_OK);
109
+ accessSync(context.cwd, constants.R_OK);
110
+ return pass('State/data directories are accessible and the working directory is readable. Write access is checked without writing files.');
111
+ }),
112
+ check('runtime.assets', 'runtime', 'Terminal assets', async () => {
113
+ const files = [assets.cli, assets.openTui, assets.piExtension];
114
+ const missing = files.filter(file => !existsSync(file));
115
+ return missing.length ? { status: 'warning', evidence: `Configured terminal assets are missing: ${missing.join(', ')}.`, remedy: 'Build the Harness or verify the host-supplied assets.' } : pass('Configured terminal assets are present.');
116
+ }),
117
+ check('runtime.recovery', 'runtime', 'Startup recovery', async () => harness.recovery.migrationError
118
+ ? fail('Startup recorded a storage migration error.', 'Review the recovery diagnostics before starting work.')
119
+ : { status: harness.recovery.interruptedRuns ? 'warning' : 'pass', evidence: `${harness.recovery.interruptedRuns} interrupted runs recovered; no recorded migration error.` }),
120
+ check('variant', 'variant', 'Pinned variant and prompt', async () => {
121
+ if (!harness.dataRoot)
122
+ return { status: 'blocked', evidence: 'Variant and prompt inspection needs an open data root.', remedy: 'Open a data location.' };
123
+ if (!context.variant) {
124
+ compile(harness.env, context.caller, {});
125
+ return pass('No variant is selected; the foundation prompt compiles.');
126
+ }
127
+ const variant = materialise(harness.env.root, context.variant, { trust: harness.trust });
128
+ validate(PI_SURFACE, variant.files);
129
+ compile(harness.env, context.caller, { tools: [...context.tools] }, variant);
130
+ return { status: variant.untrustedPlugins.length ? 'warning' : 'pass', evidence: `Variant ${variant.fingerprint} validates and its prompt compiles; ${variant.untrustedPlugins.length} code resources withheld for trust.` };
131
+ }),
132
+ check('plugins', 'plugins', 'Plugins, skills and resources', async () => {
133
+ if (!harness.dataRoot)
134
+ return { status: 'blocked', evidence: 'Plugin inspection needs an open data root.', remedy: 'Open a data location.' };
135
+ const plugins = await listPlugins(harness, { ...context.caller, cwd: context.cwd, accountId: context.accountId });
136
+ const contributions = plugins.flatMap(plugin => plugin.contributions);
137
+ const problems = [];
138
+ for (const item of contributions.filter(item => item.state === 'on')) {
139
+ if (item.problem)
140
+ problems.push(`${item.name}: recorded resource error`);
141
+ if (item.path) {
142
+ try {
143
+ accessSync(item.path, constants.R_OK);
144
+ if (item.kind === 'skill')
145
+ readFileSync(item.path, 'utf8');
146
+ }
147
+ catch {
148
+ problems.push(`${item.name}: resource cannot be read`);
149
+ }
150
+ }
151
+ }
152
+ const names = contributions.filter(item => item.kind === 'tool' && item.state === 'on').map(item => item.name);
153
+ const duplicates = [...new Set(names.filter((name, index) => names.indexOf(name) !== index))];
154
+ if (duplicates.length)
155
+ problems.push(`Overlapping tool contributions: ${duplicates.join(', ')}`);
156
+ const withheld = contributions.filter(item => item.state === 'untrusted').length;
157
+ return problems.length ? fail(problems.join('\n'), 'Review /plugins and the resource configuration.') : { status: withheld ? 'warning' : 'pass', evidence: `${plugins.length} plugins inspected; ${withheld} untrusted resources withheld. No plugin code was executed for diagnostics. Transitive dependencies are unverified until loaded normally.` };
158
+ })
159
+ ];
160
+ const providers = [BRAVE, TAVILY, EXA];
161
+ checks.push({
162
+ ...check('web.search', 'web', 'Web search', async () => {
163
+ const configured = (await Promise.all(providers.map(async (provider) => await secrets.get(provider.key) ? provider.title : null))).filter(Boolean);
164
+ const keyless = harness.dataRoot !== null && harness.world.setting(WEB_PLUGIN.id, KEYLESS_SEARCH) === 1;
165
+ return configured.length || keyless ? pass(`Configured: ${[...configured, ...(keyless ? ['DuckDuckGo (keyless)'] : [])].join(', ')}. Keys have not been authenticated.`) : fail('No search provider key is saved and keyless search is disabled.', 'Configure Web in /plugins.');
166
+ }), tools: ['web_search'],
167
+ live: { notice: 'Search the public web for “example domain” through configured Brave, Tavily, Exa, or DuckDuckGo endpoints; search API charges may apply.', run: async (probe) => {
168
+ const result = await probe.call('web_search', { queries: ['example domain'] });
169
+ const details = typeof result === 'string' ? undefined : result.details;
170
+ return details?.provider && Array.isArray(details.sources) && details.sources.length ? pass(`Search completed through ${String(details.provider)}.`) : fail('Search did not return verified results.', 'Review configured search providers and limits.');
171
+ } }
172
+ });
173
+ checks.push({
174
+ ...check('web.fetch', 'web', 'Public web fetch', async () => pass('Checked public HTTP reader is installed; network access is unverified.')),
175
+ tools: ['web_fetch'], live: { notice: 'Fetch https://example.com/ through the enabled web_fetch tool.', run: async (probe) => {
176
+ const result = await probe.call('web_fetch', { url: 'https://example.com/' });
177
+ return typeof result !== 'string' && result.details?.status === 200 ? pass('The public page returned HTTP 200 and readable text.') : fail('The public page could not be read.', 'Check network access and retry.');
178
+ } }
179
+ });
180
+ for (const connection of harness.dataRoot ? harness.apps.connections.list() : []) {
181
+ const inScope = allowed(connection, context.caller) && (!context.capabilities || context.capabilities.connectors.includes(connection.id));
182
+ checks.push({
183
+ ...check(`mcp.${connection.id}`, 'mcp', `MCP: ${connection.name}`, async () => {
184
+ if (!connection.enabled)
185
+ return { status: 'disabled', evidence: 'The connection is disabled.' };
186
+ if (!inScope)
187
+ return { status: 'blocked', evidence: 'The connection is outside this diagnostic scope.' };
188
+ if (connection.auth === 'oauth' && connection.authState !== 'signed_in')
189
+ return { status: 'warning', evidence: `Saved authentication state: ${connection.authState ?? 'unknown'}.`, remedy: 'Check connector authentication in the host.' };
190
+ return { status: connection.error ? 'warning' : 'pass', evidence: `Configured; last checked ${connection.checkedAt ?? 'never'}; ${connection.tools.length} cached tools. Live connectivity is unverified.` };
191
+ }),
192
+ tools: ['mcp_list_tools'],
193
+ live: { notice: `Connect to configured MCP server “${connection.name}” and list its tools. A configured local server process may start. No connector tools are invoked.`, run: async (probe) => {
194
+ if (!connection.enabled || !inScope)
195
+ return { status: 'blocked', evidence: 'This connection is disabled or outside the selected scope.' };
196
+ const result = await probe.call('mcp_list_tools', { connectionId: connection.id });
197
+ const details = typeof result === 'string' ? undefined : result.details;
198
+ return details?.doctorOk === true ? pass(`${String(details.toolCount)} tools listed.`) : fail('The MCP server could not list tools.', 'Review its transport, authentication, and scope.');
199
+ } }
200
+ });
201
+ }
202
+ // A tool without diagnostics is present in the report without claiming its backend works.
203
+ const supplied = await harness.sessions.diagnostics(context);
204
+ const covered = new Set([...checks, ...supplied].flatMap(item => item.tools ?? []));
205
+ for (const tool of context.tools.filter(tool => !covered.has(tool)))
206
+ checks.push(check(`tool.${tool}`, 'tools', tool, async () => ({ status: 'unverified', evidence: 'Enabled in this session; this provider has no readiness check.', remedy: 'Use the tool normally or add provider diagnostics.' })));
207
+ return [...checks, ...supplied];
208
+ }
@@ -0,0 +1,4 @@
1
+ import type { Harness } from "../harness.js";
2
+ import type { DoctorContext, DoctorProbeContext } from "./types.js";
3
+ /** A real, tool-only diagnostic run. Model requests, if selected, use Pi's account runtime. */
4
+ export declare function diagnosticProbe<T>(harness: Harness, context: DoctorContext, inputSignal: AbortSignal, action: (probe: DoctorProbeContext) => Promise<T>): Promise<T>;
@@ -0,0 +1,92 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { resolve } from "../capabilities/api.js";
3
+ import { freezeRun } from "../capabilities/runSnapshot.js";
4
+ import { runRecordSchema } from "../sessions/contracts.js";
5
+ import { saveRun } from "../sessions/runStore.js";
6
+ import { HarnessError } from "../core/errors.js";
7
+ import { materialise } from "../variant/materialise.js";
8
+ /** A real, tool-only diagnostic run. Model requests, if selected, use Pi's account runtime. */
9
+ export async function diagnosticProbe(harness, context, inputSignal, action) {
10
+ const interrupt = new AbortController();
11
+ const signal = AbortSignal.any([inputSignal, interrupt.signal]);
12
+ signal.throwIfAborted();
13
+ const root = harness.env.root;
14
+ const id = randomUUID();
15
+ const caller = { ...context.caller, runId: id, sessionId: id, surface: 'doctor' };
16
+ const available = await resolve(harness, { ...context.caller, cwd: context.cwd, tools: context.tools });
17
+ const capabilities = {
18
+ version: 1,
19
+ tools: available.tools.filter(tool => context.tools.includes(tool) && (!context.capabilities || context.capabilities.tools.includes(tool))),
20
+ connectors: available.connectors.filter(connector => !context.capabilities || context.capabilities.connectors.includes(connector)),
21
+ contributions: available.contributions.filter(item => !context.capabilities || context.capabilities.contributions.includes(item))
22
+ };
23
+ signal.throwIfAborted();
24
+ if (context.accountId)
25
+ harness.accounts.find(context.accountId);
26
+ const variant = context.variant ? materialise(root, context.variant, { trust: harness.trust }) : null;
27
+ saveRun(root, runRecordSchema.parse({
28
+ id, sessionId: id, mode: 'doctor', harness: 'pi', sessionType: 'structured', workingDirectory: context.cwd,
29
+ startedAt: new Date().toISOString(), status: 'running', goal: 'User-approved diagnostic probe',
30
+ accountId: context.accountId, agentId: caller.agentId ?? null, projectId: caller.projectId ?? null, trigger: 'doctor',
31
+ variantScope: variant?.scope ?? null, variantVersion: variant?.fingerprint ?? null
32
+ }));
33
+ freezeRun(root, id, caller, capabilities);
34
+ const run = harness.runs.start(id, id);
35
+ run.onInterrupt(() => interrupt.abort());
36
+ const abort = () => { run.finish('interrupted'); void harness.world.release(id); };
37
+ signal.addEventListener('abort', abort, { once: true });
38
+ const gate = harness.sessions.diagnosticGate(run, caller);
39
+ try {
40
+ signal.throwIfAborted();
41
+ const result = await action({
42
+ signal, context, run,
43
+ call: async (name, input) => {
44
+ signal.throwIfAborted();
45
+ if (run.finished || !capabilities.tools.includes(name))
46
+ throw new HarnessError('doctor_blocked', 'This tool is outside the diagnostic capability set.');
47
+ const refusal = await gate.check(name, input);
48
+ if (refusal)
49
+ throw new HarnessError('doctor_blocked', 'The tool policy refused this diagnostic call.');
50
+ signal.throwIfAborted();
51
+ const callId = randomUUID();
52
+ run.emit('tool.started', { toolCallId: callId, name, summary: 'Synthetic diagnostic input' });
53
+ try {
54
+ let result;
55
+ if (name === 'mcp_list_tools') {
56
+ if (typeof input.connectionId !== 'string')
57
+ throw new HarnessError('doctor_blocked', 'A connection must be selected.');
58
+ const broker = harness.apps.grant({ sessionId: id, runId: id, caller, readOnly: true, depth: 0, capabilities: { ...capabilities, connectors: capabilities.connectors.filter(connector => connector === input.connectionId) } });
59
+ const count = await harness.apps.diagnosticList(broker, input.connectionId, signal);
60
+ result = { text: `${count} tools listed.`, details: { doctorOk: true, toolCount: count } };
61
+ }
62
+ else {
63
+ const tools = await harness.sessions.diagnosticTools({ run, caller, allow: capabilities.tools, depth: 0, cwd: context.cwd, capabilities });
64
+ const tool = tools.find(tool => tool.name === name);
65
+ if (!tool)
66
+ throw new HarnessError('doctor_blocked', 'No provider supplies this diagnostic tool.');
67
+ signal.throwIfAborted();
68
+ result = await tool.execute(input);
69
+ }
70
+ signal.throwIfAborted();
71
+ run.emit('tool.completed', { toolCallId: callId, name, ok: true });
72
+ return result;
73
+ }
74
+ catch (error) {
75
+ run.emit('tool.completed', { toolCallId: callId, name, ok: false });
76
+ throw error;
77
+ }
78
+ }
79
+ });
80
+ return result;
81
+ }
82
+ catch (error) {
83
+ run.finish(signal.aborted ? 'interrupted' : 'failed', { code: 'doctor_failed', message: 'The diagnostic probe failed.' });
84
+ throw error;
85
+ }
86
+ finally {
87
+ signal.removeEventListener('abort', abort);
88
+ run.finish(signal.aborted ? 'interrupted' : 'completed');
89
+ harness.apps.revokeRun(id, id);
90
+ await harness.world.release(id);
91
+ }
92
+ }
@@ -0,0 +1,23 @@
1
+ import { type DoctorCheck, type DoctorContext, type DoctorInput, type DoctorProbeContext, type DoctorReport } from "./types.js";
2
+ export interface DoctorOptions {
3
+ checks(context: DoctorContext): Promise<DoctorCheck[]>;
4
+ probe<T>(context: DoctorContext, signal: AbortSignal, action: (probe: DoctorProbeContext) => Promise<T>): Promise<T>;
5
+ timeout?: {
6
+ local: number;
7
+ live: number;
8
+ model: number;
9
+ };
10
+ }
11
+ export declare class Doctor {
12
+ private readonly options;
13
+ private readonly jobs;
14
+ private closed;
15
+ constructor(options: DoctorOptions);
16
+ start(input: DoctorInput): DoctorReport;
17
+ read(id: string): DoctorReport;
18
+ cancel(id: string): DoctorReport;
19
+ close(): Promise<void>;
20
+ private job;
21
+ private run;
22
+ private bounded;
23
+ }
@@ -0,0 +1,144 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { redactLogText } from "../core/bus.js";
3
+ import { invalid, notFound } from "../core/errors.js";
4
+ import { doctorInputSchema, findingSchema } from "./types.js";
5
+ const safe = (text) => redactLogText(text).replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, '').replace(/[\x00-\x08\x0b-\x1f\x7f-\x9f]/g, ' ').slice(0, 4000);
6
+ export class Doctor {
7
+ options;
8
+ jobs = new Map();
9
+ closed = false;
10
+ constructor(options) {
11
+ this.options = options;
12
+ }
13
+ start(input) {
14
+ if (this.closed)
15
+ throw invalid('Diagnostics are closed.');
16
+ const parsed = doctorInputSchema.parse(input);
17
+ if (parsed.mode === 'live' && (!parsed.confirmed || !parsed.checks.length))
18
+ throw invalid('Select live checks and confirm their costs and isolated resources first.');
19
+ const context = structuredClone(parsed.context);
20
+ const report = {
21
+ id: randomUUID(), state: 'running', startedAt: new Date().toISOString(), endedAt: null,
22
+ mode: parsed.mode, context: { accountId: context.accountId, model: context.model },
23
+ completed: 0, total: 0, findings: [], liveChecks: []
24
+ };
25
+ const job = { report, abort: new AbortController(), settled: Promise.resolve() };
26
+ this.jobs.set(report.id, job);
27
+ job.settled = this.run(job, context, parsed.checks);
28
+ return this.read(report.id);
29
+ }
30
+ read(id) { return structuredClone(this.job(id).report); }
31
+ cancel(id) {
32
+ const job = this.job(id);
33
+ if (job.report.state === 'running') {
34
+ job.report.state = 'cancelled';
35
+ job.report.endedAt = new Date().toISOString();
36
+ job.abort.abort();
37
+ }
38
+ return this.read(id);
39
+ }
40
+ async close() {
41
+ this.closed = true;
42
+ for (const id of this.jobs.keys())
43
+ this.cancel(id);
44
+ await Promise.all([...this.jobs.values()].map(job => job.settled));
45
+ this.jobs.clear();
46
+ }
47
+ job(id) {
48
+ const job = this.jobs.get(id);
49
+ if (!job)
50
+ throw notFound('Diagnostic job');
51
+ return job;
52
+ }
53
+ async run(job, context, selected) {
54
+ const { report, abort } = job;
55
+ try {
56
+ const checks = await this.bounded(abort.signal, 10_000, () => this.options.checks(context));
57
+ const ids = new Set();
58
+ for (const check of checks) {
59
+ if (ids.has(check.id))
60
+ throw invalid(`Duplicate diagnostic check: ${check.id}`);
61
+ ids.add(check.id);
62
+ }
63
+ const enabled = (check) => !check.tools?.length || check.tools.some(tool => context.tools.includes(tool));
64
+ report.liveChecks = checks.filter(check => check.live && enabled(check)).map(check => ({ id: check.id, title: safe(check.title), notice: safe(check.live.notice) }));
65
+ if (selected.some(id => !ids.has(id)))
66
+ throw invalid('An unknown diagnostic check was selected.');
67
+ const wanted = selected.length ? checks.filter(check => selected.includes(check.id)) : checks;
68
+ report.total = wanted.length;
69
+ const execute = async (check) => {
70
+ if (abort.signal.aborted)
71
+ return;
72
+ const mode = report.mode;
73
+ const limits = this.options.timeout ?? { local: 10_000, live: 30_000, model: 60_000 };
74
+ let result;
75
+ try {
76
+ result = !enabled(check)
77
+ ? { status: 'disabled', evidence: 'This capability is disabled in the selected session.' }
78
+ : await this.bounded(abort.signal, mode === 'local' ? limits.local : check.id === 'model' ? limits.model : limits.live, signal => {
79
+ if (mode === 'local')
80
+ return check.local(signal);
81
+ if (!check.live)
82
+ return Promise.resolve({ status: 'unverified', evidence: 'This check has no live probe.' });
83
+ return this.options.probe(context, signal, probe => check.live.run(probe));
84
+ });
85
+ }
86
+ catch (error) {
87
+ const blocked = error && typeof error === 'object' && 'code' in error && error.code === 'doctor_blocked';
88
+ result = { status: blocked ? 'blocked' : 'fail', evidence: blocked ? 'The capability or tool policy refused this diagnostic call.' : 'The check failed or exceeded its time limit.', remedy: blocked ? 'Review the selected scope and tool permissions.' : 'Review the backend configuration and retry this check.' };
89
+ }
90
+ if (abort.signal.aborted)
91
+ return;
92
+ const parsed = findingSchema.safeParse({ ...result, id: check.id, category: safe(check.category), title: safe(check.title), verification: mode, checkedAt: new Date().toISOString() });
93
+ const finding = parsed.success ? parsed.data : {
94
+ id: check.id, category: safe(check.category), title: safe(check.title), verification: mode,
95
+ checkedAt: new Date().toISOString(), status: 'fail',
96
+ evidence: 'The diagnostic provider returned an invalid finding.', remedy: 'Review the provider implementation.'
97
+ };
98
+ finding.evidence = safe(finding.evidence);
99
+ if (finding.remedy)
100
+ finding.remedy = safe(finding.remedy);
101
+ report.findings.push(finding);
102
+ report.completed++;
103
+ };
104
+ // Interaction probes are serial, so only one isolated surface can own input at a time.
105
+ if (report.mode === 'live') {
106
+ for (const check of wanted)
107
+ await execute(check);
108
+ }
109
+ else {
110
+ let index = 0;
111
+ await Promise.all(Array.from({ length: Math.min(4, wanted.length) }, async () => {
112
+ while (!abort.signal.aborted && index < wanted.length)
113
+ await execute(wanted[index++]);
114
+ }));
115
+ }
116
+ }
117
+ catch {
118
+ if (!abort.signal.aborted)
119
+ report.findings.push({ id: 'doctor', title: 'Diagnostic setup', category: 'runtime', status: 'fail', verification: 'local', evidence: 'Diagnostic checks could not be prepared.', remedy: 'Check the selected scope, account, and data location.', checkedAt: new Date().toISOString() });
120
+ }
121
+ finally {
122
+ if (report.state === 'running')
123
+ report.state = 'completed';
124
+ report.endedAt ??= new Date().toISOString();
125
+ }
126
+ }
127
+ async bounded(parent, ms, action) {
128
+ parent.throwIfAborted();
129
+ const controller = new AbortController();
130
+ const abort = () => controller.abort();
131
+ parent.addEventListener('abort', abort, { once: true });
132
+ const timer = setTimeout(abort, ms);
133
+ try {
134
+ return await Promise.race([
135
+ Promise.resolve().then(() => { controller.signal.throwIfAborted(); return action(controller.signal); }),
136
+ new Promise((_, reject) => controller.signal.addEventListener('abort', () => reject(new Error('Diagnostic cancelled or timed out.')), { once: true }))
137
+ ]);
138
+ }
139
+ finally {
140
+ clearTimeout(timer);
141
+ parent.removeEventListener('abort', abort);
142
+ }
143
+ }
144
+ }
@@ -0,0 +1,141 @@
1
+ import { z } from 'zod';
2
+ import type { CallerContext } from "../core/caller.js";
3
+ import type { CapabilitySet } from "../capabilities/types.js";
4
+ import type { VariantChoice } from "../variant/materialise.js";
5
+ import type { ToolResult } from "../tools/types.js";
6
+ import type { ActiveRun } from "../sessions/registry.js";
7
+ export declare const findingSchema: z.ZodObject<{
8
+ id: z.ZodString;
9
+ category: z.ZodString;
10
+ title: z.ZodString;
11
+ status: z.ZodEnum<{
12
+ disabled: "disabled";
13
+ warning: "warning";
14
+ pass: "pass";
15
+ fail: "fail";
16
+ blocked: "blocked";
17
+ unverified: "unverified";
18
+ }>;
19
+ verification: z.ZodEnum<{
20
+ local: "local";
21
+ live: "live";
22
+ }>;
23
+ evidence: z.ZodString;
24
+ remedy: z.ZodOptional<z.ZodString>;
25
+ checkedAt: z.ZodString;
26
+ }, z.core.$strip>;
27
+ export type DoctorFinding = z.infer<typeof findingSchema>;
28
+ export type CheckResult = Pick<DoctorFinding, 'status' | 'evidence' | 'remedy'>;
29
+ export interface DoctorContext {
30
+ caller: CallerContext;
31
+ cwd: string;
32
+ accountId: string | null;
33
+ model: string | null;
34
+ tools: readonly string[];
35
+ capabilities?: CapabilitySet;
36
+ variant?: VariantChoice | null;
37
+ }
38
+ export interface DoctorCheck {
39
+ id: string;
40
+ category: string;
41
+ title: string;
42
+ tools?: readonly string[];
43
+ /** Readiness inspection only: no network, authentication or world actions. */
44
+ local(signal: AbortSignal): Promise<CheckResult>;
45
+ live?: {
46
+ /** Shown to the person before confirmation. Include destinations, costs and isolation. */
47
+ notice: string;
48
+ run(context: DoctorProbeContext): Promise<CheckResult>;
49
+ };
50
+ }
51
+ export interface DoctorProbeContext {
52
+ run: ActiveRun;
53
+ signal: AbortSignal;
54
+ context: DoctorContext;
55
+ /** Executes an enabled tool through the existing per-call gate. */
56
+ call(tool: string, input: Record<string, unknown>): Promise<string | ToolResult>;
57
+ }
58
+ /** Optional metadata on a callable tool provider; no new Harness extension point. */
59
+ export interface ProviderDiagnostics {
60
+ diagnostics?(context: DoctorContext): DoctorCheck[] | Promise<DoctorCheck[]>;
61
+ }
62
+ export declare const doctorInputSchema: z.ZodObject<{
63
+ context: z.ZodObject<{
64
+ caller: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
65
+ cwd: z.ZodString;
66
+ accountId: z.ZodNullable<z.ZodString>;
67
+ model: z.ZodNullable<z.ZodString>;
68
+ tools: z.ZodArray<z.ZodString>;
69
+ variant: z.ZodOptional<z.ZodNullable<z.ZodUnion<readonly [z.ZodObject<{
70
+ scope: z.ZodString;
71
+ version: z.ZodOptional<z.ZodNullable<z.ZodString>>;
72
+ }, z.core.$strip>, z.ZodObject<{
73
+ dir: z.ZodString;
74
+ scope: z.ZodOptional<z.ZodNullable<z.ZodString>>;
75
+ }, z.core.$strip>]>>>;
76
+ capabilities: z.ZodOptional<z.ZodObject<{
77
+ version: z.ZodLiteral<1>;
78
+ tools: z.ZodArray<z.ZodString>;
79
+ connectors: z.ZodArray<z.ZodString>;
80
+ contributions: z.ZodArray<z.ZodString>;
81
+ }, z.core.$strip>>;
82
+ }, z.core.$strip>;
83
+ mode: z.ZodDefault<z.ZodEnum<{
84
+ local: "local";
85
+ live: "live";
86
+ }>>;
87
+ checks: z.ZodDefault<z.ZodArray<z.ZodString>>;
88
+ confirmed: z.ZodDefault<z.ZodBoolean>;
89
+ }, z.core.$strip>;
90
+ export interface DoctorInput {
91
+ context: DoctorContext;
92
+ mode?: 'local' | 'live';
93
+ checks?: string[];
94
+ confirmed?: boolean;
95
+ }
96
+ export declare const doctorReportSchema: z.ZodObject<{
97
+ id: z.ZodString;
98
+ state: z.ZodEnum<{
99
+ running: "running";
100
+ completed: "completed";
101
+ cancelled: "cancelled";
102
+ }>;
103
+ startedAt: z.ZodString;
104
+ endedAt: z.ZodNullable<z.ZodString>;
105
+ mode: z.ZodEnum<{
106
+ local: "local";
107
+ live: "live";
108
+ }>;
109
+ context: z.ZodObject<{
110
+ accountId: z.ZodNullable<z.ZodString>;
111
+ model: z.ZodNullable<z.ZodString>;
112
+ }, z.core.$strip>;
113
+ completed: z.ZodNumber;
114
+ total: z.ZodNumber;
115
+ findings: z.ZodArray<z.ZodObject<{
116
+ id: z.ZodString;
117
+ category: z.ZodString;
118
+ title: z.ZodString;
119
+ status: z.ZodEnum<{
120
+ disabled: "disabled";
121
+ warning: "warning";
122
+ pass: "pass";
123
+ fail: "fail";
124
+ blocked: "blocked";
125
+ unverified: "unverified";
126
+ }>;
127
+ verification: z.ZodEnum<{
128
+ local: "local";
129
+ live: "live";
130
+ }>;
131
+ evidence: z.ZodString;
132
+ remedy: z.ZodOptional<z.ZodString>;
133
+ checkedAt: z.ZodString;
134
+ }, z.core.$strip>>;
135
+ liveChecks: z.ZodArray<z.ZodObject<{
136
+ id: z.ZodString;
137
+ title: z.ZodString;
138
+ notice: z.ZodString;
139
+ }, z.core.$strip>>;
140
+ }, z.core.$strip>;
141
+ export type DoctorReport = z.infer<typeof doctorReportSchema>;
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ export const findingSchema = z.object({
3
+ id: z.string(), category: z.string(), title: z.string(),
4
+ status: z.enum(['pass', 'warning', 'fail', 'disabled', 'blocked', 'unverified']),
5
+ verification: z.enum(['local', 'live']), evidence: z.string(), remedy: z.string().optional(),
6
+ checkedAt: z.string()
7
+ });
8
+ export const doctorInputSchema = z.object({
9
+ context: z.object({
10
+ caller: z.record(z.string(), z.unknown()).default({}), cwd: z.string().min(1),
11
+ accountId: z.string().nullable(), model: z.string().nullable(), tools: z.array(z.string()),
12
+ variant: z.union([
13
+ z.object({ scope: z.string(), version: z.string().nullable().optional() }),
14
+ z.object({ dir: z.string(), scope: z.string().nullable().optional() })
15
+ ]).nullable().optional(),
16
+ capabilities: z.object({ version: z.literal(1), tools: z.array(z.string()), connectors: z.array(z.string()), contributions: z.array(z.string()) }).optional()
17
+ }),
18
+ mode: z.enum(['local', 'live']).default('local'),
19
+ checks: z.array(z.string()).default([]),
20
+ /** A trusted host attests that the person approved these exact checks. */
21
+ confirmed: z.boolean().default(false)
22
+ });
23
+ export const doctorReportSchema = z.object({
24
+ id: z.string(), state: z.enum(['running', 'completed', 'cancelled']),
25
+ startedAt: z.string(), endedAt: z.string().nullable(), mode: z.enum(['local', 'live']),
26
+ context: z.object({ accountId: z.string().nullable(), model: z.string().nullable() }),
27
+ completed: z.number(), total: z.number(), findings: z.array(findingSchema),
28
+ liveChecks: z.array(z.object({ id: z.string(), title: z.string(), notice: z.string() }))
29
+ });