@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.
- package/CHANGELOG.md +123 -0
- package/LICENSE +21 -0
- package/README.md +760 -5
- package/bin/legacy-mcp-config.js +363 -0
- package/bin/orbit.js +810 -0
- package/bin/pi-extension-path.d.ts +4 -0
- package/bin/pi-extension-path.js +44 -0
- package/bin/provider-auth.d.ts +22 -0
- package/bin/provider-auth.js +77 -0
- package/bin/thinking-pref.js +38 -0
- package/bin/update-check.d.ts +15 -0
- package/bin/update-check.js +137 -0
- package/extensions/cli-update/index.ts +32 -0
- package/extensions/orbit/activity-hooks.ts +141 -0
- package/extensions/orbit/activity.ts +116 -0
- package/extensions/orbit/agent-dir.ts +11 -0
- package/extensions/orbit/auto-resume.ts +352 -0
- package/extensions/orbit/config.ts +3 -0
- package/extensions/orbit/confusables.ts +1 -0
- package/extensions/orbit/context.ts +957 -0
- package/extensions/orbit/dashboard-commands.ts +191 -0
- package/extensions/orbit/dashboard-store.ts +473 -0
- package/extensions/orbit/dashboard-tools.ts +1185 -0
- package/extensions/orbit/empty-completion.ts +99 -0
- package/extensions/orbit/evidence-gate.ts +1276 -0
- package/extensions/orbit/evidence-override-command.ts +294 -0
- package/extensions/orbit/exec-guard/bash-risk.ts +1408 -0
- package/extensions/orbit/exec-guard/gate.ts +181 -0
- package/extensions/orbit/exec-guard/guardian-config.ts +54 -0
- package/extensions/orbit/exec-guard/index.ts +1 -0
- package/extensions/orbit/exec-guard/model-tier.ts +36 -0
- package/extensions/orbit/exec-guard/path-jail.ts +54 -0
- package/extensions/orbit/exec-guard/policy.ts +342 -0
- package/extensions/orbit/exec-guard/runtime-state.ts +15 -0
- package/extensions/orbit/exec-guard/sensitive-read.ts +525 -0
- package/extensions/orbit/exec-guard/types.ts +42 -0
- package/extensions/orbit/execution-commands.ts +134 -0
- package/extensions/orbit/feedback-command.ts +81 -0
- package/extensions/orbit/feedback.ts +96 -0
- package/extensions/orbit/galaxy-api.test.ts +122 -0
- package/extensions/orbit/galaxy-api.ts +606 -0
- package/extensions/orbit/galaxy-artifact-link-guidance.ts +5 -0
- package/extensions/orbit/galaxy-destructive-gate.ts +113 -0
- package/extensions/orbit/galaxy-enrich.ts +1108 -0
- package/extensions/orbit/galaxy-failure.ts +101 -0
- package/extensions/orbit/galaxy-fixture.ts +126 -0
- package/extensions/orbit/galaxy-history-guard.ts +233 -0
- package/extensions/orbit/galaxy-job-block.ts +347 -0
- package/extensions/orbit/galaxy-job-ops.ts +288 -0
- package/extensions/orbit/galaxy-live-source.ts +929 -0
- package/extensions/orbit/galaxy-markdown-adapter.ts +248 -0
- package/extensions/orbit/galaxy-op-policy.ts +332 -0
- package/extensions/orbit/galaxy-ops-tools.ts +326 -0
- package/extensions/orbit/galaxy-output-store.ts +80 -0
- package/extensions/orbit/galaxy-output.ts +346 -0
- package/extensions/orbit/galaxy-page-binding.ts +222 -0
- package/extensions/orbit/galaxy-page-markdown-guidance.ts +15 -0
- package/extensions/orbit/galaxy-page-ops.ts +159 -0
- package/extensions/orbit/galaxy-page-sync.test.ts +417 -0
- package/extensions/orbit/galaxy-page-sync.ts +318 -0
- package/extensions/orbit/galaxy-pages-api.ts +203 -0
- package/extensions/orbit/galaxy-pages-sync.ts +409 -0
- package/extensions/orbit/galaxy-poll-guard.ts +189 -0
- package/extensions/orbit/galaxy-poller.ts +706 -0
- package/extensions/orbit/galaxy-provenance.ts +623 -0
- package/extensions/orbit/galaxy-reconcile.ts +956 -0
- package/extensions/orbit/galaxy-recovery.ts +176 -0
- package/extensions/orbit/galaxy-repeat-guard.ts +55 -0
- package/extensions/orbit/galaxy-submission-capture.ts +707 -0
- package/extensions/orbit/galaxy-submission.ts +502 -0
- package/extensions/orbit/galaxy-tool-source.ts +78 -0
- package/extensions/orbit/galaxy-tool-wrap.ts +234 -0
- package/extensions/orbit/galaxy-udt-block.ts +127 -0
- package/extensions/orbit/galaxy-upload-tus.ts +334 -0
- package/extensions/orbit/galaxy-upload.ts +300 -0
- package/extensions/orbit/galaxy-version-capture.ts +65 -0
- package/extensions/orbit/git.ts +173 -0
- package/extensions/orbit/harness-block-fields.ts +597 -0
- package/extensions/orbit/index.ts +593 -0
- package/extensions/orbit/init-gate.ts +284 -0
- package/extensions/orbit/instructions-command.ts +136 -0
- package/extensions/orbit/invocation-failure-hint.ts +57 -0
- package/extensions/orbit/iwc-plan-check.ts +94 -0
- package/extensions/orbit/lesson-command.ts +303 -0
- package/extensions/orbit/lesson-hint.ts +245 -0
- package/extensions/orbit/lesson-nudge.ts +106 -0
- package/extensions/orbit/lessons/compose.ts +177 -0
- package/extensions/orbit/lessons/counters.ts +120 -0
- package/extensions/orbit/lessons/enabled.ts +116 -0
- package/extensions/orbit/lessons/matcher.ts +346 -0
- package/extensions/orbit/lessons/paths.ts +286 -0
- package/extensions/orbit/lessons/pi-event-contract.ts +105 -0
- package/extensions/orbit/lessons/propose-replay.ts +103 -0
- package/extensions/orbit/lessons/propose-tool.ts +222 -0
- package/extensions/orbit/lessons/propose.ts +502 -0
- package/extensions/orbit/lessons/replay.ts +89 -0
- package/extensions/orbit/lessons/reproduction-index.ts +83 -0
- package/extensions/orbit/lessons/search-tool.ts +99 -0
- package/extensions/orbit/lessons/search.ts +136 -0
- package/extensions/orbit/lessons/store.ts +415 -0
- package/extensions/orbit/lessons/text.ts +36 -0
- package/extensions/orbit/lessons/types.ts +69 -0
- package/extensions/orbit/lessons/user-dir.ts +24 -0
- package/extensions/orbit/lessons/user-lesson.ts +88 -0
- package/extensions/orbit/lessons/wrapper.ts +61 -0
- package/extensions/orbit/lessons-command.ts +147 -0
- package/extensions/orbit/local-exec.ts +39 -0
- package/extensions/orbit/mcp-output.ts +179 -0
- package/extensions/orbit/mcp-servers.test.ts +24 -0
- package/extensions/orbit/mcp-servers.ts +25 -0
- package/extensions/orbit/model-script.ts +351 -0
- package/extensions/orbit/notebook-anchors.ts +342 -0
- package/extensions/orbit/notebook-writer.ts +863 -0
- package/extensions/orbit/observation-allowlists.ts +1109 -0
- package/extensions/orbit/observation-replay.ts +148 -0
- package/extensions/orbit/observation-triggers.ts +563 -0
- package/extensions/orbit/observation-ui.ts +175 -0
- package/extensions/orbit/observations-command.ts +421 -0
- package/extensions/orbit/observations-config.ts +200 -0
- package/extensions/orbit/observations.ts +1381 -0
- package/extensions/orbit/profiles.ts +270 -0
- package/extensions/orbit/progress-updates.ts +95 -0
- package/extensions/orbit/proposal-commands.ts +882 -0
- package/extensions/orbit/provenance-fs-file.ts +59 -0
- package/extensions/orbit/provenance-fs.ts +32 -0
- package/extensions/orbit/provenance-memory-fs.ts +59 -0
- package/extensions/orbit/record-store-file.ts +177 -0
- package/extensions/orbit/record-store-page.ts +77 -0
- package/extensions/orbit/record-store-seam.ts +47 -0
- package/extensions/orbit/record-store.ts +149 -0
- package/extensions/orbit/registry-carrier.ts +107 -0
- package/extensions/orbit/registry-eligibility.ts +95 -0
- package/extensions/orbit/registry-evaluation.ts +403 -0
- package/extensions/orbit/registry-evaluator.ts +519 -0
- package/extensions/orbit/registry-import.ts +91 -0
- package/extensions/orbit/registry-lock.ts +221 -0
- package/extensions/orbit/registry-memory-fs.ts +42 -0
- package/extensions/orbit/registry-page-carrier.ts +103 -0
- package/extensions/orbit/registry-proposal.ts +1348 -0
- package/extensions/orbit/registry-runtime.ts +234 -0
- package/extensions/orbit/registry-schema.ts +735 -0
- package/extensions/orbit/registry-submitter.ts +59 -0
- package/extensions/orbit/registry-templates.ts +346 -0
- package/extensions/orbit/registry.ts +476 -0
- package/extensions/orbit/sandbox/index.ts +120 -0
- package/extensions/orbit/sandbox/sandbox-bash.ts +93 -0
- package/extensions/orbit/sandbox/sandbox-config.ts +87 -0
- package/extensions/orbit/sandbox/sandbox-init-message.ts +28 -0
- package/extensions/orbit/secret-redaction.ts +247 -0
- package/extensions/orbit/session-index/cwd.ts +18 -0
- package/extensions/orbit/session-index/db.ts +56 -0
- package/extensions/orbit/session-index/indexer.ts +154 -0
- package/extensions/orbit/session-index/is-enabled.ts +17 -0
- package/extensions/orbit/session-index/parse.ts +254 -0
- package/extensions/orbit/session-index/query.ts +209 -0
- package/extensions/orbit/session-index/schema.ts +72 -0
- package/extensions/orbit/session-index/tools.ts +152 -0
- package/extensions/orbit/session-lifecycle.ts +321 -0
- package/extensions/orbit/skill-triggers.ts +159 -0
- package/extensions/orbit/skills-command.ts +48 -0
- package/extensions/orbit/skills-discovery.ts +435 -0
- package/extensions/orbit/skills.ts +84 -0
- package/extensions/orbit/sra-import-gate.ts +77 -0
- package/extensions/orbit/state.ts +265 -0
- package/extensions/orbit/submission-replay.ts +147 -0
- package/extensions/orbit/sync-command.ts +157 -0
- package/extensions/orbit/teams/critic-parser.ts +93 -0
- package/extensions/orbit/teams/dispatcher.ts +210 -0
- package/extensions/orbit/teams/is-enabled.ts +22 -0
- package/extensions/orbit/teams/tool.ts +187 -0
- package/extensions/orbit/teams/types.ts +57 -0
- package/extensions/orbit/teams/validate.ts +42 -0
- package/extensions/orbit/tester-id-command.ts +133 -0
- package/extensions/orbit/tools-sync.ts +279 -0
- package/extensions/orbit/tools.ts +1300 -0
- package/extensions/orbit/types.ts +41 -0
- package/extensions/orbit/ui-bridge.ts +55 -0
- package/extensions/orbit/ulid.ts +60 -0
- package/extensions/orbit/user-instructions.ts +388 -0
- package/extensions/orbit/vendor/skills/_catalog.json +68 -0
- package/extensions/orbit/vendor/skills/_manifest.json +1106 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/SKILL.md +112 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/_provenance.json +218 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/_required_tools.json +33 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/add.json +50 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/draft-extract.json +51 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/draft-next-step.json +42 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/draft-validate.json +140 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/cli/list.json +32 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/notes/galaxy-tool-job-failure-reference.md +137 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/notes/open-requirements-ledger.md +173 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/schemas/galaxy-tool-summary.schema.json +175 -0
- package/extensions/orbit/vendor/skills/advance-galaxy-draft-step/references/schemas/galaxy-workflow-draft.schema.json +2727 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/SKILL.md +82 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/_provenance.json +133 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/_required_tools.json +16 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/cli/draft-validate.json +140 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/notes/galaxy-workflow-draft-format.md +135 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/notes/open-requirements-ledger.md +173 -0
- package/extensions/orbit/vendor/skills/apply-galaxy-workflow-changeset/references/schemas/galaxy-workflow-draft.schema.json +2727 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/SKILL.md +84 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/_provenance.json +166 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/_verify.json +29 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/galaxy-workflow-testability-design.md +136 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/iwc-test-data-conventions.md +308 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/planemo-asserts-idioms.md +246 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/notes/planemo-workflow-test-architecture.md +151 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/schemas/galaxy-workflow-test-plan.schema.json +552 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/schemas/summary-galaxy-workflow.schema.json +687 -0
- package/extensions/orbit/vendor/skills/changeset-to-galaxy-test-plan/references/schemas/tests-format.schema.json +7328 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/SKILL.md +127 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/_provenance.json +198 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/_required_tools.json +16 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/cli/convert.json +123 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/galaxy-data-flow-draft-contract.md +129 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/iwc-test-data-conventions.md +308 -0
- package/extensions/orbit/vendor/skills/compare-against-iwc-exemplar/references/notes/open-requirements-ledger.md +173 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/SKILL.md +73 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/_provenance.json +160 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-collection-semantics.md +43 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-collection-semantics.yml +1250 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-tool-job-failure-reference.md +137 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/galaxy-workflow-invocation-failure-reference.md +138 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/nextflow-operators-to-galaxy-collection-recipes.md +98 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/planemo-asserts-idioms.md +246 -0
- package/extensions/orbit/vendor/skills/debug-galaxy-workflow-output/references/notes/planemo-workflow-test-architecture.md +151 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/SKILL.md +174 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/_provenance.json +130 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/_required_tools.json +18 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/_verify.json +17 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/references/cli/tool-revisions.json +48 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/references/cli/tool-search.json +95 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/references/cli/tool-versions.json +39 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/references/notes/component-tool-shed-search.md +230 -0
- package/extensions/orbit/vendor/skills/discover-shed-tool/references/schemas/galaxy-tool-discovery.schema.json +231 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/SKILL.md +93 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/_provenance.json +201 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/_required_tools.json +28 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/_verify.json +17 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/cli/planemo.md +44 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/cli/validate-tests.json +40 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/galaxy-workflow-testability-design.md +136 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/iwc-shortcuts-anti-patterns.md +357 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/iwc-test-data-conventions.md +308 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/planemo-asserts-idioms.md +246 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/notes/planemo-workflow-test-architecture.md +151 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/schemas/galaxy-workflow-test-plan.schema.json +552 -0
- package/extensions/orbit/vendor/skills/implement-galaxy-workflow-test/references/schemas/tests-format.schema.json +7328 -0
- package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/SKILL.md +81 -0
- package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/_provenance.json +93 -0
- package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/_verify.json +17 -0
- package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/references/notes/open-requirements-ledger.md +173 -0
- package/extensions/orbit/vendor/skills/interview-to-galaxy-workflow-changeset/references/schemas/summary-galaxy-workflow.schema.json +687 -0
- package/extensions/orbit/vendor/skills/pipeline-update-interview-to-galaxy/SKILL.md +81 -0
- package/extensions/orbit/vendor/skills/pipeline-update-interview-to-galaxy/_assembly.json +23 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/SKILL.md +79 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/_provenance.json +125 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/_required_tools.json +28 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/cli/planemo.md +44 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/cli/validate-tests.json +40 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/notes/galaxy-workflow-invocation-failure-reference.md +138 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/notes/planemo-asserts-idioms.md +246 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/notes/planemo-workflow-test-architecture.md +151 -0
- package/extensions/orbit/vendor/skills/run-workflow-test/references/schemas/tests-format.schema.json +7328 -0
- package/extensions/orbit/vendor/skills/skills/LICENSE +21 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/README.md +39 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/SKILL.md +892 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/api-patterns.md +927 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/apply-rules.md +1482 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/test-patterns.md +996 -0
- package/extensions/orbit/vendor/skills/skills/collection-manipulation/references/tools.md +609 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-data-libraries/SKILL.md +170 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/README.md +162 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/SKILL.md +99 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/examples/README.md +119 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/examples/tool-checking.md +419 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/examples/workflow-testing.md +617 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/galaxy-integration.md +614 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/SKILL.md +144 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/average_col3.ipynb +68 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/extract_sample_metadata.ipynb +190 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/variant_annotation.ipynb +816 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/jupyterlite/examples/vcp_variant_map.ipynb +443 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/scripts/README.md +165 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-integration/scripts/galaxy_tool_checker.py +521 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-mcp-reference/SKILL.md +128 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-mcp-reference/gotchas.md +135 -0
- package/extensions/orbit/vendor/skills/skills/galaxy-mcp-reference/history-access.md +132 -0
- package/extensions/orbit/vendor/skills/skills/reproduciblify/SKILL.md +146 -0
- package/extensions/orbit/vendor/skills/skills/reproduciblify/references/directives.yml +496 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/SKILL.md +245 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/01-minimal-echo.yml +27 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/02-single-data-in-out.yml +27 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/03-multiple-data-js.yml +28 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/04-select-integer-boolean.yml +41 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/05-resource-requirements.yml +25 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/06-biocontainer-tool.yml +38 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/07-inline-python-script.yml +56 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/examples/08-configfile-script.yml +74 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/references/common-mistakes.md +76 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/references/schema-reference.md +155 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/references/templating.md +196 -0
- package/extensions/orbit/vendor/skills/skills/udt-authoring/scripts/validate.py +109 -0
- package/extensions/orbit/vendor/skills/skills/workflow-reports/README.md +71 -0
- package/extensions/orbit/vendor/skills/skills/workflow-reports/SKILL.md +190 -0
- package/extensions/orbit/vendor/skills/skills/workflow-reports/examples/histology-staining.md +145 -0
- package/extensions/orbit/vendor/skills/skills/workflow-reports/examples/tissue-microarray-analysis.md +176 -0
- package/extensions/orbit/vendor/skills/skills/workflow-reports/references/directives.md +415 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/SKILL.md +98 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/_provenance.json +93 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/_required_tools.json +28 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/_verify.json +17 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/cli/convert.json +123 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/cli/foundry.md +25 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/cli/validate.json +142 -0
- package/extensions/orbit/vendor/skills/summarize-galaxy-workflow/references/schemas/summary-galaxy-workflow.schema.json +687 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/SKILL.md +74 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/_provenance.json +71 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/_required_tools.json +16 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/_verify.json +4 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/references/cli/validate.json +142 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/references/notes/galaxy-workflow-invocation-failure-reference.md +138 -0
- package/extensions/orbit/vendor/skills/validate-galaxy-workflow/references/notes/galaxy-workflow-testability-design.md +136 -0
- package/extensions/orbit/vendor-skills.ts +283 -0
- package/extensions/orbit/workspace-state-dir.ts +46 -0
- package/extensions/orbit-handoff/index.ts +73 -0
- package/extensions/orbit-handoff/orbit-launcher.ts +142 -0
- package/extensions/whats-new/index.ts +98 -0
- package/lessons/LICENSE +17 -0
- package/lessons/README.md +117 -0
- package/lessons/SCHEMA.md +187 -0
- package/lessons/build-snapshot.mjs +311 -0
- package/lessons/data/downloaded-file-is-not-what-its-extension-says.md +61 -0
- package/lessons/galaxy-api/403-history-is-a-hard-stop.md +57 -0
- package/lessons/galaxy-api/collection-into-single-dataset-input.md +61 -0
- package/lessons/galaxy-api/connectedvalue-in-command-line.md +62 -0
- package/lessons/galaxy-api/hid-is-not-an-id.md +59 -0
- package/lessons/galaxy-api/invoke-workflow-inputs-not-params.md +60 -0
- package/lessons/galaxy-api/repeat-param-pipe-keys.md +63 -0
- package/lessons/galaxy-api/run-tool-returns-on-submit.md +61 -0
- package/lessons/galaxy-tools/reference-index-not-on-server.md +62 -0
- package/lessons/log.md +42 -0
- package/lessons/reproduction/input-population-mismatch.md +59 -0
- package/lessons/reproduction/methods-text-vs-executed-parameters.md +62 -0
- package/lessons/snapshot.json +1004 -0
- package/lessons/stats/de-contrast-direction-and-sample-labels.md +63 -0
- package/lessons/stats/na-coerced-to-zero-in-filters.md +59 -0
- package/lessons/validate.mjs +1219 -0
- package/package.json +103 -5
- package/shared/agent-prompt.d.ts +8 -0
- package/shared/agent-prompt.js +15 -0
- package/shared/approval-prompt.d.ts +4 -0
- package/shared/approval-prompt.js +61 -0
- package/shared/brain-env.d.ts +14 -0
- package/shared/brain-env.js +108 -0
- package/shared/brain-exit.d.ts +20 -0
- package/shared/brain-exit.js +149 -0
- package/shared/capability-profile.d.ts +16 -0
- package/shared/capability-profile.js +75 -0
- package/shared/config-source.d.ts +13 -0
- package/shared/config-source.js +17 -0
- package/shared/confusables.d.ts +3 -0
- package/shared/confusables.js +93 -0
- package/shared/custom-provider.d.ts +45 -0
- package/shared/custom-provider.js +169 -0
- package/shared/dashboard-contract.d.ts +123 -0
- package/shared/dashboard-contract.js +560 -0
- package/shared/dashboard-layout-store.d.ts +44 -0
- package/shared/dashboard-layout-store.js +281 -0
- package/shared/feedback-contract.d.ts +61 -0
- package/shared/feedback-contract.js +146 -0
- package/shared/galaxy-artifact-links.d.ts +30 -0
- package/shared/galaxy-artifact-links.js +166 -0
- package/shared/galaxy-credentials.d.ts +26 -0
- package/shared/galaxy-credentials.js +71 -0
- package/shared/galaxy-destructive.d.ts +21 -0
- package/shared/galaxy-destructive.js +269 -0
- package/shared/galaxy-guidance.d.ts +2 -0
- package/shared/galaxy-guidance.js +53 -0
- package/shared/galaxy-live-contract.d.ts +92 -0
- package/shared/galaxy-live-contract.js +180 -0
- package/shared/galaxy-page-cells.d.ts +2 -0
- package/shared/galaxy-page-cells.js +22 -0
- package/shared/galaxy-tool-family.d.ts +5 -0
- package/shared/galaxy-tool-family.js +27 -0
- package/shared/galaxy-url.d.ts +1 -0
- package/shared/galaxy-url.js +48 -0
- package/shared/gtn.d.ts +31 -0
- package/shared/gtn.js +253 -0
- package/shared/handled-prompt.d.ts +3 -0
- package/shared/handled-prompt.js +26 -0
- package/shared/known-provider.d.ts +11 -0
- package/shared/known-provider.js +89 -0
- package/shared/lesson-hint-marker.d.ts +7 -0
- package/shared/lesson-hint-marker.js +32 -0
- package/shared/lesson-rules.d.ts +150 -0
- package/shared/lesson-rules.js +203 -0
- package/shared/malformed-object-ids.d.ts +1 -0
- package/shared/malformed-object-ids.js +37 -0
- package/shared/markdown-sections.d.ts +10 -0
- package/shared/markdown-sections.js +118 -0
- package/shared/notebook-fences.d.ts +12 -0
- package/shared/notebook-fences.js +53 -0
- package/shared/observation-contract.d.ts +91 -0
- package/shared/observation-contract.js +544 -0
- package/shared/orbit-config.d.ts +226 -0
- package/shared/orbit-config.js +189 -0
- package/shared/orbit-env.d.ts +13 -0
- package/shared/orbit-env.js +124 -0
- package/shared/orbit-shell-contract.d.ts +74 -0
- package/shared/orbit-shell-contract.js +30 -0
- package/shared/page-content-hash.d.ts +1 -0
- package/shared/page-content-hash.js +13 -0
- package/shared/pi-default-model.d.ts +7 -0
- package/shared/pi-default-model.js +41 -0
- package/shared/prompt-blocks.d.ts +87 -0
- package/shared/prompt-blocks.js +898 -0
- package/shared/provider-auth-caps.d.ts +22 -0
- package/shared/provider-auth-caps.js +57 -0
- package/shared/random.d.ts +2 -0
- package/shared/random.js +15 -0
- package/shared/record-excerpt.d.ts +4 -0
- package/shared/record-excerpt.js +16 -0
- package/shared/redirect-guard.d.ts +36 -0
- package/shared/redirect-guard.js +235 -0
- package/shared/skills-pin.d.ts +8 -0
- package/shared/skills-pin.js +9 -0
- package/shared/skills-router.d.ts +17 -0
- package/shared/skills-router.js +63 -0
- package/shared/sra-import.d.ts +34 -0
- package/shared/sra-import.js +206 -0
- package/shared/state-dir.d.ts +21 -0
- package/shared/state-dir.js +240 -0
- package/shared/team-dispatch-contract.d.ts +28 -0
- package/shared/team-dispatch-contract.js +1 -0
- package/shared/truncate-middle.d.ts +11 -0
- package/shared/truncate-middle.js +68 -0
- package/shared/version-compare.d.ts +10 -0
- package/shared/version-compare.js +74 -0
- package/shared/whats-new.d.ts +31 -0
- package/shared/whats-new.js +83 -0
- package/shared/wsl.d.ts +10 -0
- 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
|
+
}
|