@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,87 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import type { SandboxRuntimeConfig } from "@anthropic-ai/sandbox-runtime";
|
|
3
|
+
import { normalizeGalaxyUrl } from "../profiles";
|
|
4
|
+
import { WORKSPACE_STATE_DIR_NAMES } from "../workspace-state-dir";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Inputs for deriving the OS-sandbox profile. Pure: no I/O, fully testable.
|
|
8
|
+
* Home-relative credential paths are passed to ASRT as `~/...` literals (it
|
|
9
|
+
* expands them); cwd/tmp are absolute.
|
|
10
|
+
*/
|
|
11
|
+
export interface SandboxConfigInput {
|
|
12
|
+
/** Session working directory -- the workspace. */
|
|
13
|
+
cwd: string;
|
|
14
|
+
/** OS temp dir (os.tmpdir()). */
|
|
15
|
+
tmpDir: string;
|
|
16
|
+
/** Extra silent-write roots (guardian.extraWorkspaceRoots). */
|
|
17
|
+
extraWriteRoots?: string[];
|
|
18
|
+
/** Galaxy base URL, if known -- its host is allowlisted for bash network. */
|
|
19
|
+
galaxyUrl?: string;
|
|
20
|
+
/** Additional domains a deployment wants reachable from bash. */
|
|
21
|
+
extraAllowedDomains?: string[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Credential/secret locations under $HOME the sandbox blocks bash from reading,
|
|
25
|
+
// mirroring the exec-guard's sensitive-read set. ASRT expands the `~`.
|
|
26
|
+
const DENY_READ = [
|
|
27
|
+
"~/.ssh",
|
|
28
|
+
"~/.aws",
|
|
29
|
+
"~/.gnupg",
|
|
30
|
+
"~/.config/gcloud",
|
|
31
|
+
"~/.kube",
|
|
32
|
+
"~/.docker",
|
|
33
|
+
"~/Library/Keychains",
|
|
34
|
+
"~/.netrc",
|
|
35
|
+
"~/.pgpass",
|
|
36
|
+
"~/.npmrc",
|
|
37
|
+
"~/.loom/config.json",
|
|
38
|
+
"~/.orbit/config.json",
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
// Sensitive files the sandbox blocks bash from writing even inside the
|
|
42
|
+
// workspace (a project `.env` or a stray key).
|
|
43
|
+
const DENY_WRITE = [".env", ".env.*", "*.pem", "*.key"];
|
|
44
|
+
|
|
45
|
+
export function hostFromUrl(url?: string): string | undefined {
|
|
46
|
+
if (!url) return undefined;
|
|
47
|
+
try {
|
|
48
|
+
// Normalize via the same helper /connect and the profile system use, so a
|
|
49
|
+
// scheme-less GALAXY_URL ("usegalaxy.org") still resolves to a host.
|
|
50
|
+
const parsed = new URL(normalizeGalaxyUrl(url));
|
|
51
|
+
// Galaxy speaks http(s) only (validateGalaxyUrl enforces this on connect),
|
|
52
|
+
// so keep the host only for those schemes -- an ftp:// or file:// GALAXY_URL
|
|
53
|
+
// must not seed the bash network allowlist.
|
|
54
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return undefined;
|
|
55
|
+
return parsed.hostname || undefined;
|
|
56
|
+
} catch {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Build the ASRT profile: writable = workspace + tmp + both state-dir spellings
|
|
63
|
+
* (ASRT itself refuses an allow path that symlinks out of bounds); readable = everything except the credential set; network
|
|
64
|
+
* = deny-all for bash by default, allowlisting only the Galaxy host (Galaxy work
|
|
65
|
+
* itself flows over MCP, not bash, so a tight bash network default is safe).
|
|
66
|
+
*/
|
|
67
|
+
export function buildSandboxConfig(input: SandboxConfigInput): SandboxRuntimeConfig {
|
|
68
|
+
const allowWrite = [
|
|
69
|
+
input.cwd,
|
|
70
|
+
input.tmpDir,
|
|
71
|
+
...WORKSPACE_STATE_DIR_NAMES.map((name) => path.join(input.cwd, name)),
|
|
72
|
+
...(input.extraWriteRoots ?? []),
|
|
73
|
+
];
|
|
74
|
+
const galaxyHost = hostFromUrl(input.galaxyUrl);
|
|
75
|
+
const allowedDomains = [
|
|
76
|
+
...(galaxyHost ? [galaxyHost] : []),
|
|
77
|
+
...(input.extraAllowedDomains ?? []),
|
|
78
|
+
];
|
|
79
|
+
return {
|
|
80
|
+
network: { allowedDomains, deniedDomains: [] },
|
|
81
|
+
filesystem: {
|
|
82
|
+
denyRead: [...DENY_READ],
|
|
83
|
+
allowWrite,
|
|
84
|
+
denyWrite: [...DENY_WRITE],
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* apt package names that provide the Linux sandbox runtime binaries ASRT shells
|
|
3
|
+
* out to: `ripgrep` -> rg, `socat` -> socat, `bubblewrap` -> bwrap. These ship as
|
|
4
|
+
* deb `recommends` (see app/forge.config.ts), so a `--no-install-recommends`
|
|
5
|
+
* install -- or a distro/derivative that strips Recommends -- can still be missing
|
|
6
|
+
* them and trip the init failure in issue #305. (#305 only named rg + socat, but
|
|
7
|
+
* ASRT requires bwrap on Linux too.)
|
|
8
|
+
*/
|
|
9
|
+
export const LINUX_SANDBOX_APT_PACKAGES = ["ripgrep", "socat", "bubblewrap"];
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* User-facing message for a failed bash-sandbox init. On Linux, when ASRT reports
|
|
13
|
+
* its runtime prerequisites are missing, append the exact apt install line so the
|
|
14
|
+
* user can fix it in one step instead of decoding "ripgrep (rg) not found". Pure:
|
|
15
|
+
* takes the platform and the underlying error message, does no IO.
|
|
16
|
+
*/
|
|
17
|
+
export function describeSandboxInitFailure(
|
|
18
|
+
platform: NodeJS.Platform,
|
|
19
|
+
errorMessage: string,
|
|
20
|
+
): string {
|
|
21
|
+
const base = `Bash sandbox init failed (${errorMessage}); bash stays gated per action.`;
|
|
22
|
+
// ASRT's initialize() throws "Sandbox dependencies not available: ..." only when
|
|
23
|
+
// the Linux binary checks fail; anchor on that so unrelated failures stay terse.
|
|
24
|
+
if (platform === "linux" && /dependencies not available/i.test(errorMessage)) {
|
|
25
|
+
return `${base} On Debian/Ubuntu, install the prerequisites with: sudo apt install ${LINUX_SANDBOX_APT_PACKAGES.join(" ")}`;
|
|
26
|
+
}
|
|
27
|
+
return base;
|
|
28
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret redaction for tool OUTPUT (#183).
|
|
3
|
+
*
|
|
4
|
+
* The exec-guard decides whether a path may be read; this is the data-shaped
|
|
5
|
+
* companion that ensures a known secret VALUE never rides a tool result back
|
|
6
|
+
* into the model's context (and from there into the provider's request logs).
|
|
7
|
+
* It is value-based by design: we redact the concrete keys Orbit holds -- the
|
|
8
|
+
* provider/Galaxy API keys in ~/.orbit/config.json and the secret-valued env
|
|
9
|
+
* vars the agent process carries -- so there are no false positives on ordinary
|
|
10
|
+
* output. It is a defense-in-depth backstop for the guard, and it also catches
|
|
11
|
+
* vectors the guard can't (an `env` dump, a key pasted into some other file).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import * as fs from "fs";
|
|
15
|
+
import * as path from "path";
|
|
16
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
17
|
+
import { loadConfig } from "../../shared/orbit-config.js";
|
|
18
|
+
import type { OrbitConfig } from "../../shared/orbit-config.js";
|
|
19
|
+
import { installedConfigSource } from "../../shared/config-source.js";
|
|
20
|
+
import { piAgentDir } from "./agent-dir";
|
|
21
|
+
import { galaxyCredentials } from "./galaxy-api";
|
|
22
|
+
|
|
23
|
+
export const REDACTED = "[redacted]";
|
|
24
|
+
|
|
25
|
+
// Below this length a "secret" is too short to redact safely -- scrubbing a
|
|
26
|
+
// 3-char value would mangle ordinary output. Real API keys are far longer.
|
|
27
|
+
const MIN_SECRET_LEN = 8;
|
|
28
|
+
|
|
29
|
+
// Env vars whose VALUE is a live secret. The agent process carries these at
|
|
30
|
+
// runtime (the CLI exports the active provider's key from config; Orbit injects
|
|
31
|
+
// the decrypted key when it spawns the brain), so an `env`/`printenv` dump would
|
|
32
|
+
// otherwise leak them even when the config file itself is locked down. Only
|
|
33
|
+
// secret-VALUED vars belong here -- not names like AWS_PROFILE. Every LOOM_ name
|
|
34
|
+
// is paired with its ORBIT_ twin (tests/orbit-env-security.test.ts enforces it):
|
|
35
|
+
// either spelling can carry the value, and brain-env forwards both prefixes.
|
|
36
|
+
export const SECRET_ENV_VARS = [
|
|
37
|
+
"ANTHROPIC_API_KEY",
|
|
38
|
+
"ANTHROPIC_OAUTH_TOKEN",
|
|
39
|
+
"OPENAI_API_KEY",
|
|
40
|
+
"GEMINI_API_KEY",
|
|
41
|
+
"GOOGLE_API_KEY",
|
|
42
|
+
"GROQ_API_KEY",
|
|
43
|
+
"MISTRAL_API_KEY",
|
|
44
|
+
"XAI_API_KEY",
|
|
45
|
+
"DEEPSEEK_API_KEY",
|
|
46
|
+
"OPENROUTER_API_KEY",
|
|
47
|
+
"CEREBRAS_API_KEY",
|
|
48
|
+
"AI_GATEWAY_API_KEY",
|
|
49
|
+
"AZURE_OPENAI_API_KEY",
|
|
50
|
+
"HF_TOKEN",
|
|
51
|
+
"GALAXY_API_KEY",
|
|
52
|
+
// Custom OpenAI-compatible endpoints carry their key here (pi --api-key). With
|
|
53
|
+
// the dev/CI env fallback this can be the only place the key lives, so its
|
|
54
|
+
// value would otherwise dodge redaction.
|
|
55
|
+
"LOOM_ACTIVE_LLM_API_KEY",
|
|
56
|
+
"ORBIT_ACTIVE_LLM_API_KEY",
|
|
57
|
+
// Shell-side secrets that still ride into the brain through the LOOM_/ORBIT_
|
|
58
|
+
// prefix forwarding, so an `env` dump would otherwise show them.
|
|
59
|
+
"LOOM_WEB_TOKEN",
|
|
60
|
+
"ORBIT_WEB_TOKEN",
|
|
61
|
+
"LOOM_FEEDBACK_KEY",
|
|
62
|
+
"ORBIT_FEEDBACK_KEY",
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
// Keys in a stored pi credential that are metadata rather than secret. Every
|
|
66
|
+
// other long-enough string in the entry gets collected, deliberately: pi-ai's
|
|
67
|
+
// OAuthCredentials carries an open index signature (`[key: string]: unknown`),
|
|
68
|
+
// so a provider can add a token-shaped field whenever it likes. The two failure
|
|
69
|
+
// modes are not symmetric -- missing a field leaks a live token, over-matching
|
|
70
|
+
// costs a `[redacted]` where an account id used to print -- so this errs toward
|
|
71
|
+
// collecting.
|
|
72
|
+
const AUTH_METADATA_KEYS = new Set(["type", "expires"]);
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Read pi's credential store (~/.pi/agent/auth.json, or wherever
|
|
76
|
+
* PI_CODING_AGENT_DIR points). Best-effort: absent, unreadable, or mid-write
|
|
77
|
+
* under pi's lock all yield null and simply contribute no secrets, exactly as
|
|
78
|
+
* an unconfigured provider does. Never throws -- a redaction pass that failed
|
|
79
|
+
* closed would drop every tool result.
|
|
80
|
+
*/
|
|
81
|
+
export function loadPiAuth(agentDir: string = piAgentDir()): unknown {
|
|
82
|
+
try {
|
|
83
|
+
return JSON.parse(fs.readFileSync(path.join(agentDir, "auth.json"), "utf8"));
|
|
84
|
+
} catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Minimal structural shape for a pi tool-result content item. */
|
|
90
|
+
interface ContentItem {
|
|
91
|
+
type: string;
|
|
92
|
+
text?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Gather the concrete secret strings to scrub: every API key in the config
|
|
97
|
+
* (plaintext apiKey AND the apiKeyEncrypted blob, for LLM providers and Galaxy
|
|
98
|
+
* profiles) plus the known secret-valued env vars. Pure -- env is passed in so
|
|
99
|
+
* it's testable. `testerId` is deliberately not a secret, so it survives (the
|
|
100
|
+
* #189 path can read it without leaking keys). `extra` is for values a caller
|
|
101
|
+
* already holds that live in none of those places.
|
|
102
|
+
*/
|
|
103
|
+
export function collectSecretValues(
|
|
104
|
+
config: OrbitConfig,
|
|
105
|
+
env: Record<string, string | undefined>,
|
|
106
|
+
auth: unknown = null,
|
|
107
|
+
extra: readonly unknown[] = [],
|
|
108
|
+
): string[] {
|
|
109
|
+
const out = new Set<string>();
|
|
110
|
+
const add = (v: unknown): void => {
|
|
111
|
+
if (typeof v === "string" && v.length >= MIN_SECRET_LEN) out.add(v);
|
|
112
|
+
};
|
|
113
|
+
for (const p of Object.values(config.llm?.providers ?? {})) {
|
|
114
|
+
add(p?.apiKey);
|
|
115
|
+
add(p?.apiKeyEncrypted);
|
|
116
|
+
}
|
|
117
|
+
for (const p of Object.values(config.galaxy?.profiles ?? {})) {
|
|
118
|
+
add(p?.apiKey);
|
|
119
|
+
add(p?.apiKeyEncrypted);
|
|
120
|
+
}
|
|
121
|
+
for (const name of SECRET_ENV_VARS) add(env[name]);
|
|
122
|
+
// pi's auth.json: the one credential class Orbit cannot encrypt at rest, so
|
|
123
|
+
// value-redaction is the only backstop its tokens get.
|
|
124
|
+
for (const cred of Object.values((auth ?? {}) as Record<string, unknown>)) {
|
|
125
|
+
if (!cred || typeof cred !== "object") continue;
|
|
126
|
+
for (const [key, value] of Object.entries(cred as Record<string, unknown>)) {
|
|
127
|
+
if (AUTH_METADATA_KEYS.has(key)) continue;
|
|
128
|
+
if (typeof value === "string") add(value);
|
|
129
|
+
// An api-key credential nests provider-scoped config under `env`
|
|
130
|
+
// (Cloudflare account/gateway ids and the like), which can itself be secret.
|
|
131
|
+
else if (value && typeof value === "object")
|
|
132
|
+
for (const nested of Object.values(value as Record<string, unknown>)) add(nested);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
for (const v of extra) add(v);
|
|
136
|
+
return [...out];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Everything the redactor scrubs right now: the config's keys, the secret env
|
|
141
|
+
* vars, pi's auth.json where pi runs natively, the Galaxy key the transport
|
|
142
|
+
* holds, and whatever the shell's config source lists. `auth: false` leaves
|
|
143
|
+
* auth.json out: only the tool_result redactor has ever read it, and the
|
|
144
|
+
* activity log and lesson text keep the set they had.
|
|
145
|
+
*/
|
|
146
|
+
export function currentSecretValues({ auth = true }: { auth?: boolean } = {}): string[] {
|
|
147
|
+
const source = installedConfigSource();
|
|
148
|
+
// A shell that hands over the config hands over its secrets too; auth.json is pi's own store.
|
|
149
|
+
const piAuth = auth && !source ? loadPiAuth() : null;
|
|
150
|
+
return collectSecretValues(loadConfig(), process.env, piAuth, [
|
|
151
|
+
galaxyCredentials().apiKey,
|
|
152
|
+
...(source?.secrets?.() ?? []),
|
|
153
|
+
]);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Replace every occurrence of each known secret with the placeholder. Literal
|
|
158
|
+
* (no regex, so key characters can't be misread as patterns); longest-first so a
|
|
159
|
+
* key that contains a shorter one is scrubbed whole. Short/empty values ignored.
|
|
160
|
+
*/
|
|
161
|
+
export function redactSecrets(text: string, secrets: Iterable<string>): string {
|
|
162
|
+
let out = text;
|
|
163
|
+
const sorted = [...secrets]
|
|
164
|
+
.filter((s) => s.length >= MIN_SECRET_LEN)
|
|
165
|
+
.sort((a, b) => b.length - a.length);
|
|
166
|
+
for (const s of sorted) {
|
|
167
|
+
if (out.includes(s)) out = out.split(s).join(REDACTED);
|
|
168
|
+
}
|
|
169
|
+
return out;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Redact text items of a tool-result content array. Returns a changed copy, or
|
|
174
|
+
* `null` if nothing matched (so the caller can no-op). Non-text items (images)
|
|
175
|
+
* pass through untouched; the original array is never mutated.
|
|
176
|
+
*/
|
|
177
|
+
export function redactContent<T extends ContentItem>(content: T[], secrets: string[]): T[] | null {
|
|
178
|
+
if (secrets.length === 0) return null;
|
|
179
|
+
let changed = false;
|
|
180
|
+
const next = content.map((c) => {
|
|
181
|
+
if (c && c.type === "text" && typeof c.text === "string") {
|
|
182
|
+
const red = redactSecrets(c.text, secrets);
|
|
183
|
+
if (red !== c.text) {
|
|
184
|
+
changed = true;
|
|
185
|
+
return { ...c, text: red };
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return c;
|
|
189
|
+
});
|
|
190
|
+
return changed ? next : null;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Register the output-redaction hook. Runs after every tool and rewrites the
|
|
195
|
+
* result content the model receives, so a leaked key never reaches the provider.
|
|
196
|
+
* Reloads config each time so a key added mid-session is covered immediately;
|
|
197
|
+
* a clean result returns nothing (pi keeps the original).
|
|
198
|
+
*/
|
|
199
|
+
export function registerSecretRedaction(pi: ExtensionAPI): void {
|
|
200
|
+
pi.on("tool_result", async (event) => {
|
|
201
|
+
const secrets = currentSecretValues();
|
|
202
|
+
const content = redactContent(event.content, secrets);
|
|
203
|
+
// An in-process Galaxy result keeps its whole envelope here, and codemode hands it to the
|
|
204
|
+
// model's script; a spilled one previews only part of it in `content`.
|
|
205
|
+
const structured = event.structuredContent;
|
|
206
|
+
const scrubbed = structured === undefined ? undefined : redactValue(structured, secrets);
|
|
207
|
+
if (!content && scrubbed === structured) return;
|
|
208
|
+
return {
|
|
209
|
+
...(content ? { content } : {}),
|
|
210
|
+
...(scrubbed === undefined ? {} : { structuredContent: scrubbed }),
|
|
211
|
+
};
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/** `value` with every string redacted, or `value` itself when nothing matched. */
|
|
216
|
+
function redactValue<T>(value: T, secrets: string[]): T {
|
|
217
|
+
if (secrets.length === 0) return value;
|
|
218
|
+
if (typeof value === "string") return redactSecrets(value, secrets) as T;
|
|
219
|
+
if (Array.isArray(value)) {
|
|
220
|
+
const next = value.map((v) => redactValue(v, secrets));
|
|
221
|
+
return next.some((v, i) => v !== value[i]) ? (next as T) : value;
|
|
222
|
+
}
|
|
223
|
+
if (value && typeof value === "object") {
|
|
224
|
+
// What reaches the model is the serialized form, which an object's toJSON decides.
|
|
225
|
+
if (typeof (value as { toJSON?: unknown }).toJSON === "function") {
|
|
226
|
+
let plain: unknown;
|
|
227
|
+
try {
|
|
228
|
+
plain = JSON.parse(JSON.stringify(value));
|
|
229
|
+
} catch {
|
|
230
|
+
return value;
|
|
231
|
+
}
|
|
232
|
+
const r = redactValue(plain, secrets);
|
|
233
|
+
return r !== plain ? (r as T) : value;
|
|
234
|
+
}
|
|
235
|
+
let changed = false;
|
|
236
|
+
const next = Object.fromEntries(
|
|
237
|
+
Object.entries(value).map(([k, v]) => {
|
|
238
|
+
const key = redactSecrets(k, secrets);
|
|
239
|
+
const r = redactValue(v, secrets);
|
|
240
|
+
if (r !== v || key !== k) changed = true;
|
|
241
|
+
return [key, r];
|
|
242
|
+
}),
|
|
243
|
+
);
|
|
244
|
+
return changed ? (next as T) : value;
|
|
245
|
+
}
|
|
246
|
+
return value;
|
|
247
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pi.dev encodes each working directory as "--<path-with-slashes-as-dashes>--"
|
|
3
|
+
* and uses that as the per-cwd session directory name under ~/.pi/agent/sessions/.
|
|
4
|
+
*
|
|
5
|
+
* Lossy by design -- a cwd with a literal hyphen collides with one where a
|
|
6
|
+
* slash sat in the same position. This matches Pi's own on-disk encoding
|
|
7
|
+
* (see Pi's SessionManager.getDefaultSessionDir). Do not add escaping; the
|
|
8
|
+
* indexer needs to reproduce the exact directory name Pi writes.
|
|
9
|
+
*/
|
|
10
|
+
export function encodeCwd(cwd: string): string {
|
|
11
|
+
return `--${cwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function decodeCwd(encoded: string): string | null {
|
|
15
|
+
if (!encoded.startsWith("--") || !encoded.endsWith("--")) return null;
|
|
16
|
+
const inner = encoded.slice(2, -2);
|
|
17
|
+
return "/" + inner.replace(/-/g, "/");
|
|
18
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import Database, { type Database as Db } from "better-sqlite3";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { SCHEMA_SQL, SCHEMA_VERSION } from "./schema";
|
|
5
|
+
import { resolveStateDir } from "../../../shared/state-dir.js";
|
|
6
|
+
|
|
7
|
+
export { SCHEMA_VERSION };
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Open (and if needed rebuild) the session-index database.
|
|
11
|
+
*
|
|
12
|
+
* The index is a derived cache -- Pi's JSONL files are the source of truth --
|
|
13
|
+
* so a schema-version mismatch triggers a clean rebuild rather than a
|
|
14
|
+
* migration. Cheap because the next scan will repopulate.
|
|
15
|
+
*/
|
|
16
|
+
export function openIndexDb(filePath: string): Db {
|
|
17
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
18
|
+
let db = new Database(filePath);
|
|
19
|
+
db.pragma("journal_mode = WAL");
|
|
20
|
+
db.pragma("foreign_keys = ON");
|
|
21
|
+
|
|
22
|
+
const existing = isSchemaCurrent(db);
|
|
23
|
+
if (!existing) {
|
|
24
|
+
// Single-writer assumption: the session-index DB has one owner per user.
|
|
25
|
+
// If a second process opens between close() and the rmSync calls, its
|
|
26
|
+
// handle becomes invalid -- accepted tradeoff for a derived-cache layer.
|
|
27
|
+
db.close();
|
|
28
|
+
fs.rmSync(filePath, { force: true });
|
|
29
|
+
fs.rmSync(filePath + "-wal", { force: true });
|
|
30
|
+
fs.rmSync(filePath + "-shm", { force: true });
|
|
31
|
+
db = new Database(filePath);
|
|
32
|
+
db.pragma("journal_mode = WAL");
|
|
33
|
+
db.pragma("foreign_keys = ON");
|
|
34
|
+
db.exec(SCHEMA_SQL);
|
|
35
|
+
db.prepare("INSERT INTO meta(key, value) VALUES ('schema_version', ?)").run(
|
|
36
|
+
String(SCHEMA_VERSION),
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return db;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function isSchemaCurrent(db: Db): boolean {
|
|
43
|
+
try {
|
|
44
|
+
const row = db.prepare("SELECT value FROM meta WHERE key='schema_version'").get() as
|
|
45
|
+
{ value: string } | undefined;
|
|
46
|
+
return row?.value === String(SCHEMA_VERSION);
|
|
47
|
+
} catch {
|
|
48
|
+
// meta table doesn't exist yet
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Default location: <state dir>/sessions-index.db. */
|
|
54
|
+
export function defaultDbPath(): string {
|
|
55
|
+
return path.join(resolveStateDir(), "sessions-index.db");
|
|
56
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import type { Database as Db } from "better-sqlite3";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { parseSessionFile, type EntryRow, type ToolCallRow } from "./parse";
|
|
6
|
+
import { decodeCwd } from "./cwd";
|
|
7
|
+
|
|
8
|
+
export interface ScanReport {
|
|
9
|
+
sessionsSeen: number;
|
|
10
|
+
sessionsRemoved: number;
|
|
11
|
+
entriesInserted: number;
|
|
12
|
+
toolCallsInserted: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Default location of Pi's session corpus.
|
|
17
|
+
*/
|
|
18
|
+
export function defaultSessionsDir(): string {
|
|
19
|
+
return path.join(os.homedir(), ".pi", "agent", "sessions");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Incrementally synchronize the index DB against a sessions directory.
|
|
24
|
+
*
|
|
25
|
+
* Safe to call repeatedly. On the first call, indexes every file in bulk.
|
|
26
|
+
* Subsequent calls resume per-file from the stored byte offset; files
|
|
27
|
+
* whose mtime hasn't advanced are skipped. Sessions whose file has been
|
|
28
|
+
* deleted are removed from the index.
|
|
29
|
+
*/
|
|
30
|
+
export function scanSessions(db: Db, sessionsDir: string = defaultSessionsDir()): ScanReport {
|
|
31
|
+
const report: ScanReport = {
|
|
32
|
+
sessionsSeen: 0,
|
|
33
|
+
sessionsRemoved: 0,
|
|
34
|
+
entriesInserted: 0,
|
|
35
|
+
toolCallsInserted: 0,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
if (!fs.existsSync(sessionsDir)) return report;
|
|
39
|
+
|
|
40
|
+
const knownFiles = listJsonlFiles(sessionsDir);
|
|
41
|
+
const seenPaths = new Set(knownFiles);
|
|
42
|
+
|
|
43
|
+
// Stale-session cleanup (ON DELETE CASCADE handles entries + tool_calls)
|
|
44
|
+
const existing = db.prepare("SELECT session_id, file_path FROM sessions").all() as Array<{
|
|
45
|
+
session_id: string;
|
|
46
|
+
file_path: string;
|
|
47
|
+
}>;
|
|
48
|
+
const del = db.prepare("DELETE FROM sessions WHERE session_id = ?");
|
|
49
|
+
for (const row of existing) {
|
|
50
|
+
if (!seenPaths.has(row.file_path)) {
|
|
51
|
+
del.run(row.session_id);
|
|
52
|
+
report.sessionsRemoved++;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const selState = db.prepare(
|
|
57
|
+
"SELECT session_id, last_indexed_offset FROM sessions WHERE file_path = ?",
|
|
58
|
+
);
|
|
59
|
+
const upsertSession = db.prepare(`
|
|
60
|
+
INSERT INTO sessions(
|
|
61
|
+
session_id, file_path, cwd, name, parent_session, notebook_path,
|
|
62
|
+
created_at, last_indexed_at, last_indexed_offset
|
|
63
|
+
)
|
|
64
|
+
VALUES (@session_id, @file_path, @cwd, @name, @parent_session, @notebook_path,
|
|
65
|
+
@created_at, @last_indexed_at, @last_indexed_offset)
|
|
66
|
+
ON CONFLICT(session_id) DO UPDATE SET
|
|
67
|
+
name = COALESCE(excluded.name, sessions.name),
|
|
68
|
+
notebook_path = COALESCE(excluded.notebook_path, sessions.notebook_path),
|
|
69
|
+
last_indexed_at = excluded.last_indexed_at,
|
|
70
|
+
last_indexed_offset = excluded.last_indexed_offset
|
|
71
|
+
`);
|
|
72
|
+
const insEntry = db.prepare(`
|
|
73
|
+
INSERT OR IGNORE INTO entries(
|
|
74
|
+
entry_id, session_id, parent_id, entry_type, timestamp, role, text_content, raw_json
|
|
75
|
+
) VALUES (@entry_id, @session_id, @parent_id, @entry_type, @timestamp, @role, @text_content, @raw_json)
|
|
76
|
+
`);
|
|
77
|
+
const insTc = db.prepare(`
|
|
78
|
+
INSERT OR IGNORE INTO tool_calls(entry_id, session_id, tool_use_id, tool_name, arguments_json, result_text)
|
|
79
|
+
VALUES (@entry_id, @session_id, @tool_use_id, @tool_name, @arguments_json, @result_text)
|
|
80
|
+
`);
|
|
81
|
+
|
|
82
|
+
const indexOne = db.transaction((filePath: string) => {
|
|
83
|
+
const prior = selState.get(filePath) as
|
|
84
|
+
{ session_id: string; last_indexed_offset: number } | undefined;
|
|
85
|
+
const startOffset = prior?.last_indexed_offset ?? 0;
|
|
86
|
+
const fileSize = fs.statSync(filePath).size;
|
|
87
|
+
if (prior && startOffset >= fileSize) return;
|
|
88
|
+
|
|
89
|
+
const parsed = parseSessionFile(filePath, {
|
|
90
|
+
startOffset,
|
|
91
|
+
skipHeader: startOffset > 0,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Decode cwd from directory name (fallback to header.cwd when decode fails)
|
|
95
|
+
const enclosingDir = path.basename(path.dirname(filePath));
|
|
96
|
+
const cwd = decodeCwd(enclosingDir) ?? parsed.header.cwd ?? "";
|
|
97
|
+
|
|
98
|
+
const sessionId = prior?.session_id ?? parsed.header.id;
|
|
99
|
+
if (!sessionId) return;
|
|
100
|
+
|
|
101
|
+
upsertSession.run({
|
|
102
|
+
session_id: sessionId,
|
|
103
|
+
file_path: filePath,
|
|
104
|
+
cwd,
|
|
105
|
+
name: parsed.sessionName,
|
|
106
|
+
parent_session: parsed.header.parentSession,
|
|
107
|
+
notebook_path: parsed.notebookPath,
|
|
108
|
+
created_at: parsed.header.createdAt || new Date().toISOString(),
|
|
109
|
+
last_indexed_at: new Date().toISOString(),
|
|
110
|
+
last_indexed_offset: parsed.endOffset,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
for (const entry of parsed.entries) {
|
|
114
|
+
const info = insEntry.run({
|
|
115
|
+
...entry,
|
|
116
|
+
session_id: sessionId,
|
|
117
|
+
} as EntryRow & { session_id: string });
|
|
118
|
+
if (info.changes > 0) report.entriesInserted++;
|
|
119
|
+
}
|
|
120
|
+
for (const tc of parsed.tool_calls) {
|
|
121
|
+
const info = insTc.run({
|
|
122
|
+
...tc,
|
|
123
|
+
session_id: sessionId,
|
|
124
|
+
} as ToolCallRow & { session_id: string });
|
|
125
|
+
if (info.changes > 0) report.toolCallsInserted++;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
report.sessionsSeen++;
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
for (const fp of knownFiles) {
|
|
132
|
+
try {
|
|
133
|
+
indexOne(fp);
|
|
134
|
+
} catch {
|
|
135
|
+
// Broken file -- skip, don't halt the scan
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return report;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function listJsonlFiles(root: string): string[] {
|
|
143
|
+
const out: string[] = [];
|
|
144
|
+
for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
|
|
145
|
+
if (!entry.isDirectory()) continue;
|
|
146
|
+
const sub = path.join(root, entry.name);
|
|
147
|
+
for (const file of fs.readdirSync(sub, { withFileTypes: true })) {
|
|
148
|
+
if (!file.isFile()) continue;
|
|
149
|
+
if (!file.name.endsWith(".jsonl")) continue;
|
|
150
|
+
out.push(path.join(sub, file.name));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return out;
|
|
154
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { loadConfig } from "../config";
|
|
2
|
+
import { readEnv } from "../../../shared/orbit-env.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Whether the experimental session-index tools are opted in.
|
|
6
|
+
*
|
|
7
|
+
* Resolution order mirrors isTeamDispatchEnabled():
|
|
8
|
+
* 1. LOOM_SESSION_INDEX env var -- "1" -> on, "0" -> off, else defer.
|
|
9
|
+
* 2. config.experiments.sessionIndex -- boolean.
|
|
10
|
+
* 3. Default: off.
|
|
11
|
+
*/
|
|
12
|
+
export function isSessionIndexEnabled(): boolean {
|
|
13
|
+
const env = readEnv("SESSION_INDEX");
|
|
14
|
+
if (env === "1") return true;
|
|
15
|
+
if (env === "0") return false;
|
|
16
|
+
return loadConfig().experiments?.sessionIndex === true;
|
|
17
|
+
}
|