spawnfile 0.1.17 → 0.1.18
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 +1 -1
- package/dist/auth/importers.js +21 -5
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.js +1 -0
- package/dist/auth/profileStore.js +4 -1
- package/dist/auth/trainingGrokWriteback.d.ts +4 -0
- package/dist/auth/trainingGrokWriteback.js +119 -0
- package/dist/auth/trainingGrokWritebackLock.d.ts +5 -0
- package/dist/auth/trainingGrokWritebackLock.js +56 -0
- package/dist/cli/authCommands.js +9 -5
- package/dist/cli/compileBuildCommands.js +4 -0
- package/dist/cli/devCommands.js +4 -2
- package/dist/cli/downCommand.d.ts +2 -0
- package/dist/cli/downCommand.js +3 -0
- package/dist/cli/envFileOption.d.ts +18 -0
- package/dist/cli/envFileOption.js +20 -0
- package/dist/cli/lifecycleCommands.d.ts +1 -1
- package/dist/cli/lifecycleCommands.js +3 -1
- package/dist/cli/lifecyclePlan.d.ts +1 -0
- package/dist/cli/lifecyclePlan.js +2 -0
- package/dist/cli/paideiaDelegation.d.ts +2 -1
- package/dist/cli/paideiaDelegation.js +5 -4
- package/dist/cli/recordCommands.d.ts +17 -0
- package/dist/cli/recordCommands.js +43 -0
- package/dist/cli/releaseCommand.d.ts +6 -0
- package/dist/cli/releaseCommand.js +91 -0
- package/dist/cli/runCli.d.ts +7 -1
- package/dist/cli/runCli.js +11 -6
- package/dist/cli/runPublishCommands.js +5 -3
- package/dist/cli/trainCommand.js +73 -20
- package/dist/cli/upCommand.js +5 -1
- package/dist/cli/volumeCommands.d.ts +8 -0
- package/dist/cli/volumeCommands.js +53 -0
- package/dist/compiler/agentNodeMerge.js +3 -2
- package/dist/compiler/buildCompilePlan.js +4 -0
- package/dist/compiler/buildCompilePlanAgent.js +3 -1
- package/dist/compiler/buildCompilePlanTraversal.js +2 -0
- package/dist/compiler/buildCompilePlanTraversalHelpers.d.ts +2 -2
- package/dist/compiler/buildCompilePlanTraversalHelpers.js +4 -3
- package/dist/compiler/buildProject.d.ts +10 -0
- package/dist/compiler/buildProject.js +14 -2
- package/dist/compiler/cleanCompileOutput.d.ts +2 -0
- package/dist/compiler/cleanCompileOutput.js +14 -0
- package/dist/compiler/compilePlanHelpers.js +2 -0
- package/dist/compiler/compileProject.d.ts +10 -0
- package/dist/compiler/compileProject.js +29 -3
- package/dist/compiler/containerArtifactSummaries.js +1 -0
- package/dist/compiler/containerArtifacts.d.ts +4 -4
- package/dist/compiler/containerArtifacts.js +18 -34
- package/dist/compiler/containerArtifactsPlans.js +7 -0
- package/dist/compiler/containerArtifactsTypes.d.ts +7 -0
- package/dist/compiler/containerDaimonBrokerRender.d.ts +3 -1
- package/dist/compiler/containerDaimonBrokerRender.js +6 -3
- package/dist/compiler/containerDaimonGrokTaskClock.d.ts +5 -0
- package/dist/compiler/containerDaimonGrokTaskClock.js +29 -0
- package/dist/compiler/containerDaimonGrokWorkerProvisioning.d.ts +1 -1
- package/dist/compiler/containerDaimonGrokWorkerProvisioning.js +38 -16
- package/dist/compiler/containerDaimonGrokWorkerRender.d.ts +33 -8
- package/dist/compiler/containerDaimonGrokWorkerRender.js +18 -5
- package/dist/compiler/containerDaimonOwnershipGuardRender.d.ts +14 -1
- package/dist/compiler/containerDaimonOwnershipGuardRender.js +15 -2
- package/dist/compiler/containerDaimonUidEntrypointRender.js +6 -12
- package/dist/compiler/containerTargetResources.d.ts +10 -0
- package/dist/compiler/containerTargetResources.js +21 -13
- package/dist/compiler/containerWorkspaceResourceRender.js +4 -1
- package/dist/compiler/index.d.ts +2 -0
- package/dist/compiler/index.js +2 -0
- package/dist/compiler/mcpPlaceholders.d.ts +11 -0
- package/dist/compiler/mcpPlaceholders.js +58 -0
- package/dist/compiler/mcpServerInheritance.d.ts +18 -0
- package/dist/compiler/mcpServerInheritance.js +43 -0
- package/dist/compiler/moltnetArtifactTypes.d.ts +1 -0
- package/dist/compiler/moltnetArtifacts.js +1 -0
- package/dist/compiler/preflightCompilePlan.d.ts +9 -0
- package/dist/compiler/preflightCompilePlan.js +38 -0
- package/dist/compiler/recordingAgentFacts.d.ts +4 -0
- package/dist/compiler/recordingAgentFacts.js +35 -0
- package/dist/compiler/recordingCapability.d.ts +4 -0
- package/dist/compiler/recordingCapability.js +22 -0
- package/dist/compiler/recordingReport.d.ts +4 -0
- package/dist/compiler/recordingReport.js +18 -0
- package/dist/compiler/runProject.d.ts +2 -1
- package/dist/compiler/runProject.js +2 -0
- package/dist/compiler/surfaces.d.ts +1 -2
- package/dist/compiler/surfaces.js +0 -1
- package/dist/compiler/syncProjectAuth.js +2 -1
- package/dist/compiler/training/broker/clockProbe.d.ts +6 -0
- package/dist/compiler/training/broker/clockProbe.js +27 -0
- package/dist/compiler/training/broker/declaration.d.ts +4 -2
- package/dist/compiler/training/broker/declaration.js +4 -2
- package/dist/compiler/training/broker/entrypoint.js +33 -18
- package/dist/compiler/training/broker/evaluatorSecrets.d.ts +2 -0
- package/dist/compiler/training/broker/evaluatorSecrets.js +60 -0
- package/dist/compiler/training/broker/index.d.ts +3 -2
- package/dist/compiler/training/broker/index.js +3 -2
- package/dist/compiler/training/broker/main.js +1 -1
- package/dist/compiler/training/broker/paths.d.ts +96 -56
- package/dist/compiler/training/broker/paths.js +97 -89
- package/dist/compiler/training/broker/processes.d.ts +9 -0
- package/dist/compiler/training/broker/processes.js +4 -1
- package/dist/compiler/training/broker/projection.d.ts +3 -2
- package/dist/compiler/training/broker/projection.js +21 -9
- package/dist/compiler/training/broker/provisioning.d.ts +6 -15
- package/dist/compiler/training/broker/provisioning.js +71 -53
- package/dist/compiler/training/broker/registration.d.ts +3 -1
- package/dist/compiler/training/broker/registration.js +29 -21
- package/dist/compiler/training/broker/reset.d.ts +9 -0
- package/dist/compiler/training/broker/reset.js +71 -0
- package/dist/compiler/training/broker/runtime.d.ts +10 -13
- package/dist/compiler/training/broker/runtime.js +69 -115
- package/dist/compiler/training/broker/supervisor.d.ts +10 -11
- package/dist/compiler/training/broker/supervisor.js +22 -23
- package/dist/compiler/training/broker/taskClock.d.ts +5 -0
- package/dist/compiler/training/broker/taskClock.js +41 -0
- package/dist/compiler/training/compiledAgent.d.ts +21 -0
- package/dist/compiler/training/compiledAgent.js +62 -0
- package/dist/compiler/training/container/contract.d.ts +23 -0
- package/dist/compiler/training/container/contract.js +23 -5
- package/dist/compiler/training/container/evaluators.d.ts +48 -0
- package/dist/compiler/training/container/evaluators.js +50 -0
- package/dist/compiler/training/container/grokWriteback.d.ts +8 -0
- package/dist/compiler/training/container/grokWriteback.js +26 -0
- package/dist/compiler/training/container/index.d.ts +2 -1
- package/dist/compiler/training/container/index.js +2 -1
- package/dist/compiler/training/container/launch.d.ts +3 -0
- package/dist/compiler/training/container/launch.js +119 -28
- package/dist/compiler/training/container/nativeSlots.d.ts +14 -0
- package/dist/compiler/training/container/nativeSlots.js +13 -0
- package/dist/compiler/training/container/outputCopy.d.ts +2 -0
- package/dist/compiler/training/container/outputCopy.js +72 -0
- package/dist/compiler/training/container/outputVolume.d.ts +27 -0
- package/dist/compiler/training/container/outputVolume.js +161 -0
- package/dist/compiler/training/container/prepare.d.ts +3 -1
- package/dist/compiler/training/container/prepare.js +57 -12
- package/dist/compiler/training/container/security.d.ts +5 -3
- package/dist/compiler/training/container/security.js +15 -5
- package/dist/compiler/training/container/subjectIsolation.d.ts +5 -0
- package/dist/compiler/training/container/subjectIsolation.js +15 -0
- package/dist/compiler/training/context.d.ts +8 -0
- package/dist/compiler/training/context.js +12 -12
- package/dist/compiler/training/contract.d.ts +2 -0
- package/dist/compiler/training/contract.js +2 -0
- package/dist/compiler/training/execution.d.ts +417 -0
- package/dist/compiler/training/execution.js +160 -0
- package/dist/compiler/training/index.d.ts +8 -0
- package/dist/compiler/training/index.js +7 -0
- package/dist/compiler/training/moments.d.ts +80 -0
- package/dist/compiler/training/moments.js +118 -0
- package/dist/compiler/training/output.d.ts +2 -0
- package/dist/compiler/training/output.js +20 -0
- package/dist/compiler/training/plan/contract.d.ts +287 -0
- package/dist/compiler/training/plan/contract.js +49 -0
- package/dist/compiler/training/plan/index.d.ts +5 -0
- package/dist/compiler/training/plan/index.js +4 -0
- package/dist/compiler/training/plan/load.d.ts +9 -0
- package/dist/compiler/training/plan/load.js +153 -0
- package/dist/compiler/training/plan/references.d.ts +19 -0
- package/dist/compiler/training/plan/references.js +57 -0
- package/dist/compiler/training/plan/resolve.d.ts +4 -0
- package/dist/compiler/training/plan/resolve.js +73 -0
- package/dist/compiler/training/plan/targets.d.ts +11 -0
- package/dist/compiler/training/plan/targets.js +71 -0
- package/dist/compiler/training/plan/types.d.ts +36 -0
- package/dist/compiler/training/plan/types.js +1 -0
- package/dist/compiler/training/preparation/assets/Dockerfile +13 -2
- package/dist/compiler/training/preparation/assets/package-lock.json +2 -2
- package/dist/compiler/training/preparation/broker.d.ts +3 -3
- package/dist/compiler/training/preparation/broker.js +6 -4
- package/dist/compiler/training/preparation/contract.d.ts +27 -2
- package/dist/compiler/training/preparation/contract.js +23 -4
- package/dist/compiler/training/preparation/files.d.ts +5 -1
- package/dist/compiler/training/preparation/files.js +76 -15
- package/dist/compiler/training/preparation/image.js +9 -4
- package/dist/compiler/training/preparation/inputs.d.ts +1 -0
- package/dist/compiler/training/preparation/inputs.js +18 -10
- package/dist/compiler/training/preparation/prepare.d.ts +5 -0
- package/dist/compiler/training/preparation/prepare.js +66 -29
- package/dist/compiler/training/preparation/scratch.d.ts +6 -17
- package/dist/compiler/training/preparation/scratch.js +89 -23
- package/dist/compiler/training/repair/contract.d.ts +338 -4
- package/dist/compiler/training/repair/contract.js +2 -0
- package/dist/compiler/training/repair/index.d.ts +1 -1
- package/dist/compiler/training/repair/index.js +1 -1
- package/dist/compiler/training/repair/prepare.d.ts +155 -3
- package/dist/compiler/training/repair/prepare.js +6 -2
- package/dist/compiler/training/repair/witness.d.ts +152 -3
- package/dist/compiler/training/repair/witness.js +8 -2
- package/dist/compiler/training/resolution.d.ts +25 -0
- package/dist/compiler/training/resolution.js +69 -0
- package/dist/compiler/training/rewind/contract.d.ts +321 -0
- package/dist/compiler/training/rewind/contract.js +39 -0
- package/dist/compiler/training/rewind/deployedResource.d.ts +22 -0
- package/dist/compiler/training/rewind/deployedResource.js +19 -0
- package/dist/compiler/training/rewind/feed.d.ts +12 -0
- package/dist/compiler/training/rewind/feed.js +182 -0
- package/dist/compiler/training/rewind/feedContent.d.ts +6 -0
- package/dist/compiler/training/rewind/feedContent.js +38 -0
- package/dist/compiler/training/rewind/git.d.ts +8 -0
- package/dist/compiler/training/rewind/git.js +159 -0
- package/dist/compiler/training/rewind/gitArchive.d.ts +2 -0
- package/dist/compiler/training/rewind/gitArchive.js +7 -0
- package/dist/compiler/training/rewind/gitHistory.d.ts +3 -0
- package/dist/compiler/training/rewind/gitHistory.js +55 -0
- package/dist/compiler/training/rewind/gitProcess.d.ts +19 -0
- package/dist/compiler/training/rewind/gitProcess.js +81 -0
- package/dist/compiler/training/rewind/gitTree.d.ts +14 -0
- package/dist/compiler/training/rewind/gitTree.js +90 -0
- package/dist/compiler/training/rewind/history.d.ts +28 -0
- package/dist/compiler/training/rewind/history.js +239 -0
- package/dist/compiler/training/rewind/index.d.ts +18 -0
- package/dist/compiler/training/rewind/index.js +15 -0
- package/dist/compiler/training/rewind/inputs.d.ts +9 -0
- package/dist/compiler/training/rewind/inputs.js +67 -0
- package/dist/compiler/training/rewind/instant.d.ts +4 -0
- package/dist/compiler/training/rewind/instant.js +24 -0
- package/dist/compiler/training/rewind/leakCheck.d.ts +10 -0
- package/dist/compiler/training/rewind/leakCheck.js +56 -0
- package/dist/compiler/training/rewind/leakFeed.d.ts +5 -0
- package/dist/compiler/training/rewind/leakFeed.js +25 -0
- package/dist/compiler/training/rewind/leakFiles.d.ts +10 -0
- package/dist/compiler/training/rewind/leakFiles.js +106 -0
- package/dist/compiler/training/rewind/leakGit.d.ts +3 -0
- package/dist/compiler/training/rewind/leakGit.js +78 -0
- package/dist/compiler/training/rewind/leakGitPayload.d.ts +4 -0
- package/dist/compiler/training/rewind/leakGitPayload.js +57 -0
- package/dist/compiler/training/rewind/leakInputs.d.ts +7 -0
- package/dist/compiler/training/rewind/leakInputs.js +135 -0
- package/dist/compiler/training/rewind/leakLayout.d.ts +2 -0
- package/dist/compiler/training/rewind/leakLayout.js +17 -0
- package/dist/compiler/training/rewind/leakProvenance.d.ts +3 -0
- package/dist/compiler/training/rewind/leakProvenance.js +88 -0
- package/dist/compiler/training/rewind/materialize.d.ts +136 -0
- package/dist/compiler/training/rewind/materialize.js +212 -0
- package/dist/compiler/training/rewind/memory.d.ts +10 -0
- package/dist/compiler/training/rewind/memory.js +84 -0
- package/dist/compiler/training/rewind/memorySchemas.d.ts +87 -0
- package/dist/compiler/training/rewind/memorySchemas.js +50 -0
- package/dist/compiler/training/rewind/moltnet.d.ts +2 -0
- package/dist/compiler/training/rewind/moltnet.js +54 -0
- package/dist/compiler/training/rewind/moltnetJson.d.ts +13 -0
- package/dist/compiler/training/rewind/moltnetJson.js +180 -0
- package/dist/compiler/training/rewind/moltnetSchemas.d.ts +1226 -0
- package/dist/compiler/training/rewind/moltnetSchemas.js +75 -0
- package/dist/compiler/training/rewind/moltnetSqlite.d.ts +31 -0
- package/dist/compiler/training/rewind/moltnetSqlite.js +192 -0
- package/dist/compiler/training/rewind/moltnetSqliteData.d.ts +10 -0
- package/dist/compiler/training/rewind/moltnetSqliteData.js +113 -0
- package/dist/compiler/training/rewind/recordInput.d.ts +40 -0
- package/dist/compiler/training/rewind/recordInput.js +49 -0
- package/dist/compiler/training/rewind/recordedBundle.d.ts +4 -0
- package/dist/compiler/training/rewind/recordedBundle.js +58 -0
- package/dist/compiler/training/rewind/recordedCommit.d.ts +2 -0
- package/dist/compiler/training/rewind/recordedCommit.js +10 -0
- package/dist/compiler/training/rewind/select.d.ts +18 -0
- package/dist/compiler/training/rewind/select.js +64 -0
- package/dist/compiler/training/rewind/snapshotManifest.d.ts +42 -0
- package/dist/compiler/training/rewind/snapshotManifest.js +134 -0
- package/dist/compiler/training/rewind/taskClock.d.ts +12 -0
- package/dist/compiler/training/rewind/taskClock.js +40 -0
- package/dist/compiler/training/rewind/timestamps.d.ts +4 -0
- package/dist/compiler/training/rewind/timestamps.js +26 -0
- package/dist/compiler/training/rewind/types.d.ts +43 -0
- package/dist/compiler/training/rewind/types.js +1 -0
- package/dist/compiler/training/rewind/volumes.d.ts +12 -0
- package/dist/compiler/training/rewind/volumes.js +58 -0
- package/dist/compiler/training/selection.d.ts +7 -0
- package/dist/compiler/training/selection.js +15 -0
- package/dist/compiler/types.d.ts +6 -3
- package/dist/compiler/upProject.d.ts +1 -0
- package/dist/compiler/upProject.js +21 -5
- package/dist/compiler/workspaceBundleArtifacts.d.ts +16 -1
- package/dist/compiler/workspaceBundleArtifacts.js +69 -20
- package/dist/compiler/workspaceBundleCache.d.ts +23 -0
- package/dist/compiler/workspaceBundleCache.js +79 -0
- package/dist/compiler/workspaceBundleDependencies.d.ts +21 -0
- package/dist/compiler/workspaceBundleDependencies.js +122 -0
- package/dist/compiler/workspaceBundleFiles.d.ts +51 -0
- package/dist/compiler/workspaceBundleFiles.js +251 -0
- package/dist/compiler/workspaceBundleGenerated.d.ts +25 -0
- package/dist/compiler/workspaceBundleGenerated.js +103 -0
- package/dist/compiler/workspaceBundleGit.d.ts +64 -0
- package/dist/compiler/workspaceBundleGit.js +154 -0
- package/dist/compiler/workspaceBundleKey.d.ts +34 -0
- package/dist/compiler/workspaceBundleKey.js +17 -0
- package/dist/compiler/workspaceBundleResolve.d.ts +56 -0
- package/dist/compiler/workspaceBundleResolve.js +144 -0
- package/dist/compiler/workspaceBundleRun.d.ts +41 -0
- package/dist/compiler/workspaceBundleRun.js +79 -0
- package/dist/compiler/workspaceBundleTar.d.ts +47 -0
- package/dist/compiler/workspaceBundleTar.js +140 -0
- package/dist/compiler/workspaceBundleTree.d.ts +15 -0
- package/dist/compiler/workspaceBundleTree.js +58 -0
- package/dist/compiler/workspaceGitFetch.d.ts +41 -0
- package/dist/compiler/workspaceGitFetch.js +155 -0
- package/dist/compiler/workspaceGitPins.d.ts +33 -0
- package/dist/compiler/workspaceGitPins.js +127 -0
- package/dist/compiler/workspaceResources.d.ts +5 -1
- package/dist/compiler/workspaceResources.js +32 -5
- package/dist/deployment/activation.d.ts +3 -0
- package/dist/deployment/activation.js +12 -0
- package/dist/deployment/canaryCutover.d.ts +1 -1
- package/dist/deployment/candidateRecording.d.ts +8 -0
- package/dist/deployment/candidateRecording.js +22 -0
- package/dist/deployment/dockerManager.d.ts +5 -3
- package/dist/deployment/dockerManager.js +12 -2
- package/dist/deployment/downDeployment.d.ts +2 -0
- package/dist/deployment/downDeployment.js +6 -2
- package/dist/deployment/homeStore.d.ts +9 -1
- package/dist/deployment/homeStore.js +16 -53
- package/dist/deployment/index.d.ts +6 -0
- package/dist/deployment/index.js +6 -0
- package/dist/deployment/pidLock.d.ts +25 -0
- package/dist/deployment/pidLock.js +81 -0
- package/dist/deployment/record.d.ts +85 -1
- package/dist/deployment/record.js +11 -5
- package/dist/deployment/recordPublication.d.ts +15 -0
- package/dist/deployment/recordPublication.js +76 -0
- package/dist/deployment/recordedMemoryRetention.d.ts +18 -0
- package/dist/deployment/recordedMemoryRetention.js +27 -0
- package/dist/deployment/resourceLog.d.ts +140 -0
- package/dist/deployment/resourceLog.js +78 -0
- package/dist/distribution/buildDistributionReport.d.ts +3 -0
- package/dist/distribution/buildDistributionReport.js +5 -0
- package/dist/distribution/consumeImage.d.ts +3 -0
- package/dist/distribution/consumeImage.js +23 -31
- package/dist/distribution/consumeImageLifecycle.d.ts +4 -1
- package/dist/distribution/consumeImageLifecycle.js +14 -3
- package/dist/distribution/consumeImageSupport.d.ts +7 -0
- package/dist/distribution/consumeImageSupport.js +25 -0
- package/dist/distribution/distributionReportSchema.d.ts +47 -0
- package/dist/distribution/distributionReportSchema.js +20 -0
- package/dist/distribution/renderImageInterface.js +1 -1
- package/dist/distribution/types.d.ts +15 -0
- package/dist/filesystem/durableWrite.d.ts +10 -0
- package/dist/filesystem/durableWrite.js +87 -0
- package/dist/filesystem/index.d.ts +2 -0
- package/dist/filesystem/index.js +2 -0
- package/dist/filesystem/retainedJsonl.d.ts +23 -0
- package/dist/filesystem/retainedJsonl.js +123 -0
- package/dist/manifest/commandSchemas.d.ts +5 -0
- package/dist/manifest/commandSchemas.js +5 -0
- package/dist/manifest/executionSchemas.d.ts +20 -0
- package/dist/manifest/executionSchemas.js +13 -3
- package/dist/manifest/index.d.ts +2 -0
- package/dist/manifest/index.js +2 -0
- package/dist/manifest/loadManifest.js +3 -26
- package/dist/manifest/mcpSchemas.d.ts +61 -0
- package/dist/manifest/mcpSchemas.js +57 -11
- package/dist/manifest/memorySchemas.d.ts +1 -1
- package/dist/manifest/memorySchemas.js +1 -1
- package/dist/manifest/parseManifest.d.ts +7 -0
- package/dist/manifest/parseManifest.js +65 -0
- package/dist/manifest/renderSpawnfile.js +4 -1
- package/dist/manifest/renderSpawnfileWorkspace.js +6 -2
- package/dist/manifest/schemas.d.ts +1206 -132
- package/dist/manifest/schemas.js +14 -4
- package/dist/manifest/teamNetworkSchemas.d.ts +1 -1
- package/dist/manifest/trainingDataSchemas.d.ts +357 -0
- package/dist/manifest/trainingDataSchemas.js +31 -0
- package/dist/manifest/trainingSchemas.d.ts +49 -0
- package/dist/manifest/trainingSchemas.js +44 -0
- package/dist/manifest/volumeFeedSchemas.d.ts +52 -0
- package/dist/manifest/volumeFeedSchemas.js +104 -0
- package/dist/manifest/workspaceSchemas.d.ts +182 -5
- package/dist/manifest/workspaceSchemas.js +111 -7
- package/dist/recording/compose.d.ts +3 -0
- package/dist/recording/compose.js +93 -0
- package/dist/recording/deployment.d.ts +15 -0
- package/dist/recording/deployment.js +38 -0
- package/dist/recording/history.d.ts +16 -0
- package/dist/recording/history.js +47 -0
- package/dist/recording/index.d.ts +9 -0
- package/dist/recording/index.js +9 -0
- package/dist/recording/moment.d.ts +61 -0
- package/dist/recording/moment.js +36 -0
- package/dist/recording/parse.d.ts +15 -0
- package/dist/recording/parse.js +74 -0
- package/dist/recording/read.d.ts +8 -0
- package/dist/recording/read.js +61 -0
- package/dist/recording/store.d.ts +10 -0
- package/dist/recording/store.js +94 -0
- package/dist/recording/sync.d.ts +24 -0
- package/dist/recording/sync.js +126 -0
- package/dist/recording/types.d.ts +45 -0
- package/dist/recording/types.js +2 -0
- package/dist/release/drainControl.d.ts +54 -0
- package/dist/release/drainControl.js +137 -0
- package/dist/release/drainPhase.d.ts +37 -0
- package/dist/release/drainPhase.js +161 -0
- package/dist/release/index.d.ts +11 -0
- package/dist/release/index.js +11 -0
- package/dist/release/ledger.d.ts +75 -0
- package/dist/release/ledger.js +111 -0
- package/dist/release/notify.d.ts +58 -0
- package/dist/release/notify.js +126 -0
- package/dist/release/pending.d.ts +35 -0
- package/dist/release/pending.js +60 -0
- package/dist/release/postDeploy.d.ts +32 -0
- package/dist/release/postDeploy.js +62 -0
- package/dist/release/releaseDefaults.d.ts +9 -0
- package/dist/release/releaseDefaults.js +115 -0
- package/dist/release/releaseDocker.d.ts +38 -0
- package/dist/release/releaseDocker.js +94 -0
- package/dist/release/releaseTypes.d.ts +94 -0
- package/dist/release/releaseTypes.js +1 -0
- package/dist/release/runRelease.d.ts +9 -0
- package/dist/release/runRelease.js +218 -0
- package/dist/release/swap.d.ts +23 -0
- package/dist/release/swap.js +55 -0
- package/dist/release/types.d.ts +50 -0
- package/dist/release/types.js +29 -0
- package/dist/report/index.d.ts +1 -0
- package/dist/report/index.js +1 -0
- package/dist/report/recording.d.ts +57 -0
- package/dist/report/recording.js +26 -0
- package/dist/report/types.d.ts +58 -0
- package/dist/runtime/container.js +8 -13
- package/dist/runtime/daimon/adapter.js +15 -4
- package/dist/runtime/daimon/config.d.ts +4 -0
- package/dist/runtime/daimon/config.js +53 -4
- package/dist/runtime/daimon/contract-manifest.json +1 -0
- package/dist/runtime/daimon/contract-manifest.sha256 +1 -0
- package/dist/runtime/daimon/contractManifest.d.ts +59 -8
- package/dist/runtime/daimon/contractManifest.js +26 -10
- package/dist/runtime/daimon/grokTurnLimits.d.ts +25 -0
- package/dist/runtime/daimon/grokTurnLimits.js +51 -0
- package/dist/runtime/daimon/grokWorkerConfigBytes.d.ts +17 -0
- package/dist/runtime/daimon/grokWorkerConfigBytes.js +17 -0
- package/dist/runtime/daimon/grokWorkerContract.d.ts +5 -0
- package/dist/runtime/daimon/grokWorkerContract.js +13 -1
- package/dist/runtime/daimon/recording.d.ts +19 -0
- package/dist/runtime/daimon/recording.js +50 -0
- package/dist/runtime/daimon/scheduleAuthority.d.ts +8 -0
- package/dist/runtime/daimon/scheduleAuthority.js +19 -5
- package/dist/runtime/daimon/wakeMoments.d.ts +15 -0
- package/dist/runtime/daimon/wakeMoments.js +17 -0
- package/dist/runtime/daimonInstall.d.ts +3 -0
- package/dist/runtime/daimonInstall.js +25 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/install.d.ts +2 -0
- package/dist/runtime/install.js +1 -0
- package/dist/runtime/openclaw/adapter.js +3 -0
- package/dist/runtime/pi/adapter.js +3 -0
- package/dist/runtime/pi/containerTargets.js +6 -0
- package/dist/runtime/picoclaw/adapter.js +3 -0
- package/dist/runtime/registry.d.ts +3 -0
- package/dist/runtime/registry.js +13 -1
- package/dist/runtime/types.d.ts +15 -0
- package/dist/runtime/usageLedgerRead.d.ts +6 -0
- package/dist/runtime/usageLedgerRead.js +3 -3
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.js +1 -0
- package/dist/shared/recording.d.ts +8 -0
- package/dist/shared/recording.js +25 -0
- package/dist/target/dockerCommandExecutorCore.js +1 -1
- package/dist/target/dockerTargetBinding.js +2 -1
- package/dist/volume/feedLand.d.ts +31 -0
- package/dist/volume/feedLand.js +174 -0
- package/dist/volume/feedLandings.d.ts +45 -0
- package/dist/volume/feedLandings.js +111 -0
- package/dist/volume/feedLayout.d.ts +61 -0
- package/dist/volume/feedLayout.js +234 -0
- package/dist/volume/feedLock.d.ts +7 -0
- package/dist/volume/feedLock.js +131 -0
- package/dist/volume/feedManifest.d.ts +27 -0
- package/dist/volume/feedManifest.js +123 -0
- package/dist/volume/feedPrepare.d.ts +16 -0
- package/dist/volume/feedPrepare.js +228 -0
- package/dist/volume/feedProject.d.ts +39 -0
- package/dist/volume/feedProject.js +92 -0
- package/dist/volume/feedRecord.d.ts +55 -0
- package/dist/volume/feedRecord.js +148 -0
- package/dist/volume/feedRef.d.ts +43 -0
- package/dist/volume/feedRef.js +117 -0
- package/dist/volume/feedRefresh.d.ts +15 -0
- package/dist/volume/feedRefresh.js +187 -0
- package/dist/volume/feedSource.d.ts +66 -0
- package/dist/volume/feedSource.js +104 -0
- package/dist/volume/feedTarget.d.ts +70 -0
- package/dist/volume/feedTarget.js +9 -0
- package/dist/volume/feedTestKit.d.ts +11 -0
- package/dist/volume/feedTestKit.js +45 -0
- package/dist/volume/feedVerify.d.ts +18 -0
- package/dist/volume/feedVerify.js +104 -0
- package/dist/volume/index.d.ts +13 -0
- package/dist/volume/index.js +13 -0
- package/package.json +3 -3
- package/runtimes.yaml +8 -6
|
@@ -1,31 +1,59 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { chmod, mkdtemp, readFile, realpath,
|
|
2
|
+
import { chmod, mkdtemp, readFile, realpath, stat, writeFile } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { DAIMON_CODEX_NATIVE_SANDBOX_DOCKER_SECURITY_OPTS } from "../../../shared/index.js";
|
|
5
|
+
import { parseTrainingBrokerDeclaration } from "../broker/declaration.js";
|
|
6
|
+
import { trainingSlotsDocument, TRAINING_SLOTS_FILE } from "../broker/paths.js";
|
|
5
7
|
import { assertNotDesktopGrokAuth } from "../broker/entrypoint.js";
|
|
6
|
-
import { TRAINING_BROKER_ENTRYPOINT, trainingBrokerMounts, trainingBrokerSecurityArgs, trainingBrokerTmpfsTargets } from "./security.js";
|
|
8
|
+
import { TRAINING_BROKER_ENTRYPOINT, trainingBrokerMounts, trainingBrokerSecurityArgs, trainingBrokerTmpfsTargets, trainingRunRequestMount } from "./security.js";
|
|
7
9
|
import { parseDetachedContainerInspect } from "../../runProjectDocker.js";
|
|
10
|
+
import { mapTrainingExecution, trainingExecutionSchema, TRAINING_EXECUTION_FILE, TRAINING_EXECUTION_CAPABILITY_LABEL, TRAINING_EXECUTION_VERSION } from "../execution.js";
|
|
11
|
+
import { verifyCanonicalPins } from "../preparation/inputs.js";
|
|
12
|
+
import { removeTrainingPreparationScratch } from "../preparation/scratch.js";
|
|
8
13
|
import { trainingImageSchema } from "./contract.js";
|
|
14
|
+
import { prepareTrainingEvaluators } from "./evaluators.js";
|
|
9
15
|
import { prepareTrainingContainer } from "./prepare.js";
|
|
10
16
|
import { runTrainingDocker } from "./process.js";
|
|
11
17
|
import { repairEnvelopeSchema } from "../repair/contract.js";
|
|
12
18
|
import { hashJson } from "../preparation/files.js";
|
|
13
19
|
import { parseTrainingMappedPreparation } from "../preparation/contract.js";
|
|
20
|
+
import { persistTrainingGrokCredential } from "./grokWriteback.js";
|
|
21
|
+
import { nativeTrainingSlotsDocument } from "./nativeSlots.js";
|
|
22
|
+
import { createTrainingOutputVolume, trainingOutputVolumeEnabled } from "./outputVolume.js";
|
|
23
|
+
// The image bakes /run/training/inputs as 0:2000 0750 for brokered worker isolation; the
|
|
24
|
+
// non-brokered host-uid evaluator joins that group so it can still traverse its own inputs.
|
|
25
|
+
export const TRAINING_INPUTS_GID = 2_000;
|
|
14
26
|
const inspectFormat = "{{json .Id}}\n{{json .Name}}\n{{json .Image}}\n{{json .Config.Labels}}";
|
|
15
27
|
export const launchTrainingContainer = async (options) => {
|
|
16
28
|
if (options.signal?.aborted)
|
|
17
29
|
return 130;
|
|
18
30
|
const image = trainingImageSchema.parse(options.image);
|
|
31
|
+
const volumeEnabled = trainingOutputVolumeEnabled();
|
|
19
32
|
const uid = process.getuid?.(), gid = process.getgid?.();
|
|
20
33
|
if (uid === undefined || gid === undefined || uid === 0)
|
|
21
34
|
throw Error("Training requires an explicit non-root local user");
|
|
22
35
|
const configBytes = await readFile(options.configPath, "utf8");
|
|
23
36
|
if (Buffer.byteLength(configBytes) > 1024 * 1024)
|
|
24
37
|
throw Error("Training launch config exceeds 1 MiB");
|
|
25
|
-
const
|
|
38
|
+
const raw = JSON.parse(configBytes);
|
|
39
|
+
const prepared = await prepareTrainingContainer(options.execution
|
|
40
|
+
? { ...raw, output: { ...raw.output, source: options.execution.output } } : raw, options.context, options.args, { createOutput: options.execution !== undefined && !options.args.includes("--resume") });
|
|
41
|
+
const execution = options.execution ? mapTrainingExecution(options.execution, file => {
|
|
42
|
+
const absolute = path.resolve(file);
|
|
43
|
+
const binding = [...prepared.config.inputs, prepared.config.output].find(entry => absolute === entry.source || absolute.startsWith(entry.source + path.sep));
|
|
44
|
+
if (!binding)
|
|
45
|
+
throw Error(`Training execution path is not covered by a declared mount: ${file}`);
|
|
46
|
+
return path.posix.join(binding.destination, path.relative(binding.source, absolute).split(path.sep).join("/"));
|
|
47
|
+
}) : undefined;
|
|
48
|
+
if (options.execution)
|
|
49
|
+
await verifyCanonicalPins(prepared.config.inputs.map((input, index) => ({ ...input, id: String(index), digest: "" })), options.execution.datasetPins, prepared.config.inputs.map(input => input.source));
|
|
26
50
|
// D2: the training Grok login is a dedicated one. Refuse the developer's desktop leaf before Docker ever sees it.
|
|
27
|
-
if (prepared.config.broker)
|
|
51
|
+
if (prepared.config.broker) {
|
|
28
52
|
assertNotDesktopGrokAuth(prepared.config.broker.bootstrap);
|
|
53
|
+
const declaration = parseTrainingBrokerDeclaration(JSON.parse(await readFile(prepared.config.broker.declaration, "utf8")));
|
|
54
|
+
if (declaration.slots !== prepared.config.slots)
|
|
55
|
+
throw Error("Training launch and broker declaration slots differ");
|
|
56
|
+
}
|
|
29
57
|
if (options.preparationPath) {
|
|
30
58
|
if (await realpath(options.preparationPath) !== options.preparationPath)
|
|
31
59
|
throw Error("Preparation receipt path must be canonical");
|
|
@@ -46,23 +74,24 @@ export const launchTrainingContainer = async (options) => {
|
|
|
46
74
|
const interrupt = () => { interrupted = true; controller.abort(); };
|
|
47
75
|
const timer = setTimeout(() => { timedOut = true; controller.abort(); }, options.timeoutMs);
|
|
48
76
|
options.signal?.addEventListener("abort", interrupt, { once: true });
|
|
49
|
-
process.
|
|
50
|
-
process.
|
|
77
|
+
process.on("SIGINT", interrupt);
|
|
78
|
+
process.on("SIGTERM", interrupt);
|
|
51
79
|
if (options.signal?.aborted)
|
|
52
80
|
interrupt();
|
|
53
81
|
const prefix = ["--context", prepared.config.dockerContext];
|
|
54
|
-
const call = async (args, cleanup = false, stream = false) => {
|
|
82
|
+
const call = async (args, cleanup = false, stream = false, cleanupTimeoutMs = 10_000) => {
|
|
55
83
|
if (!cleanup && controller.signal.aborted)
|
|
56
84
|
throw Error("Container operation cancelled");
|
|
57
85
|
return execute([...prefix, ...args], {
|
|
58
|
-
timeoutMs: cleanup ?
|
|
86
|
+
timeoutMs: cleanup ? cleanupTimeoutMs : Math.max(1, deadline - Date.now()),
|
|
59
87
|
...(cleanup ? {} : { signal: controller.signal }), ...(stream ? options.streams : {})
|
|
60
88
|
});
|
|
61
89
|
};
|
|
62
90
|
const name = `spawnfile-training-${randomUUID()}`;
|
|
63
91
|
const labels = { "com.spawnfile.training.owner": name };
|
|
64
|
-
let privateRoot, containerId, creationAttempted = false;
|
|
92
|
+
let privateRoot, containerId, creationAttempted = false, startAttempted = false;
|
|
65
93
|
let expectedImage, lastLine = "", closureVerified = false;
|
|
94
|
+
let outputVolume;
|
|
66
95
|
try {
|
|
67
96
|
const endpoint = await execute(["context", "inspect", prepared.config.dockerContext, "--format", "{{json .Endpoints.docker.Host}}"], { timeoutMs: 10_000, signal: controller.signal });
|
|
68
97
|
if (endpoint.code !== 0 || !/^unix:\/\//u.test(JSON.parse(endpoint.stdout)))
|
|
@@ -71,38 +100,69 @@ export const launchTrainingContainer = async (options) => {
|
|
|
71
100
|
expectedImage = inspected.stdout.trim();
|
|
72
101
|
if (inspected.code !== 0 || !/^sha256:[a-f0-9]{64}$/u.test(expectedImage) || (image.startsWith("sha256:") && image !== expectedImage))
|
|
73
102
|
throw Error("Training image must be locally available with an immutable identity");
|
|
103
|
+
if (execution) {
|
|
104
|
+
const capability = await call(["image", "inspect", expectedImage, "--format", `{{json (index .Config.Labels "${TRAINING_EXECUTION_CAPABILITY_LABEL}")}}`]);
|
|
105
|
+
if (capability.code !== 0 || capability.stdout.trim() !== JSON.stringify(TRAINING_EXECUTION_VERSION)) {
|
|
106
|
+
throw Error(`Authored training requires an image implementing --spawnfile-execution ${TRAINING_EXECUTION_FILE} and labelled ${TRAINING_EXECUTION_CAPABILITY_LABEL}=${TRAINING_EXECUTION_VERSION}; legacy Paideia datasets are incompatible`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
74
109
|
privateRoot = await realpath(await mkdtemp(path.join(path.dirname(prepared.config.output.source), ".spawnfile-training-container-")));
|
|
75
110
|
await chmod(privateRoot, 0o700);
|
|
76
111
|
const contextFile = path.join(privateRoot, "context.json");
|
|
77
112
|
await writeFile(contextFile, JSON.stringify(prepared.context), { mode: 0o444, flag: "wx" });
|
|
78
|
-
const
|
|
79
|
-
|
|
113
|
+
const executionFile = path.join(privateRoot, "execution.json");
|
|
114
|
+
if (execution)
|
|
115
|
+
await writeFile(executionFile, JSON.stringify(trainingExecutionSchema.parse(execution)), { mode: 0o444, flag: "wx" });
|
|
116
|
+
const evaluators = await prepareTrainingEvaluators(privateRoot, prepared.config, prepared.args);
|
|
117
|
+
if (volumeEnabled) {
|
|
118
|
+
outputVolume = createTrainingOutputVolume({ name, image: expectedImage, host: prepared.config.output.source, scratch: privateRoot,
|
|
119
|
+
uid, gid, runtimeUid: prepared.config.broker ? 2000 : uid, runtimeGid: prepared.config.broker ? 2000 : gid,
|
|
120
|
+
context: prepared.config.dockerContext, call: (args, cleanup) => call(args, cleanup, false, 120_000), stderr: options.streams.stderr });
|
|
121
|
+
await outputVolume.seed();
|
|
122
|
+
}
|
|
123
|
+
const mounts = [...evaluators.mounts, ...prepared.config.inputs.map((entry) => `type=bind,src=${entry.source},dst=${entry.destination},readonly`),
|
|
124
|
+
outputVolume?.mount ?? `type=bind,src=${prepared.config.output.source},dst=/run/training/output`,
|
|
80
125
|
`type=bind,src=${contextFile},dst=/run/paideia/context.json,readonly`,
|
|
126
|
+
...execution ? [`type=bind,src=${executionFile},dst=${TRAINING_EXECUTION_FILE},readonly`] : [],
|
|
81
127
|
...options.preparationPath ? [`type=bind,src=${options.preparationPath},dst=/run/paideia/preparation.json,readonly`] : [],
|
|
82
128
|
...options.repairPath ? [`type=bind,src=${options.repairPath},dst=/run/paideia/repair.json,readonly`] : [],
|
|
83
129
|
...prepared.config.auth.map((entry) => `type=bind,src=${entry.source},dst=/run/paideia-auth/${entry.provider},readonly`)];
|
|
84
130
|
const broker = prepared.config.broker;
|
|
131
|
+
if (broker) {
|
|
132
|
+
mounts.push(trainingRunRequestMount(prepared.config.output.source, prepared.args));
|
|
133
|
+
const slotsFile = path.join(privateRoot, "slots.json");
|
|
134
|
+
await writeFile(slotsFile, `${JSON.stringify(trainingSlotsDocument(prepared.config.slots))}\n`, { mode: 0o444, flag: "wx" });
|
|
135
|
+
mounts.push(`type=bind,src=${slotsFile},dst=${TRAINING_SLOTS_FILE},readonly`);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
const slotsFile = path.join(privateRoot, "slots.json");
|
|
139
|
+
await writeFile(slotsFile, `${JSON.stringify(nativeTrainingSlotsDocument(prepared.config.slots, uid))}\n`, { mode: 0o444, flag: "wx" });
|
|
140
|
+
mounts.push(`type=bind,src=${slotsFile},dst=${TRAINING_SLOTS_FILE},readonly`);
|
|
141
|
+
}
|
|
85
142
|
// A brokered Grok slot runs the launcher, the broker and the model's own worker uid inside this container, so it
|
|
86
143
|
// starts as root with the production Daimon capability set instead of the host user with no capabilities at all.
|
|
87
144
|
const privilege = broker
|
|
88
145
|
? [...await trainingBrokerSecurityArgs(privateRoot), "--pids-limit", "2048",
|
|
89
|
-
...trainingBrokerTmpfsTargets().flatMap((entry) => ["--tmpfs", `${entry.path}:rw,nosuid,nodev,size=${entry.size},mode=${entry.mode}`])]
|
|
90
|
-
: ["--user", `${uid}:${gid}`, "--cap-drop", "ALL", "--security-opt", "no-new-privileges",
|
|
91
|
-
...DAIMON_CODEX_NATIVE_SANDBOX_DOCKER_SECURITY_OPTS, "--pids-limit",
|
|
92
|
-
"--tmpfs", `/tmp:rw,nosuid,nodev,size
|
|
93
|
-
"--tmpfs", `/home/training:rw,nosuid,nodev,size
|
|
146
|
+
...trainingBrokerTmpfsTargets(prepared.config.slots).flatMap((entry) => ["--tmpfs", `${entry.path}:rw,nosuid,nodev,size=${entry.size},mode=${entry.mode}`])]
|
|
147
|
+
: ["--user", `${uid}:${gid}`, "--group-add", String(TRAINING_INPUTS_GID), "--cap-drop", "ALL", "--security-opt", "no-new-privileges",
|
|
148
|
+
...DAIMON_CODEX_NATIVE_SANDBOX_DOCKER_SECURITY_OPTS, "--pids-limit", String(512 * prepared.config.slots),
|
|
149
|
+
"--tmpfs", `/tmp:rw,nosuid,nodev,size=${prepared.config.slots}g,uid=${uid},gid=${gid},mode=1777`, "--tmpfs", `/work:rw,nosuid,nodev,size=${4 * prepared.config.slots}g,uid=${uid},gid=${gid},mode=700`,
|
|
150
|
+
"--tmpfs", `/home/training:rw,nosuid,nodev,size=${prepared.config.slots}g,uid=${uid},gid=${gid},mode=700`];
|
|
94
151
|
const args = ["create", "--name", name, "--label", `com.spawnfile.training.owner=${name}`,
|
|
95
152
|
"--init", "--read-only", ...privilege,
|
|
96
153
|
"--env", "HOME=/home/training", "--workdir", "/work", "--entrypoint", broker ? TRAINING_BROKER_ENTRYPOINT : "/opt/training/bin/train",
|
|
154
|
+
...(broker ? ["--env", "PAIDEIA_MODEL_REQUEST_CAP=broker"] : []),
|
|
155
|
+
...evaluators.env.flatMap(value => ["--env", value]),
|
|
97
156
|
...[...mounts, ...(broker ? trainingBrokerMounts(broker) : [])].flatMap((mount) => ["--mount", mount]),
|
|
98
157
|
...(prepared.viewerPort === undefined ? [] : ["--publish", `127.0.0.1:${prepared.viewerPort}:${prepared.viewerPort}`]), expectedImage,
|
|
99
|
-
"train", "--spawnfile-context", "/run/paideia/context.json",
|
|
158
|
+
"train", "--spawnfile-context", "/run/paideia/context.json",
|
|
159
|
+
...(execution ? ["--spawnfile-execution", TRAINING_EXECUTION_FILE] : []), ...prepared.args];
|
|
100
160
|
creationAttempted = true;
|
|
101
161
|
const created = await call(args);
|
|
102
162
|
containerId = created.stdout.trim();
|
|
103
163
|
if (created.code !== 0 || !/^[a-f0-9]{64}$/u.test(containerId)) {
|
|
104
164
|
let diagnostic = created.stderr;
|
|
105
|
-
for (const auth of prepared.config.auth)
|
|
165
|
+
for (const auth of [...prepared.config.auth, ...prepared.config.evaluatorSecrets ?? []])
|
|
106
166
|
diagnostic = diagnostic.replaceAll(auth.source, "[auth source]");
|
|
107
167
|
diagnostic = diagnostic.replace(/\p{Cc}/gu, " ").trim().slice(0, 2048);
|
|
108
168
|
throw Error(`Docker did not return a valid training container identity${diagnostic ? `: ${diagnostic}` : ""}`);
|
|
@@ -112,6 +172,7 @@ export const launchTrainingContainer = async (options) => {
|
|
|
112
172
|
throw Error("Training container identity mismatch");
|
|
113
173
|
if (controller.signal.aborted)
|
|
114
174
|
throw Error("Container operation cancelled");
|
|
175
|
+
startAttempted = true;
|
|
115
176
|
const result = await execute([...prefix, "start", "--attach", containerId], {
|
|
116
177
|
timeoutMs: Math.max(1, deadline - Date.now()), signal: controller.signal,
|
|
117
178
|
stdout: (line) => { if (line.trim())
|
|
@@ -121,6 +182,7 @@ export const launchTrainingContainer = async (options) => {
|
|
|
121
182
|
const state = JSON.parse(terminal.stdout);
|
|
122
183
|
if (terminal.code !== 0 || state.Running !== false || !Number.isInteger(state.ExitCode) || result.code !== state.ExitCode)
|
|
123
184
|
throw Error("Training container final state is unverified");
|
|
185
|
+
await outputVolume?.export();
|
|
124
186
|
if (state.ExitCode !== 0 && state.ExitCode !== 1)
|
|
125
187
|
return state.ExitCode;
|
|
126
188
|
const receipt = JSON.parse(lastLine);
|
|
@@ -140,9 +202,6 @@ export const launchTrainingContainer = async (options) => {
|
|
|
140
202
|
}
|
|
141
203
|
finally {
|
|
142
204
|
clearTimeout(timer);
|
|
143
|
-
options.signal?.removeEventListener("abort", interrupt);
|
|
144
|
-
process.removeListener("SIGINT", interrupt);
|
|
145
|
-
process.removeListener("SIGTERM", interrupt);
|
|
146
205
|
try {
|
|
147
206
|
if (creationAttempted) {
|
|
148
207
|
// A timed-out create may still have created our uniquely labelled container.
|
|
@@ -151,11 +210,28 @@ export const launchTrainingContainer = async (options) => {
|
|
|
151
210
|
const id = JSON.parse(found.stdout.split("\n")[0]);
|
|
152
211
|
if (typeof id !== "string" || parseDetachedContainerInspect(found.stdout, id, labels, name).imageId !== expectedImage || (containerId && /^[a-f0-9]{64}$/u.test(containerId) && id !== containerId))
|
|
153
212
|
throw Error("Refusing cleanup of unverified training container");
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
213
|
+
try {
|
|
214
|
+
if (startAttempted) {
|
|
215
|
+
const current = await call(["inspect", "--format", "{{json .State}}", id], true);
|
|
216
|
+
if (current.code !== 0)
|
|
217
|
+
throw Error("Cannot verify training writer state");
|
|
218
|
+
if (JSON.parse(current.stdout).Running === true) {
|
|
219
|
+
const stopped = await call(["stop", "--time", "5", id], true);
|
|
220
|
+
if (stopped.code !== 0)
|
|
221
|
+
throw Error("Cannot stop training output writer");
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (startAttempted && prepared.config.broker && privateRoot) {
|
|
225
|
+
await persistTrainingGrokCredential(id, prepared.config.broker.bootstrap, privateRoot, call);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
finally {
|
|
229
|
+
const removed = await call(["rm", "--force", id], true);
|
|
230
|
+
const remaining = await call(["container", "ls", "--all", "--no-trunc", "--filter", `id=${id}`, "--format", "{{.ID}}"], true);
|
|
231
|
+
if (removed.code !== 0 || remaining.code !== 0 || remaining.stdout.trim())
|
|
232
|
+
throw Error("Training container cleanup is unverified");
|
|
233
|
+
closureVerified = true;
|
|
234
|
+
}
|
|
159
235
|
}
|
|
160
236
|
else {
|
|
161
237
|
const remaining = await call(["container", "ls", "--all", "--filter", `name=^/${name}$`, "--format", "{{.ID}}"], true);
|
|
@@ -166,8 +242,23 @@ export const launchTrainingContainer = async (options) => {
|
|
|
166
242
|
}
|
|
167
243
|
}
|
|
168
244
|
finally {
|
|
169
|
-
|
|
170
|
-
|
|
245
|
+
try {
|
|
246
|
+
const closed = !creationAttempted || closureVerified;
|
|
247
|
+
try {
|
|
248
|
+
if (closed)
|
|
249
|
+
await outputVolume?.export();
|
|
250
|
+
}
|
|
251
|
+
finally {
|
|
252
|
+
await outputVolume?.dispose(closed);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
finally {
|
|
256
|
+
options.signal?.removeEventListener("abort", interrupt);
|
|
257
|
+
process.removeListener("SIGINT", interrupt);
|
|
258
|
+
process.removeListener("SIGTERM", interrupt);
|
|
259
|
+
if (privateRoot && (!creationAttempted || closureVerified) && (!outputVolume || outputVolume.safeToCleanup()))
|
|
260
|
+
await removeTrainingPreparationScratch(privateRoot);
|
|
261
|
+
}
|
|
171
262
|
}
|
|
172
263
|
}
|
|
173
264
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Native trials keep fresh per-trial roots; only their port blocks are provisioned. */
|
|
2
|
+
export declare const nativeTrainingSlotsDocument: (slots: number, workerUid: number) => {
|
|
3
|
+
schema: "spawnfile.training-slots.v2";
|
|
4
|
+
slots: {
|
|
5
|
+
index: number;
|
|
6
|
+
workerUid: number;
|
|
7
|
+
isolation: "shared-uid";
|
|
8
|
+
roots: {};
|
|
9
|
+
ports: {
|
|
10
|
+
base: number;
|
|
11
|
+
count: number;
|
|
12
|
+
};
|
|
13
|
+
}[];
|
|
14
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { assertTrainingSlotCount, TRAINING_PORT_BASE, TRAINING_PORT_STRIDE } from "../broker/paths.js";
|
|
2
|
+
/** Native trials keep fresh per-trial roots; only their port blocks are provisioned. */
|
|
3
|
+
export const nativeTrainingSlotsDocument = (slots, workerUid) => {
|
|
4
|
+
if (!Number.isInteger(workerUid) || workerUid <= 0 || workerUid > 4_294_967_294)
|
|
5
|
+
throw Error("Native slots require a non-root worker uid");
|
|
6
|
+
return {
|
|
7
|
+
schema: "spawnfile.training-slots.v2",
|
|
8
|
+
slots: Array.from({ length: assertTrainingSlotCount(slots) }, (_, index) => ({
|
|
9
|
+
index, workerUid, isolation: "shared-uid", roots: {},
|
|
10
|
+
ports: { base: TRAINING_PORT_BASE + index * TRAINING_PORT_STRIDE, count: TRAINING_PORT_STRIDE }
|
|
11
|
+
}))
|
|
12
|
+
};
|
|
13
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/** Runs only in the verified Linux training image. No project code is imported. */
|
|
2
|
+
export const trainingOutputCopyProgram = String.raw `
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const [source, destination, owner, group] = process.argv.slice(1);
|
|
6
|
+
const uid = Number(owner), gid = Number(group);
|
|
7
|
+
const limits = { entries: 1_000_000, bytes: 64 * 1024 ** 3, depth: 64 };
|
|
8
|
+
let entries = 0, bytes = 0;
|
|
9
|
+
const links = new Map();
|
|
10
|
+
const buffer = Buffer.alloc(1024 * 1024);
|
|
11
|
+
// Linux fd-relative traversal keeps renamed directories and symlink swaps from
|
|
12
|
+
// redirecting reads/writes outside the two mounts. The fallback permits local QA.
|
|
13
|
+
const fdPath = (fd, file) => process.platform === 'linux' ? '/proc/self/fd/' + fd : file;
|
|
14
|
+
const directory = fs.constants.O_RDONLY | fs.constants.O_DIRECTORY | fs.constants.O_NOFOLLOW;
|
|
15
|
+
function copy(src, dst, depth) {
|
|
16
|
+
if (++entries > limits.entries || depth > limits.depth) throw Error('Output tree exceeds entry/depth limit');
|
|
17
|
+
const info = fs.lstatSync(src);
|
|
18
|
+
if (info.isSymbolicLink()) {
|
|
19
|
+
const target = fs.readlinkSync(src);
|
|
20
|
+
bytes += Buffer.byteLength(target);
|
|
21
|
+
if (bytes > limits.bytes) throw Error('Output exceeds 64 GiB');
|
|
22
|
+
fs.symlinkSync(target, dst); fs.lchownSync(dst, uid, gid);
|
|
23
|
+
fs.lutimesSync(dst, info.atime, info.mtime);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (info.isDirectory()) {
|
|
27
|
+
const input = fs.openSync(src, directory);
|
|
28
|
+
let output;
|
|
29
|
+
try {
|
|
30
|
+
if (depth !== 0) fs.mkdirSync(dst, { mode: 0o700 });
|
|
31
|
+
output = fs.openSync(dst, directory);
|
|
32
|
+
fs.fchownSync(output, uid, gid);
|
|
33
|
+
const from = fdPath(input, src), to = fdPath(output, dst);
|
|
34
|
+
if (depth === 0 && fs.readdirSync(to).length) throw Error('Output copy destination must be empty');
|
|
35
|
+
for (const name of fs.readdirSync(from)) copy(path.join(from, name), path.join(to, name), depth + 1);
|
|
36
|
+
fs.fchownSync(output, uid, gid); fs.fchmodSync(output, info.mode & 0o7777);
|
|
37
|
+
fs.futimesSync(output, info.atime, info.mtime); fs.fsyncSync(output);
|
|
38
|
+
} finally { if (output !== undefined) fs.closeSync(output); fs.closeSync(input); }
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (!info.isFile()) throw Error('Output contains a special file');
|
|
42
|
+
const input = fs.openSync(src, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK);
|
|
43
|
+
let output;
|
|
44
|
+
try {
|
|
45
|
+
const opened = fs.fstatSync(input);
|
|
46
|
+
if (!opened.isFile() || opened.dev !== info.dev || opened.ino !== info.ino) throw Error('Output changed during copy');
|
|
47
|
+
const key = info.dev + ':' + info.ino;
|
|
48
|
+
// Store a path rooted at the destination mount, not an fd that closes after recursion.
|
|
49
|
+
const previous = links.get(key);
|
|
50
|
+
if (previous) { fs.linkSync(previous, dst); return; }
|
|
51
|
+
bytes += info.size;
|
|
52
|
+
if (bytes > limits.bytes) throw Error('Output exceeds 64 GiB');
|
|
53
|
+
output = fs.openSync(dst, fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_NOFOLLOW, 0o600);
|
|
54
|
+
fs.fchownSync(output, uid, gid);
|
|
55
|
+
let position = 0;
|
|
56
|
+
while (position < info.size) {
|
|
57
|
+
const count = fs.readSync(input, buffer, 0, Math.min(buffer.length, info.size - position), position);
|
|
58
|
+
if (!count) throw Error('Output truncated during copy');
|
|
59
|
+
let written = 0;
|
|
60
|
+
while (written < count) written += fs.writeSync(output, buffer, written, count - written);
|
|
61
|
+
position += count;
|
|
62
|
+
}
|
|
63
|
+
const after = fs.fstatSync(input);
|
|
64
|
+
if (after.size !== info.size || after.mtimeMs !== info.mtimeMs) throw Error('Output changed during copy');
|
|
65
|
+
fs.fchownSync(output, uid, gid); fs.fchmodSync(output, info.mode & 0o7777);
|
|
66
|
+
fs.futimesSync(output, info.atime, info.mtime); fs.fsyncSync(output);
|
|
67
|
+
links.set(key, fs.realpathSync(dst));
|
|
68
|
+
} finally { if (output !== undefined) fs.closeSync(output); fs.closeSync(input); }
|
|
69
|
+
}
|
|
70
|
+
copy(source, destination, 0);
|
|
71
|
+
console.log('spawnfile-output-copy-complete');
|
|
72
|
+
`;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
type DockerCall = (args: string[], cleanup?: boolean) => Promise<{
|
|
2
|
+
code: number;
|
|
3
|
+
stdout: string;
|
|
4
|
+
stderr: string;
|
|
5
|
+
}>;
|
|
6
|
+
export declare const trainingOutputVolumeEnabled: () => boolean;
|
|
7
|
+
/** One launch owns this volume; budgets and auth volumes are never touched. */
|
|
8
|
+
export declare const createTrainingOutputVolume: (options: {
|
|
9
|
+
name: string;
|
|
10
|
+
image: string;
|
|
11
|
+
host: string;
|
|
12
|
+
scratch: string;
|
|
13
|
+
uid: number;
|
|
14
|
+
gid: number;
|
|
15
|
+
runtimeUid: number;
|
|
16
|
+
runtimeGid: number;
|
|
17
|
+
context: string;
|
|
18
|
+
call: DockerCall;
|
|
19
|
+
stderr(line: string): void;
|
|
20
|
+
}) => {
|
|
21
|
+
safeToCleanup: () => boolean;
|
|
22
|
+
mount: string;
|
|
23
|
+
seed(): Promise<void>;
|
|
24
|
+
export(): Promise<void>;
|
|
25
|
+
dispose(closureVerified: boolean): Promise<void>;
|
|
26
|
+
};
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { lstat, mkdir, open, realpath, rename } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { parseDetachedContainerInspect } from "../../runProjectDocker.js";
|
|
5
|
+
import { trainingOutputCopyProgram } from "./outputCopy.js";
|
|
6
|
+
const ownerLabel = "com.spawnfile.training.owner";
|
|
7
|
+
const inspectFormat = "{{json .Id}}\n{{json .Name}}\n{{json .Image}}\n{{json .Config.Labels}}";
|
|
8
|
+
const target = "/run/training/output";
|
|
9
|
+
export const trainingOutputVolumeEnabled = () => {
|
|
10
|
+
const setting = process.env.SPAWNFILE_TRAINING_OUTPUT_STORAGE;
|
|
11
|
+
if (setting !== undefined && setting !== "volume" && setting !== "bind")
|
|
12
|
+
throw Error("SPAWNFILE_TRAINING_OUTPUT_STORAGE must be volume or bind");
|
|
13
|
+
return setting !== "bind";
|
|
14
|
+
};
|
|
15
|
+
/** One launch owns this volume; budgets and auth volumes are never touched. */
|
|
16
|
+
export const createTrainingOutputVolume = (options) => {
|
|
17
|
+
const { call } = options;
|
|
18
|
+
const volume = `${options.name}-output`;
|
|
19
|
+
let attempted = false, seeded = false, exported = false, exportAttempted = false, helperClosed = true;
|
|
20
|
+
const recovery = () => `Training output retained in Docker volume ${volume}. Recover with: docker --context ${options.context} run --rm --network none --read-only --mount type=volume,src=${volume},dst=/output,readonly --entrypoint /bin/tar ${options.image} -C /output -cpf - . > training-output-recovery.tar`;
|
|
21
|
+
const owned = async () => {
|
|
22
|
+
const result = await call(["volume", "inspect", volume, "--format", "{{json .}}"], true);
|
|
23
|
+
if (result.code !== 0) {
|
|
24
|
+
const listed = await call(["volume", "ls", "--filter", `name=^${volume}$`, "--format", "{{.Name}}"], true);
|
|
25
|
+
if (listed.code === 0 && !listed.stdout.trim())
|
|
26
|
+
return false;
|
|
27
|
+
throw Error("Training output volume closure is unknown");
|
|
28
|
+
}
|
|
29
|
+
const info = JSON.parse(result.stdout);
|
|
30
|
+
if (info.Name !== volume || info.Driver !== "local" || (info.Options && Object.keys(info.Options).length) || info.Labels?.[ownerLabel] !== options.name)
|
|
31
|
+
throw Error("Refusing unverified training output volume");
|
|
32
|
+
return true;
|
|
33
|
+
};
|
|
34
|
+
const transfer = async (direction) => {
|
|
35
|
+
if (!await owned())
|
|
36
|
+
throw Error("Training output volume is missing");
|
|
37
|
+
const name = `${volume}-${direction}`;
|
|
38
|
+
const labels = { [ownerLabel]: name };
|
|
39
|
+
const hostStage = path.join(options.scratch, "output-export");
|
|
40
|
+
if (direction === "export")
|
|
41
|
+
await mkdir(hostStage, { mode: 0o700 });
|
|
42
|
+
const mounts = direction === "seed"
|
|
43
|
+
? [`type=bind,src=${options.host},dst=/source,readonly`, `type=volume,src=${volume},dst=/destination,volume-nocopy`]
|
|
44
|
+
: [`type=volume,src=${volume},dst=/source,readonly,volume-nocopy`, `type=bind,src=${hostStage},dst=/destination`];
|
|
45
|
+
let creationAttempted = false, containerId;
|
|
46
|
+
try {
|
|
47
|
+
creationAttempted = true;
|
|
48
|
+
helperClosed = false;
|
|
49
|
+
const created = await call(["container", "create", "--name", name, "--label", `${ownerLabel}=${name}`,
|
|
50
|
+
"--network", "none", "--read-only", "--user", "0:0", "--security-opt", "no-new-privileges",
|
|
51
|
+
// Retain only Docker's default CHOWN, DAC_OVERRIDE, FOWNER and FSETID for copying
|
|
52
|
+
// private runtime files and assigning the native/broker uid. No cap-add.
|
|
53
|
+
...["AUDIT_WRITE", "KILL", "MKNOD", "NET_BIND_SERVICE", "NET_RAW", "SETFCAP", "SETGID", "SETPCAP", "SETUID", "SYS_CHROOT"].flatMap(cap => ["--cap-drop", cap]),
|
|
54
|
+
"--pids-limit", "32", "--memory", "256m", "--cpus", "1", "--workdir", "/",
|
|
55
|
+
...mounts.flatMap(mount => ["--mount", mount]), "--entrypoint", "node", options.image,
|
|
56
|
+
"-e", trainingOutputCopyProgram, "/source", "/destination",
|
|
57
|
+
String(direction === "seed" ? options.runtimeUid : options.uid), String(direction === "seed" ? options.runtimeGid : options.gid)], direction === "export");
|
|
58
|
+
const id = created.stdout.trim();
|
|
59
|
+
containerId = id;
|
|
60
|
+
if (created.code !== 0 || !/^[a-f0-9]{64}$/u.test(id))
|
|
61
|
+
throw Error(`Cannot create training output ${direction} helper`);
|
|
62
|
+
const checked = await call(["container", "inspect", "--format", inspectFormat, name], true);
|
|
63
|
+
if (checked.code !== 0 || parseDetachedContainerInspect(checked.stdout, id, labels, name).imageId !== options.image)
|
|
64
|
+
throw Error("Training output helper identity mismatch");
|
|
65
|
+
const result = await call(["container", "start", "--attach", id], direction === "export");
|
|
66
|
+
const terminal = await call(["container", "inspect", "--format", "{{json .State}}", id], true);
|
|
67
|
+
const state = JSON.parse(terminal.stdout);
|
|
68
|
+
if (result.code !== 0 || result.stdout.trim() !== "spawnfile-output-copy-complete" || terminal.code !== 0 || state.Running !== false || state.ExitCode !== 0)
|
|
69
|
+
throw Error(`Training output ${direction} failed (copy incomplete or exceeds limits): ${result.stderr.replace(/\p{Cc}/gu, " ").slice(0, 2048)}`);
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
if (creationAttempted) {
|
|
73
|
+
const found = await call(["container", "inspect", "--format", inspectFormat, name], true);
|
|
74
|
+
if (found.code === 0) {
|
|
75
|
+
const id = JSON.parse(found.stdout.split("\n")[0]);
|
|
76
|
+
if (typeof id !== "string" || parseDetachedContainerInspect(found.stdout, id, labels, name).imageId !== options.image || (containerId && /^[a-f0-9]{64}$/u.test(containerId) && id !== containerId))
|
|
77
|
+
throw Error("Refusing cleanup of unverified training output helper");
|
|
78
|
+
const removed = await call(["container", "rm", "--force", id], true);
|
|
79
|
+
if (removed.code !== 0)
|
|
80
|
+
throw Error("Cannot remove training output helper");
|
|
81
|
+
}
|
|
82
|
+
const remaining = await call(["container", "ls", "--all", "--filter", `name=^/${name}$`, "--format", "{{.ID}}"], true);
|
|
83
|
+
if (remaining.code !== 0 || remaining.stdout.trim())
|
|
84
|
+
throw Error("Training output helper closure is unknown");
|
|
85
|
+
helperClosed = true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (direction === "export") {
|
|
89
|
+
if (await realpath(options.host) !== options.host || !(await lstat(options.host)).isDirectory())
|
|
90
|
+
throw Error("Training host output changed before export");
|
|
91
|
+
const backup = path.join(options.scratch, "output-before-export");
|
|
92
|
+
await rename(options.host, backup);
|
|
93
|
+
try {
|
|
94
|
+
await rename(hostStage, options.host);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
await rename(backup, options.host);
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
for (const directory of [options.scratch, path.dirname(options.host)]) {
|
|
101
|
+
const handle = await open(directory, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
|
|
102
|
+
try {
|
|
103
|
+
await handle.sync();
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
await handle.close();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
return {
|
|
112
|
+
safeToCleanup: () => helperClosed && (!exportAttempted || exported),
|
|
113
|
+
mount: `type=volume,src=${volume},dst=${target},volume-nocopy`,
|
|
114
|
+
async seed() {
|
|
115
|
+
attempted = true;
|
|
116
|
+
const created = await call(["volume", "create", "--driver", "local", "--label", `${ownerLabel}=${options.name}`, volume]);
|
|
117
|
+
if (created.code !== 0 || created.stdout.trim() !== volume || !await owned())
|
|
118
|
+
throw Error("Cannot create owned training output volume");
|
|
119
|
+
await transfer("seed");
|
|
120
|
+
seeded = true;
|
|
121
|
+
options.stderr(`Training output uses VM-local volume ${volume}; host checkpoints update at exit.`);
|
|
122
|
+
},
|
|
123
|
+
async export() {
|
|
124
|
+
if (!seeded || exportAttempted)
|
|
125
|
+
return;
|
|
126
|
+
exportAttempted = true;
|
|
127
|
+
try {
|
|
128
|
+
await transfer("export");
|
|
129
|
+
exported = true;
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
options.stderr(`Training output export failed: ${error instanceof Error ? error.message : "unknown failure"}. Scratch retained at ${options.scratch}. ${recovery()}`);
|
|
133
|
+
throw Error(`Training output export failed. ${recovery()}`, { cause: error });
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
async dispose(closureVerified) {
|
|
137
|
+
if (!attempted)
|
|
138
|
+
return;
|
|
139
|
+
try {
|
|
140
|
+
if (!await owned())
|
|
141
|
+
return;
|
|
142
|
+
if (!helperClosed)
|
|
143
|
+
throw Error("Training output helper closure is unverified");
|
|
144
|
+
if (!closureVerified) {
|
|
145
|
+
options.stderr(recovery());
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (seeded && !exported)
|
|
149
|
+
throw Error("Training output has not been exported");
|
|
150
|
+
const removed = await call(["volume", "rm", volume], true);
|
|
151
|
+
const remaining = await call(["volume", "ls", "--filter", `name=^${volume}$`, "--format", "{{.Name}}"], true);
|
|
152
|
+
if (removed.code !== 0 || remaining.code !== 0 || remaining.stdout.trim())
|
|
153
|
+
throw Error("Training output volume removal is unverified");
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
options.stderr(recovery());
|
|
157
|
+
throw Error(recovery(), { cause: error });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type TrainingContext } from "../contract.js";
|
|
2
2
|
import { type TrainingContainerConfig } from "./contract.js";
|
|
3
|
-
export declare const prepareTrainingContainer: (raw: unknown, context: TrainingContext, args: readonly string[]
|
|
3
|
+
export declare const prepareTrainingContainer: (raw: unknown, context: TrainingContext, args: readonly string[], options?: {
|
|
4
|
+
createOutput?: boolean;
|
|
5
|
+
}) => Promise<{
|
|
4
6
|
config: TrainingContainerConfig;
|
|
5
7
|
context: TrainingContext;
|
|
6
8
|
args: string[];
|