@galaxyproject/orbit 0.0.0 → 0.9.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 (451) hide show
  1. package/CHANGELOG.md +123 -0
  2. package/LICENSE +21 -0
  3. package/README.md +760 -5
  4. package/bin/legacy-mcp-config.js +363 -0
  5. package/bin/orbit.js +810 -0
  6. package/bin/pi-extension-path.d.ts +4 -0
  7. package/bin/pi-extension-path.js +44 -0
  8. package/bin/provider-auth.d.ts +22 -0
  9. package/bin/provider-auth.js +77 -0
  10. package/bin/thinking-pref.js +38 -0
  11. package/bin/update-check.d.ts +15 -0
  12. package/bin/update-check.js +137 -0
  13. package/extensions/cli-update/index.ts +32 -0
  14. package/extensions/orbit/activity-hooks.ts +141 -0
  15. package/extensions/orbit/activity.ts +116 -0
  16. package/extensions/orbit/agent-dir.ts +11 -0
  17. package/extensions/orbit/auto-resume.ts +352 -0
  18. package/extensions/orbit/config.ts +3 -0
  19. package/extensions/orbit/confusables.ts +1 -0
  20. package/extensions/orbit/context.ts +957 -0
  21. package/extensions/orbit/dashboard-commands.ts +191 -0
  22. package/extensions/orbit/dashboard-store.ts +473 -0
  23. package/extensions/orbit/dashboard-tools.ts +1185 -0
  24. package/extensions/orbit/empty-completion.ts +99 -0
  25. package/extensions/orbit/evidence-gate.ts +1276 -0
  26. package/extensions/orbit/evidence-override-command.ts +294 -0
  27. package/extensions/orbit/exec-guard/bash-risk.ts +1408 -0
  28. package/extensions/orbit/exec-guard/gate.ts +181 -0
  29. package/extensions/orbit/exec-guard/guardian-config.ts +54 -0
  30. package/extensions/orbit/exec-guard/index.ts +1 -0
  31. package/extensions/orbit/exec-guard/model-tier.ts +36 -0
  32. package/extensions/orbit/exec-guard/path-jail.ts +54 -0
  33. package/extensions/orbit/exec-guard/policy.ts +342 -0
  34. package/extensions/orbit/exec-guard/runtime-state.ts +15 -0
  35. package/extensions/orbit/exec-guard/sensitive-read.ts +525 -0
  36. package/extensions/orbit/exec-guard/types.ts +42 -0
  37. package/extensions/orbit/execution-commands.ts +134 -0
  38. package/extensions/orbit/feedback-command.ts +81 -0
  39. package/extensions/orbit/feedback.ts +96 -0
  40. package/extensions/orbit/galaxy-api.test.ts +122 -0
  41. package/extensions/orbit/galaxy-api.ts +606 -0
  42. package/extensions/orbit/galaxy-artifact-link-guidance.ts +5 -0
  43. package/extensions/orbit/galaxy-destructive-gate.ts +113 -0
  44. package/extensions/orbit/galaxy-enrich.ts +1108 -0
  45. package/extensions/orbit/galaxy-failure.ts +101 -0
  46. package/extensions/orbit/galaxy-fixture.ts +126 -0
  47. package/extensions/orbit/galaxy-history-guard.ts +233 -0
  48. package/extensions/orbit/galaxy-job-block.ts +347 -0
  49. package/extensions/orbit/galaxy-job-ops.ts +288 -0
  50. package/extensions/orbit/galaxy-live-source.ts +929 -0
  51. package/extensions/orbit/galaxy-markdown-adapter.ts +248 -0
  52. package/extensions/orbit/galaxy-op-policy.ts +332 -0
  53. package/extensions/orbit/galaxy-ops-tools.ts +326 -0
  54. package/extensions/orbit/galaxy-output-store.ts +80 -0
  55. package/extensions/orbit/galaxy-output.ts +346 -0
  56. package/extensions/orbit/galaxy-page-binding.ts +222 -0
  57. package/extensions/orbit/galaxy-page-markdown-guidance.ts +15 -0
  58. package/extensions/orbit/galaxy-page-ops.ts +159 -0
  59. package/extensions/orbit/galaxy-page-sync.test.ts +417 -0
  60. package/extensions/orbit/galaxy-page-sync.ts +318 -0
  61. package/extensions/orbit/galaxy-pages-api.ts +203 -0
  62. package/extensions/orbit/galaxy-pages-sync.ts +409 -0
  63. package/extensions/orbit/galaxy-poll-guard.ts +189 -0
  64. package/extensions/orbit/galaxy-poller.ts +706 -0
  65. package/extensions/orbit/galaxy-provenance.ts +623 -0
  66. package/extensions/orbit/galaxy-reconcile.ts +956 -0
  67. package/extensions/orbit/galaxy-recovery.ts +176 -0
  68. package/extensions/orbit/galaxy-repeat-guard.ts +55 -0
  69. package/extensions/orbit/galaxy-submission-capture.ts +707 -0
  70. package/extensions/orbit/galaxy-submission.ts +502 -0
  71. package/extensions/orbit/galaxy-tool-source.ts +78 -0
  72. package/extensions/orbit/galaxy-tool-wrap.ts +234 -0
  73. package/extensions/orbit/galaxy-udt-block.ts +127 -0
  74. package/extensions/orbit/galaxy-upload-tus.ts +334 -0
  75. package/extensions/orbit/galaxy-upload.ts +300 -0
  76. package/extensions/orbit/galaxy-version-capture.ts +65 -0
  77. package/extensions/orbit/git.ts +173 -0
  78. package/extensions/orbit/harness-block-fields.ts +597 -0
  79. package/extensions/orbit/index.ts +593 -0
  80. package/extensions/orbit/init-gate.ts +284 -0
  81. package/extensions/orbit/instructions-command.ts +136 -0
  82. package/extensions/orbit/invocation-failure-hint.ts +57 -0
  83. package/extensions/orbit/iwc-plan-check.ts +94 -0
  84. package/extensions/orbit/lesson-command.ts +303 -0
  85. package/extensions/orbit/lesson-hint.ts +245 -0
  86. package/extensions/orbit/lesson-nudge.ts +106 -0
  87. package/extensions/orbit/lessons/compose.ts +177 -0
  88. package/extensions/orbit/lessons/counters.ts +120 -0
  89. package/extensions/orbit/lessons/enabled.ts +116 -0
  90. package/extensions/orbit/lessons/matcher.ts +346 -0
  91. package/extensions/orbit/lessons/paths.ts +286 -0
  92. package/extensions/orbit/lessons/pi-event-contract.ts +105 -0
  93. package/extensions/orbit/lessons/propose-replay.ts +103 -0
  94. package/extensions/orbit/lessons/propose-tool.ts +222 -0
  95. package/extensions/orbit/lessons/propose.ts +502 -0
  96. package/extensions/orbit/lessons/replay.ts +89 -0
  97. package/extensions/orbit/lessons/reproduction-index.ts +83 -0
  98. package/extensions/orbit/lessons/search-tool.ts +99 -0
  99. package/extensions/orbit/lessons/search.ts +136 -0
  100. package/extensions/orbit/lessons/store.ts +415 -0
  101. package/extensions/orbit/lessons/text.ts +36 -0
  102. package/extensions/orbit/lessons/types.ts +69 -0
  103. package/extensions/orbit/lessons/user-dir.ts +24 -0
  104. package/extensions/orbit/lessons/user-lesson.ts +88 -0
  105. package/extensions/orbit/lessons/wrapper.ts +61 -0
  106. package/extensions/orbit/lessons-command.ts +147 -0
  107. package/extensions/orbit/local-exec.ts +39 -0
  108. package/extensions/orbit/mcp-output.ts +179 -0
  109. package/extensions/orbit/mcp-servers.test.ts +24 -0
  110. package/extensions/orbit/mcp-servers.ts +25 -0
  111. package/extensions/orbit/model-script.ts +351 -0
  112. package/extensions/orbit/notebook-anchors.ts +342 -0
  113. package/extensions/orbit/notebook-writer.ts +863 -0
  114. package/extensions/orbit/observation-allowlists.ts +1109 -0
  115. package/extensions/orbit/observation-replay.ts +148 -0
  116. package/extensions/orbit/observation-triggers.ts +563 -0
  117. package/extensions/orbit/observation-ui.ts +175 -0
  118. package/extensions/orbit/observations-command.ts +421 -0
  119. package/extensions/orbit/observations-config.ts +200 -0
  120. package/extensions/orbit/observations.ts +1381 -0
  121. package/extensions/orbit/profiles.ts +270 -0
  122. package/extensions/orbit/progress-updates.ts +95 -0
  123. package/extensions/orbit/proposal-commands.ts +882 -0
  124. package/extensions/orbit/provenance-fs-file.ts +59 -0
  125. package/extensions/orbit/provenance-fs.ts +32 -0
  126. package/extensions/orbit/provenance-memory-fs.ts +59 -0
  127. package/extensions/orbit/record-store-file.ts +177 -0
  128. package/extensions/orbit/record-store-page.ts +77 -0
  129. package/extensions/orbit/record-store-seam.ts +47 -0
  130. package/extensions/orbit/record-store.ts +149 -0
  131. package/extensions/orbit/registry-carrier.ts +107 -0
  132. package/extensions/orbit/registry-eligibility.ts +95 -0
  133. package/extensions/orbit/registry-evaluation.ts +403 -0
  134. package/extensions/orbit/registry-evaluator.ts +519 -0
  135. package/extensions/orbit/registry-import.ts +91 -0
  136. package/extensions/orbit/registry-lock.ts +221 -0
  137. package/extensions/orbit/registry-memory-fs.ts +42 -0
  138. package/extensions/orbit/registry-page-carrier.ts +103 -0
  139. package/extensions/orbit/registry-proposal.ts +1348 -0
  140. package/extensions/orbit/registry-runtime.ts +234 -0
  141. package/extensions/orbit/registry-schema.ts +735 -0
  142. package/extensions/orbit/registry-submitter.ts +59 -0
  143. package/extensions/orbit/registry-templates.ts +346 -0
  144. package/extensions/orbit/registry.ts +476 -0
  145. package/extensions/orbit/sandbox/index.ts +120 -0
  146. package/extensions/orbit/sandbox/sandbox-bash.ts +93 -0
  147. package/extensions/orbit/sandbox/sandbox-config.ts +87 -0
  148. package/extensions/orbit/sandbox/sandbox-init-message.ts +28 -0
  149. package/extensions/orbit/secret-redaction.ts +247 -0
  150. package/extensions/orbit/session-index/cwd.ts +18 -0
  151. package/extensions/orbit/session-index/db.ts +56 -0
  152. package/extensions/orbit/session-index/indexer.ts +154 -0
  153. package/extensions/orbit/session-index/is-enabled.ts +17 -0
  154. package/extensions/orbit/session-index/parse.ts +254 -0
  155. package/extensions/orbit/session-index/query.ts +209 -0
  156. package/extensions/orbit/session-index/schema.ts +72 -0
  157. package/extensions/orbit/session-index/tools.ts +152 -0
  158. package/extensions/orbit/session-lifecycle.ts +321 -0
  159. package/extensions/orbit/skill-triggers.ts +159 -0
  160. package/extensions/orbit/skills-command.ts +48 -0
  161. package/extensions/orbit/skills-discovery.ts +435 -0
  162. package/extensions/orbit/skills.ts +84 -0
  163. package/extensions/orbit/sra-import-gate.ts +77 -0
  164. package/extensions/orbit/state.ts +265 -0
  165. package/extensions/orbit/submission-replay.ts +147 -0
  166. package/extensions/orbit/sync-command.ts +157 -0
  167. package/extensions/orbit/teams/critic-parser.ts +93 -0
  168. package/extensions/orbit/teams/dispatcher.ts +210 -0
  169. package/extensions/orbit/teams/is-enabled.ts +22 -0
  170. package/extensions/orbit/teams/tool.ts +187 -0
  171. package/extensions/orbit/teams/types.ts +57 -0
  172. package/extensions/orbit/teams/validate.ts +42 -0
  173. package/extensions/orbit/tester-id-command.ts +133 -0
  174. package/extensions/orbit/tools-sync.ts +279 -0
  175. package/extensions/orbit/tools.ts +1300 -0
  176. package/extensions/orbit/types.ts +41 -0
  177. package/extensions/orbit/ui-bridge.ts +55 -0
  178. package/extensions/orbit/ulid.ts +60 -0
  179. package/extensions/orbit/user-instructions.ts +388 -0
  180. package/extensions/orbit/vendor/skills/_catalog.json +68 -0
  181. package/extensions/orbit/vendor/skills/_manifest.json +1106 -0
  182. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/SKILL.md +112 -0
  183. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/_provenance.json +218 -0
  184. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/_required_tools.json +33 -0
  185. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/_verify.json +4 -0
  186. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/add.json +50 -0
  187. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/draft-extract.json +51 -0
  188. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/draft-next-step.json +42 -0
  189. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/draft-validate.json +140 -0
  190. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/list.json +32 -0
  191. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/notes/galaxy-tool-job-failure-reference.md +137 -0
  192. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/notes/open-requirements-ledger.md +173 -0
  193. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/schemas/galaxy-tool-summary.schema.json +175 -0
  194. package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/schemas/galaxy-workflow-draft.schema.json +2727 -0
  195. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/SKILL.md +82 -0
  196. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/_provenance.json +133 -0
  197. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/_required_tools.json +16 -0
  198. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/_verify.json +4 -0
  199. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/cli/draft-validate.json +140 -0
  200. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/notes/galaxy-workflow-draft-format.md +135 -0
  201. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/notes/open-requirements-ledger.md +173 -0
  202. package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/schemas/galaxy-workflow-draft.schema.json +2727 -0
  203. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/SKILL.md +84 -0
  204. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/_provenance.json +166 -0
  205. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/_verify.json +29 -0
  206. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/galaxy-workflow-testability-design.md +136 -0
  207. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
  208. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/iwc-test-data-conventions.md +308 -0
  209. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/planemo-asserts-idioms.md +246 -0
  210. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/planemo-workflow-test-architecture.md +151 -0
  211. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/schemas/galaxy-workflow-test-plan.schema.json +552 -0
  212. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/schemas/summary-galaxy-workflow.schema.json +687 -0
  213. package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/schemas/tests-format.schema.json +7328 -0
  214. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/SKILL.md +127 -0
  215. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/_provenance.json +198 -0
  216. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/_required_tools.json +16 -0
  217. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/_verify.json +4 -0
  218. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/cli/convert.json +123 -0
  219. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/galaxy-data-flow-draft-contract.md +129 -0
  220. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
  221. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/iwc-test-data-conventions.md +308 -0
  222. package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/open-requirements-ledger.md +173 -0
  223. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/SKILL.md +73 -0
  224. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/_provenance.json +160 -0
  225. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/_verify.json +4 -0
  226. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-collection-semantics.md +43 -0
  227. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-collection-semantics.yml +1250 -0
  228. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-tool-job-failure-reference.md +137 -0
  229. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-workflow-invocation-failure-reference.md +138 -0
  230. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
  231. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/nextflow-operators-to-galaxy-collection-recipes.md +98 -0
  232. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/planemo-asserts-idioms.md +246 -0
  233. package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/planemo-workflow-test-architecture.md +151 -0
  234. package/extensions/orbit/vendor/skills/discover-shed-tool/SKILL.md +174 -0
  235. package/extensions/orbit/vendor/skills/discover-shed-tool/_provenance.json +130 -0
  236. package/extensions/orbit/vendor/skills/discover-shed-tool/_required_tools.json +18 -0
  237. package/extensions/orbit/vendor/skills/discover-shed-tool/_verify.json +17 -0
  238. package/extensions/orbit/vendor/skills/discover-shed-tool/references/cli/tool-revisions.json +48 -0
  239. package/extensions/orbit/vendor/skills/discover-shed-tool/references/cli/tool-search.json +95 -0
  240. package/extensions/orbit/vendor/skills/discover-shed-tool/references/cli/tool-versions.json +39 -0
  241. package/extensions/orbit/vendor/skills/discover-shed-tool/references/notes/component-tool-shed-search.md +230 -0
  242. package/extensions/orbit/vendor/skills/discover-shed-tool/references/schemas/galaxy-tool-discovery.schema.json +231 -0
  243. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/SKILL.md +93 -0
  244. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/_provenance.json +201 -0
  245. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/_required_tools.json +28 -0
  246. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/_verify.json +17 -0
  247. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/cli/planemo.md +44 -0
  248. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/cli/validate-tests.json +40 -0
  249. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/galaxy-workflow-testability-design.md +136 -0
  250. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
  251. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/iwc-test-data-conventions.md +308 -0
  252. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/planemo-asserts-idioms.md +246 -0
  253. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/planemo-workflow-test-architecture.md +151 -0
  254. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/schemas/galaxy-workflow-test-plan.schema.json +552 -0
  255. package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/schemas/tests-format.schema.json +7328 -0
  256. package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/SKILL.md +81 -0
  257. package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/_provenance.json +93 -0
  258. package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/_verify.json +17 -0
  259. package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/references/notes/open-requirements-ledger.md +173 -0
  260. package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/references/schemas/summary-galaxy-workflow.schema.json +687 -0
  261. package/extensions/orbit/vendor/skills/pipeline-update-interview-to-galaxy/SKILL.md +81 -0
  262. package/extensions/orbit/vendor/skills/pipeline-update-interview-to-galaxy/_assembly.json +23 -0
  263. package/extensions/orbit/vendor/skills/run-workflow-test/SKILL.md +79 -0
  264. package/extensions/orbit/vendor/skills/run-workflow-test/_provenance.json +125 -0
  265. package/extensions/orbit/vendor/skills/run-workflow-test/_required_tools.json +28 -0
  266. package/extensions/orbit/vendor/skills/run-workflow-test/_verify.json +4 -0
  267. package/extensions/orbit/vendor/skills/run-workflow-test/references/cli/planemo.md +44 -0
  268. package/extensions/orbit/vendor/skills/run-workflow-test/references/cli/validate-tests.json +40 -0
  269. package/extensions/orbit/vendor/skills/run-workflow-test/references/notes/galaxy-workflow-invocation-failure-reference.md +138 -0
  270. package/extensions/orbit/vendor/skills/run-workflow-test/references/notes/planemo-asserts-idioms.md +246 -0
  271. package/extensions/orbit/vendor/skills/run-workflow-test/references/notes/planemo-workflow-test-architecture.md +151 -0
  272. package/extensions/orbit/vendor/skills/run-workflow-test/references/schemas/tests-format.schema.json +7328 -0
  273. package/extensions/orbit/vendor/skills/skills/LICENSE +21 -0
  274. package/extensions/orbit/vendor/skills/skills/collection-manipulation/README.md +39 -0
  275. package/extensions/orbit/vendor/skills/skills/collection-manipulation/SKILL.md +892 -0
  276. package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/api-patterns.md +927 -0
  277. package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/apply-rules.md +1482 -0
  278. package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/test-patterns.md +996 -0
  279. package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/tools.md +609 -0
  280. package/extensions/orbit/vendor/skills/skills/galaxy-data-libraries/SKILL.md +170 -0
  281. package/extensions/orbit/vendor/skills/skills/galaxy-integration/README.md +162 -0
  282. package/extensions/orbit/vendor/skills/skills/galaxy-integration/SKILL.md +99 -0
  283. package/extensions/orbit/vendor/skills/skills/galaxy-integration/examples/README.md +119 -0
  284. package/extensions/orbit/vendor/skills/skills/galaxy-integration/examples/tool-checking.md +419 -0
  285. package/extensions/orbit/vendor/skills/skills/galaxy-integration/examples/workflow-testing.md +617 -0
  286. package/extensions/orbit/vendor/skills/skills/galaxy-integration/galaxy-integration.md +614 -0
  287. package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/SKILL.md +144 -0
  288. package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/average_col3.ipynb +68 -0
  289. package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/extract_sample_metadata.ipynb +190 -0
  290. package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/variant_annotation.ipynb +816 -0
  291. package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/vcp_variant_map.ipynb +443 -0
  292. package/extensions/orbit/vendor/skills/skills/galaxy-integration/scripts/README.md +165 -0
  293. package/extensions/orbit/vendor/skills/skills/galaxy-integration/scripts/galaxy_tool_checker.py +521 -0
  294. package/extensions/orbit/vendor/skills/skills/galaxy-mcp-reference/SKILL.md +128 -0
  295. package/extensions/orbit/vendor/skills/skills/galaxy-mcp-reference/gotchas.md +135 -0
  296. package/extensions/orbit/vendor/skills/skills/galaxy-mcp-reference/history-access.md +132 -0
  297. package/extensions/orbit/vendor/skills/skills/reproduciblify/SKILL.md +146 -0
  298. package/extensions/orbit/vendor/skills/skills/reproduciblify/references/directives.yml +496 -0
  299. package/extensions/orbit/vendor/skills/skills/udt-authoring/SKILL.md +245 -0
  300. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/01-minimal-echo.yml +27 -0
  301. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/02-single-data-in-out.yml +27 -0
  302. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/03-multiple-data-js.yml +28 -0
  303. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/04-select-integer-boolean.yml +41 -0
  304. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/05-resource-requirements.yml +25 -0
  305. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/06-biocontainer-tool.yml +38 -0
  306. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/07-inline-python-script.yml +56 -0
  307. package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/08-configfile-script.yml +74 -0
  308. package/extensions/orbit/vendor/skills/skills/udt-authoring/references/common-mistakes.md +76 -0
  309. package/extensions/orbit/vendor/skills/skills/udt-authoring/references/schema-reference.md +155 -0
  310. package/extensions/orbit/vendor/skills/skills/udt-authoring/references/templating.md +196 -0
  311. package/extensions/orbit/vendor/skills/skills/udt-authoring/scripts/validate.py +109 -0
  312. package/extensions/orbit/vendor/skills/skills/workflow-reports/README.md +71 -0
  313. package/extensions/orbit/vendor/skills/skills/workflow-reports/SKILL.md +190 -0
  314. package/extensions/orbit/vendor/skills/skills/workflow-reports/examples/histology-staining.md +145 -0
  315. package/extensions/orbit/vendor/skills/skills/workflow-reports/examples/tissue-microarray-analysis.md +176 -0
  316. package/extensions/orbit/vendor/skills/skills/workflow-reports/references/directives.md +415 -0
  317. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/SKILL.md +98 -0
  318. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/_provenance.json +93 -0
  319. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/_required_tools.json +28 -0
  320. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/_verify.json +17 -0
  321. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/cli/convert.json +123 -0
  322. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/cli/foundry.md +25 -0
  323. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/cli/validate.json +142 -0
  324. package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/schemas/summary-galaxy-workflow.schema.json +687 -0
  325. package/extensions/orbit/vendor/skills/validate-galaxy-workflow/SKILL.md +74 -0
  326. package/extensions/orbit/vendor/skills/validate-galaxy-workflow/_provenance.json +71 -0
  327. package/extensions/orbit/vendor/skills/validate-galaxy-workflow/_required_tools.json +16 -0
  328. package/extensions/orbit/vendor/skills/validate-galaxy-workflow/_verify.json +4 -0
  329. package/extensions/orbit/vendor/skills/validate-galaxy-workflow/references/cli/validate.json +142 -0
  330. package/extensions/orbit/vendor/skills/validate-galaxy-workflow/references/notes/galaxy-workflow-invocation-failure-reference.md +138 -0
  331. package/extensions/orbit/vendor/skills/validate-galaxy-workflow/references/notes/galaxy-workflow-testability-design.md +136 -0
  332. package/extensions/orbit/vendor-skills.ts +283 -0
  333. package/extensions/orbit/workspace-state-dir.ts +46 -0
  334. package/extensions/orbit-handoff/index.ts +73 -0
  335. package/extensions/orbit-handoff/orbit-launcher.ts +142 -0
  336. package/extensions/whats-new/index.ts +98 -0
  337. package/lessons/LICENSE +17 -0
  338. package/lessons/README.md +117 -0
  339. package/lessons/SCHEMA.md +187 -0
  340. package/lessons/build-snapshot.mjs +311 -0
  341. package/lessons/data/downloaded-file-is-not-what-its-extension-says.md +61 -0
  342. package/lessons/galaxy-api/403-history-is-a-hard-stop.md +57 -0
  343. package/lessons/galaxy-api/collection-into-single-dataset-input.md +61 -0
  344. package/lessons/galaxy-api/connectedvalue-in-command-line.md +62 -0
  345. package/lessons/galaxy-api/hid-is-not-an-id.md +59 -0
  346. package/lessons/galaxy-api/invoke-workflow-inputs-not-params.md +60 -0
  347. package/lessons/galaxy-api/repeat-param-pipe-keys.md +63 -0
  348. package/lessons/galaxy-api/run-tool-returns-on-submit.md +61 -0
  349. package/lessons/galaxy-tools/reference-index-not-on-server.md +62 -0
  350. package/lessons/log.md +42 -0
  351. package/lessons/reproduction/input-population-mismatch.md +59 -0
  352. package/lessons/reproduction/methods-text-vs-executed-parameters.md +62 -0
  353. package/lessons/snapshot.json +1004 -0
  354. package/lessons/stats/de-contrast-direction-and-sample-labels.md +63 -0
  355. package/lessons/stats/na-coerced-to-zero-in-filters.md +59 -0
  356. package/lessons/validate.mjs +1219 -0
  357. package/package.json +103 -5
  358. package/shared/agent-prompt.d.ts +8 -0
  359. package/shared/agent-prompt.js +15 -0
  360. package/shared/approval-prompt.d.ts +4 -0
  361. package/shared/approval-prompt.js +61 -0
  362. package/shared/brain-env.d.ts +14 -0
  363. package/shared/brain-env.js +108 -0
  364. package/shared/brain-exit.d.ts +20 -0
  365. package/shared/brain-exit.js +149 -0
  366. package/shared/capability-profile.d.ts +16 -0
  367. package/shared/capability-profile.js +75 -0
  368. package/shared/config-source.d.ts +13 -0
  369. package/shared/config-source.js +17 -0
  370. package/shared/confusables.d.ts +3 -0
  371. package/shared/confusables.js +93 -0
  372. package/shared/custom-provider.d.ts +45 -0
  373. package/shared/custom-provider.js +169 -0
  374. package/shared/dashboard-contract.d.ts +123 -0
  375. package/shared/dashboard-contract.js +560 -0
  376. package/shared/dashboard-layout-store.d.ts +44 -0
  377. package/shared/dashboard-layout-store.js +281 -0
  378. package/shared/feedback-contract.d.ts +61 -0
  379. package/shared/feedback-contract.js +146 -0
  380. package/shared/galaxy-artifact-links.d.ts +30 -0
  381. package/shared/galaxy-artifact-links.js +166 -0
  382. package/shared/galaxy-credentials.d.ts +26 -0
  383. package/shared/galaxy-credentials.js +71 -0
  384. package/shared/galaxy-destructive.d.ts +21 -0
  385. package/shared/galaxy-destructive.js +269 -0
  386. package/shared/galaxy-guidance.d.ts +2 -0
  387. package/shared/galaxy-guidance.js +53 -0
  388. package/shared/galaxy-live-contract.d.ts +92 -0
  389. package/shared/galaxy-live-contract.js +180 -0
  390. package/shared/galaxy-page-cells.d.ts +2 -0
  391. package/shared/galaxy-page-cells.js +22 -0
  392. package/shared/galaxy-tool-family.d.ts +5 -0
  393. package/shared/galaxy-tool-family.js +27 -0
  394. package/shared/galaxy-url.d.ts +1 -0
  395. package/shared/galaxy-url.js +48 -0
  396. package/shared/gtn.d.ts +31 -0
  397. package/shared/gtn.js +253 -0
  398. package/shared/handled-prompt.d.ts +3 -0
  399. package/shared/handled-prompt.js +26 -0
  400. package/shared/known-provider.d.ts +11 -0
  401. package/shared/known-provider.js +89 -0
  402. package/shared/lesson-hint-marker.d.ts +7 -0
  403. package/shared/lesson-hint-marker.js +32 -0
  404. package/shared/lesson-rules.d.ts +150 -0
  405. package/shared/lesson-rules.js +203 -0
  406. package/shared/malformed-object-ids.d.ts +1 -0
  407. package/shared/malformed-object-ids.js +37 -0
  408. package/shared/markdown-sections.d.ts +10 -0
  409. package/shared/markdown-sections.js +118 -0
  410. package/shared/notebook-fences.d.ts +12 -0
  411. package/shared/notebook-fences.js +53 -0
  412. package/shared/observation-contract.d.ts +91 -0
  413. package/shared/observation-contract.js +544 -0
  414. package/shared/orbit-config.d.ts +226 -0
  415. package/shared/orbit-config.js +189 -0
  416. package/shared/orbit-env.d.ts +13 -0
  417. package/shared/orbit-env.js +124 -0
  418. package/shared/orbit-shell-contract.d.ts +74 -0
  419. package/shared/orbit-shell-contract.js +30 -0
  420. package/shared/page-content-hash.d.ts +1 -0
  421. package/shared/page-content-hash.js +13 -0
  422. package/shared/pi-default-model.d.ts +7 -0
  423. package/shared/pi-default-model.js +41 -0
  424. package/shared/prompt-blocks.d.ts +87 -0
  425. package/shared/prompt-blocks.js +898 -0
  426. package/shared/provider-auth-caps.d.ts +22 -0
  427. package/shared/provider-auth-caps.js +57 -0
  428. package/shared/random.d.ts +2 -0
  429. package/shared/random.js +15 -0
  430. package/shared/record-excerpt.d.ts +4 -0
  431. package/shared/record-excerpt.js +16 -0
  432. package/shared/redirect-guard.d.ts +36 -0
  433. package/shared/redirect-guard.js +235 -0
  434. package/shared/skills-pin.d.ts +8 -0
  435. package/shared/skills-pin.js +9 -0
  436. package/shared/skills-router.d.ts +17 -0
  437. package/shared/skills-router.js +63 -0
  438. package/shared/sra-import.d.ts +34 -0
  439. package/shared/sra-import.js +206 -0
  440. package/shared/state-dir.d.ts +21 -0
  441. package/shared/state-dir.js +240 -0
  442. package/shared/team-dispatch-contract.d.ts +28 -0
  443. package/shared/team-dispatch-contract.js +1 -0
  444. package/shared/truncate-middle.d.ts +11 -0
  445. package/shared/truncate-middle.js +68 -0
  446. package/shared/version-compare.d.ts +10 -0
  447. package/shared/version-compare.js +74 -0
  448. package/shared/whats-new.d.ts +31 -0
  449. package/shared/whats-new.js +83 -0
  450. package/shared/wsl.d.ts +10 -0
  451. package/shared/wsl.js +24 -0
@@ -0,0 +1,101 @@
1
+ /**
2
+ * What kind of failure a Galaxy call was, read from the call itself rather than from its text.
3
+ *
4
+ * galaxy-ops reports a typed `errorKind` on the envelope, and the wrapper knows when its own
5
+ * deadline fired, so the wrapper records the kind on `details.galaxy.kind` and the guards read
6
+ * that first. A shell's extras record no kind, so their failures are read by their wording.
7
+ */
8
+ import type { GalaxyErrorKind } from "@galaxyproject/galaxy-ops";
9
+ import type { GalaxyToolFamily } from "../../shared/galaxy-tool-family.js";
10
+ import { record } from "./galaxy-output";
11
+
12
+ // A dropped transport: the server is gone and a new connection fixes it.
13
+ const DROPPED_ERROR_PATTERNS: RegExp[] = [
14
+ /not connected(?!\s+to\s+galaxy)/i, // bare SDK "Not connected"; exclude the verbose auth error
15
+ /connection closed/i, // -32000, and pi's "MCP connection closed"
16
+ /MCP client is (?:closed|connecting)/i, // pi: a call on a client that already went away
17
+ /-32000/,
18
+ ];
19
+
20
+ // A timeout proves only that no response arrived within the request budget.
21
+ // Narrow reads first; reconnect can help a wedge but not an oversized query.
22
+ const TIMEOUT_ERROR_PATTERNS: RegExp[] = [
23
+ /request timed out/i, // -32001
24
+ /-32001/,
25
+ ];
26
+
27
+ /**
28
+ * Which kind of failure this is, so callers can give advice that can work. `auth` comes only from
29
+ * an in-process call's details; no text reads as one.
30
+ */
31
+ export type GalaxyFailureKind = "dropped" | "timeout" | "auth" | null;
32
+
33
+ /** The kind a failure's text reads as, for a result that recorded none. */
34
+ export function classifyGalaxyFailure(
35
+ toolName: string | undefined,
36
+ text: string | undefined,
37
+ family: GalaxyToolFamily,
38
+ ): Exclude<GalaxyFailureKind, "auth"> {
39
+ if (family.toolName(toolName) === undefined || !text) return null;
40
+ // Timeout first: a -32001 body can also mention "not connected" downstream,
41
+ // and the timeout reading is the actionable one.
42
+ if (TIMEOUT_ERROR_PATTERNS.some((p) => p.test(text))) return "timeout";
43
+ if (DROPPED_ERROR_PATTERNS.some((p) => p.test(text))) return "dropped";
44
+ return null;
45
+ }
46
+
47
+ /** A failure kind the recovery guidance has advice for. */
48
+ export type GalaxyCallKind = Exclude<GalaxyFailureKind, null>;
49
+
50
+ // Keeps "request timed out", so a reader that only has the text still sees a timeout.
51
+ export const GALAXY_DEADLINE_TEXT =
52
+ "Galaxy request timed out after 300 seconds. Its result is unknown; this does not mean a Galaxy job failed.";
53
+
54
+ /**
55
+ * The recovery kind behind galaxy-ops' own error kind. Only a request that never got an answer
56
+ * (`connection`) or one Galaxy refused for its credentials (`auth`) has recovery advice; a
57
+ * not-found or a validation failure is the model's to read and fix.
58
+ */
59
+ export function kindOfEnvelope(
60
+ errorKind: GalaxyErrorKind | string | undefined,
61
+ ): "dropped" | "auth" | undefined {
62
+ if (errorKind === "connection") return "dropped";
63
+ if (errorKind === "auth") return "auth";
64
+ return undefined;
65
+ }
66
+
67
+ /**
68
+ * `details.galaxy.kind` when an in-process call recorded one, else the text classifier's reading.
69
+ * A failed in-process op always records the key, null when its errorKind has no recovery advice:
70
+ * Galaxy's own message can quote a wire phrase ("request timed out") the text classifier would
71
+ * misread. Only a shell's extras, which record no kind, are read by their text.
72
+ */
73
+ export function galaxyFailureKind(
74
+ details: unknown,
75
+ text: string | undefined,
76
+ toolName: string | undefined,
77
+ family: GalaxyToolFamily,
78
+ ): GalaxyFailureKind {
79
+ const galaxy = record(record(details)?.galaxy);
80
+ if (galaxy && "kind" in galaxy) {
81
+ return typeof galaxy.kind === "string" ? (galaxy.kind as GalaxyCallKind) : null;
82
+ }
83
+ return classifyGalaxyFailure(toolName, text, family);
84
+ }
85
+
86
+ /**
87
+ * The first string `code` down an error's cause chain, or an AggregateError's first error's.
88
+ * undici hides why a request failed on `cause` and galaxy-ops keeps only `.message`, so this is
89
+ * the one place a connect timeout and a refused connection still differ.
90
+ */
91
+ export function transportCode(err: unknown): string | undefined {
92
+ let cur: unknown = err;
93
+ for (let depth = 0; cur && depth < 6; depth++) {
94
+ const { code, errors, cause } = cur as { code?: unknown; errors?: unknown; cause?: unknown };
95
+ if (typeof code === "string" && code) return code;
96
+ const first = Array.isArray(errors) ? (errors[0] as { code?: unknown } | undefined) : undefined;
97
+ if (typeof first?.code === "string" && first.code) return first.code;
98
+ cur = cause;
99
+ }
100
+ return undefined;
101
+ }
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Answering Galaxy calls from a recorded fixture, for the Tier-1 evals.
3
+ *
4
+ * Reconcile and enrichment are driven by what Galaxy says after the submit --
5
+ * listings, job details, a 502 followed by a 200 -- and the Tier-1 scenarios
6
+ * are model-free and network-free by design. `LOOM_GALAXY_FIXTURE` names a
7
+ * JSON file in the session directory; while it is set, every Galaxy call made
8
+ * through galaxy-api.ts (galaxy-ops' included) is answered from it.
9
+ *
10
+ * Same constraints as the submission replay seam: off unless the variable is
11
+ * set, the file must resolve inside the session directory, and a
12
+ * `galaxy.fixture` activity row is written first, so a notebook whose runs
13
+ * were reconciled or enriched from a fixture says so in its own log.
14
+ *
15
+ * File shape:
16
+ *
17
+ * ```json
18
+ * { "routes": [
19
+ * { "method": "GET", "path": "/api/jobs/aa11", "query": { "full": "true" },
20
+ * "responses": [ { "status": 502, "body": "bad gateway" },
21
+ * { "status": 200, "body": { "id": "aa11", "state": "ok" } } ] }
22
+ * ] }
23
+ * ```
24
+ *
25
+ * A route matches on method, exact path, and every query key it names (keys it
26
+ * does not name are ignored). Routes are tried in order. Each request takes
27
+ * the route's next response; the last one repeats. Anything unmatched is a 404.
28
+ */
29
+
30
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
31
+ import * as fs from "fs";
32
+ import * as path from "path";
33
+ import { readEnv } from "../../shared/orbit-env.js";
34
+ import { appendActivityEvent } from "./activity";
35
+ import { setGalaxyFetchOverride } from "./galaxy-api";
36
+ import { resolveReplayPath } from "./submission-replay";
37
+
38
+ interface FixtureResponse {
39
+ status: number;
40
+ body?: unknown;
41
+ }
42
+
43
+ interface FixtureRoute {
44
+ method?: string;
45
+ path: string;
46
+ query?: Record<string, string>;
47
+ responses: FixtureResponse[];
48
+ }
49
+
50
+ export function isGalaxyFixtureEnabled(): boolean {
51
+ return !!readEnv("GALAXY_FIXTURE")?.trim();
52
+ }
53
+
54
+ export function parseGalaxyFixture(raw: string): FixtureRoute[] {
55
+ const parsed = JSON.parse(raw) as { routes?: unknown };
56
+ if (!Array.isArray(parsed.routes)) return [];
57
+ return parsed.routes.filter(
58
+ (r): r is FixtureRoute =>
59
+ !!r &&
60
+ typeof r === "object" &&
61
+ typeof (r as FixtureRoute).path === "string" &&
62
+ Array.isArray((r as FixtureRoute).responses) &&
63
+ (r as FixtureRoute).responses.length > 0,
64
+ );
65
+ }
66
+
67
+ /** A fetch that answers from `routes`. Exported for the seam's own test. */
68
+ export function fixtureFetch(
69
+ routes: FixtureRoute[],
70
+ ): (url: string, init: RequestInit) => Promise<Response> {
71
+ const served = new Map<FixtureRoute, number>();
72
+ return async (url, init) => {
73
+ const u = new URL(url);
74
+ const method = (init.method ?? "GET").toUpperCase();
75
+ const route = routes.find(
76
+ (r) =>
77
+ (r.method ?? "GET").toUpperCase() === method &&
78
+ r.path === u.pathname &&
79
+ Object.entries(r.query ?? {}).every(([k, v]) => u.searchParams.get(k) === v),
80
+ );
81
+ if (!route) {
82
+ return new Response(JSON.stringify({ err_msg: `no fixture for ${method} ${u.pathname}` }), {
83
+ status: 404,
84
+ headers: { "content-type": "application/json" },
85
+ });
86
+ }
87
+ const index = served.get(route) ?? 0;
88
+ served.set(route, index + 1);
89
+ const response = route.responses[Math.min(index, route.responses.length - 1)];
90
+ const body =
91
+ typeof response.body === "string" ? response.body : JSON.stringify(response.body ?? null);
92
+ return new Response(body, {
93
+ status: response.status,
94
+ headers: { "content-type": "application/json" },
95
+ });
96
+ };
97
+ }
98
+
99
+ /**
100
+ * Install the fixture now, at registration, rather than on session start: the
101
+ * poller's first tick fires inside session start and must not reach a real
102
+ * server first.
103
+ */
104
+ export function registerGalaxyFixture(pi: ExtensionAPI): void {
105
+ const configured = readEnv("GALAXY_FIXTURE")?.trim();
106
+ if (!configured) return;
107
+ const sessionDir = process.cwd();
108
+ const file = resolveReplayPath(sessionDir, configured);
109
+ if (!file || !fs.existsSync(file)) return;
110
+ let routes: FixtureRoute[];
111
+ try {
112
+ routes = parseGalaxyFixture(fs.readFileSync(file, "utf-8"));
113
+ } catch (err) {
114
+ console.error("[galaxy-fixture] unreadable fixture:", err);
115
+ return;
116
+ }
117
+ setGalaxyFetchOverride(fixtureFetch(routes));
118
+ pi.on("session_start", async () => {
119
+ appendActivityEvent(sessionDir, {
120
+ timestamp: new Date().toISOString(),
121
+ kind: "galaxy.fixture",
122
+ source: "galaxy-fixture",
123
+ payload: { file: path.relative(sessionDir, file), routes: routes.length },
124
+ });
125
+ });
126
+ }
@@ -0,0 +1,233 @@
1
+ /**
2
+ * Refuse a Galaxy tool run whose inputs live in a history other than the one
3
+ * the job runs in. Galaxy allows it, but an agent that does it has nearly
4
+ * always copied the wrong id, and the job answers a question nobody asked.
5
+ * Ported from the browser shell's run_tool check, refusal text and all.
6
+ *
7
+ * Also refuse any Galaxy write aimed at a history another user owns. Galaxy
8
+ * stops that for an ordinary key, but an admin key can write anywhere, and an
9
+ * agent that moves the whole job -- inputs and target together -- into someone
10
+ * else's history gets past the input check above.
11
+ */
12
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
13
+ import { galaxyGet, getGalaxyConfig } from "./galaxy-api";
14
+ import type { GalaxyToolFamily } from "../../shared/galaxy-tool-family.js";
15
+
16
+ type Row = Record<string, unknown>;
17
+
18
+ const isRow = (value: unknown): value is Row =>
19
+ !!value && typeof value === "object" && !Array.isArray(value);
20
+
21
+ /**
22
+ * Sources a history owns: where each answers its history_id, and how to ask for
23
+ * little more than that.
24
+ */
25
+ const HISTORY_SCOPED_SRCS: Record<string, { path: string; brief: string }> = {
26
+ hda: { path: "/datasets", brief: "?keys=history_id,name" },
27
+ hdca: { path: "/dataset_collections", brief: "?view=collection" },
28
+ };
29
+
30
+ /** How many references are looked up at once. */
31
+ const LOOKUPS = 4;
32
+
33
+ /** Every history-scoped reference in a tool payload, with the field that carries it. */
34
+ function hdaInputs(inputs: unknown): [string, string, string][] {
35
+ const found: [string, string, string][] = [];
36
+ const walk = (name: string, value: unknown) => {
37
+ if (Array.isArray(value)) {
38
+ value.forEach((item, index) => walk(`${name}[${index}]`, item));
39
+ } else if (isRow(value)) {
40
+ if (
41
+ typeof value.src === "string" &&
42
+ Object.hasOwn(HISTORY_SCOPED_SRCS, value.src) &&
43
+ value.id
44
+ ) {
45
+ found.push([name, String(value.id), value.src]);
46
+ return;
47
+ }
48
+ for (const [key, item] of Object.entries(value)) {
49
+ walk(name ? `${name}.${key}` : key, item);
50
+ }
51
+ }
52
+ };
53
+ walk("", inputs || {});
54
+ return found;
55
+ }
56
+
57
+ /**
58
+ * Inputs that belong to a history other than `historyId`, each looked up once.
59
+ * An id Galaxy won't resolve, or a lookup that fails, is not known to be
60
+ * foreign: the run is left to report it.
61
+ */
62
+ async function foreignInputs(inputs: unknown, historyId: string, signal?: AbortSignal) {
63
+ const refs = hdaInputs(inputs);
64
+ const distinct = [...new Set(refs.map(([, id, src]) => `${src}/${id}`))];
65
+ const found = new Map<string, Row>();
66
+ const lookup = async () => {
67
+ for (let ref = distinct.pop(); ref !== undefined; ref = distinct.pop()) {
68
+ const [src, id] = [ref.slice(0, ref.indexOf("/")), ref.slice(ref.indexOf("/") + 1)];
69
+ // `.` and `..` would name a parent path, not an id.
70
+ if (/^(\.|%2e){0,2}$/i.test(id)) continue;
71
+ const { path, brief } = HISTORY_SCOPED_SRCS[src];
72
+ try {
73
+ const detail = await galaxyGet(`${path}/${encodeURIComponent(id)}${brief}`, signal);
74
+ if (isRow(detail)) found.set(ref, detail);
75
+ } catch {
76
+ // Fail open: a Galaxy that can't answer here can't be shown to disagree.
77
+ }
78
+ }
79
+ };
80
+ await Promise.all(Array.from({ length: Math.min(LOOKUPS, distinct.length) }, lookup));
81
+ return refs.flatMap(([input, id, src]) => {
82
+ const detail = found.get(`${src}/${id}`);
83
+ const where = detail?.history_id;
84
+ return where && where !== historyId
85
+ ? [{ input, supplied_id: id, history_id: where, name: detail?.name ?? null }]
86
+ : [];
87
+ });
88
+ }
89
+
90
+ /**
91
+ * Galaxy tools that write into the history named by their `history_id`: run a
92
+ * job there, upload into it, invoke a workflow into it, edit it, or attach a
93
+ * page to it. Each one leaves `history_id` optional or defaults it to a history
94
+ * of the user's own, so only an explicit id is checked.
95
+ */
96
+ const HISTORY_WRITERS: ReadonlySet<string> = new Set([
97
+ "run_tool",
98
+ "run_user_tool",
99
+ "invoke_workflow",
100
+ "upload_file",
101
+ "upload_file_from_url",
102
+ "update_history",
103
+ "create_page",
104
+ ]);
105
+
106
+ /**
107
+ * Orbit's own tools that write into an explicit `history_id`; not galaxy-ops
108
+ * operations, so not in the family. Pushing an unbound notebook creates a page
109
+ * attached to that history, the same write as create_page.
110
+ */
111
+ const ORBIT_WRITERS: ReadonlySet<string> = new Set([
112
+ "galaxy_upload_local_file",
113
+ "notebook_push_to_galaxy",
114
+ ]);
115
+
116
+ /** How long the shared who-am-I lookup may take; no one caller's signal owns it. */
117
+ const CURRENT_USER_TIMEOUT_MS = 15_000;
118
+
119
+ /**
120
+ * The signed-in user's id, remembered for the credentials it was asked with: a
121
+ * /connect or profile switch changes the URL or key, and the next check asks
122
+ * again. Only an answer is kept, so a failed lookup is retried next time.
123
+ */
124
+ let currentUser: { url: string; apiKey: string; id: Promise<string | null> } | undefined;
125
+
126
+ /** Forget the signed-in user, as a new session must. */
127
+ export function resetGalaxyCurrentUser(): void {
128
+ currentUser = undefined;
129
+ }
130
+
131
+ function currentUserId(signal?: AbortSignal): Promise<string | null> {
132
+ const config = getGalaxyConfig();
133
+ if (!config) return Promise.resolve(null);
134
+ if (currentUser?.url === config.url && currentUser.apiKey === config.apiKey) {
135
+ return untilAborted(currentUser.id, signal);
136
+ }
137
+ const entry = {
138
+ ...config,
139
+ // Shared by every check until it settles, so it runs on its own timeout: one
140
+ // aborted tool call must not hand a null to another one waiting on it.
141
+ id: galaxyGet<unknown>("/users/current", AbortSignal.timeout(CURRENT_USER_TIMEOUT_MS)).then(
142
+ (user) => (isRow(user) && typeof user.id === "string" && user.id ? user.id : null),
143
+ () => null,
144
+ ),
145
+ };
146
+ currentUser = entry;
147
+ // An anonymous answer or a failure is not worth keeping.
148
+ void entry.id.then((id) => {
149
+ if (id === null && currentUser === entry) currentUser = undefined;
150
+ });
151
+ return untilAborted(entry.id, signal);
152
+ }
153
+
154
+ /** `pending`, or null as soon as `signal` aborts. */
155
+ function untilAborted<T>(pending: Promise<T | null>, signal?: AbortSignal): Promise<T | null> {
156
+ if (!signal) return pending;
157
+ if (signal.aborted) return Promise.resolve(null);
158
+ return new Promise((resolve) => {
159
+ const abort = () => resolve(null);
160
+ signal.addEventListener("abort", abort, { once: true });
161
+ void pending.then((value) => {
162
+ signal.removeEventListener("abort", abort);
163
+ resolve(value);
164
+ });
165
+ });
166
+ }
167
+
168
+ /**
169
+ * Whether Galaxy names an owner of `historyId` other than the signed-in user. Fails open: no credentials, a lookup that fails, an
170
+ * anonymous session or a history with no named owner can't be shown to belong
171
+ * to someone else, so the write is left to Galaxy.
172
+ */
173
+ async function ownedByAnother(historyId: string, signal?: AbortSignal): Promise<boolean> {
174
+ // `.` and `..` would name a parent path, not an id.
175
+ if (/^(\.|%2e){0,2}$/i.test(historyId)) return false;
176
+ const [me, history] = await Promise.all([
177
+ currentUserId(signal),
178
+ galaxyGet<unknown>(`/histories/${encodeURIComponent(historyId)}?keys=id,user_id`, signal).catch(
179
+ () => null,
180
+ ),
181
+ ]);
182
+ if (!me || !isRow(history)) return false;
183
+ // A 200 for some other resource is not an answer about this history.
184
+ // Galaxy decodes hex ids in either case and answers in lowercase.
185
+ if (history.id !== undefined && String(history.id).toLowerCase() !== historyId.toLowerCase()) {
186
+ return false;
187
+ }
188
+ const owner = history.user_id;
189
+ return typeof owner === "string" && owner !== "" && owner !== me;
190
+ }
191
+
192
+ function otherOwnerRefusal(historyId: string, family: GalaxyToolFamily) {
193
+ return {
194
+ block: true,
195
+ reason:
196
+ `Refused: history ${historyId} belongs to another Galaxy user, not to ` +
197
+ "the account this session is signed in as. Don't run jobs, upload, or change anything " +
198
+ `in someone else's history: use a history of the user's own -- take its id from ` +
199
+ `${family.tool("get_histories")}, or make one with ${family.tool("create_history")}. ` +
200
+ "If the user really means to work in that history, ask them first before trying again.",
201
+ };
202
+ }
203
+
204
+ export function registerGalaxyHistoryGuard(pi: ExtensionAPI, family: GalaxyToolFamily): void {
205
+ pi.on("session_start", () => {
206
+ resetGalaxyCurrentUser();
207
+ });
208
+ pi.on("tool_call", async (event, ctx) => {
209
+ const tool = family.toolName(event.toolName);
210
+ const writes =
211
+ (tool !== undefined && HISTORY_WRITERS.has(tool)) || ORBIT_WRITERS.has(event.toolName);
212
+ if (!writes) return;
213
+ const args = event.input as Row;
214
+ if (typeof args.history_id !== "string" || !args.history_id) return;
215
+ const [another, foreign] = await Promise.all([
216
+ ownedByAnother(args.history_id, ctx?.signal),
217
+ tool === "run_tool"
218
+ ? foreignInputs(args.inputs, args.history_id, ctx?.signal)
219
+ : Promise.resolve([]),
220
+ ]);
221
+ if (another) return otherOwnerRefusal(args.history_id, family);
222
+ if (!foreign.length) return;
223
+ return {
224
+ block: true,
225
+ reason:
226
+ `Refused: these inputs are in another history, not in history ${args.history_id} ` +
227
+ `where this job runs: ${JSON.stringify(foreign)}. An id from another history is ` +
228
+ "usually the wrong one: take the input's `id` from get_history_contents for this " +
229
+ "history. If the user does mean that data, say which history it is in and ask them " +
230
+ "to copy it into this one in Galaxy, then use the copy's id.",
231
+ };
232
+ });
233
+ }