spawnfile 0.1.10 → 0.1.12

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.
Files changed (198) hide show
  1. package/README.md +13 -2
  2. package/dist/cli/lifecycleCommands.js +101 -1
  3. package/dist/cli/modelCommands.js +3 -0
  4. package/dist/cli/resolveCommandInput.d.ts +19 -0
  5. package/dist/cli/resolveCommandInput.js +25 -0
  6. package/dist/cli/runCli.d.ts +4 -1
  7. package/dist/cli/runCli.js +37 -13
  8. package/dist/cli/runtimeCommands.js +1 -0
  9. package/dist/cli/statusCommand.d.ts +42 -0
  10. package/dist/cli/statusCommand.js +394 -0
  11. package/dist/cli/surfaceCommands.js +4 -0
  12. package/dist/compiler/agentSurfaces.js +2 -4
  13. package/dist/compiler/buildCompilePlanTeams.js +3 -1
  14. package/dist/compiler/compileProject.js +19 -10
  15. package/dist/compiler/compileProjectSupport.d.ts +1 -0
  16. package/dist/compiler/compileProjectSupport.js +1 -1
  17. package/dist/compiler/containerArtifacts.d.ts +1 -0
  18. package/dist/compiler/containerArtifacts.js +208 -32
  19. package/dist/compiler/containerArtifactsPlans.js +7 -4
  20. package/dist/compiler/containerArtifactsRender.d.ts +7 -1
  21. package/dist/compiler/containerArtifactsRender.js +6 -0
  22. package/dist/compiler/containerArtifactsTypes.d.ts +9 -0
  23. package/dist/compiler/containerEntrypointRender.js +18 -31
  24. package/dist/compiler/index.d.ts +1 -0
  25. package/dist/compiler/index.js +1 -0
  26. package/dist/compiler/moltnetArtifacts.d.ts +2 -0
  27. package/dist/compiler/moltnetArtifacts.js +58 -99
  28. package/dist/compiler/moltnetClientConfig.d.ts +2 -2
  29. package/dist/compiler/moltnetClientConfig.js +16 -23
  30. package/dist/compiler/moltnetConfigLowering.d.ts +3 -0
  31. package/dist/compiler/moltnetConfigLowering.js +13 -2
  32. package/dist/compiler/moltnetNodeConfig.d.ts +27 -0
  33. package/dist/compiler/moltnetNodeConfig.js +68 -0
  34. package/dist/compiler/moltnetResolution.js +1 -1
  35. package/dist/compiler/moltnetRoomMemberships.js +1 -2
  36. package/dist/compiler/moltnetRoomPolicyCompatibility.d.ts +4 -0
  37. package/dist/compiler/moltnetRoomPolicyCompatibility.js +28 -0
  38. package/dist/compiler/moltnetRuntimeConfig.d.ts +1 -1
  39. package/dist/compiler/moltnetRuntimeConfig.js +1 -13
  40. package/dist/compiler/networkBinding.d.ts +14 -0
  41. package/dist/compiler/networkBinding.js +34 -0
  42. package/dist/compiler/publishProject.d.ts +13 -0
  43. package/dist/compiler/publishProject.js +72 -0
  44. package/dist/compiler/runProject.d.ts +26 -12
  45. package/dist/compiler/runProject.js +102 -125
  46. package/dist/compiler/runProjectAuth.d.ts +5 -0
  47. package/dist/compiler/runProjectAuth.js +98 -0
  48. package/dist/compiler/runProjectDocker.d.ts +19 -0
  49. package/dist/compiler/runProjectDocker.js +57 -0
  50. package/dist/compiler/types.d.ts +3 -2
  51. package/dist/compiler/upProject.d.ts +6 -0
  52. package/dist/compiler/upProject.js +42 -8
  53. package/dist/compiler/view/buildOrganizationView.js +27 -3
  54. package/dist/compiler/view/declarations.d.ts +4 -0
  55. package/dist/compiler/view/declarations.js +104 -0
  56. package/dist/compiler/view/renderNetworks.js +12 -3
  57. package/dist/compiler/view/renderTree.js +16 -3
  58. package/dist/compiler/view/types.d.ts +77 -1
  59. package/dist/deployment/dockerInspect.d.ts +29 -0
  60. package/dist/deployment/dockerInspect.js +130 -0
  61. package/dist/deployment/dockerLabels.d.ts +16 -0
  62. package/dist/deployment/dockerLabels.js +32 -0
  63. package/dist/deployment/dockerLogs.d.ts +24 -0
  64. package/dist/deployment/dockerLogs.js +96 -0
  65. package/dist/deployment/dockerManager.d.ts +59 -0
  66. package/dist/deployment/dockerManager.js +76 -0
  67. package/dist/deployment/dockerProbeGateway.d.ts +16 -0
  68. package/dist/deployment/dockerProbeGateway.js +48 -0
  69. package/dist/deployment/homeStore.d.ts +19 -0
  70. package/dist/deployment/homeStore.js +130 -0
  71. package/dist/deployment/index.d.ts +9 -0
  72. package/dist/deployment/index.js +9 -0
  73. package/dist/deployment/names.d.ts +3 -0
  74. package/dist/deployment/names.js +12 -0
  75. package/dist/deployment/record.d.ts +76 -0
  76. package/dist/deployment/record.js +174 -0
  77. package/dist/deployment/target.d.ts +35 -0
  78. package/dist/deployment/target.js +96 -0
  79. package/dist/distribution/buildDistributionReport.d.ts +22 -0
  80. package/dist/distribution/buildDistributionReport.js +51 -0
  81. package/dist/distribution/consumeImage.d.ts +29 -0
  82. package/dist/distribution/consumeImage.js +254 -0
  83. package/dist/distribution/consumeImageSupport.d.ts +18 -0
  84. package/dist/distribution/consumeImageSupport.js +63 -0
  85. package/dist/distribution/distributionReportSchema.d.ts +84 -0
  86. package/dist/distribution/distributionReportSchema.js +107 -0
  87. package/dist/distribution/dockerRunner.d.ts +5 -0
  88. package/dist/distribution/dockerRunner.js +21 -0
  89. package/dist/distribution/extractImage.d.ts +25 -0
  90. package/dist/distribution/extractImage.js +96 -0
  91. package/dist/distribution/fingerprint.d.ts +2 -0
  92. package/dist/distribution/fingerprint.js +14 -0
  93. package/dist/distribution/imageRef.d.ts +9 -0
  94. package/dist/distribution/imageRef.js +65 -0
  95. package/dist/distribution/imageRuntimeAuth.d.ts +19 -0
  96. package/dist/distribution/imageRuntimeAuth.js +71 -0
  97. package/dist/distribution/index.d.ts +24 -0
  98. package/dist/distribution/index.js +16 -0
  99. package/dist/distribution/preflight.d.ts +11 -0
  100. package/dist/distribution/preflight.js +65 -0
  101. package/dist/distribution/projectImageView.d.ts +8 -0
  102. package/dist/distribution/projectImageView.js +83 -0
  103. package/dist/distribution/projectName.d.ts +1 -0
  104. package/dist/distribution/projectName.js +12 -0
  105. package/dist/distribution/renderImageInterface.d.ts +30 -0
  106. package/dist/distribution/renderImageInterface.js +86 -0
  107. package/dist/distribution/tarReader.d.ts +10 -0
  108. package/dist/distribution/tarReader.js +69 -0
  109. package/dist/distribution/types.d.ts +80 -0
  110. package/dist/distribution/types.js +4 -0
  111. package/dist/distribution/verifyDistributionReport.d.ts +12 -0
  112. package/dist/distribution/verifyDistributionReport.js +29 -0
  113. package/dist/filesystem/paths.d.ts +6 -0
  114. package/dist/filesystem/paths.js +11 -0
  115. package/dist/manifest/loadManifest.js +22 -2
  116. package/dist/manifest/renderSpawnfile.js +2 -4
  117. package/dist/manifest/renderSpawnfileNetworks.js +5 -0
  118. package/dist/manifest/schemas.d.ts +71 -41
  119. package/dist/manifest/surfaceSchemas.d.ts +19 -47
  120. package/dist/manifest/surfaceSchemas.js +3 -6
  121. package/dist/manifest/teamNetworkAccessSchemas.d.ts +15 -0
  122. package/dist/manifest/teamNetworkAccessSchemas.js +8 -0
  123. package/dist/manifest/teamNetworkConsoleSchemas.d.ts +7 -0
  124. package/dist/manifest/teamNetworkConsoleSchemas.js +19 -0
  125. package/dist/manifest/teamNetworkSchemas.d.ts +60 -0
  126. package/dist/manifest/teamNetworkSchemas.js +20 -7
  127. package/dist/report/createReport.d.ts +7 -1
  128. package/dist/report/createReport.js +28 -1
  129. package/dist/report/types.d.ts +43 -0
  130. package/dist/runtime/container.js +0 -16
  131. package/dist/runtime/index.d.ts +1 -0
  132. package/dist/runtime/index.js +1 -0
  133. package/dist/runtime/install.d.ts +0 -10
  134. package/dist/runtime/install.js +0 -45
  135. package/dist/runtime/openclaw/adapter.js +9 -1
  136. package/dist/runtime/openclaw/configAuth.d.ts +15 -0
  137. package/dist/runtime/openclaw/configAuth.js +46 -0
  138. package/dist/runtime/openclaw/runAuth.d.ts +6 -0
  139. package/dist/runtime/openclaw/runAuth.js +7 -55
  140. package/dist/runtime/openclaw/statusProbes.d.ts +2 -0
  141. package/dist/runtime/openclaw/statusProbes.js +31 -0
  142. package/dist/runtime/picoclaw/adapter.js +10 -0
  143. package/dist/runtime/picoclaw/runAuth.d.ts +7 -0
  144. package/dist/runtime/picoclaw/runAuth.js +8 -68
  145. package/dist/runtime/picoclaw/statusProbes.d.ts +2 -0
  146. package/dist/runtime/picoclaw/statusProbes.js +100 -0
  147. package/dist/runtime/registry.d.ts +0 -5
  148. package/dist/runtime/registry.js +2 -12
  149. package/dist/runtime/statusProbes.d.ts +16 -0
  150. package/dist/runtime/statusProbes.js +41 -0
  151. package/dist/runtime/types.d.ts +52 -1
  152. package/dist/shared/errors.d.ts +6 -0
  153. package/dist/shared/errors.js +9 -0
  154. package/dist/status/buildStatus.d.ts +13 -0
  155. package/dist/status/buildStatus.js +266 -0
  156. package/dist/status/compileReport.d.ts +96 -0
  157. package/dist/status/compileReport.js +230 -0
  158. package/dist/status/compiledContainerObservations.d.ts +5 -0
  159. package/dist/status/compiledContainerObservations.js +63 -0
  160. package/dist/status/deploymentLogs.d.ts +12 -0
  161. package/dist/status/deploymentLogs.js +45 -0
  162. package/dist/status/deployments.d.ts +14 -0
  163. package/dist/status/deployments.js +128 -0
  164. package/dist/status/imageStatusReport.d.ts +10 -0
  165. package/dist/status/imageStatusReport.js +73 -0
  166. package/dist/status/index.d.ts +14 -0
  167. package/dist/status/index.js +14 -0
  168. package/dist/status/moltnetProbes.d.ts +21 -0
  169. package/dist/status/moltnetProbes.js +240 -0
  170. package/dist/status/registryDrift.d.ts +28 -0
  171. package/dist/status/registryDrift.js +119 -0
  172. package/dist/status/renderStatus.d.ts +2 -0
  173. package/dist/status/renderStatus.js +230 -0
  174. package/dist/status/runtimeProbes.d.ts +13 -0
  175. package/dist/status/runtimeProbes.js +111 -0
  176. package/dist/status/selectionSubjects.d.ts +8 -0
  177. package/dist/status/selectionSubjects.js +77 -0
  178. package/dist/status/selectors.d.ts +14 -0
  179. package/dist/status/selectors.js +90 -0
  180. package/dist/status/traversal.d.ts +6 -0
  181. package/dist/status/traversal.js +15 -0
  182. package/dist/status/types.d.ts +113 -0
  183. package/dist/status/types.js +1 -0
  184. package/package.json +4 -2
  185. package/runtimes.yaml +22 -15
  186. package/dist/runtime/tinyclaw/adapter.d.ts +0 -2
  187. package/dist/runtime/tinyclaw/adapter.js +0 -284
  188. package/dist/runtime/tinyclaw/runAuth.d.ts +0 -2
  189. package/dist/runtime/tinyclaw/runAuth.js +0 -49
  190. package/dist/runtime/tinyclaw/scaffold-assets/AGENTS.md +0 -160
  191. package/dist/runtime/tinyclaw/scaffold-assets/CLAUDE.md +0 -5
  192. package/dist/runtime/tinyclaw/scaffold-assets/SOUL.md +0 -177
  193. package/dist/runtime/tinyclaw/scaffold.d.ts +0 -2
  194. package/dist/runtime/tinyclaw/scaffold.js +0 -24
  195. package/dist/runtime/tinyclaw/schedules.d.ts +0 -9
  196. package/dist/runtime/tinyclaw/schedules.js +0 -62
  197. package/dist/runtime/tinyclaw/surfaces.d.ts +0 -8
  198. package/dist/runtime/tinyclaw/surfaces.js +0 -94
@@ -20,10 +20,6 @@ const installHints = new Map([
20
20
  ecosystem: "node",
21
21
  installHint: "Download the pinned OpenClaw artifact archive from the release."
22
22
  },
23
- github_release_bundle: {
24
- ecosystem: "node",
25
- installHint: "Download the pinned OpenClaw bundle artifact from the release."
26
- },
27
23
  npm: {
28
24
  ecosystem: "node",
29
25
  installHint: "Install the pinned OpenClaw package version from npm."
@@ -45,10 +41,6 @@ const installHints = new Map([
45
41
  ecosystem: "go",
46
42
  installHint: "Download the pinned PicoClaw release archive for the target platform."
47
43
  },
48
- github_release_bundle: {
49
- ecosystem: "node",
50
- installHint: "Download the pinned PicoClaw bundle artifact from the release."
51
- },
52
44
  npm: {
53
45
  ecosystem: "node",
54
46
  installHint: "Install the pinned PicoClaw package version from npm."
@@ -58,31 +50,6 @@ const installHints = new Map([
58
50
  installHint: "Checkout the pinned repo ref and build/install from the repository root."
59
51
  }
60
52
  }
61
- ],
62
- [
63
- "tinyclaw",
64
- {
65
- container_image: {
66
- ecosystem: "node",
67
- installHint: "Copy the pinned TinyClaw runtime files from the official container image."
68
- },
69
- github_release_archive: {
70
- ecosystem: "go",
71
- installHint: "Download the pinned TinyClaw release archive for the target platform."
72
- },
73
- github_release_bundle: {
74
- ecosystem: "node",
75
- installHint: "Download the pinned TinyClaw bundle artifact from the release."
76
- },
77
- npm: {
78
- ecosystem: "node",
79
- installHint: "Install the pinned TinyClaw package version from npm."
80
- },
81
- source_repo: {
82
- ecosystem: "node",
83
- installHint: "Checkout the pinned repo ref and run the TinyAGI install flow from the repository root."
84
- }
85
- }
86
53
  ]
87
54
  ]);
88
55
  export const resolveRuntimeInstallSelection = async (runtimeName) => {
@@ -127,18 +94,6 @@ export const resolveRuntimeInstallSelection = async (runtimeName) => {
127
94
  tag: runtime.install.tag,
128
95
  versionedAssets: runtime.install.assets
129
96
  };
130
- case "github_release_bundle":
131
- return {
132
- ecosystem: "node",
133
- installHint: installProfile.github_release_bundle.installHint,
134
- asset: runtime.install.asset,
135
- kind: "github_release_bundle",
136
- repository: runtime.install.repository,
137
- runtimeName: runtime.name,
138
- runtimeRef: runtime.ref,
139
- selectionSource: "runtime_registry_install",
140
- tag: runtime.install.tag
141
- };
142
97
  case "source_repo":
143
98
  case undefined:
144
99
  return {
@@ -1,10 +1,12 @@
1
1
  import { listEffectiveExecutionModelTargets } from "../../compiler/modelEnv.js";
2
2
  import { createAgentCapabilities, createDiagnostic, createDocumentFiles, createSkillFiles } from "../common.js";
3
3
  import { SpawnfileError } from "../../shared/index.js";
4
+ import { applyOpenClawImportAuthConfig, resolveOpenClawImportAuthModes } from "./configAuth.js";
4
5
  import { prepareOpenClawRuntimeAuth } from "./runAuth.js";
5
6
  import { createOpenClawAgentScaffold } from "./scaffold.js";
6
7
  import { assertSupportedOpenClawSurfaces, buildOpenClawChannelConfig, buildOpenClawSurfaceEnvBindings } from "./surfaces.js";
7
8
  import { buildOpenClawMoltnetConfig, buildOpenClawMoltnetEnvBindings, validateOpenClawMoltnetRuntimeOptions } from "./moltnet.js";
9
+ import { openClawStatusProbes } from "./statusProbes.js";
8
10
  const buildEnvSecretRef = (envName) => ({
9
11
  id: envName,
10
12
  provider: "default",
@@ -86,7 +88,10 @@ const buildOpenClawConfig = (node) => {
86
88
  if (moltnet) {
87
89
  config.moltnet = moltnet;
88
90
  }
89
- return `${JSON.stringify(config, null, 2)}\n`;
91
+ // Bake the import-auth (claude-code/codex) OAuth structure at compile time so
92
+ // the image is self-sufficient; only the credential tokens are injected later.
93
+ const authBaked = applyOpenClawImportAuthConfig(config, resolveOpenClawImportAuthModes(node));
94
+ return `${JSON.stringify(authBaked, null, 2)}\n`;
90
95
  };
91
96
  const createOpenClawStateFiles = () => [
92
97
  {
@@ -107,6 +112,7 @@ const createContainerTargets = async (inputs) => inputs.map((input) => {
107
112
  ? [
108
113
  {
109
114
  envName: "OPENCLAW_HOOKS_TOKEN",
115
+ generated: true,
110
116
  jsonPath: "hooks.token"
111
117
  }
112
118
  ]
@@ -153,6 +159,7 @@ export const openClawAdapter = {
153
159
  env: [
154
160
  {
155
161
  description: "Gateway auth token required for non-loopback OpenClaw access",
162
+ generated: true,
156
163
  name: "OPENCLAW_GATEWAY_TOKEN",
157
164
  required: true
158
165
  }
@@ -217,6 +224,7 @@ export const openClawAdapter = {
217
224
  name: "openclaw",
218
225
  prepareRuntimeAuth: prepareOpenClawRuntimeAuth,
219
226
  scaffoldAgentProject: createOpenClawAgentScaffold,
227
+ statusProbes: openClawStatusProbes,
220
228
  validateRuntimeOptions(options) {
221
229
  const diagnostics = validateOpenClawMoltnetRuntimeOptions(options).map((message) => createDiagnostic("error", message));
222
230
  if ("profile" in options && typeof options.profile !== "string") {
@@ -0,0 +1,15 @@
1
+ import type { ResolvedAgentNode } from "../../compiler/types.js";
2
+ export interface OpenClawImportAuthModes {
3
+ useClaudeCode: boolean;
4
+ useCodex: boolean;
5
+ }
6
+ /** Determines which import-based auth modes an agent's models declare. */
7
+ export declare const resolveOpenClawImportAuthModes: (node: ResolvedAgentNode) => OpenClawImportAuthModes;
8
+ export declare const normalizeOpenClawCodexModel: (model: string) => string;
9
+ /**
10
+ * Applies the import-auth structure (OAuth profiles, provider order, and the
11
+ * Codex model rename) to an OpenClaw config. This is deterministic from the
12
+ * declared auth methods, so it is baked into the image at compile time. Only
13
+ * the OAuth credential tokens are injected at run time.
14
+ */
15
+ export declare const applyOpenClawImportAuthConfig: (config: Record<string, unknown>, modes: OpenClawImportAuthModes) => Record<string, unknown>;
@@ -0,0 +1,46 @@
1
+ import { listEffectiveExecutionModelTargets } from "../../compiler/modelEnv.js";
2
+ /** Determines which import-based auth modes an agent's models declare. */
3
+ export const resolveOpenClawImportAuthModes = (node) => {
4
+ const targets = listEffectiveExecutionModelTargets(node.execution);
5
+ return {
6
+ useClaudeCode: targets.some((target) => target.provider === "anthropic" && target.auth.method === "claude-code"),
7
+ useCodex: targets.some((target) => target.provider === "openai" && target.auth.method === "codex")
8
+ };
9
+ };
10
+ export const normalizeOpenClawCodexModel = (model) => {
11
+ const modelName = model.slice("openai/".length);
12
+ return modelName === "gpt-5" ? "gpt-5.4" : modelName;
13
+ };
14
+ /**
15
+ * Applies the import-auth structure (OAuth profiles, provider order, and the
16
+ * Codex model rename) to an OpenClaw config. This is deterministic from the
17
+ * declared auth methods, so it is baked into the image at compile time. Only
18
+ * the OAuth credential tokens are injected at run time.
19
+ */
20
+ export const applyOpenClawImportAuthConfig = (config, modes) => {
21
+ if (!modes.useClaudeCode && !modes.useCodex) {
22
+ return config;
23
+ }
24
+ const agents = config.agents ?? {};
25
+ const defaults = agents.defaults ?? {};
26
+ const model = defaults.model;
27
+ const auth = config.auth ?? {};
28
+ const profiles = auth.profiles ?? {};
29
+ const order = auth.order ?? {};
30
+ if (modes.useCodex && typeof model === "string" && model.startsWith("openai/")) {
31
+ defaults.model = `openai-codex/${normalizeOpenClawCodexModel(model)}`;
32
+ }
33
+ if (modes.useClaudeCode) {
34
+ profiles["anthropic:default"] = { mode: "oauth", provider: "anthropic" };
35
+ order.anthropic = ["anthropic:default"];
36
+ }
37
+ if (modes.useCodex) {
38
+ profiles["openai-codex:default"] = { mode: "oauth", provider: "openai-codex" };
39
+ order["openai-codex"] = ["openai-codex:default"];
40
+ }
41
+ return {
42
+ ...config,
43
+ agents: { ...agents, defaults },
44
+ auth: { ...auth, order, profiles }
45
+ };
46
+ };
@@ -1,2 +1,8 @@
1
1
  import type { RuntimeAuthPreparationInput, RuntimeAuthPreparationResult } from "../types.js";
2
+ /**
3
+ * Injects the consumer's imported OAuth credentials for an OpenClaw instance.
4
+ * The OAuth-mode config is already baked into the image at compile time, so this
5
+ * only materializes and mounts the credential tokens — no source rootfs needed,
6
+ * which is what lets it run for both project deployments and sourceless images.
7
+ */
2
8
  export declare const prepareOpenClawRuntimeAuth: (input: RuntimeAuthPreparationInput) => Promise<RuntimeAuthPreparationResult>;
@@ -1,7 +1,6 @@
1
1
  import path from "node:path";
2
2
  import { loadImportedClaudeCodeCredential, loadImportedCodexCredential } from "../../auth/index.js";
3
- import { ensureDirectory, readUtf8File, writeUtf8File } from "../../filesystem/index.js";
4
- const resolveRootfsSourcePath = (outputDirectory, containerPath) => path.join(outputDirectory, "container", "rootfs", ...path.posix.relative("/", containerPath).split("/"));
3
+ import { ensureDirectory, writeUtf8File } from "../../filesystem/index.js";
5
4
  const writeJsonFile = async (tempRoot, relativePath, value) => {
6
5
  const hostPath = path.join(tempRoot, relativePath);
7
6
  await ensureDirectory(path.dirname(hostPath));
@@ -35,47 +34,12 @@ const createOpenClawCredential = (provider, credential) => credential && "type"
35
34
  refresh: credential.refresh,
36
35
  type: "oauth"
37
36
  };
38
- const normalizeOpenClawCodexModel = (model) => {
39
- const modelName = model.slice("openai/".length);
40
- return modelName === "gpt-5" ? "gpt-5.4" : modelName;
41
- };
42
- const patchOpenClawConfig = (config, options) => {
43
- const agents = config.agents ?? {};
44
- const defaults = agents.defaults ?? {};
45
- const model = defaults.model;
46
- const auth = config.auth ?? {};
47
- const profiles = auth.profiles ?? {};
48
- const order = auth.order ?? {};
49
- if (options.useCodex && typeof model === "string" && model.startsWith("openai/")) {
50
- defaults.model = `openai-codex/${normalizeOpenClawCodexModel(model)}`;
51
- }
52
- if (options.useClaudeCode) {
53
- profiles["anthropic:default"] = {
54
- mode: "oauth",
55
- provider: "anthropic"
56
- };
57
- order.anthropic = ["anthropic:default"];
58
- }
59
- if (options.useCodex) {
60
- profiles["openai-codex:default"] = {
61
- mode: "oauth",
62
- provider: "openai-codex"
63
- };
64
- order["openai-codex"] = ["openai-codex:default"];
65
- }
66
- return {
67
- ...config,
68
- agents: {
69
- ...agents,
70
- defaults
71
- },
72
- auth: {
73
- ...auth,
74
- order,
75
- profiles
76
- }
77
- };
78
- };
37
+ /**
38
+ * Injects the consumer's imported OAuth credentials for an OpenClaw instance.
39
+ * The OAuth-mode config is already baked into the image at compile time, so this
40
+ * only materializes and mounts the credential tokens — no source rootfs needed,
41
+ * which is what lets it run for both project deployments and sourceless images.
42
+ */
79
43
  export const prepareOpenClawRuntimeAuth = async (input) => {
80
44
  if (!input.instance.home_path) {
81
45
  return { coveredModelSecrets: [], mountArgs: [] };
@@ -88,7 +52,6 @@ export const prepareOpenClawRuntimeAuth = async (input) => {
88
52
  : null;
89
53
  const coveredModelSecrets = [];
90
54
  const authProfiles = {};
91
- let patchedConfig = null;
92
55
  const useClaudeCode = input.instance.model_auth_methods.anthropic === "claude-code" && claudeCode;
93
56
  const useCodex = input.instance.model_auth_methods.openai === "codex" && codex;
94
57
  if (useClaudeCode) {
@@ -99,13 +62,6 @@ export const prepareOpenClawRuntimeAuth = async (input) => {
99
62
  authProfiles["openai-codex:default"] = createOpenClawCredential("openai-codex", codex);
100
63
  coveredModelSecrets.push("OPENAI_API_KEY");
101
64
  }
102
- if (useClaudeCode || useCodex) {
103
- const sourceConfig = JSON.parse(await readUtf8File(resolveRootfsSourcePath(input.outputDirectory, input.instance.config_path)));
104
- patchedConfig = patchOpenClawConfig(sourceConfig, {
105
- useClaudeCode: Boolean(useClaudeCode),
106
- useCodex: Boolean(useCodex)
107
- });
108
- }
109
65
  const mountArgs = [];
110
66
  if (Object.keys(authProfiles).length > 0) {
111
67
  const authStorePath = await writeJsonFile(input.tempRoot, path.join("runtime-auth", "openclaw", input.instance.id, "auth-profiles.json"), {
@@ -114,10 +70,6 @@ export const prepareOpenClawRuntimeAuth = async (input) => {
114
70
  });
115
71
  mountArgs.push(...createMountArgs(authStorePath, path.posix.join(input.instance.home_path, ".openclaw", "agents", "main", "agent", "auth-profiles.json")));
116
72
  }
117
- if (patchedConfig) {
118
- const patchedConfigPath = await writeJsonFile(input.tempRoot, path.join("runtime-auth", "openclaw", input.instance.id, "openclaw.json"), patchedConfig);
119
- mountArgs.push(...createMountArgs(patchedConfigPath, input.instance.config_path));
120
- }
121
73
  return {
122
74
  coveredModelSecrets,
123
75
  mountArgs
@@ -0,0 +1,2 @@
1
+ import type { RuntimeStatusProbe } from "../types.js";
2
+ export declare const openClawStatusProbes: RuntimeStatusProbe[];
@@ -0,0 +1,31 @@
1
+ import { createRuntimeHttpProbe, createRuntimePathProbe } from "../statusProbes.js";
2
+ export const openClawStatusProbes = [
3
+ createRuntimePathProbe({
4
+ id: "home",
5
+ key: "runtime.home",
6
+ label: "OpenClaw home",
7
+ pathFor: (instance) => instance.home_path,
8
+ testFlag: "-d"
9
+ }),
10
+ createRuntimePathProbe({
11
+ id: "workspace",
12
+ key: "runtime.workspace",
13
+ label: "OpenClaw workspace",
14
+ pathFor: (instance) => instance.workspace_path,
15
+ testFlag: "-d"
16
+ }),
17
+ createRuntimePathProbe({
18
+ id: "config",
19
+ key: "runtime.config",
20
+ label: "OpenClaw config",
21
+ pathFor: (instance) => instance.config_path,
22
+ testFlag: "-f"
23
+ }),
24
+ createRuntimeHttpProbe({
25
+ id: "healthz",
26
+ key: "runtime.health",
27
+ label: "OpenClaw gateway",
28
+ path: "/healthz",
29
+ portFor: (instance) => instance.internal_port
30
+ })
31
+ ];
@@ -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
- import { copyDirectory, ensureDirectory, readUtf8File, writeUtf8File } from "../../filesystem/index.js";
4
- const resolveRootfsSourcePath = (outputDirectory, containerPath) => path.join(outputDirectory, "container", "rootfs", ...path.posix.relative("/", containerPath).split("/"));
5
- const createMountArgs = (hostPath, containerPath) => [
6
- "-v",
7
- `${hostPath}:${containerPath}`
8
- ];
9
- const createMountedHomeDirectory = async (input, patchedConfig) => {
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
- const coveredModelSecrets = [];
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,2 @@
1
+ import type { RuntimeStatusProbe } from "../types.js";
2
+ export declare const picoClawStatusProbes: RuntimeStatusProbe[];
@@ -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
+ ];
@@ -11,11 +11,6 @@ export type RuntimeRegistryInstall = {
11
11
  binary: string;
12
12
  repository: string;
13
13
  tag: string;
14
- } | {
15
- kind: "github_release_bundle";
16
- asset: string;
17
- repository: string;
18
- tag: string;
19
14
  } | {
20
15
  kind: "npm";
21
16
  package: string;
@@ -4,11 +4,9 @@ import { z } from "zod";
4
4
  import { SpawnfileError } from "../shared/index.js";
5
5
  import { openClawAdapter } from "./openclaw/adapter.js";
6
6
  import { picoClawAdapter } from "./picoclaw/adapter.js";
7
- import { tinyClawAdapter } from "./tinyclaw/adapter.js";
8
7
  const runtimeAdapters = new Map([
9
8
  [openClawAdapter.name, openClawAdapter],
10
- [picoClawAdapter.name, picoClawAdapter],
11
- [tinyClawAdapter.name, tinyClawAdapter]
9
+ [picoClawAdapter.name, picoClawAdapter]
12
10
  ]);
13
11
  const runtimeInstallSchema = z.discriminatedUnion("kind", [
14
12
  z
@@ -34,14 +32,6 @@ const runtimeInstallSchema = z.discriminatedUnion("kind", [
34
32
  tag: z.string().min(1)
35
33
  })
36
34
  .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
35
  z
46
36
  .object({
47
37
  kind: z.literal("source_repo")
@@ -106,7 +96,7 @@ export const hasRuntimeAdapter = (runtimeName) => runtimeAdapters.has(runtimeNam
106
96
  export const assertRuntimeCanCompile = async (runtimeName) => {
107
97
  const registeredRuntime = await getRegisteredRuntime(runtimeName);
108
98
  if (!registeredRuntime) {
109
- throw new SpawnfileError("runtime_error", `Unknown runtime binding: ${runtimeName}`);
99
+ throw new SpawnfileError("validation_error", `Unknown runtime binding: ${runtimeName}`);
110
100
  }
111
101
  if (registeredRuntime.status === "exploratory") {
112
102
  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;