spawnfile 0.1.11 → 0.1.13
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 +21 -3
- package/dist/auth/runtimeCredentials.js +18 -2
- package/dist/cli/devCommands.d.ts +3 -0
- package/dist/cli/devCommands.js +115 -0
- package/dist/cli/lifecycleCommands.js +103 -1
- package/dist/cli/modelCommands.js +3 -0
- package/dist/cli/resolveCommandInput.d.ts +19 -0
- package/dist/cli/resolveCommandInput.js +25 -0
- package/dist/cli/runCli.d.ts +10 -1
- package/dist/cli/runCli.js +41 -13
- package/dist/cli/runtimeCommands.js +1 -0
- package/dist/cli/statusCommand.d.ts +43 -0
- package/dist/cli/statusCommand.js +428 -0
- package/dist/cli/surfaceCommands.js +4 -0
- package/dist/compiler/agentSurfaces.js +2 -4
- package/dist/compiler/buildProject.d.ts +9 -1
- package/dist/compiler/buildProject.js +44 -5
- package/dist/compiler/compileProject.d.ts +2 -0
- package/dist/compiler/compileProject.js +22 -11
- package/dist/compiler/containerArtifacts.d.ts +1 -0
- package/dist/compiler/containerArtifacts.js +208 -32
- package/dist/compiler/containerArtifactsPlans.js +7 -4
- package/dist/compiler/containerArtifactsRender.d.ts +7 -1
- package/dist/compiler/containerArtifactsRender.js +31 -69
- package/dist/compiler/containerArtifactsTypes.d.ts +9 -0
- package/dist/compiler/containerEntrypointRender.js +22 -32
- package/dist/compiler/containerPackageRender.d.ts +15 -0
- package/dist/compiler/containerPackageRender.js +63 -0
- package/dist/compiler/containerTargetResources.js +3 -1
- package/dist/compiler/index.d.ts +1 -0
- package/dist/compiler/index.js +1 -0
- package/dist/compiler/moltnetArtifacts.js +21 -1
- package/dist/compiler/moltnetBinaries.d.ts +4 -1
- package/dist/compiler/moltnetBinaries.js +24 -3
- package/dist/compiler/moltnetClientConfig.d.ts +1 -1
- package/dist/compiler/moltnetClientConfig.js +14 -16
- package/dist/compiler/moltnetNodeConfig.js +2 -4
- package/dist/compiler/moltnetResolution.js +1 -1
- package/dist/compiler/moltnetRoomMemberships.js +1 -2
- package/dist/compiler/moltnetRuntimeConfig.d.ts +1 -1
- package/dist/compiler/moltnetRuntimeConfig.js +9 -10
- package/dist/compiler/networkBinding.d.ts +14 -0
- package/dist/compiler/networkBinding.js +34 -0
- package/dist/compiler/publishProject.d.ts +13 -0
- package/dist/compiler/publishProject.js +72 -0
- package/dist/compiler/runProject.d.ts +26 -12
- package/dist/compiler/runProject.js +109 -126
- package/dist/compiler/runProjectAuth.d.ts +5 -0
- package/dist/compiler/runProjectAuth.js +98 -0
- package/dist/compiler/runProjectDocker.d.ts +19 -0
- package/dist/compiler/runProjectDocker.js +202 -0
- package/dist/compiler/types.d.ts +1 -2
- package/dist/compiler/upProject.d.ts +6 -0
- package/dist/compiler/upProject.js +43 -8
- package/dist/compiler/view/buildOrganizationView.js +4 -1
- package/dist/compiler/view/declarations.d.ts +4 -0
- package/dist/compiler/view/declarations.js +104 -0
- package/dist/compiler/view/renderNetworks.js +1 -2
- package/dist/compiler/view/renderTree.js +6 -2
- package/dist/compiler/view/types.d.ts +64 -1
- package/dist/deployment/dockerInspect.d.ts +29 -0
- package/dist/deployment/dockerInspect.js +130 -0
- package/dist/deployment/dockerLabels.d.ts +16 -0
- package/dist/deployment/dockerLabels.js +32 -0
- package/dist/deployment/dockerLogs.d.ts +24 -0
- package/dist/deployment/dockerLogs.js +96 -0
- package/dist/deployment/dockerManager.d.ts +59 -0
- package/dist/deployment/dockerManager.js +76 -0
- package/dist/deployment/dockerProbeGateway.d.ts +16 -0
- package/dist/deployment/dockerProbeGateway.js +48 -0
- package/dist/deployment/dockerRecover.d.ts +17 -0
- package/dist/deployment/dockerRecover.js +129 -0
- package/dist/deployment/homeStore.d.ts +19 -0
- package/dist/deployment/homeStore.js +130 -0
- package/dist/deployment/index.d.ts +10 -0
- package/dist/deployment/index.js +10 -0
- package/dist/deployment/names.d.ts +3 -0
- package/dist/deployment/names.js +12 -0
- package/dist/deployment/record.d.ts +76 -0
- package/dist/deployment/record.js +174 -0
- package/dist/deployment/target.d.ts +35 -0
- package/dist/deployment/target.js +96 -0
- package/dist/dev/activity.d.ts +14 -0
- package/dist/dev/activity.js +48 -0
- package/dist/dev/docker.d.ts +16 -0
- package/dist/dev/docker.js +71 -0
- package/dist/dev/index.d.ts +2 -0
- package/dist/dev/index.js +2 -0
- package/dist/dev/project.d.ts +35 -0
- package/dist/dev/project.js +164 -0
- package/dist/distribution/buildDistributionReport.d.ts +22 -0
- package/dist/distribution/buildDistributionReport.js +51 -0
- package/dist/distribution/consumeImage.d.ts +29 -0
- package/dist/distribution/consumeImage.js +254 -0
- package/dist/distribution/consumeImageSupport.d.ts +18 -0
- package/dist/distribution/consumeImageSupport.js +63 -0
- package/dist/distribution/distributionReportSchema.d.ts +84 -0
- package/dist/distribution/distributionReportSchema.js +107 -0
- package/dist/distribution/dockerRunner.d.ts +5 -0
- package/dist/distribution/dockerRunner.js +21 -0
- package/dist/distribution/extractImage.d.ts +25 -0
- package/dist/distribution/extractImage.js +96 -0
- package/dist/distribution/fingerprint.d.ts +2 -0
- package/dist/distribution/fingerprint.js +14 -0
- package/dist/distribution/imageRef.d.ts +9 -0
- package/dist/distribution/imageRef.js +65 -0
- package/dist/distribution/imageRuntimeAuth.d.ts +19 -0
- package/dist/distribution/imageRuntimeAuth.js +71 -0
- package/dist/distribution/index.d.ts +24 -0
- package/dist/distribution/index.js +16 -0
- package/dist/distribution/preflight.d.ts +11 -0
- package/dist/distribution/preflight.js +65 -0
- package/dist/distribution/projectImageView.d.ts +8 -0
- package/dist/distribution/projectImageView.js +83 -0
- package/dist/distribution/projectName.d.ts +1 -0
- package/dist/distribution/projectName.js +12 -0
- package/dist/distribution/renderImageInterface.d.ts +30 -0
- package/dist/distribution/renderImageInterface.js +86 -0
- package/dist/distribution/tarReader.d.ts +10 -0
- package/dist/distribution/tarReader.js +69 -0
- package/dist/distribution/types.d.ts +80 -0
- package/dist/distribution/types.js +4 -0
- package/dist/distribution/verifyDistributionReport.d.ts +12 -0
- package/dist/distribution/verifyDistributionReport.js +29 -0
- package/dist/filesystem/paths.d.ts +6 -0
- package/dist/filesystem/paths.js +11 -0
- package/dist/manifest/loadManifest.js +22 -2
- package/dist/manifest/renderSpawnfile.js +2 -4
- package/dist/manifest/schemas.d.ts +17 -41
- package/dist/manifest/surfaceSchemas.d.ts +19 -47
- package/dist/manifest/surfaceSchemas.js +3 -6
- package/dist/report/createReport.d.ts +7 -1
- package/dist/report/createReport.js +28 -1
- package/dist/report/types.d.ts +43 -0
- package/dist/runtime/common.d.ts +2 -0
- package/dist/runtime/common.js +1 -1
- package/dist/runtime/container.d.ts +1 -0
- package/dist/runtime/container.js +82 -15
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/install.d.ts +1 -11
- package/dist/runtime/install.js +27 -30
- package/dist/runtime/openclaw/adapter.js +9 -1
- package/dist/runtime/openclaw/configAuth.d.ts +15 -0
- package/dist/runtime/openclaw/configAuth.js +46 -0
- package/dist/runtime/openclaw/runAuth.d.ts +6 -0
- package/dist/runtime/openclaw/runAuth.js +7 -55
- package/dist/runtime/openclaw/statusProbes.d.ts +2 -0
- package/dist/runtime/openclaw/statusProbes.js +31 -0
- package/dist/runtime/pi/adapter.d.ts +4 -0
- package/dist/runtime/pi/adapter.js +198 -0
- package/dist/runtime/pi/appActivitySource.d.ts +1 -0
- package/dist/runtime/pi/appActivitySource.js +87 -0
- package/dist/runtime/pi/appCoreSource.d.ts +1 -0
- package/dist/runtime/pi/appCoreSource.js +354 -0
- package/dist/runtime/pi/appPreludeSource.d.ts +1 -0
- package/dist/runtime/pi/appPreludeSource.js +103 -0
- package/dist/runtime/pi/appSource.d.ts +1 -0
- package/dist/runtime/pi/appSource.js +8 -0
- package/dist/runtime/pi/appTemplate.d.ts +28 -0
- package/dist/runtime/pi/appTemplate.js +144 -0
- package/dist/runtime/pi/runAuth.d.ts +2 -0
- package/dist/runtime/pi/runAuth.js +68 -0
- package/dist/runtime/picoclaw/adapter.js +10 -0
- package/dist/runtime/picoclaw/runAuth.d.ts +7 -0
- package/dist/runtime/picoclaw/runAuth.js +8 -68
- package/dist/runtime/picoclaw/statusProbes.d.ts +2 -0
- package/dist/runtime/picoclaw/statusProbes.js +100 -0
- package/dist/runtime/registry.d.ts +0 -5
- package/dist/runtime/registry.js +5 -12
- package/dist/runtime/statusProbes.d.ts +16 -0
- package/dist/runtime/statusProbes.js +41 -0
- package/dist/runtime/types.d.ts +53 -1
- package/dist/shared/errors.d.ts +6 -0
- package/dist/shared/errors.js +9 -0
- package/dist/status/buildStatus.d.ts +13 -0
- package/dist/status/buildStatus.js +266 -0
- package/dist/status/compileReport.d.ts +96 -0
- package/dist/status/compileReport.js +230 -0
- package/dist/status/compiledContainerObservations.d.ts +5 -0
- package/dist/status/compiledContainerObservations.js +63 -0
- package/dist/status/deploymentLogs.d.ts +12 -0
- package/dist/status/deploymentLogs.js +45 -0
- package/dist/status/deployments.d.ts +14 -0
- package/dist/status/deployments.js +121 -0
- package/dist/status/imageStatusReport.d.ts +10 -0
- package/dist/status/imageStatusReport.js +73 -0
- package/dist/status/index.d.ts +14 -0
- package/dist/status/index.js +14 -0
- package/dist/status/moltnetProbes.d.ts +21 -0
- package/dist/status/moltnetProbes.js +240 -0
- package/dist/status/registryDrift.d.ts +28 -0
- package/dist/status/registryDrift.js +119 -0
- package/dist/status/renderStatus.d.ts +2 -0
- package/dist/status/renderStatus.js +230 -0
- package/dist/status/runtimeProbes.d.ts +13 -0
- package/dist/status/runtimeProbes.js +111 -0
- package/dist/status/selectionSubjects.d.ts +8 -0
- package/dist/status/selectionSubjects.js +77 -0
- package/dist/status/selectors.d.ts +14 -0
- package/dist/status/selectors.js +90 -0
- package/dist/status/traversal.d.ts +6 -0
- package/dist/status/traversal.js +15 -0
- package/dist/status/types.d.ts +113 -0
- package/dist/status/types.js +1 -0
- package/package.json +9 -2
- package/runtimes.yaml +44 -21
- package/dist/runtime/tinyclaw/adapter.d.ts +0 -2
- package/dist/runtime/tinyclaw/adapter.js +0 -284
- package/dist/runtime/tinyclaw/runAuth.d.ts +0 -2
- package/dist/runtime/tinyclaw/runAuth.js +0 -49
- package/dist/runtime/tinyclaw/scaffold-assets/AGENTS.md +0 -160
- package/dist/runtime/tinyclaw/scaffold-assets/CLAUDE.md +0 -5
- package/dist/runtime/tinyclaw/scaffold-assets/SOUL.md +0 -177
- package/dist/runtime/tinyclaw/scaffold.d.ts +0 -2
- package/dist/runtime/tinyclaw/scaffold.js +0 -24
- package/dist/runtime/tinyclaw/schedules.d.ts +0 -9
- package/dist/runtime/tinyclaw/schedules.js +0 -62
- package/dist/runtime/tinyclaw/surfaces.d.ts +0 -8
- package/dist/runtime/tinyclaw/surfaces.js +0 -94
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { chmod } from "node:fs/promises";
|
|
3
|
+
import { loadImportedClaudeCodeCredential, loadImportedCodexCredential } from "../../auth/index.js";
|
|
4
|
+
import { ensureDirectory, writeUtf8File } from "../../filesystem/index.js";
|
|
5
|
+
const createMountArgs = (hostPath, containerPath) => [
|
|
6
|
+
"-v",
|
|
7
|
+
`${hostPath}:${containerPath}`
|
|
8
|
+
];
|
|
9
|
+
const writeJsonFile = async (tempRoot, relativePath, value) => {
|
|
10
|
+
const hostPath = path.join(tempRoot, relativePath);
|
|
11
|
+
const hostDirectory = path.dirname(hostPath);
|
|
12
|
+
await ensureDirectory(hostDirectory);
|
|
13
|
+
await writeUtf8File(hostPath, `${JSON.stringify(value, null, 2)}\n`);
|
|
14
|
+
await chmod(hostDirectory, 0o700);
|
|
15
|
+
// Docker bind mounts preserve host file mode; the generated image runs as
|
|
16
|
+
// the non-root `spawnfile` user, so the mounted auth file must be readable
|
|
17
|
+
// by a UID that usually differs from the host owner.
|
|
18
|
+
await chmod(hostPath, 0o644);
|
|
19
|
+
return hostPath;
|
|
20
|
+
};
|
|
21
|
+
const collectCoveredSecrets = (instanceSecrets, enabled, secretName) => enabled && instanceSecrets.includes(secretName) ? [secretName] : [];
|
|
22
|
+
export const preparePiRuntimeAuth = async (input) => {
|
|
23
|
+
if (!input.instance.home_path) {
|
|
24
|
+
return { coveredModelSecrets: [], mountArgs: [] };
|
|
25
|
+
}
|
|
26
|
+
const codex = input.authProfile.imports.codex
|
|
27
|
+
? await loadImportedCodexCredential(input.authProfile.imports.codex.path)
|
|
28
|
+
: null;
|
|
29
|
+
const claudeCode = input.authProfile.imports["claude-code"]
|
|
30
|
+
? await loadImportedClaudeCodeCredential(input.authProfile.imports["claude-code"].path)
|
|
31
|
+
: null;
|
|
32
|
+
const useCodex = input.instance.model_auth_methods.openai === "codex" && codex;
|
|
33
|
+
const useClaudeCode = input.instance.model_auth_methods.anthropic === "claude-code" && claudeCode;
|
|
34
|
+
if (!useCodex && !useClaudeCode) {
|
|
35
|
+
return { coveredModelSecrets: [], mountArgs: [] };
|
|
36
|
+
}
|
|
37
|
+
const authProfiles = {};
|
|
38
|
+
if (useCodex) {
|
|
39
|
+
authProfiles["openai-codex"] = {
|
|
40
|
+
access: codex.access,
|
|
41
|
+
...(codex.accountId ? { accountId: codex.accountId } : {}),
|
|
42
|
+
expires: codex.expires,
|
|
43
|
+
refresh: codex.refresh,
|
|
44
|
+
type: "oauth"
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (useClaudeCode) {
|
|
48
|
+
authProfiles.anthropic = claudeCode.type === "oauth" && claudeCode.refresh
|
|
49
|
+
? {
|
|
50
|
+
access: claudeCode.access,
|
|
51
|
+
expires: claudeCode.expires,
|
|
52
|
+
refresh: claudeCode.refresh,
|
|
53
|
+
type: "oauth"
|
|
54
|
+
}
|
|
55
|
+
: {
|
|
56
|
+
key: claudeCode.access,
|
|
57
|
+
type: "api_key"
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const authPath = await writeJsonFile(input.tempRoot, path.join("runtime-auth", "pi", input.instance.id, "auth.json"), authProfiles);
|
|
61
|
+
return {
|
|
62
|
+
coveredModelSecrets: [
|
|
63
|
+
...collectCoveredSecrets(input.instance.model_secrets_required, Boolean(useCodex), "OPENAI_API_KEY"),
|
|
64
|
+
...collectCoveredSecrets(input.instance.model_secrets_required, Boolean(useClaudeCode), "ANTHROPIC_API_KEY")
|
|
65
|
+
],
|
|
66
|
+
mountArgs: createMountArgs(authPath, path.posix.join(input.instance.home_path, ".pi", "agent", "auth.json"))
|
|
67
|
+
};
|
|
68
|
+
};
|
|
@@ -6,6 +6,7 @@ import { createPicoClawAgentScaffold } from "./scaffold.js";
|
|
|
6
6
|
import { createPicoClawCronStoreFile, createScheduleDiagnostics, scheduleOutcomeFor } from "./schedules.js";
|
|
7
7
|
import { assertSupportedPicoClawSurfaces, buildPicoClawChannelConfig, buildPicoClawSurfaceEnvBindings } from "./surfaces.js";
|
|
8
8
|
import { PICOCLAW_GATEWAY_BASE_PORT, PICOCLAW_INTERNAL_PICO_TOKEN } from "./pico.js";
|
|
9
|
+
import { picoClawStatusProbes } from "./statusProbes.js";
|
|
9
10
|
const formatModelName = (node) => {
|
|
10
11
|
const primary = node.execution?.model?.primary;
|
|
11
12
|
if (!primary)
|
|
@@ -55,6 +56,14 @@ const buildModelList = (node) => {
|
|
|
55
56
|
workspace: "<workspace-path>"
|
|
56
57
|
};
|
|
57
58
|
}
|
|
59
|
+
// Bake claude-cli (Claude Code subscription) auth at compile time so the
|
|
60
|
+
// image is self-sufficient; only the credential import is mounted at run.
|
|
61
|
+
if (target.provider === "anthropic" && target.auth.method === "claude-code") {
|
|
62
|
+
return {
|
|
63
|
+
model: `claude-cli/${target.name.replaceAll(".", "-")}`,
|
|
64
|
+
model_name: target.name
|
|
65
|
+
};
|
|
66
|
+
}
|
|
58
67
|
return {
|
|
59
68
|
...(target.auth.method === "api_key"
|
|
60
69
|
? {
|
|
@@ -230,6 +239,7 @@ export const picoClawAdapter = {
|
|
|
230
239
|
name: "picoclaw",
|
|
231
240
|
prepareRuntimeAuth: preparePicoClawRuntimeAuth,
|
|
232
241
|
scaffoldAgentProject: createPicoClawAgentScaffold,
|
|
242
|
+
statusProbes: picoClawStatusProbes,
|
|
233
243
|
validateRuntimeOptions(options) {
|
|
234
244
|
if ("restrict_to_workspace" in options &&
|
|
235
245
|
typeof options.restrict_to_workspace !== "boolean") {
|
|
@@ -1,2 +1,9 @@
|
|
|
1
1
|
import type { RuntimeAuthPreparationInput, RuntimeAuthPreparationResult } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* PicoClaw claude-cli (Claude Code) auth: the claude-cli model config is baked
|
|
4
|
+
* into the image at compile time and the credential import (~/.claude) is
|
|
5
|
+
* mounted into the runtime home by the caller, so this only reports that the
|
|
6
|
+
* model secret is covered. No source rootfs is read, which is what lets it run
|
|
7
|
+
* for both project deployments and sourceless images.
|
|
8
|
+
*/
|
|
2
9
|
export declare const preparePicoClawRuntimeAuth: (input: RuntimeAuthPreparationInput) => Promise<RuntimeAuthPreparationResult>;
|
|
@@ -1,59 +1,11 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
1
|
import { loadImportedClaudeCodeCredential } from "../../auth/index.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const sourceHomePath = resolveRootfsSourcePath(input.outputDirectory, input.instance.home_path);
|
|
11
|
-
const mountedHomePath = path.join("runtime-auth", "picoclaw", input.instance.id, "home");
|
|
12
|
-
const hostHomePath = path.join(input.tempRoot, mountedHomePath);
|
|
13
|
-
await ensureDirectory(path.dirname(hostHomePath));
|
|
14
|
-
await copyDirectory(sourceHomePath, hostHomePath);
|
|
15
|
-
const relativeConfigPath = path.posix.relative(input.instance.home_path, input.instance.config_path);
|
|
16
|
-
const hostConfigPath = path.join(hostHomePath, ...relativeConfigPath.split("/"));
|
|
17
|
-
await ensureDirectory(path.dirname(hostConfigPath));
|
|
18
|
-
await writeUtf8File(hostConfigPath, `${JSON.stringify(patchedConfig, null, 2)}\n`);
|
|
19
|
-
return hostHomePath;
|
|
20
|
-
};
|
|
21
|
-
const normalizeClaudeCliModelName = (modelName) => modelName.replaceAll(".", "-");
|
|
22
|
-
const patchPicoClawConfig = (config, options) => {
|
|
23
|
-
const agents = config.agents ?? {};
|
|
24
|
-
const defaults = agents.defaults ?? {};
|
|
25
|
-
const providers = (config.providers ?? {});
|
|
26
|
-
const modelList = Array.isArray(config.model_list) ? config.model_list : [];
|
|
27
|
-
const nextProviders = { ...providers };
|
|
28
|
-
const nextModelList = modelList.map((entry) => {
|
|
29
|
-
if (!entry || typeof entry !== "object") {
|
|
30
|
-
return entry;
|
|
31
|
-
}
|
|
32
|
-
const record = { ...entry };
|
|
33
|
-
const model = record.model;
|
|
34
|
-
const modelName = typeof record.model_name === "string" ? record.model_name : null;
|
|
35
|
-
if (options.useClaudeCode && typeof model === "string" && model.startsWith("anthropic/")) {
|
|
36
|
-
delete record.api_key;
|
|
37
|
-
delete record.auth_method;
|
|
38
|
-
if (modelName) {
|
|
39
|
-
record.model = `claude-cli/${normalizeClaudeCliModelName(modelName)}`;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return record;
|
|
43
|
-
});
|
|
44
|
-
if (options.useClaudeCode) {
|
|
45
|
-
delete nextProviders.anthropic;
|
|
46
|
-
}
|
|
47
|
-
return {
|
|
48
|
-
...config,
|
|
49
|
-
agents: {
|
|
50
|
-
...agents,
|
|
51
|
-
defaults
|
|
52
|
-
},
|
|
53
|
-
model_list: nextModelList,
|
|
54
|
-
providers: nextProviders
|
|
55
|
-
};
|
|
56
|
-
};
|
|
2
|
+
/**
|
|
3
|
+
* PicoClaw claude-cli (Claude Code) auth: the claude-cli model config is baked
|
|
4
|
+
* into the image at compile time and the credential import (~/.claude) is
|
|
5
|
+
* mounted into the runtime home by the caller, so this only reports that the
|
|
6
|
+
* model secret is covered. No source rootfs is read, which is what lets it run
|
|
7
|
+
* for both project deployments and sourceless images.
|
|
8
|
+
*/
|
|
57
9
|
export const preparePicoClawRuntimeAuth = async (input) => {
|
|
58
10
|
if (!input.instance.home_path) {
|
|
59
11
|
return { coveredModelSecrets: [], mountArgs: [] };
|
|
@@ -65,17 +17,5 @@ export const preparePicoClawRuntimeAuth = async (input) => {
|
|
|
65
17
|
if (!useClaudeCode) {
|
|
66
18
|
return { coveredModelSecrets: [], mountArgs: [] };
|
|
67
19
|
}
|
|
68
|
-
|
|
69
|
-
if (useClaudeCode) {
|
|
70
|
-
coveredModelSecrets.push("ANTHROPIC_API_KEY");
|
|
71
|
-
}
|
|
72
|
-
const sourceConfig = JSON.parse(await readUtf8File(resolveRootfsSourcePath(input.outputDirectory, input.instance.config_path)));
|
|
73
|
-
const patchedConfig = patchPicoClawConfig(sourceConfig, {
|
|
74
|
-
useClaudeCode: Boolean(useClaudeCode)
|
|
75
|
-
});
|
|
76
|
-
const mountedHomePath = await createMountedHomeDirectory(input, patchedConfig);
|
|
77
|
-
return {
|
|
78
|
-
coveredModelSecrets,
|
|
79
|
-
mountArgs: createMountArgs(mountedHomePath, input.instance.home_path)
|
|
80
|
-
};
|
|
20
|
+
return { coveredModelSecrets: ["ANTHROPIC_API_KEY"], mountArgs: [] };
|
|
81
21
|
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createRuntimeHttpProbe, createRuntimePathProbe } from "../statusProbes.js";
|
|
2
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3
|
+
const toNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
4
|
+
const toString = (value) => typeof value === "string" ? value : null;
|
|
5
|
+
const cronStorePathFor = (workspacePath) => workspacePath ? `${workspacePath}/cron/jobs.json` : null;
|
|
6
|
+
const earliestNextRun = (parsed) => {
|
|
7
|
+
const jobs = isRecord(parsed) && Array.isArray(parsed.jobs) ? parsed.jobs : [];
|
|
8
|
+
const dueJobs = jobs.flatMap((job) => {
|
|
9
|
+
if (!isRecord(job)) {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
const state = isRecord(job.state) ? job.state : {};
|
|
13
|
+
const nextRunAtMs = toNumber(state.nextRunAtMs ?? state.next_run_at_ms);
|
|
14
|
+
return nextRunAtMs === null
|
|
15
|
+
? []
|
|
16
|
+
: [{ jobId: toString(job.id), nextRunAtMs }];
|
|
17
|
+
});
|
|
18
|
+
return dueJobs.sort((left, right) => left.nextRunAtMs - right.nextRunAtMs)[0] ?? null;
|
|
19
|
+
};
|
|
20
|
+
const formatIso = (epochMs) => new Date(epochMs).toISOString();
|
|
21
|
+
const createPicoClawScheduleProbe = () => ({
|
|
22
|
+
id: "schedule-next-run",
|
|
23
|
+
label: "PicoClaw schedule next run",
|
|
24
|
+
async run(context) {
|
|
25
|
+
const cronStorePath = cronStorePathFor(context.instance.workspace_path);
|
|
26
|
+
if (!cronStorePath) {
|
|
27
|
+
return [{
|
|
28
|
+
key: "schedule.next_run",
|
|
29
|
+
message: "PicoClaw workspace path is not present in the compile report",
|
|
30
|
+
severity: "unknown"
|
|
31
|
+
}];
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const result = await context.manager.exec(["cat", cronStorePath]);
|
|
35
|
+
const nextRun = earliestNextRun(JSON.parse(result.stdout));
|
|
36
|
+
if (!nextRun) {
|
|
37
|
+
return [{
|
|
38
|
+
key: "schedule.next_run",
|
|
39
|
+
message: `PicoClaw cron store ${cronStorePath} has no computed next run`,
|
|
40
|
+
severity: "unknown"
|
|
41
|
+
}];
|
|
42
|
+
}
|
|
43
|
+
return [{
|
|
44
|
+
details: {
|
|
45
|
+
job_id: nextRun.jobId,
|
|
46
|
+
next_run_at: formatIso(nextRun.nextRunAtMs),
|
|
47
|
+
next_run_at_ms: nextRun.nextRunAtMs
|
|
48
|
+
},
|
|
49
|
+
key: "schedule.next_run",
|
|
50
|
+
message: `next scheduled PicoClaw wake for ${nextRun.jobId ?? "job"} at ${formatIso(nextRun.nextRunAtMs)}`,
|
|
51
|
+
severity: "ok"
|
|
52
|
+
}];
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
return [{
|
|
56
|
+
key: "schedule.next_run",
|
|
57
|
+
message: `PicoClaw cron store unavailable at ${cronStorePath}: ${error instanceof Error ? error.message : String(error)}`,
|
|
58
|
+
severity: "unknown"
|
|
59
|
+
}];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
export const picoClawStatusProbes = [
|
|
64
|
+
createRuntimePathProbe({
|
|
65
|
+
id: "home",
|
|
66
|
+
key: "runtime.home",
|
|
67
|
+
label: "PicoClaw home",
|
|
68
|
+
pathFor: (instance) => instance.home_path,
|
|
69
|
+
testFlag: "-d"
|
|
70
|
+
}),
|
|
71
|
+
createRuntimePathProbe({
|
|
72
|
+
id: "workspace",
|
|
73
|
+
key: "runtime.workspace",
|
|
74
|
+
label: "PicoClaw workspace",
|
|
75
|
+
pathFor: (instance) => instance.workspace_path,
|
|
76
|
+
testFlag: "-d"
|
|
77
|
+
}),
|
|
78
|
+
createRuntimePathProbe({
|
|
79
|
+
id: "config",
|
|
80
|
+
key: "runtime.config",
|
|
81
|
+
label: "PicoClaw config",
|
|
82
|
+
pathFor: (instance) => instance.config_path,
|
|
83
|
+
testFlag: "-f"
|
|
84
|
+
}),
|
|
85
|
+
createRuntimeHttpProbe({
|
|
86
|
+
id: "health",
|
|
87
|
+
key: "runtime.health",
|
|
88
|
+
label: "PicoClaw health",
|
|
89
|
+
path: "/health",
|
|
90
|
+
portFor: (instance) => instance.internal_port
|
|
91
|
+
}),
|
|
92
|
+
createRuntimeHttpProbe({
|
|
93
|
+
id: "ready",
|
|
94
|
+
key: "runtime.ready",
|
|
95
|
+
label: "PicoClaw readiness",
|
|
96
|
+
path: "/ready",
|
|
97
|
+
portFor: (instance) => instance.internal_port
|
|
98
|
+
}),
|
|
99
|
+
createPicoClawScheduleProbe()
|
|
100
|
+
];
|
package/dist/runtime/registry.js
CHANGED
|
@@ -3,12 +3,13 @@ import { parse as parseYaml } from "yaml";
|
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { SpawnfileError } from "../shared/index.js";
|
|
5
5
|
import { openClawAdapter } from "./openclaw/adapter.js";
|
|
6
|
+
import { daimonAdapter, piAdapter } from "./pi/adapter.js";
|
|
6
7
|
import { picoClawAdapter } from "./picoclaw/adapter.js";
|
|
7
|
-
import { tinyClawAdapter } from "./tinyclaw/adapter.js";
|
|
8
8
|
const runtimeAdapters = new Map([
|
|
9
|
+
[daimonAdapter.name, daimonAdapter],
|
|
9
10
|
[openClawAdapter.name, openClawAdapter],
|
|
10
|
-
[
|
|
11
|
-
[
|
|
11
|
+
[piAdapter.name, piAdapter],
|
|
12
|
+
[picoClawAdapter.name, picoClawAdapter]
|
|
12
13
|
]);
|
|
13
14
|
const runtimeInstallSchema = z.discriminatedUnion("kind", [
|
|
14
15
|
z
|
|
@@ -34,14 +35,6 @@ const runtimeInstallSchema = z.discriminatedUnion("kind", [
|
|
|
34
35
|
tag: z.string().min(1)
|
|
35
36
|
})
|
|
36
37
|
.strict(),
|
|
37
|
-
z
|
|
38
|
-
.object({
|
|
39
|
-
asset: z.string().min(1),
|
|
40
|
-
kind: z.literal("github_release_bundle"),
|
|
41
|
-
repository: z.string().min(1),
|
|
42
|
-
tag: z.string().min(1)
|
|
43
|
-
})
|
|
44
|
-
.strict(),
|
|
45
38
|
z
|
|
46
39
|
.object({
|
|
47
40
|
kind: z.literal("source_repo")
|
|
@@ -106,7 +99,7 @@ export const hasRuntimeAdapter = (runtimeName) => runtimeAdapters.has(runtimeNam
|
|
|
106
99
|
export const assertRuntimeCanCompile = async (runtimeName) => {
|
|
107
100
|
const registeredRuntime = await getRegisteredRuntime(runtimeName);
|
|
108
101
|
if (!registeredRuntime) {
|
|
109
|
-
throw new SpawnfileError("
|
|
102
|
+
throw new SpawnfileError("validation_error", `Unknown runtime binding: ${runtimeName}`);
|
|
110
103
|
}
|
|
111
104
|
if (registeredRuntime.status === "exploratory") {
|
|
112
105
|
throw new SpawnfileError("runtime_error", `Runtime ${runtimeName} is exploratory and cannot be compiled in v0.1`);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ContainerRuntimeInstanceReport } from "../report/index.js";
|
|
2
|
+
import type { RuntimeStatusProbe } from "./types.js";
|
|
3
|
+
export declare const createRuntimePathProbe: (input: {
|
|
4
|
+
id: string;
|
|
5
|
+
key: string;
|
|
6
|
+
label: string;
|
|
7
|
+
pathFor(instance: ContainerRuntimeInstanceReport): string | null | undefined;
|
|
8
|
+
testFlag: "-d" | "-e" | "-f";
|
|
9
|
+
}) => RuntimeStatusProbe;
|
|
10
|
+
export declare const createRuntimeHttpProbe: (input: {
|
|
11
|
+
id: string;
|
|
12
|
+
key: string;
|
|
13
|
+
label: string;
|
|
14
|
+
path: string;
|
|
15
|
+
portFor(instance: ContainerRuntimeInstanceReport): number | null | undefined;
|
|
16
|
+
}) => RuntimeStatusProbe;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const observation = (key, severity, message) => ({ key, message, severity });
|
|
2
|
+
const errorMessage = (error) => error instanceof Error ? error.message : String(error);
|
|
3
|
+
export const createRuntimePathProbe = (input) => ({
|
|
4
|
+
id: input.id,
|
|
5
|
+
label: input.label,
|
|
6
|
+
async run(context) {
|
|
7
|
+
const targetPath = input.pathFor(context.instance);
|
|
8
|
+
if (!targetPath) {
|
|
9
|
+
return [
|
|
10
|
+
observation(input.key, "unknown", `${input.label} path is not present in the compile report`)
|
|
11
|
+
];
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
await context.manager.exec(["test", input.testFlag, targetPath]);
|
|
15
|
+
return [observation(input.key, "ok", `${input.label} exists at ${targetPath}`)];
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
return [
|
|
19
|
+
observation(input.key, "error", `${input.label} missing at ${targetPath}: ${errorMessage(error)}`)
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
export const createRuntimeHttpProbe = (input) => ({
|
|
25
|
+
id: input.id,
|
|
26
|
+
label: input.label,
|
|
27
|
+
async run(context) {
|
|
28
|
+
const port = input.portFor(context.instance);
|
|
29
|
+
if (!port) {
|
|
30
|
+
return [
|
|
31
|
+
observation(input.key, "unknown", `${input.label} port is not present in the compile report`)
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
const response = await context.manager.httpGet(port, input.path);
|
|
35
|
+
return [
|
|
36
|
+
response.ok
|
|
37
|
+
? observation(input.key, "ok", `${input.label} responded on ${input.path}`)
|
|
38
|
+
: observation(input.key, "error", `${input.label} failed on ${input.path}: ${response.error ?? "request failed"}`)
|
|
39
|
+
];
|
|
40
|
+
}
|
|
41
|
+
});
|
package/dist/runtime/types.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ import type { ResolvedAuthProfile } from "../auth/index.js";
|
|
|
3
3
|
import type { AgentManifest } from "../manifest/index.js";
|
|
4
4
|
import type { CapabilityReport, DiagnosticReport } from "../report/index.js";
|
|
5
5
|
import type { ContainerRuntimeInstanceReport } from "../report/index.js";
|
|
6
|
+
import type { DeploymentRecord, DockerUnitInspection } from "../deployment/index.js";
|
|
7
|
+
import type { ModelAuthMethod } from "../shared/index.js";
|
|
6
8
|
export interface EmittedFile {
|
|
7
9
|
content: string;
|
|
8
10
|
mode?: number;
|
|
@@ -38,6 +40,7 @@ export interface RuntimeContainerInstancePaths {
|
|
|
38
40
|
}
|
|
39
41
|
export interface RuntimeContainerConfigEnvBinding {
|
|
40
42
|
envName: string;
|
|
43
|
+
generated?: boolean;
|
|
41
44
|
jsonPath: string;
|
|
42
45
|
}
|
|
43
46
|
export interface RuntimeContainerMeta {
|
|
@@ -46,6 +49,7 @@ export interface RuntimeContainerMeta {
|
|
|
46
49
|
configPathEnv?: string;
|
|
47
50
|
env?: Array<{
|
|
48
51
|
description: string;
|
|
52
|
+
generated?: boolean;
|
|
49
53
|
name: string;
|
|
50
54
|
required: boolean;
|
|
51
55
|
}>;
|
|
@@ -55,15 +59,30 @@ export interface RuntimeContainerMeta {
|
|
|
55
59
|
port?: number;
|
|
56
60
|
portStride?: number;
|
|
57
61
|
portEnv?: string;
|
|
62
|
+
postRootfsCommands?: string[];
|
|
58
63
|
standaloneBaseImage: string;
|
|
59
64
|
startCommand: string[];
|
|
60
65
|
staticEnv?: Record<string, string>;
|
|
61
66
|
systemDeps: string[];
|
|
62
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* The minimal runtime-instance shape an auth preparer needs. Both the compile
|
|
70
|
+
* report's `ContainerRuntimeInstanceReport` and the distribution report's
|
|
71
|
+
* runtime instances structurally satisfy this, so sourceless image consumption
|
|
72
|
+
* can reuse the same preparers without casting through compiler-only types.
|
|
73
|
+
*/
|
|
74
|
+
export interface RuntimeAuthInstance {
|
|
75
|
+
config_path: string;
|
|
76
|
+
home_path: string | null;
|
|
77
|
+
id: string;
|
|
78
|
+
model_auth_methods: Record<string, ModelAuthMethod>;
|
|
79
|
+
model_secrets_required: string[];
|
|
80
|
+
runtime: string;
|
|
81
|
+
}
|
|
63
82
|
export interface RuntimeAuthPreparationInput {
|
|
64
83
|
authProfile: ResolvedAuthProfile;
|
|
65
84
|
env: Record<string, string>;
|
|
66
|
-
instance:
|
|
85
|
+
instance: RuntimeAuthInstance;
|
|
67
86
|
outputDirectory: string;
|
|
68
87
|
tempRoot: string;
|
|
69
88
|
}
|
|
@@ -71,6 +90,38 @@ export interface RuntimeAuthPreparationResult {
|
|
|
71
90
|
coveredModelSecrets: string[];
|
|
72
91
|
mountArgs: string[];
|
|
73
92
|
}
|
|
93
|
+
export interface RuntimeProbeExecResult {
|
|
94
|
+
stderr: string;
|
|
95
|
+
stdout: string;
|
|
96
|
+
}
|
|
97
|
+
export interface RuntimeProbeHttpResult {
|
|
98
|
+
body: string;
|
|
99
|
+
error?: string;
|
|
100
|
+
ok: boolean;
|
|
101
|
+
}
|
|
102
|
+
export interface RuntimeProbeGateway {
|
|
103
|
+
exec(command: string[]): Promise<RuntimeProbeExecResult>;
|
|
104
|
+
httpGet(port: number, requestPath: string, headers?: Record<string, string>): Promise<RuntimeProbeHttpResult>;
|
|
105
|
+
inspectUnit(): Promise<DockerUnitInspection>;
|
|
106
|
+
}
|
|
107
|
+
export interface RuntimeProbeObservation {
|
|
108
|
+
details?: Record<string, unknown>;
|
|
109
|
+
key: string;
|
|
110
|
+
message: string;
|
|
111
|
+
severity: "error" | "ok" | "unknown" | "warn";
|
|
112
|
+
}
|
|
113
|
+
export interface RuntimeStatusProbeContext {
|
|
114
|
+
deployment: DeploymentRecord;
|
|
115
|
+
instance: ContainerRuntimeInstanceReport;
|
|
116
|
+
manager: RuntimeProbeGateway;
|
|
117
|
+
timeoutMs: number;
|
|
118
|
+
unit: DeploymentRecord["units"][number];
|
|
119
|
+
}
|
|
120
|
+
export interface RuntimeStatusProbe {
|
|
121
|
+
id: string;
|
|
122
|
+
label: string;
|
|
123
|
+
run(context: RuntimeStatusProbeContext): Promise<RuntimeProbeObservation[]>;
|
|
124
|
+
}
|
|
74
125
|
export interface RuntimeSystemInstructionSurfaceInput {
|
|
75
126
|
node: ResolvedAgentNode;
|
|
76
127
|
}
|
|
@@ -94,6 +145,7 @@ export interface RuntimeAdapter {
|
|
|
94
145
|
name: string;
|
|
95
146
|
prepareRuntimeAuth?(input: RuntimeAuthPreparationInput): Promise<RuntimeAuthPreparationResult>;
|
|
96
147
|
scaffoldAgentProject?(): RuntimeAgentScaffold;
|
|
148
|
+
statusProbes?: RuntimeStatusProbe[];
|
|
97
149
|
systemInstructionSurface?: RuntimeSystemInstructionSurface;
|
|
98
150
|
validateRuntimeOptions?(options: Record<string, unknown>): DiagnosticReport[];
|
|
99
151
|
}
|
package/dist/shared/errors.d.ts
CHANGED
|
@@ -4,3 +4,9 @@ export declare class SpawnfileError extends Error {
|
|
|
4
4
|
constructor(code: SpawnfileErrorCode, message: string);
|
|
5
5
|
}
|
|
6
6
|
export declare const isSpawnfileError: (value: unknown) => value is SpawnfileError;
|
|
7
|
+
/**
|
|
8
|
+
* Maps an error to the shared CLI exit-code convention: 2 for usage/input
|
|
9
|
+
* errors, 1 for runtime failures. Used wherever the CLI turns a caught error
|
|
10
|
+
* into a process exit code, so every path agrees (see specs/SPEC.md §9.1).
|
|
11
|
+
*/
|
|
12
|
+
export declare const errorExitCode: (error: unknown) => 1 | 2;
|
package/dist/shared/errors.js
CHANGED
|
@@ -7,3 +7,12 @@ export class SpawnfileError extends Error {
|
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
export const isSpawnfileError = (value) => value instanceof SpawnfileError;
|
|
10
|
+
// Codes that mean the input itself was bad (usage/input errors → exit 2).
|
|
11
|
+
// Everything else is a runtime failure that surfaced after validation (→ exit 1).
|
|
12
|
+
const USAGE_ERROR_CODES = new Set(["validation_error", "invalid_manifest"]);
|
|
13
|
+
/**
|
|
14
|
+
* Maps an error to the shared CLI exit-code convention: 2 for usage/input
|
|
15
|
+
* errors, 1 for runtime failures. Used wherever the CLI turns a caught error
|
|
16
|
+
* into a process exit code, so every path agrees (see specs/SPEC.md §9.1).
|
|
17
|
+
*/
|
|
18
|
+
export const errorExitCode = (error) => isSpawnfileError(error) && USAGE_ERROR_CODES.has(error.code) ? 2 : 1;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type LoadedCompileReport } from "./compileReport.js";
|
|
2
|
+
import type { StaticStatus, StatusDeploymentSummary, StatusExitCode, StatusLiveRequest, StatusObservation, StatusObservationCounts, StatusSelection } from "./types.js";
|
|
3
|
+
export declare const countObservations: (observations: StatusObservation[]) => StatusObservationCounts;
|
|
4
|
+
export declare const getVisibleObservations: (status: StaticStatus) => StatusObservation[];
|
|
5
|
+
export declare const exitCodeForStatus: (status: StaticStatus) => StatusExitCode;
|
|
6
|
+
export declare const createStaticStatus: (view: StaticStatus["view"], loadedReport: LoadedCompileReport, input: {
|
|
7
|
+
deployments?: StatusDeploymentSummary[];
|
|
8
|
+
inputPath: string;
|
|
9
|
+
liveObservations?: StatusObservation[];
|
|
10
|
+
live?: StatusLiveRequest;
|
|
11
|
+
outputDirectory: string;
|
|
12
|
+
selection: StatusSelection | null;
|
|
13
|
+
}) => StaticStatus;
|