spawnfile 0.1.14 → 0.1.17
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 +60 -159
- package/dist/audit/checksShared.d.ts +1 -1
- package/dist/auth/importers.d.ts +10 -0
- package/dist/auth/importers.js +29 -4
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.js +1 -0
- package/dist/auth/paths.d.ts +1 -1
- package/dist/auth/profileStore.js +9 -9
- package/dist/auth/targetSecretSourceFsIdentity.d.ts +40 -0
- package/dist/auth/targetSecretSourceFsIdentity.js +42 -0
- package/dist/auth/targetSecretSourceFsPublish.d.ts +2 -0
- package/dist/auth/targetSecretSourceFsPublish.js +3 -1
- package/dist/auth/targetSecretSourceFsPublishImmutable.d.ts +2 -1
- package/dist/auth/targetSecretSourceFsPublishImmutable.js +104 -71
- package/dist/auth/targetSecretSourceFsRead.js +5 -14
- package/dist/auth/trainingAuth.d.ts +21 -0
- package/dist/auth/trainingAuth.js +86 -0
- package/dist/auth/types.d.ts +1 -1
- package/dist/cli/authCommands.d.ts +1 -1
- package/dist/cli/authCommands.js +9 -0
- package/dist/cli/canaryCutoverCommand.d.ts +2 -0
- package/dist/cli/canaryCutoverCommand.js +30 -0
- package/dist/cli/capabilitiesCommand.d.ts +3 -0
- package/dist/cli/capabilitiesCommand.js +12 -0
- package/dist/cli/capabilitiesReceipt.d.ts +56 -0
- package/dist/cli/capabilitiesReceipt.js +56 -0
- package/dist/cli/compileBuildCommands.js +13 -0
- package/dist/cli/composedLifecycleContractSet.d.ts +21 -0
- package/dist/cli/composedLifecycleContractSet.js +204 -0
- package/dist/cli/devCommands.js +2 -0
- package/dist/cli/downCommand.js +19 -8
- package/dist/cli/evidenceExportHelperCommand.d.ts +13 -0
- package/dist/cli/evidenceExportHelperCommand.js +51 -0
- package/dist/cli/index.js +12 -3
- package/dist/cli/lifecycleMachine.d.ts +7 -1
- package/dist/cli/lifecycleMachine.js +2 -2
- package/dist/cli/paideiaDelegation.d.ts +17 -0
- package/dist/cli/paideiaDelegation.js +210 -0
- package/dist/cli/paideiaSupervisor.d.ts +17 -0
- package/dist/cli/paideiaSupervisor.js +48 -0
- package/dist/cli/productStateCloneCommand.d.ts +2 -0
- package/dist/cli/productStateCloneCommand.js +34 -0
- package/dist/cli/runCli.d.ts +13 -3
- package/dist/cli/runCli.js +37 -9
- package/dist/cli/targetCommands.d.ts +4 -7
- package/dist/cli/targetCommands.js +16 -46
- package/dist/cli/targetConfigPreparedPlan.d.ts +3 -0
- package/dist/cli/targetConfigPreparedPlan.js +74 -0
- package/dist/cli/targetConfigResolver.d.ts +3 -0
- package/dist/cli/targetConfigResolver.js +111 -0
- package/dist/cli/targetConfigResolverCommand.d.ts +6 -0
- package/dist/cli/targetConfigResolverCommand.js +43 -0
- package/dist/cli/targetConfigResolverContracts.d.ts +56 -0
- package/dist/cli/targetConfigResolverContracts.js +30 -0
- package/dist/cli/targetConfigResolverDocker.d.ts +4 -0
- package/dist/cli/targetConfigResolverDocker.js +47 -0
- package/dist/cli/targetConfigResolverValidation.d.ts +10 -0
- package/dist/cli/targetConfigResolverValidation.js +94 -0
- package/dist/cli/targetDefaultAuthorities.d.ts +2 -0
- package/dist/cli/targetDefaultAuthorities.js +3 -0
- package/dist/cli/targetDefaultConfig.d.ts +7 -0
- package/dist/cli/targetDefaultConfig.js +22 -5
- package/dist/cli/targetDefaultConfigStdin.js +7 -1
- package/dist/cli/targetDefaultHandlerFactory.js +23 -2
- package/dist/cli/targetDefaultHandlers.d.ts +2 -2
- package/dist/cli/targetProductionCommands.d.ts +5 -0
- package/dist/cli/targetProductionCommands.js +45 -0
- package/dist/cli/trainCommand.d.ts +3 -0
- package/dist/cli/trainCommand.js +61 -0
- package/dist/cli/upCommand.js +35 -6
- package/dist/cli/upLifecycleRecovery.d.ts +2 -2
- package/dist/cli/upLifecycleRecovery.js +188 -44
- package/dist/cli/usageCommand.d.ts +40 -0
- package/dist/cli/usageCommand.js +284 -0
- package/dist/cli/usageCommandLive.d.ts +84 -0
- package/dist/cli/usageCommandLive.js +95 -0
- package/dist/cli/usageDeploymentSource.d.ts +9 -0
- package/dist/cli/usageDeploymentSource.js +22 -0
- package/dist/cli/workspaceResourceMigrationCommand.d.ts +8 -0
- package/dist/cli/workspaceResourceMigrationCommand.js +36 -0
- package/dist/compiler/buildCompilePlanTeams.d.ts +1 -1
- package/dist/compiler/buildCompilePlanTeams.js +6 -1
- package/dist/compiler/compilePlanHelpers.js +3 -0
- package/dist/compiler/compileProject.d.ts +2 -0
- package/dist/compiler/compileProject.js +5 -1
- package/dist/compiler/compileProjectSupport.js +9 -0
- package/dist/compiler/containerArtifacts.d.ts +3 -1
- package/dist/compiler/containerArtifacts.js +92 -40
- package/dist/compiler/containerArtifactsPlans.d.ts +1 -1
- package/dist/compiler/containerArtifactsPlans.js +24 -7
- package/dist/compiler/containerArtifactsRender.d.ts +2 -1
- package/dist/compiler/containerArtifactsRender.js +91 -58
- package/dist/compiler/containerArtifactsTypes.d.ts +8 -0
- package/dist/compiler/containerBackedMountRender.d.ts +56 -0
- package/dist/compiler/containerBackedMountRender.js +101 -0
- package/dist/compiler/containerDaimonBrokerRender.d.ts +112 -0
- package/dist/compiler/containerDaimonBrokerRender.js +191 -0
- package/dist/compiler/containerDaimonGrokWorkerProvisioning.d.ts +38 -0
- package/dist/compiler/containerDaimonGrokWorkerProvisioning.js +108 -0
- package/dist/compiler/containerDaimonGrokWorkerRender.d.ts +172 -0
- package/dist/compiler/containerDaimonGrokWorkerRender.js +268 -0
- package/dist/compiler/containerDaimonOwnershipGuardRender.d.ts +12 -0
- package/dist/compiler/containerDaimonOwnershipGuardRender.js +191 -0
- package/dist/compiler/containerDaimonUidEntrypointRender.d.ts +24 -0
- package/dist/compiler/containerDaimonUidEntrypointRender.js +297 -0
- package/dist/compiler/containerEntrypointRender.d.ts +7 -0
- package/dist/compiler/containerEntrypointRender.js +28 -22
- package/dist/compiler/containerPersistentMounts.d.ts +30 -0
- package/dist/compiler/containerPersistentMounts.js +66 -0
- package/dist/compiler/containerReadinessPaths.d.ts +1 -0
- package/dist/compiler/containerReadinessPaths.js +1 -0
- package/dist/compiler/containerRuntimeLinkMaterializer.d.ts +2 -0
- package/dist/compiler/containerRuntimeLinkMaterializer.js +12 -0
- package/dist/compiler/containerRuntimeReadinessRender.d.ts +7 -0
- package/dist/compiler/containerRuntimeReadinessRender.js +40 -0
- package/dist/compiler/containerStateOwnershipRender.d.ts +4 -0
- package/dist/compiler/containerStateOwnershipRender.js +75 -0
- package/dist/compiler/containerTargetResources.d.ts +22 -1
- package/dist/compiler/containerTargetResources.js +94 -2
- package/dist/compiler/containerVolumeBootstrap.d.ts +3 -0
- package/dist/compiler/containerVolumeBootstrap.js +3 -0
- package/dist/compiler/containerWorkspaceResourceRender.js +49 -1
- package/dist/compiler/daimonTelemetryArtifacts.d.ts +2 -2
- package/dist/compiler/daimonTelemetryArtifacts.js +5 -10
- package/dist/compiler/deploymentLineage.d.ts +40 -0
- package/dist/compiler/deploymentLineage.js +50 -0
- package/dist/compiler/index.d.ts +3 -0
- package/dist/compiler/index.js +3 -0
- package/dist/compiler/initProject.d.ts +2 -0
- package/dist/compiler/initProject.js +39 -1
- package/dist/compiler/localMoltnetAuthority.d.ts +64 -0
- package/dist/compiler/localMoltnetAuthority.js +177 -0
- package/dist/compiler/memoryArtifacts.d.ts +1 -1
- package/dist/compiler/memoryArtifacts.js +108 -32
- package/dist/compiler/modelEnv.d.ts +5 -0
- package/dist/compiler/modelEnv.js +8 -2
- package/dist/compiler/moltnetArtifactPaths.d.ts +17 -12
- package/dist/compiler/moltnetArtifactPaths.js +17 -15
- package/dist/compiler/moltnetArtifactTypes.d.ts +10 -0
- package/dist/compiler/moltnetArtifacts.d.ts +1 -1
- package/dist/compiler/moltnetArtifacts.js +52 -12
- package/dist/compiler/moltnetBinaries.d.ts +16 -4
- package/dist/compiler/moltnetBinaries.js +46 -6
- package/dist/compiler/moltnetClientConfig.js +1 -1
- package/dist/compiler/moltnetConfigLowering.d.ts +3 -1
- package/dist/compiler/moltnetConfigLowering.js +30 -6
- package/dist/compiler/moltnetNodeConfig.js +1 -1
- package/dist/compiler/moltnetReleaseAuthority.d.ts +24 -1
- package/dist/compiler/moltnetReleaseAuthority.js +33 -4
- package/dist/compiler/moltnetRepresentativeResolution.d.ts +1 -1
- package/dist/compiler/moltnetRepresentativeResolution.js +2 -2
- package/dist/compiler/moltnetResolution.js +9 -15
- package/dist/compiler/moltnetRoomMemberships.js +20 -5
- package/dist/compiler/moltnetRoomPolicyCompatibility.d.ts +1 -1
- package/dist/compiler/moltnetRoomPolicyCompatibility.js +3 -1
- package/dist/compiler/moltnetRuntimeConfig.d.ts +1 -1
- package/dist/compiler/moltnetRuntimeConfig.js +22 -2
- package/dist/compiler/moltnetServerPlans.js +19 -0
- package/dist/compiler/organizationExternalParticipants.d.ts +3 -0
- package/dist/compiler/organizationExternalParticipants.js +176 -0
- package/dist/compiler/organizationIdentity.d.ts +3 -9
- package/dist/compiler/organizationIdentity.js +37 -270
- package/dist/compiler/organizationIdentityGraph.d.ts +15 -0
- package/dist/compiler/organizationIdentityGraph.js +115 -0
- package/dist/compiler/organizationReadyEvidence.d.ts +8 -0
- package/dist/compiler/organizationReadyEvidence.js +23 -3
- package/dist/compiler/runProject.d.ts +4 -2
- package/dist/compiler/runProject.js +32 -6
- package/dist/compiler/runProjectAuth.d.ts +3 -1
- package/dist/compiler/runProjectAuth.js +19 -3
- package/dist/compiler/runProjectDaimonCodexDocker.d.ts +3 -0
- package/dist/compiler/runProjectDaimonCodexDocker.js +36 -0
- package/dist/compiler/runProjectDocker.d.ts +8 -4
- package/dist/compiler/runProjectDocker.js +43 -18
- package/dist/compiler/runProjectDockerDaimonGuards.d.ts +15 -0
- package/dist/compiler/runProjectDockerDaimonGuards.js +122 -0
- package/dist/compiler/runProjectDockerReservation.d.ts +3 -0
- package/dist/compiler/runProjectDockerReservation.js +118 -0
- package/dist/compiler/runProjectLifecycle.js +1 -1
- package/dist/compiler/training/broker/declaration.d.ts +45 -0
- package/dist/compiler/training/broker/declaration.js +55 -0
- package/dist/compiler/training/broker/entrypoint.d.ts +39 -0
- package/dist/compiler/training/broker/entrypoint.js +111 -0
- package/dist/compiler/training/broker/index.d.ts +10 -0
- package/dist/compiler/training/broker/index.js +10 -0
- package/dist/compiler/training/broker/main.d.ts +2 -0
- package/dist/compiler/training/broker/main.js +14 -0
- package/dist/compiler/training/broker/paths.d.ts +196 -0
- package/dist/compiler/training/broker/paths.js +241 -0
- package/dist/compiler/training/broker/processes.d.ts +42 -0
- package/dist/compiler/training/broker/processes.js +99 -0
- package/dist/compiler/training/broker/projection.d.ts +51 -0
- package/dist/compiler/training/broker/projection.js +76 -0
- package/dist/compiler/training/broker/provisioning.d.ts +87 -0
- package/dist/compiler/training/broker/provisioning.js +213 -0
- package/dist/compiler/training/broker/receipt.d.ts +77 -0
- package/dist/compiler/training/broker/receipt.js +110 -0
- package/dist/compiler/training/broker/registration.d.ts +41 -0
- package/dist/compiler/training/broker/registration.js +102 -0
- package/dist/compiler/training/broker/runtime.d.ts +25 -0
- package/dist/compiler/training/broker/runtime.js +173 -0
- package/dist/compiler/training/broker/seccompRoutes.d.ts +31 -0
- package/dist/compiler/training/broker/seccompRoutes.js +36 -0
- package/dist/compiler/training/broker/supervisor.d.ts +109 -0
- package/dist/compiler/training/broker/supervisor.js +173 -0
- package/dist/compiler/training/container/contract.d.ts +31 -0
- package/dist/compiler/training/container/contract.js +33 -0
- package/dist/compiler/training/container/index.d.ts +4 -0
- package/dist/compiler/training/container/index.js +2 -0
- package/dist/compiler/training/container/launch.d.ts +18 -0
- package/dist/compiler/training/container/launch.js +173 -0
- package/dist/compiler/training/container/prepare.d.ts +8 -0
- package/dist/compiler/training/container/prepare.js +80 -0
- package/dist/compiler/training/container/process.d.ts +14 -0
- package/dist/compiler/training/container/process.js +70 -0
- package/dist/compiler/training/container/security.d.ts +36 -0
- package/dist/compiler/training/container/security.js +58 -0
- package/dist/compiler/training/context.d.ts +7 -0
- package/dist/compiler/training/context.js +93 -0
- package/dist/compiler/training/contract.d.ts +142 -0
- package/dist/compiler/training/contract.js +34 -0
- package/dist/compiler/training/index.d.ts +4 -0
- package/dist/compiler/training/index.js +3 -0
- package/dist/compiler/training/preparation/assets/Dockerfile +98 -0
- package/dist/compiler/training/preparation/assets/package-lock.json +3787 -0
- package/dist/compiler/training/preparation/broker.d.ts +21 -0
- package/dist/compiler/training/preparation/broker.js +43 -0
- package/dist/compiler/training/preparation/contextModes.d.ts +12 -0
- package/dist/compiler/training/preparation/contextModes.js +38 -0
- package/dist/compiler/training/preparation/contract.d.ts +182 -0
- package/dist/compiler/training/preparation/contract.js +94 -0
- package/dist/compiler/training/preparation/copyAssets.d.ts +1 -0
- package/dist/compiler/training/preparation/copyAssets.js +8 -0
- package/dist/compiler/training/preparation/daimonParent.d.ts +42 -0
- package/dist/compiler/training/preparation/daimonParent.js +114 -0
- package/dist/compiler/training/preparation/files.d.ts +25 -0
- package/dist/compiler/training/preparation/files.js +85 -0
- package/dist/compiler/training/preparation/image.d.ts +28 -0
- package/dist/compiler/training/preparation/image.js +102 -0
- package/dist/compiler/training/preparation/index.d.ts +3 -0
- package/dist/compiler/training/preparation/index.js +2 -0
- package/dist/compiler/training/preparation/inputs.d.ts +23 -0
- package/dist/compiler/training/preparation/inputs.js +93 -0
- package/dist/compiler/training/preparation/prepare.d.ts +33 -0
- package/dist/compiler/training/preparation/prepare.js +186 -0
- package/dist/compiler/training/preparation/scratch.d.ts +19 -0
- package/dist/compiler/training/preparation/scratch.js +48 -0
- package/dist/compiler/training/repair/compatibility.d.ts +11 -0
- package/dist/compiler/training/repair/compatibility.js +34 -0
- package/dist/compiler/training/repair/contract.d.ts +506 -0
- package/dist/compiler/training/repair/contract.js +31 -0
- package/dist/compiler/training/repair/index.d.ts +3 -0
- package/dist/compiler/training/repair/index.js +3 -0
- package/dist/compiler/training/repair/prepare.d.ts +230 -0
- package/dist/compiler/training/repair/prepare.js +74 -0
- package/dist/compiler/training/repair/witness.d.ts +203 -0
- package/dist/compiler/training/repair/witness.js +42 -0
- package/dist/compiler/types.d.ts +2 -0
- package/dist/compiler/upProject.d.ts +26 -1
- package/dist/compiler/upProject.js +117 -178
- package/dist/compiler/upProjectHandoff.d.ts +62 -0
- package/dist/compiler/upProjectHandoff.js +204 -0
- package/dist/compiler/upReceipt.js +49 -4
- package/dist/compiler/updateProjectModels.js +1 -0
- package/dist/compiler/view/types.d.ts +1 -1
- package/dist/compiler/workspaceBundleArtifacts.d.ts +3 -0
- package/dist/compiler/workspaceBundleArtifacts.js +106 -0
- package/dist/compiler/workspaceResources.d.ts +4 -1
- package/dist/compiler/workspaceResources.js +12 -7
- package/dist/deployment/artifactsExportPlan.js +51 -1
- package/dist/deployment/canaryCutover.d.ts +42 -0
- package/dist/deployment/canaryCutover.js +140 -0
- package/dist/deployment/candidateDiagnostics.d.ts +15 -0
- package/dist/deployment/candidateDiagnostics.js +90 -0
- package/dist/deployment/dockerLogs.js +4 -1
- package/dist/deployment/dockerManager.js +9 -3
- package/dist/deployment/dockerProbeGateway.d.ts +17 -0
- package/dist/deployment/dockerProbeGateway.js +17 -2
- package/dist/deployment/downDeployment.d.ts +5 -0
- package/dist/deployment/downDeployment.js +109 -8
- package/dist/deployment/downReceiptTypes.d.ts +17 -2
- package/dist/deployment/downReceiptTypes.js +17 -2
- package/dist/deployment/index.d.ts +4 -0
- package/dist/deployment/index.js +4 -0
- package/dist/deployment/lifecycleCompletionContracts.d.ts +66 -0
- package/dist/deployment/lifecycleCompletionContracts.js +34 -0
- package/dist/deployment/lifecycleCompletionPaths.d.ts +4 -1
- package/dist/deployment/lifecycleCompletionPaths.js +3 -0
- package/dist/deployment/lifecycleCompletionPublication.d.ts +2 -0
- package/dist/deployment/lifecycleCompletionPublication.js +18 -4
- package/dist/deployment/lifecycleCompletionStore.d.ts +1 -1
- package/dist/deployment/lifecycleCompletionStore.js +7 -7
- package/dist/deployment/lifecycleUpRecords.d.ts +11 -0
- package/dist/deployment/lifecycleUpRecords.js +127 -0
- package/dist/deployment/native/AGENTS.md +11 -0
- package/dist/deployment/native/rename-noreplace-arm64 +0 -0
- package/dist/deployment/native/rename-noreplace-arm64.provenance.json +1 -0
- package/dist/deployment/native/rename-noreplace-x64 +0 -0
- package/dist/deployment/native/rename-noreplace-x64.provenance.json +1 -0
- package/dist/deployment/noReplaceActivation.d.ts +17 -0
- package/dist/deployment/noReplaceActivation.js +50 -0
- package/dist/deployment/organizationHandoffAuthorityFsBudget.d.ts +110 -0
- package/dist/deployment/organizationHandoffAuthorityFsBudget.js +156 -0
- package/dist/deployment/organizationHandoffAuthorityFsClient.js +82 -27
- package/dist/deployment/organizationHandoffAuthorityFsElection.d.ts +21 -0
- package/dist/deployment/organizationHandoffAuthorityFsElection.js +57 -0
- package/dist/deployment/organizationHandoffAuthorityFsWorker.js +254 -108
- package/dist/deployment/organizationHandoffAuthorityFsWorkerStall.fixture.d.ts +1 -0
- package/dist/deployment/organizationHandoffAuthorityFsWorkerStall.fixture.js +16 -0
- package/dist/deployment/organizationHandoffAuthorityStore.js +14 -7
- package/dist/deployment/organizationHandoffAuthorityTypes.d.ts +2 -2
- package/dist/deployment/organizationHandoffAuthorityTypes.js +2 -1
- package/dist/deployment/organizationReady.d.ts +2 -0
- package/dist/deployment/organizationReady.js +36 -4
- package/dist/deployment/productStateClone.d.ts +43 -0
- package/dist/deployment/productStateClone.js +319 -0
- package/dist/deployment/upLifecycleRecoveryState.d.ts +23 -0
- package/dist/deployment/upLifecycleRecoveryState.js +12 -0
- package/dist/deployment/upReceiptTypes.d.ts +32 -6
- package/dist/deployment/upReceiptTypes.js +29 -2
- package/dist/deployment/workspaceResourceMigration.d.ts +55 -0
- package/dist/deployment/workspaceResourceMigration.js +315 -0
- package/dist/dev/project.d.ts +7 -0
- package/dist/dev/project.js +9 -0
- package/dist/distribution/consumeImage.d.ts +2 -0
- package/dist/distribution/consumeImage.js +98 -73
- package/dist/distribution/consumeImageDaimonDocker.d.ts +3 -0
- package/dist/distribution/consumeImageDaimonDocker.js +45 -0
- package/dist/distribution/consumeImageLifecycle.d.ts +17 -0
- package/dist/distribution/consumeImageLifecycle.js +231 -0
- package/dist/distribution/consumeImageSupport.d.ts +12 -0
- package/dist/distribution/consumeImageSupport.js +15 -0
- package/dist/distribution/distributionReportSchema.d.ts +11 -1
- package/dist/distribution/distributionReportSchema.js +15 -2
- package/dist/distribution/dockerRunner.d.ts +6 -1
- package/dist/distribution/dockerRunner.js +31 -4
- package/dist/distribution/imageRuntimeAuth.d.ts +9 -1
- package/dist/distribution/imageRuntimeAuth.js +70 -1
- package/dist/distribution/index.d.ts +1 -1
- package/dist/distribution/index.js +1 -1
- package/dist/distribution/preflight.js +5 -1
- package/dist/distribution/types.d.ts +14 -1
- package/dist/distribution/types.js +3 -0
- package/dist/evidenceExportHelper/boundedExecutor.d.ts +3 -0
- package/dist/evidenceExportHelper/boundedExecutor.js +33 -0
- package/dist/evidenceExportHelper/helperProgram.mjs +156 -0
- package/dist/evidenceExportHelper/index.d.ts +4 -0
- package/dist/evidenceExportHelper/index.js +4 -0
- package/dist/evidenceExportHelper/preparedAuthority.d.ts +64 -0
- package/dist/evidenceExportHelper/preparedAuthority.js +228 -0
- package/dist/evidenceExportHelper/preparedBuilder.d.ts +10 -0
- package/dist/evidenceExportHelper/preparedBuilder.js +183 -0
- package/dist/evidenceExportHelper/preparedBuilderTypes.d.ts +19 -0
- package/dist/evidenceExportHelper/preparedBuilderTypes.js +1 -0
- package/dist/evidenceExportHelper/recipe.d.ts +7 -0
- package/dist/evidenceExportHelper/recipe.js +83 -0
- package/dist/filesystem/io.d.ts +2 -0
- package/dist/filesystem/io.js +16 -1
- package/dist/manifest/executionSchemas.d.ts +27 -0
- package/dist/manifest/executionSchemas.js +21 -2
- package/dist/manifest/mcpSchemas.d.ts +1 -0
- package/dist/manifest/mcpSchemas.js +3 -0
- package/dist/manifest/renderSpawnfileNetworks.js +11 -0
- package/dist/manifest/renderSpawnfileWorkspace.js +5 -0
- package/dist/manifest/scheduleSchemas.d.ts +3 -1
- package/dist/manifest/scheduleSchemas.js +91 -5
- package/dist/manifest/schemas.d.ts +237 -12
- package/dist/manifest/schemas.js +5 -2
- package/dist/manifest/teamNetworkAccessSchemas.d.ts +5 -1
- package/dist/manifest/teamNetworkAccessSchemas.js +11 -0
- package/dist/manifest/teamNetworkAuthSchemas.d.ts +1 -1
- package/dist/manifest/teamNetworkSchemas.d.ts +17 -3
- package/dist/manifest/teamNetworkSchemas.js +19 -1
- package/dist/manifest/teamNetworkServerSchemas.d.ts +8 -3
- package/dist/manifest/teamNetworkServerSchemas.js +18 -2
- package/dist/manifest/workspaceSchemas.d.ts +16 -0
- package/dist/manifest/workspaceSchemas.js +11 -0
- package/dist/report/types.d.ts +34 -4
- package/dist/runtime/common.d.ts +28 -1
- package/dist/runtime/common.js +33 -3
- package/dist/runtime/container.js +49 -33
- package/dist/runtime/daimon/adapter.d.ts +14 -0
- package/dist/runtime/daimon/adapter.js +243 -0
- package/dist/runtime/daimon/attention.d.ts +8 -0
- package/dist/runtime/daimon/attention.js +32 -0
- package/dist/runtime/daimon/config.d.ts +25 -0
- package/dist/runtime/daimon/config.js +272 -0
- package/dist/runtime/daimon/contractManifest.d.ts +295 -0
- package/dist/runtime/daimon/contractManifest.js +319 -0
- package/dist/runtime/daimon/grokModel.d.ts +19 -0
- package/dist/runtime/daimon/grokModel.js +33 -0
- package/dist/runtime/daimon/grokWorkerConfigBytes.d.ts +26 -0
- package/dist/runtime/daimon/grokWorkerConfigBytes.js +36 -0
- package/dist/runtime/daimon/grokWorkerContract.d.ts +22 -0
- package/dist/runtime/daimon/grokWorkerContract.js +48 -0
- package/dist/runtime/daimon/memory.d.ts +57 -0
- package/dist/runtime/daimon/memory.js +125 -0
- package/dist/runtime/daimon/runAuth.d.ts +51 -0
- package/dist/runtime/daimon/runAuth.js +279 -0
- package/dist/runtime/daimon/runtimeIdentity.d.ts +22 -0
- package/dist/runtime/daimon/runtimeIdentity.js +22 -0
- package/dist/runtime/daimon/scheduleAuthority.d.ts +3 -0
- package/dist/runtime/daimon/scheduleAuthority.js +17 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/install.d.ts +3 -0
- package/dist/runtime/install.js +3 -0
- package/dist/runtime/localDaimonAuthority.d.ts +11 -0
- package/dist/runtime/localDaimonAuthority.js +77 -0
- package/dist/runtime/mnemeMcp.d.ts +13 -0
- package/dist/runtime/mnemeMcp.js +26 -0
- package/dist/runtime/openclaw/adapter.js +2 -2
- package/dist/runtime/pi/adapter.d.ts +0 -1
- package/dist/runtime/pi/adapter.js +2 -6
- package/dist/runtime/pi/appCliSource.js +1 -1
- package/dist/runtime/pi/appScheduleSource.js +6 -2
- package/dist/runtime/pi/appTemplateTypes.d.ts +1 -1
- package/dist/runtime/picoclaw/adapter.js +2 -2
- package/dist/runtime/registry.d.ts +3 -0
- package/dist/runtime/registry.js +19 -2
- package/dist/runtime/scheduleUtils.d.ts +1 -0
- package/dist/runtime/scheduleUtils.js +5 -1
- package/dist/runtime/types.d.ts +25 -0
- package/dist/runtime/usageLedger.d.ts +158 -0
- package/dist/runtime/usageLedger.js +269 -0
- package/dist/runtime/usageLedgerRead.d.ts +48 -0
- package/dist/runtime/usageLedgerRead.js +102 -0
- package/dist/runtime/usageRequestLedger.d.ts +42 -0
- package/dist/runtime/usageRequestLedger.js +72 -0
- package/dist/shared/daimonCodexDocker.d.ts +32 -0
- package/dist/shared/daimonCodexDocker.js +120 -0
- package/dist/shared/daimonGrokSeccompProfile.d.ts +10 -0
- package/dist/shared/daimonGrokSeccompProfile.js +11 -0
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/index.js +2 -0
- package/dist/shared/types.d.ts +1 -1
- package/dist/shared/volumeNames.d.ts +6 -0
- package/dist/shared/volumeNames.js +14 -0
- package/dist/target/dockerArtifactsProvider.js +34 -7
- package/dist/target/dockerBaseImage.d.ts +2 -0
- package/dist/target/dockerBaseImage.js +11 -0
- package/dist/target/dockerCommandExecutor.d.ts +11 -0
- package/dist/target/dockerCommandExecutor.js +53 -2
- package/dist/target/dockerCommandExecutorCore.d.ts +2 -1
- package/dist/target/dockerCommandExecutorCore.js +4 -2
- package/dist/target/dockerPublicArtifactSnapshot.d.ts +3 -3
- package/dist/target/dockerPublicArtifactSnapshot.js +17 -33
- package/dist/target/dockerTarget.d.ts +1 -0
- package/dist/target/dockerTargetBinding.d.ts +1 -2
- package/dist/target/dockerTargetBinding.js +2 -3
- package/dist/target/dockerTargetExecFile.d.ts +19 -0
- package/dist/target/dockerTargetExecFile.js +194 -0
- package/dist/target/dockerWorldServiceProvider.d.ts +4 -0
- package/dist/target/dockerWorldServiceProvider.js +13 -1
- package/dist/target/evidenceExport.d.ts +3 -1
- package/dist/target/evidenceExport.js +12 -3
- package/dist/target/evidenceExportOperationsTestKit.js +3 -3
- package/dist/target/evidenceExportProvider.d.ts +2 -0
- package/dist/target/evidenceExportProvider.js +15 -5
- package/dist/target/publicArtifactSnapshot.d.ts +31 -0
- package/dist/target/publicArtifactSnapshot.js +37 -3
- package/examples/README.md +45 -0
- package/examples/agent-with-subagents/AGENTS.md +3 -0
- package/examples/agent-with-subagents/Spawnfile +30 -0
- package/examples/agent-with-subagents/subagents/critic/AGENTS.md +3 -0
- package/examples/agent-with-subagents/subagents/critic/Spawnfile +15 -0
- package/examples/agent-with-subagents/subagents/researcher/AGENTS.md +3 -0
- package/examples/agent-with-subagents/subagents/researcher/Spawnfile +17 -0
- package/examples/daimon-org/Spawnfile +68 -0
- package/examples/daimon-org/TEAM.md +4 -0
- package/examples/daimon-org/agents/mapper/AGENTS.md +4 -0
- package/examples/daimon-org/agents/mapper/Spawnfile +37 -0
- package/examples/daimon-org/shared/skills/file-note/SKILL.md +9 -0
- package/examples/daimon-org/teams/review/Spawnfile +53 -0
- package/examples/daimon-org/teams/review/agents/reviewer/AGENTS.md +4 -0
- package/examples/daimon-org/teams/review/agents/reviewer/Spawnfile +37 -0
- package/examples/daimon-public-host/AGENTS.md +3 -0
- package/examples/daimon-public-host/Spawnfile +21 -0
- package/examples/distribution-org/Spawnfile +43 -0
- package/examples/distribution-org/TEAM.md +4 -0
- package/examples/distribution-org/agents/coordinator/AGENTS.md +1 -0
- package/examples/distribution-org/agents/coordinator/Spawnfile +20 -0
- package/examples/distribution-org/agents/researcher/AGENTS.md +1 -0
- package/examples/distribution-org/agents/researcher/Spawnfile +20 -0
- package/examples/jungian-daimon-org/Spawnfile +41 -0
- package/examples/jungian-daimon-org/TEAM.md +21 -0
- package/examples/jungian-daimon-org/teams/luna/Spawnfile +47 -0
- package/examples/jungian-daimon-org/teams/luna/TEAM.md +4 -0
- package/examples/jungian-daimon-org/teams/luna/agents/animus/AGENTS.md +10 -0
- package/examples/jungian-daimon-org/teams/luna/agents/animus/Spawnfile +33 -0
- package/examples/jungian-daimon-org/teams/luna/agents/representative/AGENTS.md +21 -0
- package/examples/jungian-daimon-org/teams/luna/agents/representative/Spawnfile +30 -0
- package/examples/jungian-daimon-org/teams/luna/agents/shadow/AGENTS.md +10 -0
- package/examples/jungian-daimon-org/teams/luna/agents/shadow/Spawnfile +33 -0
- package/examples/jungian-daimon-org/teams/selene/Spawnfile +47 -0
- package/examples/jungian-daimon-org/teams/selene/TEAM.md +4 -0
- package/examples/jungian-daimon-org/teams/selene/agents/animus/AGENTS.md +10 -0
- package/examples/jungian-daimon-org/teams/selene/agents/animus/Spawnfile +33 -0
- package/examples/jungian-daimon-org/teams/selene/agents/representative/AGENTS.md +19 -0
- package/examples/jungian-daimon-org/teams/selene/agents/representative/Spawnfile +33 -0
- package/examples/jungian-daimon-org/teams/selene/agents/shadow/AGENTS.md +10 -0
- package/examples/jungian-daimon-org/teams/selene/agents/shadow/Spawnfile +30 -0
- package/examples/mixed-runtime-org/Spawnfile +71 -0
- package/examples/mixed-runtime-org/TEAM.md +8 -0
- package/examples/mixed-runtime-org/agents/analyst/AGENTS.md +8 -0
- package/examples/mixed-runtime-org/agents/analyst/Spawnfile +27 -0
- package/examples/mixed-runtime-org/agents/conductor/AGENTS.md +8 -0
- package/examples/mixed-runtime-org/agents/conductor/Spawnfile +27 -0
- package/examples/mixed-runtime-org/agents/localist/AGENTS.md +7 -0
- package/examples/mixed-runtime-org/agents/localist/Spawnfile +50 -0
- package/examples/moltnet-team-chat/Spawnfile +43 -0
- package/examples/moltnet-team-chat/TEAM.md +5 -0
- package/examples/moltnet-team-chat/agents/coordinator/AGENTS.md +9 -0
- package/examples/moltnet-team-chat/agents/coordinator/Spawnfile +26 -0
- package/examples/moltnet-team-chat/teams/analysis/Spawnfile +23 -0
- package/examples/moltnet-team-chat/teams/analysis/TEAM.md +3 -0
- package/examples/moltnet-team-chat/teams/analysis/agents/observer/AGENTS.md +5 -0
- package/examples/moltnet-team-chat/teams/analysis/agents/observer/Spawnfile +19 -0
- package/examples/moltnet-team-chat/teams/analysis/agents/representative/AGENTS.md +5 -0
- package/examples/moltnet-team-chat/teams/analysis/agents/representative/Spawnfile +19 -0
- package/examples/moltnet-team-chat/teams/field/Spawnfile +41 -0
- package/examples/moltnet-team-chat/teams/field/TEAM.md +3 -0
- package/examples/moltnet-team-chat/teams/field/agents/observer/AGENTS.md +5 -0
- package/examples/moltnet-team-chat/teams/field/agents/observer/Spawnfile +26 -0
- package/examples/moltnet-team-chat/teams/field/agents/representative/AGENTS.md +11 -0
- package/examples/moltnet-team-chat/teams/field/agents/representative/Spawnfile +26 -0
- package/examples/single-agent/AGENTS.md +3 -0
- package/examples/single-agent/HEARTBEAT.md +3 -0
- package/examples/single-agent/IDENTITY.md +3 -0
- package/examples/single-agent/MEMORY.md +3 -0
- package/examples/single-agent/SOUL.md +3 -0
- package/examples/single-agent/Spawnfile +41 -0
- package/examples/single-agent/skills/web_search/SKILL.md +6 -0
- package/moltnet-releases.json +5 -4
- package/package.json +36 -9
- package/runtimes.yaml +5 -2
- package/dist/cli/targetWorldClockCrossProcess.test-helper.d.ts +0 -13
- package/dist/cli/targetWorldClockCrossProcess.test-helper.js +0 -109
- package/dist/deployment/providerRuntimeBoundaryScanner.test-helper.d.ts +0 -8
- package/dist/deployment/providerRuntimeBoundaryScanner.test-helper.js +0 -60
- package/dist/deployment/simfileFixtureBoundary.test-helper.d.ts +0 -8
- package/dist/deployment/simfileFixtureBoundary.test-helper.js +0 -103
- package/dist/ownership/simfileRunOperatorInputs.d.ts +0 -103
- package/dist/ownership/simfileRunOperatorInputs.js +0 -139
- package/dist/target/cleanupRunDocker.test-helper.d.ts +0 -67
- package/dist/target/cleanupRunDocker.test-helper.js +0 -238
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import type { CliStreams } from "./runCli.js";
|
|
3
|
+
import { type UsageCommandLiveHandlers } from "./usageCommandLive.js";
|
|
4
|
+
/**
|
|
5
|
+
* `spawnfile usage` — what did this organization consume.
|
|
6
|
+
*
|
|
7
|
+
* A separate command from `status` on purpose. `status` answers "is it
|
|
8
|
+
* healthy"; usage answers "what did it consume". Different question, different
|
|
9
|
+
* cadence, and `status` must not read a growing ledger on every invocation.
|
|
10
|
+
*
|
|
11
|
+
* Every number this command prints is a LOWER BOUND. Neither metered engine's
|
|
12
|
+
* stream carries an incompleteness marker — grok's `streaming-messages-json`
|
|
13
|
+
* and AGY's `stream-json` both zero-fill a bucket they cannot account for — so
|
|
14
|
+
* a turn whose usage was partially zero-filled sums to a plausible total and is
|
|
15
|
+
* indistinguishable from a real one. Counts are therefore reported as `>=`, and
|
|
16
|
+
* coverage is always stated explicitly. AGY additionally reports no cost at
|
|
17
|
+
* all, so its notional column is always `—`.
|
|
18
|
+
*/
|
|
19
|
+
export interface UsageCommandOptions {
|
|
20
|
+
agent?: string;
|
|
21
|
+
exported?: string;
|
|
22
|
+
by?: string;
|
|
23
|
+
deployment?: string;
|
|
24
|
+
dockerCommand?: string;
|
|
25
|
+
json?: boolean;
|
|
26
|
+
out?: string;
|
|
27
|
+
since?: string;
|
|
28
|
+
timeout?: string;
|
|
29
|
+
top?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface UsageCommandResult {
|
|
32
|
+
error?: string;
|
|
33
|
+
/** The shared CLI convention (specs/SPEC.md §9.1, `errorExitCode`): 0 on
|
|
34
|
+
* success, 2 for a usage/input error, 1 for a runtime failure that surfaced
|
|
35
|
+
* after validation. */
|
|
36
|
+
exitCode: 0 | 1 | 2;
|
|
37
|
+
output?: string;
|
|
38
|
+
}
|
|
39
|
+
export declare const executeUsageCommand: (inputPath: string, options: UsageCommandOptions, handlers?: UsageCommandLiveHandlers) => Promise<UsageCommandResult>;
|
|
40
|
+
export declare const registerUsageCommand: (program: Command, streams: CliStreams, setExitCode: (exitCode: 0 | 1 | 2) => void, handlers?: UsageCommandLiveHandlers) => void;
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { readFile, stat } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { listDeploymentRecords, parseExportIndex } from "../deployment/index.js";
|
|
4
|
+
import { resolveProjectOutputDirectory } from "../filesystem/index.js";
|
|
5
|
+
import { DAIMON_GROK_TURN_USAGE_LEDGER } from "../runtime/daimon/contractManifest.js";
|
|
6
|
+
import { readUsageLedgerViaExec } from "../runtime/usageLedgerRead.js";
|
|
7
|
+
import { DEFAULT_OUTPUT_DIRECTORY, errorExitCode } from "../shared/index.js";
|
|
8
|
+
import { computeUsageCoverage, dedupeUsageRecordsByTurn, DEFAULT_USAGE_SINCE, findConflictingUsageTurns, filterUsageRecordsSince, groupUsageByAgent, groupUsageByEngine, parseUsageSinceDuration } from "../runtime/usageLedger.js";
|
|
9
|
+
import { resolveUsageDeploymentSource } from "./usageDeploymentSource.js";
|
|
10
|
+
import { collectOrganizationUsage, rosterForRecord, selectUsageDeployment } from "./usageCommandLive.js";
|
|
11
|
+
const inputFailure = (message) => ({ error: message, exitCode: 2 });
|
|
12
|
+
const formatTokens = (value) => {
|
|
13
|
+
if (value === 0)
|
|
14
|
+
return "—";
|
|
15
|
+
if (value >= 1_000_000)
|
|
16
|
+
return `${(value / 1_000_000).toFixed(1)}M`;
|
|
17
|
+
if (value >= 1_000)
|
|
18
|
+
return `${(value / 1_000).toFixed(1)}k`;
|
|
19
|
+
return String(value);
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* `—` means unknown, never free.
|
|
23
|
+
*
|
|
24
|
+
* A zero notional amount is never a claim worth printing: AGY's terminal frame
|
|
25
|
+
* carries no `total_cost_usd` at all, and Grok's decoder falls back to `0` for
|
|
26
|
+
* a cost it could not read. Rendering either as `$0.00` would advertise a free
|
|
27
|
+
* turn on a subscription that is being spent, which is precisely the silent
|
|
28
|
+
* loss this command exists to prevent.
|
|
29
|
+
*/
|
|
30
|
+
const formatUsd = (value, turns) => turns === 0 || value === 0 ? "—" : `$${value.toFixed(2)}`;
|
|
31
|
+
const formatShare = (value, total) => total === 0 ? "—" : `${Math.round((value / total) * 100)}%`;
|
|
32
|
+
/** An unreadable unit is UNKNOWN usage, never zero usage, so it always gets
|
|
33
|
+
* its own line and always forces the window's coverage to PARTIAL. */
|
|
34
|
+
const renderUnreadableUnit = (unit) => unit.reason === "ledger_read_failed"
|
|
35
|
+
? `UNREADABLE ${unit.unitId} (${unit.containerRef}): ledger read failed (${unit.detail ?? "no detail"}); its usage is unknown, not zero.`
|
|
36
|
+
: `UNREADABLE ${unit.unitId} (${unit.containerRef}): container ${unit.reason}; its ledger is not included.`;
|
|
37
|
+
const pad = (value, width) => value.padEnd(width);
|
|
38
|
+
const padStart = (value, width) => value.padStart(width);
|
|
39
|
+
const renderTable = (usage, windowed, options) => {
|
|
40
|
+
const groupBy = options.by ?? "agent";
|
|
41
|
+
const coverage = computeUsageCoverage(windowed, usage.roster.length, usage.unreadableUnits.length);
|
|
42
|
+
const totalTokens = dedupeUsageRecordsByTurn(windowed).reduce((sum, record) => sum + record.total, 0);
|
|
43
|
+
const lines = [];
|
|
44
|
+
const coverageLabel = coverage.partial
|
|
45
|
+
? `coverage PARTIAL (${coverage.agentsReporting} of ${coverage.agentsTotal} agents)`
|
|
46
|
+
: `coverage ${coverage.agentsReporting} of ${coverage.agentsTotal} agents`;
|
|
47
|
+
const sourceLabel = options.exported === undefined ? "" : ` · source exported ${options.exported}`;
|
|
48
|
+
lines.push(`ORG ${usage.deploymentName} · last ${options.since ?? DEFAULT_USAGE_SINCE}${sourceLabel} · ${coverageLabel}`);
|
|
49
|
+
lines.push("");
|
|
50
|
+
if (groupBy === "agent") {
|
|
51
|
+
let rows = groupUsageByAgent(windowed, usage.roster)
|
|
52
|
+
.sort((left, right) => right.tokens - left.tokens || left.agent.localeCompare(right.agent));
|
|
53
|
+
if (options.agent)
|
|
54
|
+
rows = rows.filter((row) => row.agent === options.agent);
|
|
55
|
+
if (options.top)
|
|
56
|
+
rows = rows.slice(0, Number(options.top));
|
|
57
|
+
const width = Math.max(8, ...rows.map((row) => row.agent.length));
|
|
58
|
+
lines.push(`${pad("agent", width)} ${pad("engine", 8)}${padStart("turns", 7)}${padStart("tokens", 9)}${padStart("notional", 11)}${padStart("share", 7)}`);
|
|
59
|
+
for (const row of rows) {
|
|
60
|
+
lines.push(`${pad(row.agent, width)} ${pad(row.engine ?? "—", 8)}${padStart(row.turns === 0 ? "—" : String(row.turns), 7)}${padStart(`${row.estimatedTurns > 0 ? "~" : ""}${formatTokens(row.tokens)}`, 9)}${padStart(formatUsd(row.notionalUsd, row.turns), 11)}${padStart(formatShare(row.tokens, totalTokens), 7)}`);
|
|
61
|
+
}
|
|
62
|
+
lines.push("─".repeat(width + 44));
|
|
63
|
+
}
|
|
64
|
+
const engineRows = groupUsageByEngine(windowed)
|
|
65
|
+
.sort((left, right) => right.tokens - left.tokens || left.engine.localeCompare(right.engine));
|
|
66
|
+
const engineWidth = Math.max(8, ...engineRows.map((row) => row.engine.length));
|
|
67
|
+
for (const row of engineRows) {
|
|
68
|
+
lines.push(`${pad(row.engine, engineWidth)} ${pad("", 8)}${padStart(String(row.turns), 7)}${padStart(`${row.estimatedTurns > 0 ? "~" : ""}${formatTokens(row.tokens)}`, 9)}${padStart(formatUsd(row.notionalUsd, row.turns), 11)}`);
|
|
69
|
+
}
|
|
70
|
+
if (engineRows.length === 0)
|
|
71
|
+
lines.push("no metered turns in this window");
|
|
72
|
+
lines.push("");
|
|
73
|
+
lines.push("Counts are a lower bound: the engine stream carries no completeness marker.");
|
|
74
|
+
const conflicts = findConflictingUsageTurns(windowed);
|
|
75
|
+
if (conflicts.length > 0) {
|
|
76
|
+
lines.push(`WARNING ${conflicts.length} turn(s) carry differing ledger rows under one turn key; the first row is counted and coverage is PARTIAL: ${conflicts.map((turn) => turn.slice(0, 12)).join(", ")}`);
|
|
77
|
+
}
|
|
78
|
+
if (coverage.estimatedTurnCount > 0) {
|
|
79
|
+
const estimatedRequests = engineRows.reduce((sum, row) => sum + row.estimatedRequests, 0);
|
|
80
|
+
lines.push(`~ ${coverage.estimatedTurnCount} turn(s) include ESTIMATED usage: ${estimatedRequests} request(s) returned no provider-reported usage and were charged a conservative estimate, not a measurement.`);
|
|
81
|
+
}
|
|
82
|
+
if (coverage.incompleteRecordCount > 0) {
|
|
83
|
+
lines.push(`${coverage.incompleteRecordCount} turn(s) reported all-zero usage and are counted as unknown, not free.`);
|
|
84
|
+
}
|
|
85
|
+
for (const unit of usage.unreadableUnits) {
|
|
86
|
+
lines.push(renderUnreadableUnit(unit));
|
|
87
|
+
}
|
|
88
|
+
return lines.join("\n");
|
|
89
|
+
};
|
|
90
|
+
/** Where `artifactsExportPlan.ts` lands the ledger inside an exported run
|
|
91
|
+
* directory. Both halves are derived from the same pinned contract constant the
|
|
92
|
+
* export plan derives them from, so the two cannot drift apart. */
|
|
93
|
+
const EXPORTED_USAGE_DIRECTORY = "raw/daimon";
|
|
94
|
+
const exportedLedgerPaths = (exportedDirectory) => {
|
|
95
|
+
const resolve = (absoluteContainerPath) => path.join(exportedDirectory, EXPORTED_USAGE_DIRECTORY, path.posix.basename(absoluteContainerPath));
|
|
96
|
+
return {
|
|
97
|
+
filePath: resolve(DAIMON_GROK_TURN_USAGE_LEDGER.filePath),
|
|
98
|
+
rotatedFilePath: resolve(DAIMON_GROK_TURN_USAGE_LEDGER.rotatedFilePath)
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Reads exported ledger bytes through the SAME reader the live path uses.
|
|
103
|
+
*
|
|
104
|
+
* `readUsageLedgerViaExec` is duck-typed on `exec(["cat", file])`, so feeding it
|
|
105
|
+
* a file-backed exec reuses the rotation ordering, the parse, and the
|
|
106
|
+
* absent-vs-unreadable classification verbatim rather than growing a second
|
|
107
|
+
* copy that could drift. A missing file is re-shaped into the failure a real
|
|
108
|
+
* `cat` produces — numeric exit code plus "No such file or directory" — because
|
|
109
|
+
* that is the exact shape the shared reader recognises as a legitimately absent
|
|
110
|
+
* generation. Every other filesystem error keeps its own `code`, which that
|
|
111
|
+
* reader treats as UNKNOWN rather than empty.
|
|
112
|
+
*/
|
|
113
|
+
const exportedLedgerExec = async (command) => {
|
|
114
|
+
const filePath = command[command.length - 1];
|
|
115
|
+
try {
|
|
116
|
+
return { stderr: "", stdout: await readFile(filePath, "utf8") };
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
if (error.code === "ENOENT") {
|
|
120
|
+
const message = `cat: ${filePath}: No such file or directory`;
|
|
121
|
+
throw Object.assign(new Error(message), { code: 1, stderr: message });
|
|
122
|
+
}
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
/** `stat`, not a read: a rotated generation is at least 64 MiB, so probing for
|
|
127
|
+
* presence must not pull the bytes in only to throw them away. */
|
|
128
|
+
const fileExists = async (filePath) => {
|
|
129
|
+
try {
|
|
130
|
+
return (await stat(filePath)).isFile();
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Reads one sealed, exported run instead of a live container.
|
|
138
|
+
*
|
|
139
|
+
* The roster still comes from the deployment record, exactly as the live path
|
|
140
|
+
* resolves it, so the coverage denominator means the same thing in both modes —
|
|
141
|
+
* that equivalence is the point, and it is what lets a single aggregation layer
|
|
142
|
+
* serve both.
|
|
143
|
+
*
|
|
144
|
+
* The one semantic that CANNOT be shared is what an absent ledger means. On a
|
|
145
|
+
* running container an absent file is genuinely "no turns yet", so the shared
|
|
146
|
+
* reader stays silent about it. In an export it means the bytes were never
|
|
147
|
+
* captured — a codex-only organization is never provisioned the volume, and an
|
|
148
|
+
* export taken before the first metered turn carries nothing — and neither of
|
|
149
|
+
* those is evidence that the organization cost nothing. So when the export
|
|
150
|
+
* carries no generation at all this reports an explicit unreadable unit, which
|
|
151
|
+
* forces coverage PARTIAL and keeps every notional column at `—`, rather than
|
|
152
|
+
* rendering a confident `$0.00` over a ledger nobody ever read.
|
|
153
|
+
*/
|
|
154
|
+
const collectExportedUsage = async (exportedDirectory, options, outputDirectory, handlers) => {
|
|
155
|
+
const indexPath = path.join(exportedDirectory, "spawnfile", "export-index.json");
|
|
156
|
+
let index;
|
|
157
|
+
try {
|
|
158
|
+
index = parseExportIndex(JSON.parse(await readFile(indexPath, "utf8")));
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
return {
|
|
162
|
+
error: `Not a Spawnfile export directory: ${exportedDirectory} (${indexPath}: ${error instanceof Error ? error.message : String(error)}). Produce one with \`spawnfile artifacts export --out <dir>\`.`
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
const list = handlers.listDeploymentRecords ?? listDeploymentRecords;
|
|
166
|
+
const selected = selectUsageDeployment(await list(outputDirectory), options.deployment ?? index.deployment);
|
|
167
|
+
if ("error" in selected)
|
|
168
|
+
return selected;
|
|
169
|
+
const paths = exportedLedgerPaths(exportedDirectory);
|
|
170
|
+
const present = await Promise.all([fileExists(paths.filePath), fileExists(paths.rotatedFilePath)]);
|
|
171
|
+
if (!present.some(Boolean)) {
|
|
172
|
+
return {
|
|
173
|
+
deploymentName: selected.name,
|
|
174
|
+
records: [],
|
|
175
|
+
roster: rosterForRecord(selected),
|
|
176
|
+
runId: index.run_id,
|
|
177
|
+
unreadableUnits: [{
|
|
178
|
+
containerRef: exportedDirectory,
|
|
179
|
+
detail: `${EXPORTED_USAGE_DIRECTORY}/${path.posix.basename(DAIMON_GROK_TURN_USAGE_LEDGER.filePath)} is not in this export`,
|
|
180
|
+
reason: "ledger_read_failed",
|
|
181
|
+
unitId: `export:${index.run_id}`
|
|
182
|
+
}]
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
const read = await readUsageLedgerViaExec(exportedLedgerExec, paths);
|
|
186
|
+
return {
|
|
187
|
+
deploymentName: selected.name,
|
|
188
|
+
records: read.records,
|
|
189
|
+
roster: rosterForRecord(selected),
|
|
190
|
+
runId: index.run_id,
|
|
191
|
+
unreadableUnits: read.unreadable.map((failure) => ({
|
|
192
|
+
containerRef: exportedDirectory,
|
|
193
|
+
detail: `${failure.filePath}: ${failure.reason}`,
|
|
194
|
+
reason: "ledger_read_failed",
|
|
195
|
+
unitId: `export:${index.run_id}`
|
|
196
|
+
}))
|
|
197
|
+
};
|
|
198
|
+
};
|
|
199
|
+
export const executeUsageCommand = async (inputPath, options, handlers = {}) => {
|
|
200
|
+
const since = options.since ?? DEFAULT_USAGE_SINCE;
|
|
201
|
+
const sinceMs = parseUsageSinceDuration(since);
|
|
202
|
+
if (sinceMs === null) {
|
|
203
|
+
return inputFailure(`Invalid --since "${since}". Use a duration like 30m, 24h, or 7d.`);
|
|
204
|
+
}
|
|
205
|
+
if (options.by !== undefined && options.by !== "agent" && options.by !== "engine") {
|
|
206
|
+
return inputFailure(`Invalid --by "${options.by}". Use "agent" or "engine".`);
|
|
207
|
+
}
|
|
208
|
+
if (options.top !== undefined && !/^[1-9]\d*$/u.test(options.top)) {
|
|
209
|
+
return inputFailure(`Invalid --top "${options.top}". Use a positive integer.`);
|
|
210
|
+
}
|
|
211
|
+
const timeoutMs = options.timeout === undefined ? undefined : Number(options.timeout);
|
|
212
|
+
if (timeoutMs !== undefined && (!Number.isFinite(timeoutMs) || timeoutMs <= 0)) {
|
|
213
|
+
return inputFailure(`Invalid --timeout "${options.timeout}". Use a positive number of milliseconds.`);
|
|
214
|
+
}
|
|
215
|
+
const outputDirectory = resolveProjectOutputDirectory(inputPath, options.out, DEFAULT_OUTPUT_DIRECTORY);
|
|
216
|
+
let usage;
|
|
217
|
+
try {
|
|
218
|
+
const source = await resolveUsageDeploymentSource(inputPath, options, handlers, outputDirectory);
|
|
219
|
+
const sourceHandlers = { ...handlers, listDeploymentRecords: source.loader };
|
|
220
|
+
// Source selection is explicit, never inferred from what happens to be
|
|
221
|
+
// reachable: --exported reads that sealed run and never contacts Docker,
|
|
222
|
+
// and without it the live container is read exactly as before. Passing
|
|
223
|
+
// --exported alongside a running organization still reads the export --
|
|
224
|
+
// that is the point of naming it -- and the rendered header says which
|
|
225
|
+
// source produced the numbers so a reader is never left guessing.
|
|
226
|
+
usage = options.exported === undefined
|
|
227
|
+
? await collectOrganizationUsage({
|
|
228
|
+
deployment: options.deployment,
|
|
229
|
+
dockerCommand: options.dockerCommand,
|
|
230
|
+
outputDirectory: source.outputDirectory,
|
|
231
|
+
timeoutMs
|
|
232
|
+
}, sourceHandlers)
|
|
233
|
+
: await collectExportedUsage(options.exported, options, source.outputDirectory, sourceHandlers);
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
return { error: error instanceof Error ? error.message : String(error), exitCode: errorExitCode(error) };
|
|
237
|
+
}
|
|
238
|
+
if ("error" in usage)
|
|
239
|
+
return inputFailure(usage.error);
|
|
240
|
+
const windowed = filterUsageRecordsSince(usage.records, sinceMs)
|
|
241
|
+
.filter((record) => options.agent === undefined || record.agent === options.agent);
|
|
242
|
+
if (options.json) {
|
|
243
|
+
const coverage = computeUsageCoverage(windowed, usage.roster.length, usage.unreadableUnits.length);
|
|
244
|
+
return {
|
|
245
|
+
exitCode: 0,
|
|
246
|
+
output: `${JSON.stringify({
|
|
247
|
+
version: "spawnfile.usage.v1",
|
|
248
|
+
deployment: usage.deploymentName,
|
|
249
|
+
source: options.exported === undefined ? "live" : "exported",
|
|
250
|
+
since,
|
|
251
|
+
lowerBound: true,
|
|
252
|
+
coverage,
|
|
253
|
+
byAgent: groupUsageByAgent(windowed, usage.roster),
|
|
254
|
+
byEngine: groupUsageByEngine(windowed),
|
|
255
|
+
unreadableUnits: usage.unreadableUnits
|
|
256
|
+
}, null, 2)}`
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
return { exitCode: 0, output: renderTable(usage, windowed, { ...options, since }) };
|
|
260
|
+
};
|
|
261
|
+
export const registerUsageCommand = (program, streams, setExitCode, handlers = {}) => {
|
|
262
|
+
program
|
|
263
|
+
.command("usage")
|
|
264
|
+
.description("Show what a deployed Spawnfile organization consumed, by agent and by engine")
|
|
265
|
+
.argument("[path]", "Project directory or Spawnfile path", process.cwd())
|
|
266
|
+
.option("--out <dir>", "Compile output directory")
|
|
267
|
+
.option("--exported <directory>", "Read a sealed run exported by `spawnfile artifacts export --out <dir>` instead of a live container")
|
|
268
|
+
.option("--deployment <name>", "Deployment record name")
|
|
269
|
+
.option("--since <duration>", `Window to report, e.g. 30m, 24h, 7d (default ${DEFAULT_USAGE_SINCE})`)
|
|
270
|
+
.option("--by <dimension>", "Group by \"agent\" (default) or \"engine\"")
|
|
271
|
+
.option("--agent <id>", "Report one agent")
|
|
272
|
+
.option("--top <n>", "Show only the n heaviest agents")
|
|
273
|
+
.option("--json", "Render machine-readable JSON")
|
|
274
|
+
.option("--docker-command <command>", "Docker command")
|
|
275
|
+
.option("--timeout <ms>", "Bound Docker reads in milliseconds")
|
|
276
|
+
.action(async (inputPath, options) => {
|
|
277
|
+
const result = await executeUsageCommand(inputPath, options, handlers);
|
|
278
|
+
setExitCode(result.exitCode);
|
|
279
|
+
if (result.error)
|
|
280
|
+
streams.stderr(`error: ${result.error}`);
|
|
281
|
+
if (result.output)
|
|
282
|
+
streams.stdout(result.output);
|
|
283
|
+
});
|
|
284
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { createDockerProbeGateway, inspectDockerDeployment, listDeploymentRecords, listHomeDeploymentRecords, type DeploymentRecord } from "../deployment/index.js";
|
|
2
|
+
import type { UsageRecord, UsageRosterEntry } from "../runtime/usageLedger.js";
|
|
3
|
+
/**
|
|
4
|
+
* Transport for `spawnfile usage`.
|
|
5
|
+
*
|
|
6
|
+
* The ledger lives inside the container, and the host may be macOS Docker
|
|
7
|
+
* Desktop or a remote Docker context, so a host-side `readFile` is impossible.
|
|
8
|
+
* Reads therefore go through the sanctioned channel — the docker probe gateway,
|
|
9
|
+
* which already supports `--context` / `--host` remote targets and is already
|
|
10
|
+
* used to `cat` container files. `docker exec` runs as the image user (root for
|
|
11
|
+
* a Daimon image), so a 0640 uid-2100 ledger is readable.
|
|
12
|
+
*
|
|
13
|
+
* Deferred: the stopped-container post-mortem path. `spawnfile down`
|
|
14
|
+
* deliberately preserves volumes, so a stopped unit's ledger is still on disk,
|
|
15
|
+
* but `docker exec` cannot reach it; the repo's `docker create` + `docker cp`
|
|
16
|
+
* volume-egress pattern (`artifactsExportDocker.ts`) is the intended fallback.
|
|
17
|
+
* Until it lands, a stopped unit is reported as UNREADABLE — never silently as
|
|
18
|
+
* zero usage, which would misreport a dead subscription as a cheap one.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Why a unit's usage is missing.
|
|
22
|
+
*
|
|
23
|
+
* `stopped`/`unreachable` are decided before any read is attempted, from the
|
|
24
|
+
* container inspection. `ledger_read_failed` is decided by the read itself
|
|
25
|
+
* (`readUsageLedgerViaExec`) and carries the generation and bounded reason in
|
|
26
|
+
* `detail`: the container was running and reachable, but one of its two ledger
|
|
27
|
+
* generations could not be `cat`ed — a `maxBuffer` overrun on a rotated
|
|
28
|
+
* generation, a timeout, or a daemon failure. All three mean the same thing
|
|
29
|
+
* for reporting: UNKNOWN usage, never zero.
|
|
30
|
+
*/
|
|
31
|
+
export interface UsageUnitReadFailure {
|
|
32
|
+
containerRef: string;
|
|
33
|
+
detail?: string;
|
|
34
|
+
reason: "ledger_read_failed" | "stopped" | "unreachable";
|
|
35
|
+
unitId: string;
|
|
36
|
+
}
|
|
37
|
+
export interface OrganizationUsage {
|
|
38
|
+
deploymentName: string;
|
|
39
|
+
records: UsageRecord[];
|
|
40
|
+
roster: UsageRosterEntry[];
|
|
41
|
+
unreadableUnits: UsageUnitReadFailure[];
|
|
42
|
+
}
|
|
43
|
+
export interface UsageCommandLiveHandlers {
|
|
44
|
+
createDockerProbeGateway?: typeof createDockerProbeGateway;
|
|
45
|
+
inspectDockerDeployment?: typeof inspectDockerDeployment;
|
|
46
|
+
listDeploymentRecords?: typeof listDeploymentRecords;
|
|
47
|
+
listHomeDeploymentRecords?: typeof listHomeDeploymentRecords;
|
|
48
|
+
}
|
|
49
|
+
export interface CollectOrganizationUsageOptions {
|
|
50
|
+
deployment?: string;
|
|
51
|
+
dockerCommand?: string;
|
|
52
|
+
outputDirectory: string;
|
|
53
|
+
timeoutMs?: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The org roster, from the deployment record itself.
|
|
57
|
+
*
|
|
58
|
+
* Engine assignment is not recorded per agent in a deployment record, so an
|
|
59
|
+
* agent's engine is learned from its own ledger records. An agent that never
|
|
60
|
+
* reports — every Codex agent, which is uninstrumented — keeps a `null` engine
|
|
61
|
+
* and renders as a dashed row. It still counts toward the coverage denominator,
|
|
62
|
+
* which is the whole point: a total computed over a partial roster must never be
|
|
63
|
+
* presented as the organization's cost.
|
|
64
|
+
*/
|
|
65
|
+
export declare const rosterForRecord: (record: DeploymentRecord) => UsageRosterEntry[];
|
|
66
|
+
export declare const selectUsageDeployment: (records: Array<{
|
|
67
|
+
record: DeploymentRecord;
|
|
68
|
+
}>, deployment?: string) => DeploymentRecord | {
|
|
69
|
+
error: string;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Read every unit's ledger and merge the results.
|
|
73
|
+
*
|
|
74
|
+
* A unit that is not running is recorded as unreadable rather than read as
|
|
75
|
+
* empty. A running unit whose ledger does not exist yet — the case before the
|
|
76
|
+
* first turn ever completes — reads as empty, never as an error, because
|
|
77
|
+
* `readUsageLedgerViaExec` treats an absent file (and only an absent file) as
|
|
78
|
+
* no content. Any other read failure comes back in that reader's `unreadable`
|
|
79
|
+
* list and is recorded here as a `ledger_read_failed` unit, so an unknown
|
|
80
|
+
* quantity of turns is never merged into the report as zero.
|
|
81
|
+
*/
|
|
82
|
+
export declare const collectOrganizationUsage: (options: CollectOrganizationUsageOptions, handlers?: UsageCommandLiveHandlers) => Promise<OrganizationUsage | {
|
|
83
|
+
error: string;
|
|
84
|
+
}>;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { createDockerProbeGateway, inspectDockerDeployment, listDeploymentRecords } from "../deployment/index.js";
|
|
2
|
+
import { DAIMON_GROK_TURN_USAGE_LEDGER } from "../runtime/daimon/contractManifest.js";
|
|
3
|
+
import { readUsageLedgerViaExec } from "../runtime/usageLedgerRead.js";
|
|
4
|
+
/**
|
|
5
|
+
* The org roster, from the deployment record itself.
|
|
6
|
+
*
|
|
7
|
+
* Engine assignment is not recorded per agent in a deployment record, so an
|
|
8
|
+
* agent's engine is learned from its own ledger records. An agent that never
|
|
9
|
+
* reports — every Codex agent, which is uninstrumented — keeps a `null` engine
|
|
10
|
+
* and renders as a dashed row. It still counts toward the coverage denominator,
|
|
11
|
+
* which is the whole point: a total computed over a partial roster must never be
|
|
12
|
+
* presented as the organization's cost.
|
|
13
|
+
*/
|
|
14
|
+
export const rosterForRecord = (record) => {
|
|
15
|
+
const agents = new Set();
|
|
16
|
+
for (const unit of record.units) {
|
|
17
|
+
for (const entry of unit.contains) {
|
|
18
|
+
if (entry.kind === "agent")
|
|
19
|
+
agents.add(entry.id);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return [...agents].sort().map((agent) => ({ agent, engine: null }));
|
|
23
|
+
};
|
|
24
|
+
const containerRefForUnit = (unit) => unit.container_id ?? unit.container_name ?? unit.id;
|
|
25
|
+
export const selectUsageDeployment = (records, deployment) => {
|
|
26
|
+
if (records.length === 0) {
|
|
27
|
+
return { error: "No deployment records found. Run `spawnfile up` first." };
|
|
28
|
+
}
|
|
29
|
+
if (deployment) {
|
|
30
|
+
const match = records.find((entry) => entry.record.name === deployment);
|
|
31
|
+
return match
|
|
32
|
+
? match.record
|
|
33
|
+
: { error: `Unknown deployment "${deployment}". Valid deployments: ${records.map((entry) => entry.record.name).sort().join(", ")}` };
|
|
34
|
+
}
|
|
35
|
+
if (records.length > 1) {
|
|
36
|
+
return { error: `spawnfile usage requires --deployment when multiple records exist: ${records.map((entry) => entry.record.name).sort().join(", ")}` };
|
|
37
|
+
}
|
|
38
|
+
return records[0].record;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Read every unit's ledger and merge the results.
|
|
42
|
+
*
|
|
43
|
+
* A unit that is not running is recorded as unreadable rather than read as
|
|
44
|
+
* empty. A running unit whose ledger does not exist yet — the case before the
|
|
45
|
+
* first turn ever completes — reads as empty, never as an error, because
|
|
46
|
+
* `readUsageLedgerViaExec` treats an absent file (and only an absent file) as
|
|
47
|
+
* no content. Any other read failure comes back in that reader's `unreadable`
|
|
48
|
+
* list and is recorded here as a `ledger_read_failed` unit, so an unknown
|
|
49
|
+
* quantity of turns is never merged into the report as zero.
|
|
50
|
+
*/
|
|
51
|
+
export const collectOrganizationUsage = async (options, handlers = {}) => {
|
|
52
|
+
const list = handlers.listDeploymentRecords ?? listDeploymentRecords;
|
|
53
|
+
const inspect = handlers.inspectDockerDeployment ?? inspectDockerDeployment;
|
|
54
|
+
const gatewayFor = handlers.createDockerProbeGateway ?? createDockerProbeGateway;
|
|
55
|
+
const selected = selectUsageDeployment(await list(options.outputDirectory), options.deployment);
|
|
56
|
+
if ("error" in selected)
|
|
57
|
+
return selected;
|
|
58
|
+
let inspections;
|
|
59
|
+
try {
|
|
60
|
+
inspections = await inspect(selected, { dockerCommand: options.dockerCommand, timeoutMs: options.timeoutMs });
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
64
|
+
}
|
|
65
|
+
const records = [];
|
|
66
|
+
const unreadableUnits = [];
|
|
67
|
+
for (const unit of selected.units) {
|
|
68
|
+
const inspection = inspections.get(unit.id);
|
|
69
|
+
if (inspection?.running !== true) {
|
|
70
|
+
unreadableUnits.push({
|
|
71
|
+
containerRef: containerRefForUnit(unit),
|
|
72
|
+
reason: inspection?.exists === false || inspection?.running === false ? "stopped" : "unreachable",
|
|
73
|
+
unitId: unit.id
|
|
74
|
+
});
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const gateway = gatewayFor(selected, unit, {
|
|
78
|
+
dockerCommand: options.dockerCommand,
|
|
79
|
+
inspection,
|
|
80
|
+
timeoutMs: options.timeoutMs
|
|
81
|
+
});
|
|
82
|
+
const exec = (command) => gateway.exec(command);
|
|
83
|
+
const read = await readUsageLedgerViaExec(exec, DAIMON_GROK_TURN_USAGE_LEDGER);
|
|
84
|
+
records.push(...read.records);
|
|
85
|
+
for (const failure of read.unreadable) {
|
|
86
|
+
unreadableUnits.push({
|
|
87
|
+
containerRef: containerRefForUnit(unit),
|
|
88
|
+
detail: `${failure.filePath}: ${failure.reason}`,
|
|
89
|
+
reason: "ledger_read_failed",
|
|
90
|
+
unitId: unit.id
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return { deploymentName: selected.name, records, roster: rosterForRecord(selected), unreadableUnits };
|
|
95
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { UsageCommandOptions } from "./usageCommand.js";
|
|
2
|
+
import type { UsageCommandLiveHandlers } from "./usageCommandLive.js";
|
|
3
|
+
type UsageDeploymentRecordLoader = NonNullable<UsageCommandLiveHandlers["listDeploymentRecords"]>;
|
|
4
|
+
export interface UsageDeploymentSource {
|
|
5
|
+
loader: UsageDeploymentRecordLoader;
|
|
6
|
+
outputDirectory: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const resolveUsageDeploymentSource: (inputPath: string, options: UsageCommandOptions, handlers: UsageCommandLiveHandlers, outputDirectory: string) => Promise<UsageDeploymentSource>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { listDeploymentRecords, listHomeDeploymentRecords } from "../deployment/index.js";
|
|
2
|
+
import { resolveCommandInput } from "./resolveCommandInput.js";
|
|
3
|
+
export const resolveUsageDeploymentSource = async (inputPath, options, handlers, outputDirectory) => {
|
|
4
|
+
const listProject = handlers.listDeploymentRecords ?? listDeploymentRecords;
|
|
5
|
+
const listHome = handlers.listHomeDeploymentRecords ?? listHomeDeploymentRecords;
|
|
6
|
+
const commandInput = resolveCommandInput(inputPath);
|
|
7
|
+
const usedDefaultPath = inputPath === process.cwd();
|
|
8
|
+
if (options.out !== undefined || (!usedDefaultPath && commandInput.kind === "project")) {
|
|
9
|
+
return { loader: listProject, outputDirectory };
|
|
10
|
+
}
|
|
11
|
+
if (commandInput.kind === "image" || (options.deployment !== undefined && usedDefaultPath)) {
|
|
12
|
+
return { loader: listHome, outputDirectory };
|
|
13
|
+
}
|
|
14
|
+
if (usedDefaultPath) {
|
|
15
|
+
const projectRecords = await listProject(outputDirectory);
|
|
16
|
+
if (projectRecords.length > 0) {
|
|
17
|
+
return { loader: async () => projectRecords, outputDirectory };
|
|
18
|
+
}
|
|
19
|
+
return { loader: listHome, outputDirectory };
|
|
20
|
+
}
|
|
21
|
+
return { loader: listProject, outputDirectory };
|
|
22
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { migrateWorkspaceResource } from "../deployment/workspaceResourceMigration.js";
|
|
2
|
+
export declare const isWorkspaceResourceMigrationInvocation: (argv: readonly string[]) => boolean;
|
|
3
|
+
export interface WorkspaceResourceMigrationCommandDependencies {
|
|
4
|
+
migrate?: typeof migrateWorkspaceResource;
|
|
5
|
+
stderr?: (message: string) => void;
|
|
6
|
+
stdout?: (message: string) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare const runWorkspaceResourceMigrationCommand: (argv: readonly string[], dependencies?: WorkspaceResourceMigrationCommandDependencies) => Promise<number>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { migrateWorkspaceResource } from "../deployment/workspaceResourceMigration.js";
|
|
2
|
+
export const isWorkspaceResourceMigrationInvocation = (argv) => argv[0] === "workspace-resource" && argv[1] === "migrate";
|
|
3
|
+
const usage = "usage: spawnfile workspace-resource migrate <source> <destination> --manifest <path> --resolved-identity <sha256> --source-quiesced [--json]";
|
|
4
|
+
export const runWorkspaceResourceMigrationCommand = async (argv, dependencies = {}) => {
|
|
5
|
+
const stdout = dependencies.stdout ?? ((message) => process.stdout.write(`${message}\n`));
|
|
6
|
+
const stderr = dependencies.stderr ?? ((message) => process.stderr.write(`${message}\n`));
|
|
7
|
+
if (!isWorkspaceResourceMigrationInvocation(argv))
|
|
8
|
+
return 2;
|
|
9
|
+
const sourcePath = argv[2];
|
|
10
|
+
const destinationPath = argv[3];
|
|
11
|
+
const manifestIndex = argv.indexOf("--manifest");
|
|
12
|
+
const manifestPath = manifestIndex < 0 ? undefined : argv[manifestIndex + 1];
|
|
13
|
+
const identityIndex = argv.indexOf("--resolved-identity");
|
|
14
|
+
const resolvedIdentity = identityIndex < 0 ? undefined : argv[identityIndex + 1];
|
|
15
|
+
const quiescedIndex = argv.indexOf("--source-quiesced");
|
|
16
|
+
const allowed = new Set([0, 1, 2, 3, manifestIndex, manifestIndex + 1, identityIndex, identityIndex + 1, quiescedIndex, argv.indexOf("--json")].filter((index) => index >= 0));
|
|
17
|
+
if (!sourcePath || !destinationPath || !manifestPath || !resolvedIdentity || quiescedIndex < 0 || argv.some((_value, index) => !allowed.has(index))) {
|
|
18
|
+
stderr(usage);
|
|
19
|
+
return 2;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const receipt = await (dependencies.migrate ?? migrateWorkspaceResource)({ destinationPath, manifestPath, resolvedIdentity, sourcePath, sourceQuiesced: true });
|
|
23
|
+
stdout(argv.includes("--json") ? JSON.stringify(receipt) : render(receipt));
|
|
24
|
+
return receipt.status === "activated" ? 0 : 1;
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
stderr(error instanceof Error ? error.message : String(error));
|
|
28
|
+
return 1;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const render = (receipt) => [
|
|
32
|
+
`workspace resource migration: ${receipt.status}`,
|
|
33
|
+
`active: ${receipt.active_path}`,
|
|
34
|
+
`source retained: ${receipt.source_retained ? "yes" : "no"}`,
|
|
35
|
+
`rollback: ${receipt.rollback ? "yes" : "no"}`
|
|
36
|
+
].join("\n");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type TeamManifest } from "../manifest/index.js";
|
|
2
2
|
import type { ResolvedTeamNetwork, ResolvedTeamNode } from "./types.js";
|
|
3
3
|
export declare const resolveTeamExternalIds: (manifest: TeamManifest) => string[];
|
|
4
4
|
export declare const resolveTeamNetworks: (manifest: TeamManifest) => ResolvedTeamNetwork[];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isDeclaredPairedRemoteRoomMember } from "../manifest/index.js";
|
|
1
2
|
import { SpawnfileError } from "../shared/index.js";
|
|
2
3
|
export const resolveTeamExternalIds = (manifest) => {
|
|
3
4
|
const memberIds = manifest.members.map((member) => member.id);
|
|
@@ -20,6 +21,9 @@ export const resolveTeamNetworks = (manifest) => (manifest.networks ?? []).map((
|
|
|
20
21
|
name: network.name ?? network.id,
|
|
21
22
|
provider: network.provider,
|
|
22
23
|
rooms: network.rooms.map((room) => ({
|
|
24
|
+
...(room.federation
|
|
25
|
+
? { federation: Array.isArray(room.federation) ? [...room.federation].sort() : room.federation }
|
|
26
|
+
: {}),
|
|
23
27
|
id: room.id,
|
|
24
28
|
members: [...room.members],
|
|
25
29
|
...(room.name ? { name: room.name } : {}),
|
|
@@ -40,7 +44,8 @@ export const validateTeamNetworkRooms = (teamNode) => {
|
|
|
40
44
|
for (const roomMemberId of room.members) {
|
|
41
45
|
const resolvedMember = teamNode.members.find((member) => member.id === roomMemberId);
|
|
42
46
|
if (!resolvedMember
|
|
43
|
-
&& !isAttachedExternalRoomMember(teamNode, network.id, roomMemberId)
|
|
47
|
+
&& !isAttachedExternalRoomMember(teamNode, network.id, roomMemberId)
|
|
48
|
+
&& !isDeclaredPairedRemoteRoomMember(network, room, roomMemberId)) {
|
|
44
49
|
throw new SpawnfileError("validation_error", `Team ${teamNode.name} Moltnet room ${room.id} references unknown member ${roomMemberId}`);
|
|
45
50
|
}
|
|
46
51
|
}
|
|
@@ -55,6 +55,9 @@ const collectMoltnetSecretNames = (server, secretNames) => {
|
|
|
55
55
|
if (server.mode === "managed") {
|
|
56
56
|
for (const pairing of server.pairings ?? []) {
|
|
57
57
|
secretNames.add(pairing.token_secret);
|
|
58
|
+
if (pairing.relay) {
|
|
59
|
+
secretNames.add(pairing.relay.token_secret);
|
|
60
|
+
}
|
|
58
61
|
}
|
|
59
62
|
if (server.store.kind === "postgres") {
|
|
60
63
|
secretNames.add(server.store.dsn_secret);
|
|
@@ -7,6 +7,8 @@ export type { CreateOrganizationReadinessEvidenceInput, OrganizationReadinessEvi
|
|
|
7
7
|
export interface CompileProjectOptions {
|
|
8
8
|
clean?: boolean;
|
|
9
9
|
containerArchitecture?: MoltnetTargetArchitecture;
|
|
10
|
+
/** Stable deployment identity for exclusive credential-realm reattachment. */
|
|
11
|
+
deploymentLineage?: string;
|
|
10
12
|
outputDirectory?: string;
|
|
11
13
|
/** Compile-time-only local overrides for runtime install npm packages
|
|
12
14
|
* (see src/compiler/containerPackageOverrides.ts). Only opt-in
|