firedrill-run 2.2.5 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +178 -22
- package/bin/firedrill.mjs +29 -5
- package/dist/assembly.json +13 -0
- package/dist/cli/runtime/candidate_copy.py +395 -0
- package/dist/cli/runtime/source_snapshot.py +391 -0
- package/dist/cli/src/administration.js +295 -0
- package/dist/cli/src/agent-changes.js +496 -0
- package/dist/cli/src/assessment-requests.js +67 -0
- package/dist/cli/src/auth.js +465 -0
- package/dist/cli/src/billing-commerce-contracts.js +1 -0
- package/dist/cli/src/billing-usage.js +227 -0
- package/dist/cli/src/billing-wallet-contracts.js +1 -0
- package/dist/cli/src/billing.js +170 -0
- package/dist/cli/src/bootstrap-process-lock.js +136 -0
- package/dist/cli/src/browser-links.js +14 -0
- package/dist/cli/src/campaign-controls.js +122 -0
- package/dist/cli/src/campaign-diagnoses.js +118 -0
- package/dist/cli/src/campaign-reports.js +1215 -0
- package/dist/cli/src/campaign-world.js +156 -0
- package/dist/cli/src/candidate-copy.js +376 -0
- package/dist/cli/src/catalog-contracts.js +1 -0
- package/dist/cli/src/ci-access-contracts.js +1 -0
- package/dist/cli/src/ci-configuration-contracts.js +1 -0
- package/dist/cli/src/ci-coverage.js +64 -0
- package/dist/cli/src/ci-delivery-contracts.js +1 -0
- package/dist/cli/src/ci-result-contracts.js +1 -0
- package/dist/cli/src/ci-run-contracts.js +1 -0
- package/dist/cli/src/ci-setup-proposals.js +52 -0
- package/dist/cli/src/company-policies.js +229 -0
- package/dist/cli/src/completion.js +79 -0
- package/dist/cli/src/configuration-intents.js +277 -0
- package/dist/cli/src/configuration.js +369 -0
- package/dist/cli/src/continuous-simulation.js +277 -0
- package/dist/cli/src/coordinated-checkpoints.js +133 -0
- package/dist/cli/src/credential-mode.js +139 -0
- package/dist/cli/src/credentials.js +331 -0
- package/dist/cli/src/credit-format.js +8 -0
- package/dist/cli/src/dataset-contracts.js +1 -0
- package/dist/cli/src/dataset-export.js +154 -0
- package/dist/cli/src/dataset-reads.js +37 -0
- package/dist/cli/src/dependency-preparation.js +239 -0
- package/dist/cli/src/director-tool-setup.js +104 -0
- package/dist/cli/src/driver-review.js +225 -0
- package/dist/cli/src/evaluation-authoring.js +315 -0
- package/dist/cli/src/evidence-bundles.js +367 -0
- package/dist/cli/src/execution-proposals.js +36 -0
- package/dist/cli/src/http.js +302 -0
- package/dist/cli/src/local-container-boundary.js +38 -0
- package/dist/cli/src/local-container-policy.js +201 -0
- package/dist/cli/src/local-execution-setup.js +81 -0
- package/dist/cli/src/local-source-basis.js +73 -0
- package/dist/cli/src/local-source.js +66 -0
- package/dist/cli/src/local-value-store.js +91 -0
- package/dist/cli/src/local-values.js +163 -0
- package/dist/cli/src/login-organizations.js +70 -0
- package/dist/cli/src/main.js +1622 -0
- package/dist/cli/src/mcp-connection.js +109 -0
- package/dist/cli/src/native/bindings.js +137 -0
- package/dist/cli/src/native/canonical.js +370 -0
- package/dist/cli/src/native/cloud-resources.js +942 -0
- package/dist/cli/src/native/companion-channel.js +421 -0
- package/dist/cli/src/native/companion-ipc.js +473 -0
- package/dist/cli/src/native/contracts.js +218 -0
- package/dist/cli/src/native/control-plane.js +1354 -0
- package/dist/cli/src/native/credit-approval.js +15 -0
- package/dist/cli/src/native/dependency-proxy.js +1006 -0
- package/dist/cli/src/native/drill-cleanup.js +115 -0
- package/dist/cli/src/native/drill-runner.js +1562 -0
- package/dist/cli/src/native/drivers/action-trace.js +210 -0
- package/dist/cli/src/native/drivers/function-wrapper.js +152 -0
- package/dist/cli/src/native/drivers/http.js +442 -0
- package/dist/cli/src/native/drivers/index.js +47 -0
- package/dist/cli/src/native/drivers/jsonl-process.js +538 -0
- package/dist/cli/src/native/drivers/playwright.js +600 -0
- package/dist/cli/src/native/drivers/signed-event.js +244 -0
- package/dist/cli/src/native/drivers/types.js +578 -0
- package/dist/cli/src/native/evidence-filter.js +255 -0
- package/dist/cli/src/native/isolated-access.js +241 -0
- package/dist/cli/src/native/library-sharing.js +220 -0
- package/dist/cli/src/native/local-run.js +667 -0
- package/dist/cli/src/native/local-secrets.js +19 -0
- package/dist/cli/src/native/mcp-config.js +123 -0
- package/dist/cli/src/native/metadata-requests.js +120 -0
- package/dist/cli/src/native/observations.js +1159 -0
- package/dist/cli/src/native/owned-groups.js +46 -0
- package/dist/cli/src/native/plan.js +594 -0
- package/dist/cli/src/native/png.js +159 -0
- package/dist/cli/src/native/ports.js +43 -0
- package/dist/cli/src/native/readiness.js +139 -0
- package/dist/cli/src/native/reassessments.js +206 -0
- package/dist/cli/src/native/redaction.js +235 -0
- package/dist/cli/src/native/registration.js +155 -0
- package/dist/cli/src/native/roots.js +110 -0
- package/dist/cli/src/native/run-cleanup.js +199 -0
- package/dist/cli/src/native/scratch.js +117 -0
- package/dist/cli/src/native/screenshots.js +60 -0
- package/dist/cli/src/native/session.js +556 -0
- package/dist/cli/src/native/standalone-proxy.js +580 -0
- package/dist/cli/src/native/standalone-renewals.js +183 -0
- package/dist/cli/src/native/standalone-state.js +193 -0
- package/dist/cli/src/native/standalone-tools.js +187 -0
- package/dist/cli/src/native/supervisor.js +831 -0
- package/dist/cli/src/native/target-auth.js +161 -0
- package/dist/cli/src/native/target-state.js +330 -0
- package/dist/cli/src/native/tool-reuse.js +364 -0
- package/dist/cli/src/native/tool-setups.js +336 -0
- package/dist/cli/src/native/world-reuse.js +288 -0
- package/dist/cli/src/onboarding.js +23 -0
- package/dist/cli/src/priority-requests.js +70 -0
- package/dist/cli/src/priority.js +223 -0
- package/dist/cli/src/prompts.js +184 -0
- package/dist/cli/src/real-operations.js +221 -0
- package/dist/cli/src/recipe-intents.js +58 -0
- package/dist/cli/src/recorded-context-intents.js +59 -0
- package/dist/cli/src/recorded-context.js +248 -0
- package/dist/cli/src/recordings.js +69 -0
- package/dist/cli/src/registration-guide.js +39 -0
- package/dist/cli/src/report-exports.js +213 -0
- package/dist/cli/src/request-input.js +47 -0
- package/dist/cli/src/resource-lifecycle.js +141 -0
- package/dist/cli/src/revision-requests.js +55 -0
- package/dist/cli/src/runner-abandon.js +53 -0
- package/dist/cli/src/runner-campaign-controls.js +262 -0
- package/dist/cli/src/runner-claim-reads.js +36 -0
- package/dist/cli/src/runner-completion.js +65 -0
- package/dist/cli/src/runner-configuration.js +546 -0
- package/dist/cli/src/runner-container.js +794 -0
- package/dist/cli/src/runner-evidence-erasure.js +351 -0
- package/dist/cli/src/runner-evidence-privacy.js +37 -0
- package/dist/cli/src/runner-evidence-retention.js +161 -0
- package/dist/cli/src/runner-evidence.js +326 -0
- package/dist/cli/src/runner-execute.js +92 -0
- package/dist/cli/src/runner-execution-deadline.js +25 -0
- package/dist/cli/src/runner-grants.js +307 -0
- package/dist/cli/src/runner-identity.js +615 -0
- package/dist/cli/src/runner-inputs.js +308 -0
- package/dist/cli/src/runner-jobs.js +49 -0
- package/dist/cli/src/runner-model-transport.js +392 -0
- package/dist/cli/src/runner-ownership.js +332 -0
- package/dist/cli/src/runner-process-lock.js +175 -0
- package/dist/cli/src/runner-runtime.js +396 -0
- package/dist/cli/src/runner-session-channel.js +377 -0
- package/dist/cli/src/runner-trial-completion.js +34 -0
- package/dist/cli/src/runner-trial-journal.js +358 -0
- package/dist/cli/src/runner-trial-live.js +393 -0
- package/dist/cli/src/runner-trial-protocol.js +289 -0
- package/dist/cli/src/runner-trial-sync.js +110 -0
- package/dist/cli/src/runner-trial-transfer.js +107 -0
- package/dist/cli/src/runner-voice.js +40 -0
- package/dist/cli/src/runner-world-claim.js +21 -0
- package/dist/cli/src/runner-world-collector.js +159 -0
- package/dist/cli/src/runner-world-command-evidence.js +487 -0
- package/dist/cli/src/runner-world-commands.js +268 -0
- package/dist/cli/src/runner-world-completion.js +76 -0
- package/dist/cli/src/runner-world-erasure.js +95 -0
- package/dist/cli/src/runner-world-evidence-sync.js +91 -0
- package/dist/cli/src/runner-world-journal.js +510 -0
- package/dist/cli/src/runner-world-native-filters.js +134 -0
- package/dist/cli/src/runner-world-observations.js +50 -0
- package/dist/cli/src/runner-world-session-protocol.js +134 -0
- package/dist/cli/src/saved-records.js +40 -0
- package/dist/cli/src/scenario-authoring.js +212 -0
- package/dist/cli/src/scenario-discovery.js +216 -0
- package/dist/cli/src/scenario-paths.js +68 -0
- package/dist/cli/src/scenario-requests.js +4 -0
- package/dist/cli/src/service-receipts.js +105 -0
- package/dist/cli/src/simple/authoring.js +270 -0
- package/dist/cli/src/simple/credit-approval.js +16 -0
- package/dist/cli/src/simple/help.js +98 -0
- package/dist/cli/src/simple/init.js +61 -0
- package/dist/cli/src/simple/library-sharing.js +414 -0
- package/dist/cli/src/simple/metadata-requests.js +46 -0
- package/dist/cli/src/simple/native-report.js +841 -0
- package/dist/cli/src/simple/native-tools.js +780 -0
- package/dist/cli/src/simple/plan-apply.js +506 -0
- package/dist/cli/src/simple/reassessment.js +323 -0
- package/dist/cli/src/simple/register.js +123 -0
- package/dist/cli/src/simple/run.js +122 -0
- package/dist/cli/src/simple/status.js +49 -0
- package/dist/cli/src/simple/tool-renewal.js +308 -0
- package/dist/cli/src/simple/tool-reuse.js +526 -0
- package/dist/cli/src/simple/tool-start-catalog.js +100 -0
- package/dist/cli/src/simple/tool-state.js +426 -0
- package/dist/cli/src/simple/tools-author.js +222 -0
- package/dist/cli/src/simple/watch.js +28 -0
- package/dist/cli/src/simple/world-reuse.js +586 -0
- package/dist/cli/src/simulation-intents.js +406 -0
- package/dist/cli/src/simulation-run.js +1058 -0
- package/dist/cli/src/source-batch.js +322 -0
- package/dist/cli/src/source-connection.js +451 -0
- package/dist/cli/src/source-runtime.js +346 -0
- package/dist/cli/src/source-selection-intents.js +75 -0
- package/dist/cli/src/source-sets.js +214 -0
- package/dist/cli/src/target-models.js +109 -0
- package/dist/cli/src/tool-catalog.js +224 -0
- package/dist/cli/src/tool-command-contracts.js +1 -0
- package/dist/cli/src/tool-command-export.js +245 -0
- package/dist/cli/src/tool-connection-contracts.js +1 -0
- package/dist/cli/src/tool-connection-reads.js +23 -0
- package/dist/cli/src/tool-contributions.js +58 -0
- package/dist/cli/src/tool-data.js +116 -0
- package/dist/cli/src/tool-datasets.js +176 -0
- package/dist/cli/src/tool-group-contracts.js +1 -0
- package/dist/cli/src/tool-group-reads.js +26 -0
- package/dist/cli/src/tool-group-state.js +147 -0
- package/dist/cli/src/tool-groups.js +311 -0
- package/dist/cli/src/tool-instances.js +186 -0
- package/dist/cli/src/tool-lifecycle-contracts.js +1 -0
- package/dist/cli/src/tool-lifecycle-reads.js +30 -0
- package/dist/cli/src/tool-lifecycle.js +323 -0
- package/dist/cli/src/tool-package-contracts.js +1 -0
- package/dist/cli/src/tool-package-reads.js +41 -0
- package/dist/cli/src/tool-records.js +53 -0
- package/dist/cli/src/tool-runtime.js +96 -0
- package/dist/cli/src/tool-state-contracts.js +1 -0
- package/dist/cli/src/tool-state-reads.js +31 -0
- package/dist/cli/src/tools.js +306 -0
- package/dist/cli/src/trial-actions.js +93 -0
- package/dist/cli/src/trial-checkpoints.js +133 -0
- package/dist/cli/src/trial-checks.js +70 -0
- package/dist/cli/src/trial-state.js +197 -0
- package/dist/cli/src/vault.js +266 -0
- package/dist/cli/src/workspace-registration.js +383 -0
- package/dist/cli/src/workspace-team-contracts.js +1 -0
- package/dist/cli/src/world-access.js +231 -0
- package/dist/cli/src/world-agent.js +4 -0
- package/dist/cli/src/world-checkpoint-scopes.js +15 -0
- package/dist/cli/src/world-contracts.js +6 -0
- package/dist/cli/src/world-creation.js +201 -0
- package/dist/cli/src/world-datasets.js +207 -0
- package/dist/cli/src/world-inspection.js +257 -0
- package/dist/cli/src/world-recipes.js +103 -0
- package/dist/cli/src/world-requests.js +241 -0
- package/dist/cli/src/world-session-checkpoints.js +196 -0
- package/dist/cli/src/world-session-lifecycle.js +207 -0
- package/dist/cli/src/world-session-requests.js +215 -0
- package/dist/cli/src/world-session-state.js +145 -0
- package/dist/cli/src/world-session-voice.js +66 -0
- package/dist/cli/src/world-sessions.js +288 -0
- package/dist/cli/src/world-stream.js +99 -0
- package/dist/cli/src/world-time-report.js +58 -0
- package/dist/contracts/agent-change-contracts.js +75 -0
- package/dist/contracts/agent-execution-contracts.js +38 -0
- package/dist/contracts/application-state-contracts.js +26 -0
- package/dist/contracts/assessment-aggregate-contracts.js +15 -0
- package/dist/contracts/assessment-contracts.js +74 -0
- package/dist/contracts/billing-commerce-contracts.js +107 -0
- package/dist/contracts/billing-wallet-contracts.js +43 -0
- package/dist/contracts/campaign-lifecycle.js +1 -0
- package/dist/contracts/campaign-world-contracts.js +80 -0
- package/dist/contracts/catalog-contracts.js +73 -0
- package/dist/contracts/ci-access-contracts.js +68 -0
- package/dist/contracts/ci-configuration-contracts.js +88 -0
- package/dist/contracts/ci-coverage-contracts.js +65 -0
- package/dist/contracts/ci-coverage-labels.js +25 -0
- package/dist/contracts/ci-delivery-contracts.js +61 -0
- package/dist/contracts/ci-result-contracts.js +103 -0
- package/dist/contracts/ci-run-contracts.js +51 -0
- package/dist/contracts/ci-setup-contracts.js +88 -0
- package/dist/contracts/clip-contracts.js +32 -0
- package/dist/contracts/comparison-contracts.js +53 -0
- package/dist/contracts/composite-contracts.js +34 -0
- package/dist/contracts/context-contracts.js +76 -0
- package/dist/contracts/continuation-report-contracts.js +1 -0
- package/dist/contracts/continuity-requirements.js +8 -0
- package/dist/contracts/coordinated-checkpoint-contracts.js +34 -0
- package/dist/contracts/dataset-contracts.js +88 -0
- package/dist/contracts/dependency-decision-contracts.js +36 -0
- package/dist/contracts/dependency-protocol-contracts.js +43 -0
- package/dist/contracts/director-execution.js +51 -0
- package/dist/contracts/driver-review-contracts.js +99 -0
- package/dist/contracts/evidence-contracts.js +65 -0
- package/dist/contracts/evidence-coverage-contracts.js +10 -0
- package/dist/contracts/export-contracts.js +44 -0
- package/dist/contracts/github-directory-contracts.js +96 -0
- package/dist/contracts/insight-contracts.js +11 -0
- package/dist/contracts/inspection-contracts.js +1 -0
- package/dist/contracts/local-claim-contracts.js +39 -0
- package/dist/contracts/local-configuration-contracts.js +7 -0
- package/dist/contracts/local-evidence-contracts.js +32 -0
- package/dist/contracts/local-grant-contracts.js +83 -0
- package/dist/contracts/local-input-contracts.js +19 -0
- package/dist/contracts/local-runner-contracts.js +42 -0
- package/dist/contracts/local-trial-live-contracts.js +16 -0
- package/dist/contracts/local-value-source-contracts.js +92 -0
- package/dist/contracts/local-world-native-contracts.js +8 -0
- package/dist/contracts/mcp-contracts.js +42 -0
- package/dist/contracts/media-contracts.js +28 -0
- package/dist/contracts/native-check-contracts.js +31 -0
- package/dist/contracts/native-identity-contracts.js +52 -0
- package/dist/contracts/onboarding-contracts.js +32 -0
- package/dist/contracts/performance-contracts.js +85 -0
- package/dist/contracts/planning-contracts.js +81 -0
- package/dist/contracts/real-operation-contracts.js +30 -0
- package/dist/contracts/recommendation-contracts.js +54 -0
- package/dist/contracts/report-contracts.js +1 -0
- package/dist/contracts/resource-lifecycle-contracts.js +57 -0
- package/dist/contracts/revision-contracts.js +12 -0
- package/dist/contracts/revision-request-contracts.js +39 -0
- package/dist/contracts/saved-record-contracts.js +76 -0
- package/dist/contracts/scenario-draft-comparison.js +91 -0
- package/dist/contracts/scenario-world-contracts.js +14 -0
- package/dist/contracts/service-contracts.js +1 -0
- package/dist/contracts/session-command-contracts.js +56 -0
- package/dist/contracts/session-contracts.js +65 -0
- package/dist/contracts/session-state-contracts.js +67 -0
- package/dist/contracts/session-voice-contracts.js +45 -0
- package/dist/contracts/source-set-contracts.js +26 -0
- package/dist/contracts/source-upload-contracts.js +22 -0
- package/dist/contracts/tool-command-contracts.js +57 -0
- package/dist/contracts/tool-connection-contracts.js +87 -0
- package/dist/contracts/tool-contribution-contracts.js +35 -0
- package/dist/contracts/tool-group-contracts.js +53 -0
- package/dist/contracts/tool-group-state-contracts.js +63 -0
- package/dist/contracts/tool-lifecycle-contracts.js +94 -0
- package/dist/contracts/tool-package-contracts.js +91 -0
- package/dist/contracts/tool-protocol-contracts.js +71 -0
- package/dist/contracts/tool-runtime-billing-contracts.js +28 -0
- package/dist/contracts/tool-setup-proposal.js +59 -0
- package/dist/contracts/tool-state-contracts.js +79 -0
- package/dist/contracts/trial-state-contracts.js +30 -0
- package/dist/contracts/typescript/agent-change.js +1 -0
- package/dist/contracts/typescript/assessment-aggregate.js +1 -0
- package/dist/contracts/typescript/assessment.js +1 -0
- package/dist/contracts/typescript/billing-commerce.js +1 -0
- package/dist/contracts/typescript/campaigns.js +1 -0
- package/dist/contracts/typescript/catalog.js +1 -0
- package/dist/contracts/typescript/ci-access.js +1 -0
- package/dist/contracts/typescript/ci-configuration.js +1 -0
- package/dist/contracts/typescript/ci-delivery.js +1 -0
- package/dist/contracts/typescript/ci-result.js +1 -0
- package/dist/contracts/typescript/ci-runs.js +1 -0
- package/dist/contracts/typescript/clips.js +1 -0
- package/dist/contracts/typescript/comparison.js +1 -0
- package/dist/contracts/typescript/composite.js +1 -0
- package/dist/contracts/typescript/connections.js +1 -0
- package/dist/contracts/typescript/context.js +1 -0
- package/dist/contracts/typescript/datasets.js +1 -0
- package/dist/contracts/typescript/evidence-coverage.js +1 -0
- package/dist/contracts/typescript/export.js +1 -0
- package/dist/contracts/typescript/github-directory.js +1 -0
- package/dist/contracts/typescript/insight.js +1 -0
- package/dist/contracts/typescript/inspection.js +1 -0
- package/dist/contracts/typescript/intake.js +1 -0
- package/dist/contracts/typescript/local-claim.js +1 -0
- package/dist/contracts/typescript/local-configuration.js +1 -0
- package/dist/contracts/typescript/local-evidence.js +1 -0
- package/dist/contracts/typescript/local-grant.js +1 -0
- package/dist/contracts/typescript/local-input.js +1 -0
- package/dist/contracts/typescript/local-runner.js +1 -0
- package/dist/contracts/typescript/local-trial-live.js +1 -0
- package/dist/contracts/typescript/local-value-source.js +1 -0
- package/dist/contracts/typescript/local-world-native.js +1 -0
- package/dist/contracts/typescript/mcp.js +1 -0
- package/dist/contracts/typescript/media.js +1 -0
- package/dist/contracts/typescript/native-check.js +1 -0
- package/dist/contracts/typescript/native-identity.js +1 -0
- package/dist/contracts/typescript/onboarding.js +1 -0
- package/dist/contracts/typescript/performance.js +1 -0
- package/dist/contracts/typescript/planning.js +1 -0
- package/dist/contracts/typescript/preparation.js +1 -0
- package/dist/contracts/typescript/real-operation.js +1 -0
- package/dist/contracts/typescript/recommendation.js +1 -0
- package/dist/contracts/typescript/reports.js +1 -0
- package/dist/contracts/typescript/resource-lifecycle.js +1 -0
- package/dist/contracts/typescript/saved-record.js +1 -0
- package/dist/contracts/typescript/scenarios.js +1 -0
- package/dist/contracts/typescript/services.js +1 -0
- package/dist/contracts/typescript/session-command.js +1 -0
- package/dist/contracts/typescript/session-state.js +1 -0
- package/dist/contracts/typescript/session-voice.js +1 -0
- package/dist/contracts/typescript/session.js +1 -0
- package/dist/contracts/typescript/tool-command.js +1 -0
- package/dist/contracts/typescript/tool-connection.js +1 -0
- package/dist/contracts/typescript/tool-contribution.js +1 -0
- package/dist/contracts/typescript/tool-groups.js +1 -0
- package/dist/contracts/typescript/tool-lifecycle.js +1 -0
- package/dist/contracts/typescript/tool-package.js +1 -0
- package/dist/contracts/typescript/tool-state.js +1 -0
- package/dist/contracts/typescript/trial-state.js +1 -0
- package/dist/contracts/typescript/vault.js +1 -0
- package/dist/contracts/typescript/workspace-team.js +1 -0
- package/dist/contracts/typescript/world-stream.js +1 -0
- package/dist/contracts/workspace-team-contracts.js +55 -0
- package/dist/contracts/world-command.js +65 -0
- package/dist/contracts/world-lifetime-contracts.js +74 -0
- package/dist/contracts/world-recipe-contracts.js +27 -0
- package/dist/contracts/world-stream-contracts.js +27 -0
- package/dist/package.json +1 -0
- package/package.json +16 -16
- package/LICENSE.md +0 -23
- package/PACKAGING.json +0 -50
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool definition reuse (Plan20 R10; root `native_tool_reuse.py`,
|
|
3
|
+
* `native_tool_reuse_views.py`, contract `accounts/native_tool_reuse_catalog.py`,
|
|
4
|
+
* base `/native-tool-definitions`).
|
|
5
|
+
*
|
|
6
|
+
* - Sharing is per exact inspected tool version, with workspaces of the same
|
|
7
|
+
* organization only. An administrator of the owner workspace shares, reads
|
|
8
|
+
* or withdraws an original sharing request, and revokes. The owner
|
|
9
|
+
* workspace lists its grants.
|
|
10
|
+
* - A grant shares the definition only. It never shares a running instance,
|
|
11
|
+
* session, state, credentials or runtime rights.
|
|
12
|
+
* - Using a shared version always needs an exact private copy: the package is
|
|
13
|
+
* copied server-side into this workspace (pending → copying → copied) and
|
|
14
|
+
* then inspected here like any upload. "copied" is not ready: the copy is
|
|
15
|
+
* usable only once its own inspection finishes with a new private version.
|
|
16
|
+
* This is not a tool's archive or state fork.
|
|
17
|
+
* - Request keys: the same key returns the original. A lost answer is read
|
|
18
|
+
* back by its key, or the request is withdrawn so it can never land.
|
|
19
|
+
* Nothing here starts an instance, runs anything or spends anything.
|
|
20
|
+
*/
|
|
21
|
+
import { api } from '../auth.js';
|
|
22
|
+
import { CliError } from '../http.js';
|
|
23
|
+
import { SHA256_HEX } from './contracts.js';
|
|
24
|
+
export const TOOL_COPY_STATES = ['pending', 'copying', 'copied', 'rejected', 'withdrawn'];
|
|
25
|
+
export const TOOL_UPLOAD_STATES = ['uploading', 'inspecting', 'inspected', 'rejected', 'withdrawn'];
|
|
26
|
+
export const TOOL_DEPENDENT_KINDS = ['world', 'fork'];
|
|
27
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
28
|
+
const RESPONSE_LIMIT = 4 * 1024 * 1024;
|
|
29
|
+
const PAGE = 25;
|
|
30
|
+
const PAGE_KEYS = 'count,next,page,page_size,previous,results';
|
|
31
|
+
const DEFINITION_KEYS = ['archive_sha256', 'can_fork', 'contract_digest', 'description', 'id', 'inspected_at', 'interfaces', 'key', 'name',
|
|
32
|
+
'operation_count', 'owner_workspace_id', 'reuse_requires_private_copy', 'revoked_at', 'runtime_started', 'service_count', 'state', 'tool_id',
|
|
33
|
+
'version', 'workspace_id'];
|
|
34
|
+
const SUMMARY_KEYS = DEFINITION_KEYS.join(',');
|
|
35
|
+
const DETAIL_KEYS = [...DEFINITION_KEYS, 'inspection', 'services'].sort().join(',');
|
|
36
|
+
const GRANT_KEYS = 'allow_use,created_at,id,implementation_id,recipient_workspace_id,request_key,revoked_at';
|
|
37
|
+
const COPY_KEYS = 'archive_sha256,cleanup_pending,contract_digest,created_at,finished_at,id,problem,request_key,runtime_started,source_implementation_id,state,'
|
|
38
|
+
+ 'upload,workspace_id';
|
|
39
|
+
const UPLOAD_KEYS = 'actor_id,can_upload,can_withdraw,catalog_setup_id,catalog_setup_request_key,expires_at,filename,finished_at,id,implementation_id,'
|
|
40
|
+
+ 'problem,request_key,sha256,size,state,submitted_at,withdrawn_at,workspace_id';
|
|
41
|
+
const object = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
42
|
+
const uuid = (value) => typeof value === 'string' && UUID.test(value);
|
|
43
|
+
const sha = (value) => typeof value === 'string' && SHA256_HEX.test(value);
|
|
44
|
+
const time = (value) => typeof value === 'string' && Number.isFinite(Date.parse(value));
|
|
45
|
+
const maybe = (check) => (value) => value === null || check(value);
|
|
46
|
+
const count = (value) => value === null || (Number.isSafeInteger(value) && value >= 0);
|
|
47
|
+
const keys = (value) => Object.keys(value).sort().join(',');
|
|
48
|
+
const lower = (value) => value === null ? null : value.toLowerCase();
|
|
49
|
+
const unconfirmed = (what) => new CliError('native_response_unconfirmed', `The ${what} response could not be confirmed. Nothing further was sent for it.`);
|
|
50
|
+
const scoped = (scope, signal) => ({ actor: scope.owner, workspace: scope.workspace, signal, maximumResponseBytes: RESPONSE_LIMIT });
|
|
51
|
+
const base = (scope) => `/api/workspaces/${scope.workspace}/native-tool-definitions`;
|
|
52
|
+
/** A UUID argument exactly as Firedrill printed it, lowercased. */
|
|
53
|
+
export function toolReuseId(value, label) {
|
|
54
|
+
if (!uuid(value))
|
|
55
|
+
throw new CliError('arguments_invalid', `Use the ${label} exactly as Firedrill printed it. Nothing was sent.`, 2);
|
|
56
|
+
return value.toLowerCase();
|
|
57
|
+
}
|
|
58
|
+
function pageNumber(value) {
|
|
59
|
+
const page = value ?? 1;
|
|
60
|
+
if (!Number.isSafeInteger(page) || page < 1)
|
|
61
|
+
throw new CliError('arguments_invalid', 'Use --page with a positive page number.', 2);
|
|
62
|
+
return page;
|
|
63
|
+
}
|
|
64
|
+
function searchParams(page, search) {
|
|
65
|
+
const params = new URLSearchParams({ page: String(page), page_size: String(PAGE) });
|
|
66
|
+
if (search !== undefined) {
|
|
67
|
+
// Root counts characters (code points), not UTF-16 units.
|
|
68
|
+
if ([...search].length > 120)
|
|
69
|
+
throw new CliError('arguments_invalid', 'Use a name prefix of up to 120 characters.', 2);
|
|
70
|
+
if (search)
|
|
71
|
+
params.set('q', search);
|
|
72
|
+
}
|
|
73
|
+
return params;
|
|
74
|
+
}
|
|
75
|
+
/** Root's standard page envelope for the 25-row page that was asked for. */
|
|
76
|
+
function pageOf(raw, page, row, what) {
|
|
77
|
+
if (!object(raw) || keys(raw) !== PAGE_KEYS || !Number.isSafeInteger(raw.count) || raw.count < 0 || raw.page !== page
|
|
78
|
+
|| raw.page_size !== PAGE || (raw.next !== null && typeof raw.next !== 'string') || (raw.previous !== null && typeof raw.previous !== 'string')
|
|
79
|
+
|| !Array.isArray(raw.results) || raw.results.length > PAGE || (raw.next !== null) !== (page * PAGE < raw.count))
|
|
80
|
+
throw unconfirmed(what);
|
|
81
|
+
return { count: raw.count, page, next: raw.next, previous: raw.previous, results: raw.results.map(row) };
|
|
82
|
+
}
|
|
83
|
+
function serviceRow(value) {
|
|
84
|
+
if (!object(value) || keys(value) !== 'key,name,operation_count,visual_interface_declared' || typeof value.key !== 'string'
|
|
85
|
+
|| typeof value.name !== 'string' || !Number.isSafeInteger(value.operation_count) || value.operation_count < 0
|
|
86
|
+
|| typeof value.visual_interface_declared !== 'boolean')
|
|
87
|
+
throw unconfirmed('tool definition');
|
|
88
|
+
return { key: value.key, name: value.name, operation_count: value.operation_count, visual_interface_declared: value.visual_interface_declared };
|
|
89
|
+
}
|
|
90
|
+
function definitionRow(withDetail) {
|
|
91
|
+
return (value) => {
|
|
92
|
+
if (!object(value) || keys(value) !== (withDetail ? DETAIL_KEYS : SUMMARY_KEYS) || !uuid(value.id) || !uuid(value.workspace_id)
|
|
93
|
+
|| !uuid(value.owner_workspace_id) || value.owner_workspace_id.toLowerCase() !== value.workspace_id.toLowerCase() || !uuid(value.tool_id)
|
|
94
|
+
|| typeof value.key !== 'string' || typeof value.version !== 'string' || typeof value.name !== 'string' || typeof value.description !== 'string'
|
|
95
|
+
|| typeof value.state !== 'string' || !value.state || !maybe(time)(value.inspected_at) || !maybe(time)(value.revoked_at)
|
|
96
|
+
|| !sha(value.archive_sha256) || !sha(value.contract_digest) || !count(value.service_count) || !count(value.operation_count)
|
|
97
|
+
|| !Array.isArray(value.interfaces) || value.interfaces.some((one) => typeof one !== 'string') || value.runtime_started !== false
|
|
98
|
+
|| typeof value.can_fork !== 'boolean' || (value.can_fork && value.state !== 'inspected') || value.reuse_requires_private_copy !== true
|
|
99
|
+
|| (withDetail && (!Array.isArray(value.services) || !object(value.inspection))))
|
|
100
|
+
throw unconfirmed('tool definition');
|
|
101
|
+
return {
|
|
102
|
+
id: value.id.toLowerCase(), workspace_id: value.workspace_id.toLowerCase(), owner_workspace_id: value.owner_workspace_id.toLowerCase(),
|
|
103
|
+
tool_id: value.tool_id.toLowerCase(), key: value.key, version: value.version, name: value.name, description: value.description, state: value.state,
|
|
104
|
+
inspected_at: value.inspected_at, revoked_at: value.revoked_at, archive_sha256: value.archive_sha256,
|
|
105
|
+
contract_digest: value.contract_digest, service_count: value.service_count, operation_count: value.operation_count,
|
|
106
|
+
interfaces: value.interfaces, runtime_started: false, can_fork: value.can_fork, reuse_requires_private_copy: true,
|
|
107
|
+
...(withDetail ? { services: value.services.map(serviceRow), inspection: value.inspection } : {}),
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function grantRow(implementationId) {
|
|
112
|
+
return (value) => {
|
|
113
|
+
if (!object(value) || keys(value) !== GRANT_KEYS || !uuid(value.id) || typeof value.implementation_id !== 'string'
|
|
114
|
+
|| value.implementation_id.toLowerCase() !== implementationId || !uuid(value.recipient_workspace_id) || typeof value.allow_use !== 'boolean'
|
|
115
|
+
|| !uuid(value.request_key) || !time(value.created_at) || !maybe(time)(value.revoked_at))
|
|
116
|
+
throw unconfirmed('tool sharing');
|
|
117
|
+
return { id: value.id.toLowerCase(), implementation_id: implementationId, recipient_workspace_id: value.recipient_workspace_id.toLowerCase(),
|
|
118
|
+
allow_use: value.allow_use, request_key: value.request_key.toLowerCase(), created_at: value.created_at, revoked_at: value.revoked_at };
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function uploadRow(value, workspace) {
|
|
122
|
+
if (!object(value) || keys(value) !== UPLOAD_KEYS || !uuid(value.request_key) || !uuid(value.id) || !uuid(value.workspace_id)
|
|
123
|
+
|| value.workspace_id.toLowerCase() !== workspace || !uuid(value.actor_id)
|
|
124
|
+
|| !TOOL_UPLOAD_STATES.includes(value.state) || !maybe(uuid)(value.catalog_setup_id)
|
|
125
|
+
|| !maybe(uuid)(value.catalog_setup_request_key) || typeof value.filename !== 'string' || !Number.isSafeInteger(value.size) || value.size < 1
|
|
126
|
+
|| !sha(value.sha256) || !maybe(time)(value.submitted_at) || !maybe(time)(value.finished_at) || !time(value.expires_at)
|
|
127
|
+
|| !maybe(time)(value.withdrawn_at) || !maybe(uuid)(value.implementation_id) || value.can_upload !== false || typeof value.can_withdraw !== 'boolean'
|
|
128
|
+
|| !(value.problem === null || typeof value.problem === 'string'))
|
|
129
|
+
throw unconfirmed('tool copy');
|
|
130
|
+
return {
|
|
131
|
+
request_key: value.request_key.toLowerCase(), id: value.id.toLowerCase(), workspace_id: workspace, actor_id: value.actor_id.toLowerCase(),
|
|
132
|
+
state: value.state, catalog_setup_id: lower(value.catalog_setup_id),
|
|
133
|
+
catalog_setup_request_key: lower(value.catalog_setup_request_key), filename: value.filename, size: value.size,
|
|
134
|
+
sha256: value.sha256, submitted_at: value.submitted_at, finished_at: value.finished_at, expires_at: value.expires_at,
|
|
135
|
+
withdrawn_at: value.withdrawn_at, implementation_id: lower(value.implementation_id), can_upload: false,
|
|
136
|
+
can_withdraw: value.can_withdraw, problem: value.problem,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/** One private copy of this workspace. Its package must be exactly the source's archive. */
|
|
140
|
+
function copyRow(workspace) {
|
|
141
|
+
return (value) => {
|
|
142
|
+
if (!object(value) || keys(value) !== COPY_KEYS || !uuid(value.id) || !uuid(value.source_implementation_id) || !uuid(value.workspace_id)
|
|
143
|
+
|| value.workspace_id.toLowerCase() !== workspace || !uuid(value.request_key) || !TOOL_COPY_STATES.includes(value.state)
|
|
144
|
+
|| !time(value.created_at) || !maybe(time)(value.finished_at) || !sha(value.archive_sha256) || !sha(value.contract_digest)
|
|
145
|
+
|| value.runtime_started !== false || typeof value.cleanup_pending !== 'boolean'
|
|
146
|
+
|| !(value.problem === null || typeof value.problem === 'string'))
|
|
147
|
+
throw unconfirmed('tool copy');
|
|
148
|
+
const upload = uploadRow(value.upload, workspace);
|
|
149
|
+
if (upload.sha256 !== value.archive_sha256)
|
|
150
|
+
throw unconfirmed('tool copy');
|
|
151
|
+
return {
|
|
152
|
+
id: value.id.toLowerCase(), source_implementation_id: value.source_implementation_id.toLowerCase(), workspace_id: workspace,
|
|
153
|
+
request_key: value.request_key.toLowerCase(), state: value.state, created_at: value.created_at,
|
|
154
|
+
finished_at: value.finished_at, archive_sha256: value.archive_sha256, contract_digest: value.contract_digest, upload,
|
|
155
|
+
runtime_started: false, cleanup_pending: value.cleanup_pending, problem: value.problem,
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function worldDependentRow(value) {
|
|
160
|
+
if (!object(value) || keys(value) !== 'created_at,id,kind,revision,world_id' || !uuid(value.id) || value.kind !== 'world' || !uuid(value.world_id)
|
|
161
|
+
|| !Number.isSafeInteger(value.revision) || value.revision < 1 || !time(value.created_at))
|
|
162
|
+
throw unconfirmed('tool dependents');
|
|
163
|
+
return { id: value.id.toLowerCase(), kind: 'world', world_id: value.world_id.toLowerCase(), revision: value.revision, created_at: value.created_at };
|
|
164
|
+
}
|
|
165
|
+
/** A withdrawal answer: withdrawn with no receipt, or the original that already landed. */
|
|
166
|
+
function withdrawalOf(raw, receipt, what) {
|
|
167
|
+
if (object(raw) && keys(raw) === 'receipt,state' && raw.state === 'withdrawn' && raw.receipt === null)
|
|
168
|
+
return { state: 'withdrawn' };
|
|
169
|
+
if (object(raw) && keys(raw) === 'receipt,state' && raw.state === 'committed' && raw.receipt !== null)
|
|
170
|
+
return { state: 'committed', receipt: receipt(raw.receipt) };
|
|
171
|
+
throw unconfirmed(what);
|
|
172
|
+
}
|
|
173
|
+
/** Tool versions this workspace can read (its own and those shared with it), newest first, by name prefix. */
|
|
174
|
+
export async function listToolDefinitions(scope, input) {
|
|
175
|
+
const page = pageNumber(input.page);
|
|
176
|
+
return pageOf(await api(`${base(scope)}?${searchParams(page, input.search)}`, scoped(scope, input.signal)), page, definitionRow(false), 'tool definitions');
|
|
177
|
+
}
|
|
178
|
+
/** One readable, available tool version with its declared services and inspection record. */
|
|
179
|
+
export async function getToolDefinition(scope, input) {
|
|
180
|
+
const implementationId = toolReuseId(input.implementationId, 'tool version id');
|
|
181
|
+
const row = definitionRow(true)(await api(`${base(scope)}/${implementationId}`, scoped(scope, input.signal)));
|
|
182
|
+
if (row.id !== implementationId)
|
|
183
|
+
throw unconfirmed('tool definition');
|
|
184
|
+
return row;
|
|
185
|
+
}
|
|
186
|
+
/** Other active workspaces of this organization a tool version can be shared with (administrators only), by name prefix. */
|
|
187
|
+
export async function listToolRecipients(scope, input) {
|
|
188
|
+
const page = pageNumber(input.page);
|
|
189
|
+
const own = scope.workspace.toLowerCase();
|
|
190
|
+
return pageOf(await api(`${base(scope)}/recipients?${searchParams(page, input.search)}`, scoped(scope, input.signal)), page, (value) => {
|
|
191
|
+
if (!object(value) || keys(value) !== 'id,name' || !uuid(value.id) || value.id.toLowerCase() === own || typeof value.name !== 'string') {
|
|
192
|
+
throw unconfirmed('tool recipients');
|
|
193
|
+
}
|
|
194
|
+
return { id: value.id.toLowerCase(), name: value.name };
|
|
195
|
+
}, 'tool recipients');
|
|
196
|
+
}
|
|
197
|
+
/** The sharing grants of one tool version this workspace owns, newest first, revoked ones included. */
|
|
198
|
+
export async function listToolGrants(scope, input) {
|
|
199
|
+
const implementationId = toolReuseId(input.implementationId, 'tool version id');
|
|
200
|
+
const page = pageNumber(input.page);
|
|
201
|
+
const raw = await api(`${base(scope)}/${implementationId}/grants?page=${page}&page_size=${PAGE}`, scoped(scope, input.signal));
|
|
202
|
+
return pageOf(raw, page, grantRow(implementationId), 'tool sharing');
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Share one tool version this workspace owns with another workspace of the
|
|
206
|
+
* organization, under the caller's request key, after the human approved it.
|
|
207
|
+
* The same key returns the original grant. Administrators only.
|
|
208
|
+
*/
|
|
209
|
+
export async function shareToolDefinition(scope, input) {
|
|
210
|
+
const implementationId = toolReuseId(input.implementationId, 'tool version id');
|
|
211
|
+
const recipient = toolReuseId(input.recipientWorkspaceId, 'workspace id');
|
|
212
|
+
const requestKey = toolReuseId(input.requestKey, 'request key');
|
|
213
|
+
if (recipient === scope.workspace.toLowerCase()) {
|
|
214
|
+
throw new CliError('arguments_invalid', 'Share with another workspace of this organization; this one already owns the tool. Nothing was sent.', 2);
|
|
215
|
+
}
|
|
216
|
+
const row = grantRow(implementationId)(await api(`${base(scope)}/${implementationId}/grants`, {
|
|
217
|
+
...scoped(scope, input.signal), method: 'POST', body: { request_key: requestKey, recipient_workspace_id: recipient, allow_use: input.allowUse }
|
|
218
|
+
}));
|
|
219
|
+
if (row.request_key !== requestKey || row.recipient_workspace_id !== recipient || row.allow_use !== input.allowUse)
|
|
220
|
+
throw unconfirmed('tool sharing');
|
|
221
|
+
return row;
|
|
222
|
+
}
|
|
223
|
+
/** The caller's original grant under this key, or null when root has none (which does not prove it never arrived). Administrators only. */
|
|
224
|
+
export async function recoverToolGrant(scope, input) {
|
|
225
|
+
const implementationId = toolReuseId(input.implementationId, 'tool version id');
|
|
226
|
+
const requestKey = toolReuseId(input.requestKey, 'request key');
|
|
227
|
+
try {
|
|
228
|
+
const row = grantRow(implementationId)(await api(`${base(scope)}/${implementationId}/grants/requests/${requestKey}`, scoped(scope, input.signal)));
|
|
229
|
+
if (row.request_key !== requestKey)
|
|
230
|
+
throw unconfirmed('tool sharing');
|
|
231
|
+
return row;
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
if (error instanceof CliError && error.httpStatus === 404)
|
|
235
|
+
return null;
|
|
236
|
+
throw error;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/** Withdraw a sharing request that never landed, after the human approved it. A grant that landed is returned, not undone. */
|
|
240
|
+
export async function withdrawToolGrantRequest(scope, input) {
|
|
241
|
+
const implementationId = toolReuseId(input.implementationId, 'tool version id');
|
|
242
|
+
const requestKey = toolReuseId(input.requestKey, 'request key');
|
|
243
|
+
const raw = await api(`${base(scope)}/${implementationId}/grants/requests/${requestKey}`, {
|
|
244
|
+
...scoped(scope, input.signal), method: 'DELETE', body: { withdraw_consent: true }
|
|
245
|
+
});
|
|
246
|
+
const outcome = withdrawalOf(raw, grantRow(implementationId), 'tool sharing withdrawal');
|
|
247
|
+
if (outcome.state === 'committed' && outcome.receipt.request_key !== requestKey)
|
|
248
|
+
throw unconfirmed('tool sharing withdrawal');
|
|
249
|
+
return outcome;
|
|
250
|
+
}
|
|
251
|
+
/** Revoke one grant after the human's approval. Idempotent: an already revoked grant is returned as it is. */
|
|
252
|
+
export async function revokeToolGrant(scope, input) {
|
|
253
|
+
const implementationId = toolReuseId(input.implementationId, 'tool version id');
|
|
254
|
+
const grantId = toolReuseId(input.grantId, 'grant id');
|
|
255
|
+
const row = grantRow(implementationId)(await api(`${base(scope)}/${implementationId}/grants/${grantId}`, {
|
|
256
|
+
...scoped(scope, input.signal), method: 'DELETE', body: { revoke_consent: true }
|
|
257
|
+
}));
|
|
258
|
+
if (row.id !== grantId || row.revoked_at === null)
|
|
259
|
+
throw unconfirmed('tool sharing');
|
|
260
|
+
return row;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Start an exact private copy of one copyable tool version into this
|
|
264
|
+
* workspace, after the human approved it. The copy is pinned to the source's
|
|
265
|
+
* archive and contract digests, then inspected here before it can be used.
|
|
266
|
+
* The same key returns the original copy.
|
|
267
|
+
*/
|
|
268
|
+
export async function copyToolDefinition(scope, input) {
|
|
269
|
+
const implementationId = toolReuseId(input.source.id, 'tool version id');
|
|
270
|
+
const requestKey = toolReuseId(input.requestKey, 'request key');
|
|
271
|
+
const row = copyRow(scope.workspace.toLowerCase())(await api(`${base(scope)}/${implementationId}/forks`, {
|
|
272
|
+
...scoped(scope, input.signal), method: 'POST', body: { request_key: requestKey, fork_consent: true }
|
|
273
|
+
}));
|
|
274
|
+
return checkCopy(row, { sourceId: implementationId, archive: input.source.archive_sha256, contract: input.source.contract_digest, requestKey });
|
|
275
|
+
}
|
|
276
|
+
/** A copy of exactly this source (and digests, when known) under exactly this key. */
|
|
277
|
+
export function checkCopy(row, expected) {
|
|
278
|
+
if (row.source_implementation_id !== expected.sourceId.toLowerCase() || row.request_key !== expected.requestKey.toLowerCase()
|
|
279
|
+
|| (expected.archive !== undefined && row.archive_sha256 !== expected.archive)
|
|
280
|
+
|| (expected.contract !== undefined && row.contract_digest !== expected.contract))
|
|
281
|
+
throw unconfirmed('tool copy');
|
|
282
|
+
return row;
|
|
283
|
+
}
|
|
284
|
+
/** The caller's original copy under this key, or null when root has none (which does not prove it never arrived). */
|
|
285
|
+
export async function recoverToolCopy(scope, input) {
|
|
286
|
+
const requestKey = toolReuseId(input.requestKey, 'request key');
|
|
287
|
+
try {
|
|
288
|
+
const row = copyRow(scope.workspace.toLowerCase())(await api(`${base(scope)}/forks/requests/${requestKey}`, scoped(scope, input.signal)));
|
|
289
|
+
if (row.request_key !== requestKey)
|
|
290
|
+
throw unconfirmed('tool copy');
|
|
291
|
+
return row;
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
if (error instanceof CliError && error.httpStatus === 404)
|
|
295
|
+
return null;
|
|
296
|
+
throw error;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/** Withdraw a copy request that never landed, after the human approved it. A copy that landed is returned, not undone. */
|
|
300
|
+
export async function withdrawToolCopyRequest(scope, input) {
|
|
301
|
+
const requestKey = toolReuseId(input.requestKey, 'request key');
|
|
302
|
+
const raw = await api(`${base(scope)}/forks/requests/${requestKey}`, {
|
|
303
|
+
...scoped(scope, input.signal), method: 'DELETE', body: { withdraw_consent: true }
|
|
304
|
+
});
|
|
305
|
+
const outcome = withdrawalOf(raw, copyRow(scope.workspace.toLowerCase()), 'tool copy withdrawal');
|
|
306
|
+
if (outcome.state === 'committed' && outcome.receipt.request_key !== requestKey)
|
|
307
|
+
throw unconfirmed('tool copy withdrawal');
|
|
308
|
+
return outcome;
|
|
309
|
+
}
|
|
310
|
+
/** One of the caller's copies by its id. */
|
|
311
|
+
export async function getToolCopy(scope, input) {
|
|
312
|
+
const copyId = toolReuseId(input.copyId, 'copy id');
|
|
313
|
+
const row = copyRow(scope.workspace.toLowerCase())(await api(`${base(scope)}/forks/${copyId}`, scoped(scope, input.signal)));
|
|
314
|
+
if (row.id !== copyId)
|
|
315
|
+
throw unconfirmed('tool copy');
|
|
316
|
+
return row;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Stop one of the caller's copies while it is still pending, after the human
|
|
320
|
+
* approved it. A copy already copying or finished is returned as it is.
|
|
321
|
+
*/
|
|
322
|
+
export async function withdrawToolCopy(scope, input) {
|
|
323
|
+
const copyId = toolReuseId(input.copyId, 'copy id');
|
|
324
|
+
const row = copyRow(scope.workspace.toLowerCase())(await api(`${base(scope)}/forks/${copyId}`, {
|
|
325
|
+
...scoped(scope, input.signal), method: 'DELETE', body: { withdraw_consent: true }
|
|
326
|
+
}));
|
|
327
|
+
if (row.id !== copyId)
|
|
328
|
+
throw unconfirmed('tool copy');
|
|
329
|
+
return row;
|
|
330
|
+
}
|
|
331
|
+
/** This workspace's world revisions that depend on a tool version, or the caller's copies of it (25 per page). */
|
|
332
|
+
export async function listToolDependents(scope, input) {
|
|
333
|
+
const implementationId = toolReuseId(input.implementationId, 'tool version id');
|
|
334
|
+
if (!TOOL_DEPENDENT_KINDS.includes(input.kind))
|
|
335
|
+
throw new CliError('arguments_invalid', `Use --kind ${TOOL_DEPENDENT_KINDS.join('|')} with tool dependents.`, 2);
|
|
336
|
+
const page = pageNumber(input.page);
|
|
337
|
+
const raw = await api(`${base(scope)}/${implementationId}/dependents?kind=${input.kind}&page=${page}&page_size=${PAGE}`, scoped(scope, input.signal));
|
|
338
|
+
const copies = copyRow(scope.workspace.toLowerCase());
|
|
339
|
+
const row = input.kind === 'world' ? worldDependentRow : (value) => {
|
|
340
|
+
const copy = copies(value);
|
|
341
|
+
if (copy.source_implementation_id !== implementationId)
|
|
342
|
+
throw unconfirmed('tool dependents');
|
|
343
|
+
return copy;
|
|
344
|
+
};
|
|
345
|
+
return pageOf(raw, page, row, 'tool dependents');
|
|
346
|
+
}
|
|
347
|
+
/** Where a copy stands, in the terms that matter: it is usable only once this workspace's inspection accepted it. */
|
|
348
|
+
export function copyStatus(copy) {
|
|
349
|
+
const { upload } = copy;
|
|
350
|
+
switch (copy.state) {
|
|
351
|
+
case 'pending': return { ready: false, text: 'queued to copy; it can still be withdrawn' };
|
|
352
|
+
case 'copying': return { ready: false, text: 'copying the exact package into this workspace' };
|
|
353
|
+
case 'withdrawn': return { ready: false, text: 'withdrawn; nothing was copied' };
|
|
354
|
+
case 'rejected': return { ready: false, text: `stopped: ${copy.problem ?? 'the copy could not finish'}` };
|
|
355
|
+
default:
|
|
356
|
+
if (upload.state === 'inspected' && upload.implementation_id) {
|
|
357
|
+
return { ready: true, text: `copied and inspected here: private tool version ${upload.implementation_id}` };
|
|
358
|
+
}
|
|
359
|
+
if (upload.state === 'rejected' || upload.state === 'withdrawn') {
|
|
360
|
+
return { ready: false, text: `copied, but this workspace's inspection did not accept it: ${upload.problem ?? upload.state}` };
|
|
361
|
+
}
|
|
362
|
+
return { ready: false, text: 'copied; this workspace is still inspecting it, so it is not ready to use yet' };
|
|
363
|
+
}
|
|
364
|
+
}
|