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.
Files changed (220) hide show
  1. package/README.md +21 -3
  2. package/dist/auth/runtimeCredentials.js +18 -2
  3. package/dist/cli/devCommands.d.ts +3 -0
  4. package/dist/cli/devCommands.js +115 -0
  5. package/dist/cli/lifecycleCommands.js +103 -1
  6. package/dist/cli/modelCommands.js +3 -0
  7. package/dist/cli/resolveCommandInput.d.ts +19 -0
  8. package/dist/cli/resolveCommandInput.js +25 -0
  9. package/dist/cli/runCli.d.ts +10 -1
  10. package/dist/cli/runCli.js +41 -13
  11. package/dist/cli/runtimeCommands.js +1 -0
  12. package/dist/cli/statusCommand.d.ts +43 -0
  13. package/dist/cli/statusCommand.js +428 -0
  14. package/dist/cli/surfaceCommands.js +4 -0
  15. package/dist/compiler/agentSurfaces.js +2 -4
  16. package/dist/compiler/buildProject.d.ts +9 -1
  17. package/dist/compiler/buildProject.js +44 -5
  18. package/dist/compiler/compileProject.d.ts +2 -0
  19. package/dist/compiler/compileProject.js +22 -11
  20. package/dist/compiler/containerArtifacts.d.ts +1 -0
  21. package/dist/compiler/containerArtifacts.js +208 -32
  22. package/dist/compiler/containerArtifactsPlans.js +7 -4
  23. package/dist/compiler/containerArtifactsRender.d.ts +7 -1
  24. package/dist/compiler/containerArtifactsRender.js +31 -69
  25. package/dist/compiler/containerArtifactsTypes.d.ts +9 -0
  26. package/dist/compiler/containerEntrypointRender.js +22 -32
  27. package/dist/compiler/containerPackageRender.d.ts +15 -0
  28. package/dist/compiler/containerPackageRender.js +63 -0
  29. package/dist/compiler/containerTargetResources.js +3 -1
  30. package/dist/compiler/index.d.ts +1 -0
  31. package/dist/compiler/index.js +1 -0
  32. package/dist/compiler/moltnetArtifacts.js +21 -1
  33. package/dist/compiler/moltnetBinaries.d.ts +4 -1
  34. package/dist/compiler/moltnetBinaries.js +24 -3
  35. package/dist/compiler/moltnetClientConfig.d.ts +1 -1
  36. package/dist/compiler/moltnetClientConfig.js +14 -16
  37. package/dist/compiler/moltnetNodeConfig.js +2 -4
  38. package/dist/compiler/moltnetResolution.js +1 -1
  39. package/dist/compiler/moltnetRoomMemberships.js +1 -2
  40. package/dist/compiler/moltnetRuntimeConfig.d.ts +1 -1
  41. package/dist/compiler/moltnetRuntimeConfig.js +9 -10
  42. package/dist/compiler/networkBinding.d.ts +14 -0
  43. package/dist/compiler/networkBinding.js +34 -0
  44. package/dist/compiler/publishProject.d.ts +13 -0
  45. package/dist/compiler/publishProject.js +72 -0
  46. package/dist/compiler/runProject.d.ts +26 -12
  47. package/dist/compiler/runProject.js +109 -126
  48. package/dist/compiler/runProjectAuth.d.ts +5 -0
  49. package/dist/compiler/runProjectAuth.js +98 -0
  50. package/dist/compiler/runProjectDocker.d.ts +19 -0
  51. package/dist/compiler/runProjectDocker.js +202 -0
  52. package/dist/compiler/types.d.ts +1 -2
  53. package/dist/compiler/upProject.d.ts +6 -0
  54. package/dist/compiler/upProject.js +43 -8
  55. package/dist/compiler/view/buildOrganizationView.js +4 -1
  56. package/dist/compiler/view/declarations.d.ts +4 -0
  57. package/dist/compiler/view/declarations.js +104 -0
  58. package/dist/compiler/view/renderNetworks.js +1 -2
  59. package/dist/compiler/view/renderTree.js +6 -2
  60. package/dist/compiler/view/types.d.ts +64 -1
  61. package/dist/deployment/dockerInspect.d.ts +29 -0
  62. package/dist/deployment/dockerInspect.js +130 -0
  63. package/dist/deployment/dockerLabels.d.ts +16 -0
  64. package/dist/deployment/dockerLabels.js +32 -0
  65. package/dist/deployment/dockerLogs.d.ts +24 -0
  66. package/dist/deployment/dockerLogs.js +96 -0
  67. package/dist/deployment/dockerManager.d.ts +59 -0
  68. package/dist/deployment/dockerManager.js +76 -0
  69. package/dist/deployment/dockerProbeGateway.d.ts +16 -0
  70. package/dist/deployment/dockerProbeGateway.js +48 -0
  71. package/dist/deployment/dockerRecover.d.ts +17 -0
  72. package/dist/deployment/dockerRecover.js +129 -0
  73. package/dist/deployment/homeStore.d.ts +19 -0
  74. package/dist/deployment/homeStore.js +130 -0
  75. package/dist/deployment/index.d.ts +10 -0
  76. package/dist/deployment/index.js +10 -0
  77. package/dist/deployment/names.d.ts +3 -0
  78. package/dist/deployment/names.js +12 -0
  79. package/dist/deployment/record.d.ts +76 -0
  80. package/dist/deployment/record.js +174 -0
  81. package/dist/deployment/target.d.ts +35 -0
  82. package/dist/deployment/target.js +96 -0
  83. package/dist/dev/activity.d.ts +14 -0
  84. package/dist/dev/activity.js +48 -0
  85. package/dist/dev/docker.d.ts +16 -0
  86. package/dist/dev/docker.js +71 -0
  87. package/dist/dev/index.d.ts +2 -0
  88. package/dist/dev/index.js +2 -0
  89. package/dist/dev/project.d.ts +35 -0
  90. package/dist/dev/project.js +164 -0
  91. package/dist/distribution/buildDistributionReport.d.ts +22 -0
  92. package/dist/distribution/buildDistributionReport.js +51 -0
  93. package/dist/distribution/consumeImage.d.ts +29 -0
  94. package/dist/distribution/consumeImage.js +254 -0
  95. package/dist/distribution/consumeImageSupport.d.ts +18 -0
  96. package/dist/distribution/consumeImageSupport.js +63 -0
  97. package/dist/distribution/distributionReportSchema.d.ts +84 -0
  98. package/dist/distribution/distributionReportSchema.js +107 -0
  99. package/dist/distribution/dockerRunner.d.ts +5 -0
  100. package/dist/distribution/dockerRunner.js +21 -0
  101. package/dist/distribution/extractImage.d.ts +25 -0
  102. package/dist/distribution/extractImage.js +96 -0
  103. package/dist/distribution/fingerprint.d.ts +2 -0
  104. package/dist/distribution/fingerprint.js +14 -0
  105. package/dist/distribution/imageRef.d.ts +9 -0
  106. package/dist/distribution/imageRef.js +65 -0
  107. package/dist/distribution/imageRuntimeAuth.d.ts +19 -0
  108. package/dist/distribution/imageRuntimeAuth.js +71 -0
  109. package/dist/distribution/index.d.ts +24 -0
  110. package/dist/distribution/index.js +16 -0
  111. package/dist/distribution/preflight.d.ts +11 -0
  112. package/dist/distribution/preflight.js +65 -0
  113. package/dist/distribution/projectImageView.d.ts +8 -0
  114. package/dist/distribution/projectImageView.js +83 -0
  115. package/dist/distribution/projectName.d.ts +1 -0
  116. package/dist/distribution/projectName.js +12 -0
  117. package/dist/distribution/renderImageInterface.d.ts +30 -0
  118. package/dist/distribution/renderImageInterface.js +86 -0
  119. package/dist/distribution/tarReader.d.ts +10 -0
  120. package/dist/distribution/tarReader.js +69 -0
  121. package/dist/distribution/types.d.ts +80 -0
  122. package/dist/distribution/types.js +4 -0
  123. package/dist/distribution/verifyDistributionReport.d.ts +12 -0
  124. package/dist/distribution/verifyDistributionReport.js +29 -0
  125. package/dist/filesystem/paths.d.ts +6 -0
  126. package/dist/filesystem/paths.js +11 -0
  127. package/dist/manifest/loadManifest.js +22 -2
  128. package/dist/manifest/renderSpawnfile.js +2 -4
  129. package/dist/manifest/schemas.d.ts +17 -41
  130. package/dist/manifest/surfaceSchemas.d.ts +19 -47
  131. package/dist/manifest/surfaceSchemas.js +3 -6
  132. package/dist/report/createReport.d.ts +7 -1
  133. package/dist/report/createReport.js +28 -1
  134. package/dist/report/types.d.ts +43 -0
  135. package/dist/runtime/common.d.ts +2 -0
  136. package/dist/runtime/common.js +1 -1
  137. package/dist/runtime/container.d.ts +1 -0
  138. package/dist/runtime/container.js +82 -15
  139. package/dist/runtime/index.d.ts +1 -0
  140. package/dist/runtime/index.js +1 -0
  141. package/dist/runtime/install.d.ts +1 -11
  142. package/dist/runtime/install.js +27 -30
  143. package/dist/runtime/openclaw/adapter.js +9 -1
  144. package/dist/runtime/openclaw/configAuth.d.ts +15 -0
  145. package/dist/runtime/openclaw/configAuth.js +46 -0
  146. package/dist/runtime/openclaw/runAuth.d.ts +6 -0
  147. package/dist/runtime/openclaw/runAuth.js +7 -55
  148. package/dist/runtime/openclaw/statusProbes.d.ts +2 -0
  149. package/dist/runtime/openclaw/statusProbes.js +31 -0
  150. package/dist/runtime/pi/adapter.d.ts +4 -0
  151. package/dist/runtime/pi/adapter.js +198 -0
  152. package/dist/runtime/pi/appActivitySource.d.ts +1 -0
  153. package/dist/runtime/pi/appActivitySource.js +87 -0
  154. package/dist/runtime/pi/appCoreSource.d.ts +1 -0
  155. package/dist/runtime/pi/appCoreSource.js +354 -0
  156. package/dist/runtime/pi/appPreludeSource.d.ts +1 -0
  157. package/dist/runtime/pi/appPreludeSource.js +103 -0
  158. package/dist/runtime/pi/appSource.d.ts +1 -0
  159. package/dist/runtime/pi/appSource.js +8 -0
  160. package/dist/runtime/pi/appTemplate.d.ts +28 -0
  161. package/dist/runtime/pi/appTemplate.js +144 -0
  162. package/dist/runtime/pi/runAuth.d.ts +2 -0
  163. package/dist/runtime/pi/runAuth.js +68 -0
  164. package/dist/runtime/picoclaw/adapter.js +10 -0
  165. package/dist/runtime/picoclaw/runAuth.d.ts +7 -0
  166. package/dist/runtime/picoclaw/runAuth.js +8 -68
  167. package/dist/runtime/picoclaw/statusProbes.d.ts +2 -0
  168. package/dist/runtime/picoclaw/statusProbes.js +100 -0
  169. package/dist/runtime/registry.d.ts +0 -5
  170. package/dist/runtime/registry.js +5 -12
  171. package/dist/runtime/statusProbes.d.ts +16 -0
  172. package/dist/runtime/statusProbes.js +41 -0
  173. package/dist/runtime/types.d.ts +53 -1
  174. package/dist/shared/errors.d.ts +6 -0
  175. package/dist/shared/errors.js +9 -0
  176. package/dist/status/buildStatus.d.ts +13 -0
  177. package/dist/status/buildStatus.js +266 -0
  178. package/dist/status/compileReport.d.ts +96 -0
  179. package/dist/status/compileReport.js +230 -0
  180. package/dist/status/compiledContainerObservations.d.ts +5 -0
  181. package/dist/status/compiledContainerObservations.js +63 -0
  182. package/dist/status/deploymentLogs.d.ts +12 -0
  183. package/dist/status/deploymentLogs.js +45 -0
  184. package/dist/status/deployments.d.ts +14 -0
  185. package/dist/status/deployments.js +121 -0
  186. package/dist/status/imageStatusReport.d.ts +10 -0
  187. package/dist/status/imageStatusReport.js +73 -0
  188. package/dist/status/index.d.ts +14 -0
  189. package/dist/status/index.js +14 -0
  190. package/dist/status/moltnetProbes.d.ts +21 -0
  191. package/dist/status/moltnetProbes.js +240 -0
  192. package/dist/status/registryDrift.d.ts +28 -0
  193. package/dist/status/registryDrift.js +119 -0
  194. package/dist/status/renderStatus.d.ts +2 -0
  195. package/dist/status/renderStatus.js +230 -0
  196. package/dist/status/runtimeProbes.d.ts +13 -0
  197. package/dist/status/runtimeProbes.js +111 -0
  198. package/dist/status/selectionSubjects.d.ts +8 -0
  199. package/dist/status/selectionSubjects.js +77 -0
  200. package/dist/status/selectors.d.ts +14 -0
  201. package/dist/status/selectors.js +90 -0
  202. package/dist/status/traversal.d.ts +6 -0
  203. package/dist/status/traversal.js +15 -0
  204. package/dist/status/types.d.ts +113 -0
  205. package/dist/status/types.js +1 -0
  206. package/package.json +9 -2
  207. package/runtimes.yaml +44 -21
  208. package/dist/runtime/tinyclaw/adapter.d.ts +0 -2
  209. package/dist/runtime/tinyclaw/adapter.js +0 -284
  210. package/dist/runtime/tinyclaw/runAuth.d.ts +0 -2
  211. package/dist/runtime/tinyclaw/runAuth.js +0 -49
  212. package/dist/runtime/tinyclaw/scaffold-assets/AGENTS.md +0 -160
  213. package/dist/runtime/tinyclaw/scaffold-assets/CLAUDE.md +0 -5
  214. package/dist/runtime/tinyclaw/scaffold-assets/SOUL.md +0 -177
  215. package/dist/runtime/tinyclaw/scaffold.d.ts +0 -2
  216. package/dist/runtime/tinyclaw/scaffold.js +0 -24
  217. package/dist/runtime/tinyclaw/schedules.d.ts +0 -9
  218. package/dist/runtime/tinyclaw/schedules.js +0 -62
  219. package/dist/runtime/tinyclaw/surfaces.d.ts +0 -8
  220. package/dist/runtime/tinyclaw/surfaces.js +0 -94
@@ -9,6 +9,27 @@ const convertRemoteToHttps = (remote) => {
9
9
  return remote.replace(/^git\+/, "");
10
10
  };
11
11
  const installHints = new Map([
12
+ [
13
+ "daimon",
14
+ {
15
+ container_image: {
16
+ ecosystem: "node",
17
+ installHint: "Copy a pinned Daimon runtime image."
18
+ },
19
+ github_release_archive: {
20
+ ecosystem: "node",
21
+ installHint: "Download a pinned Daimon runtime release archive."
22
+ },
23
+ npm: {
24
+ ecosystem: "node",
25
+ installHint: "Install the pinned Daimon package and Pi SDK dependencies inside the generated runtime app."
26
+ },
27
+ source_repo: {
28
+ ecosystem: "node",
29
+ installHint: "Checkout the pinned Daimon repo ref and install from the repository root."
30
+ }
31
+ }
32
+ ],
12
33
  [
13
34
  "openclaw",
14
35
  {
@@ -20,10 +41,6 @@ const installHints = new Map([
20
41
  ecosystem: "node",
21
42
  installHint: "Download the pinned OpenClaw artifact archive from the release."
22
43
  },
23
- github_release_bundle: {
24
- ecosystem: "node",
25
- installHint: "Download the pinned OpenClaw bundle artifact from the release."
26
- },
27
44
  npm: {
28
45
  ecosystem: "node",
29
46
  installHint: "Install the pinned OpenClaw package version from npm."
@@ -45,10 +62,6 @@ const installHints = new Map([
45
62
  ecosystem: "go",
46
63
  installHint: "Download the pinned PicoClaw release archive for the target platform."
47
64
  },
48
- github_release_bundle: {
49
- ecosystem: "node",
50
- installHint: "Download the pinned PicoClaw bundle artifact from the release."
51
- },
52
65
  npm: {
53
66
  ecosystem: "node",
54
67
  installHint: "Install the pinned PicoClaw package version from npm."
@@ -60,27 +73,23 @@ const installHints = new Map([
60
73
  }
61
74
  ],
62
75
  [
63
- "tinyclaw",
76
+ "pi",
64
77
  {
65
78
  container_image: {
66
79
  ecosystem: "node",
67
- installHint: "Copy the pinned TinyClaw runtime files from the official container image."
80
+ installHint: "Copy a pinned Pi harness runtime image."
68
81
  },
69
82
  github_release_archive: {
70
- ecosystem: "go",
71
- installHint: "Download the pinned TinyClaw release archive for the target platform."
72
- },
73
- github_release_bundle: {
74
83
  ecosystem: "node",
75
- installHint: "Download the pinned TinyClaw bundle artifact from the release."
84
+ installHint: "Download a pinned Pi harness release archive."
76
85
  },
77
86
  npm: {
78
87
  ecosystem: "node",
79
- installHint: "Install the pinned TinyClaw package version from npm."
88
+ installHint: "Install pinned Pi SDK dependencies inside the generated runtime app."
80
89
  },
81
90
  source_repo: {
82
91
  ecosystem: "node",
83
- installHint: "Checkout the pinned repo ref and run the TinyAGI install flow from the repository root."
92
+ installHint: "Checkout the pinned Pi repo ref and install from the repository root."
84
93
  }
85
94
  }
86
95
  ]
@@ -94,7 +103,7 @@ export const resolveRuntimeInstallSelection = async (runtimeName) => {
94
103
  switch (runtime.install?.kind) {
95
104
  case "container_image":
96
105
  return {
97
- ecosystem: "node",
106
+ ecosystem: installProfile.container_image.ecosystem,
98
107
  image: runtime.install.image,
99
108
  installHint: installProfile.container_image.installHint,
100
109
  kind: "container_image",
@@ -127,18 +136,6 @@ export const resolveRuntimeInstallSelection = async (runtimeName) => {
127
136
  tag: runtime.install.tag,
128
137
  versionedAssets: runtime.install.assets
129
138
  };
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
139
  case "source_repo":
143
140
  case undefined:
144
141
  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
+ ];
@@ -0,0 +1,4 @@
1
+ import type { RuntimeAdapter } from "../types.js";
2
+ export declare const piAdapter: RuntimeAdapter;
3
+ export declare const daimonAdapter: RuntimeAdapter;
4
+ export declare const PI_RUNTIME_PACKAGE = "@earendil-works/pi-coding-agent@0.79.9";
@@ -0,0 +1,198 @@
1
+ import path from "node:path";
2
+ import { listExecutionModelSecretNames } from "../../compiler/modelEnv.js";
3
+ import { SpawnfileError } from "../../shared/index.js";
4
+ import { createAgentCapabilities, createDiagnostic, createDocumentFiles, createSkillFiles } from "../common.js";
5
+ import { createPiAgentConfig, PI_PACKAGE_NAME, PI_PACKAGE_VERSION, renderPiApp, renderPiAppConfig, renderPiModelsConfig, renderPiPackageJson } from "./appTemplate.js";
6
+ import { preparePiRuntimeAuth } from "./runAuth.js";
7
+ const PI_CONFIG_FILE = "pi-app.json";
8
+ const PI_CONTROL_PORT = 19690;
9
+ const PI_MODELS_FILE = "home/.pi/agent/models.json";
10
+ const moveWorkspaceFileToAgentWorkspace = (file, agentSlug) => {
11
+ if (!file.path.startsWith("workspace/")) {
12
+ return file;
13
+ }
14
+ const relativePath = file.path.slice("workspace/".length);
15
+ return {
16
+ ...file,
17
+ path: path.posix.join("workspace", "agents", agentSlug, relativePath)
18
+ };
19
+ };
20
+ const createContainerTargets = async (inputs) => {
21
+ const agentInputs = inputs.filter((input) => input.kind === "agent" && input.value.kind === "agent");
22
+ if (agentInputs.length === 0) {
23
+ return [];
24
+ }
25
+ const agents = agentInputs.map((input) => createPiAgentConfig(input.value, input.slug, input.id));
26
+ const envFiles = [
27
+ ...new Set(agentInputs.flatMap((input) => listExecutionModelSecretNames(input.value.execution)))
28
+ ].map((secretName) => ({
29
+ envName: secretName,
30
+ relativePath: `secrets/${secretName}`
31
+ }));
32
+ return [
33
+ {
34
+ envFiles,
35
+ files: [
36
+ ...agentInputs.flatMap((input) => input.emittedFiles.map((file) => moveWorkspaceFileToAgentWorkspace(file, input.slug))),
37
+ {
38
+ content: renderPiAppConfig(agents),
39
+ path: PI_CONFIG_FILE
40
+ },
41
+ {
42
+ content: renderPiModelsConfig(agentInputs.map((input) => input.value)),
43
+ path: PI_MODELS_FILE
44
+ },
45
+ {
46
+ content: renderPiPackageJson(),
47
+ path: "runtime/package.json"
48
+ },
49
+ {
50
+ content: renderPiApp(),
51
+ mode: 0o755,
52
+ path: "runtime/app.mjs"
53
+ }
54
+ ],
55
+ id: "pi-app",
56
+ sourceIds: agentInputs.map((input) => input.id).sort()
57
+ }
58
+ ];
59
+ };
60
+ const scheduleOutcomeFor = (node) => {
61
+ if (!node.schedule) {
62
+ return {};
63
+ }
64
+ if (node.schedule.kind === "every" || node.schedule.kind === "disabled") {
65
+ return {
66
+ message: "Pi generated runtime app owns this schedule",
67
+ outcome: "supported"
68
+ };
69
+ }
70
+ return {
71
+ message: "Pi generated runtime app supports every schedules in Spawnfile v0.1",
72
+ outcome: "degraded"
73
+ };
74
+ };
75
+ const createScheduleDiagnostics = (node) => node.schedule?.kind === "cron"
76
+ ? [
77
+ createDiagnostic("warn", "Pi generated runtime app supports every schedules in Spawnfile v0.1; cron schedules are degraded")
78
+ ]
79
+ : [];
80
+ const moltnetCapabilityOptions = (node) => node.surfaces?.moltnet
81
+ ? {
82
+ moltnetMessage: "Pi generated runtime app exposes a control endpoint for Moltnet bridge wake delivery",
83
+ moltnetOutcome: "supported"
84
+ }
85
+ : {};
86
+ const assertSupportedPiSurfaces = (surfaces) => {
87
+ if (!surfaces) {
88
+ return;
89
+ }
90
+ const unsupported = [
91
+ surfaces.discord ? "discord" : null,
92
+ surfaces.http ? "http" : null,
93
+ surfaces.slack ? "slack" : null,
94
+ surfaces.telegram ? "telegram" : null,
95
+ surfaces.webhook ? "webhook" : null,
96
+ surfaces.whatsapp ? "whatsapp" : null
97
+ ].filter((surface) => surface !== null);
98
+ if (unsupported.length > 0) {
99
+ throw new SpawnfileError("validation_error", `Pi runtime only supports Moltnet surfaces in Spawnfile v0.1; unsupported surfaces: ${unsupported.join(", ")}`);
100
+ }
101
+ };
102
+ export const piAdapter = {
103
+ assertSupportedModelTarget(target) {
104
+ if (target.endpoint) {
105
+ if (target.provider !== "custom" && target.provider !== "local") {
106
+ throw new SpawnfileError("validation_error", "Pi runtime only supports endpoints on custom or local model providers");
107
+ }
108
+ if (target.auth.method === "none" || target.auth.method === "api_key") {
109
+ return;
110
+ }
111
+ throw new SpawnfileError("validation_error", `Pi runtime endpoint models only support none or api_key auth, got ${target.auth.method}`);
112
+ }
113
+ if (target.provider === "openai") {
114
+ if (target.auth.method === "api_key" || target.auth.method === "codex") {
115
+ return;
116
+ }
117
+ }
118
+ if (target.provider === "anthropic" && target.auth.method === "api_key") {
119
+ return;
120
+ }
121
+ if (target.provider === "anthropic" && target.auth.method === "claude-code") {
122
+ return;
123
+ }
124
+ throw new SpawnfileError("validation_error", `Pi runtime does not support model auth method ${target.auth.method} for provider ${target.provider}`);
125
+ },
126
+ assertSupportedSurfaces(surfaces) {
127
+ assertSupportedPiSurfaces(surfaces);
128
+ },
129
+ container: {
130
+ configFileName: PI_CONFIG_FILE,
131
+ configPathEnv: "SPAWNFILE_PI_CONFIG",
132
+ homeEnv: "SPAWNFILE_PI_HOME",
133
+ instancePaths: {
134
+ configPathTemplate: "<instance-root>/pi/<config-file>",
135
+ homePathTemplate: "<instance-root>/home",
136
+ sourceWorkspacePathTemplate: "<instance-root>/workspace/agents/<source-slug>",
137
+ workspacePathTemplate: "<instance-root>/workspace"
138
+ },
139
+ port: PI_CONTROL_PORT,
140
+ portEnv: "SPAWNFILE_PI_CONTROL_PORT",
141
+ standaloneBaseImage: "node:24-bookworm-slim",
142
+ startCommand: ["node", "<runtime-root>/app.mjs", "<config-path>"],
143
+ systemDeps: ["bash", "ca-certificates", "curl", "git", "procps"]
144
+ },
145
+ systemInstructionSurface: {
146
+ placement: "append_pointer",
147
+ resolvePath() {
148
+ return "workspace/AGENTS.md";
149
+ }
150
+ },
151
+ async compileAgent(node) {
152
+ const scheduleOutcome = scheduleOutcomeFor(node);
153
+ return {
154
+ capabilities: createAgentCapabilities(node, {
155
+ ...moltnetCapabilityOptions(node),
156
+ mcpOutcome: node.mcpServers.length > 0 ? "degraded" : "supported",
157
+ sandboxOutcome: node.execution?.sandbox ? "degraded" : "supported",
158
+ scheduleMessage: scheduleOutcome.message,
159
+ scheduleOutcome: scheduleOutcome.outcome,
160
+ subagentOutcome: node.subagents.length > 0 ? "degraded" : "supported"
161
+ }),
162
+ diagnostics: [
163
+ ...createScheduleDiagnostics(node),
164
+ ...(node.execution?.sandbox
165
+ ? [createDiagnostic("warn", "Pi runtime relies on container and workspace isolation; Pi itself is not a sandbox engine")]
166
+ : []),
167
+ ...(node.mcpServers.length > 0
168
+ ? [createDiagnostic("warn", "Pi runtime does not lower MCP server declarations in Spawnfile v0.1")]
169
+ : []),
170
+ ...(node.subagents.length > 0
171
+ ? [createDiagnostic("warn", "Pi runtime groups compiled agents but does not preserve native parent-owned subagent semantics in v0.1")]
172
+ : [])
173
+ ],
174
+ files: [
175
+ ...createDocumentFiles("workspace", node.docs),
176
+ ...createSkillFiles("workspace/skills", node.skills)
177
+ ]
178
+ };
179
+ },
180
+ async createContainerTargets(inputs) {
181
+ return createContainerTargets(inputs);
182
+ },
183
+ name: "pi",
184
+ prepareRuntimeAuth: preparePiRuntimeAuth,
185
+ validateRuntimeOptions(options) {
186
+ const diagnostics = [];
187
+ const unsupported = Object.keys(options).filter((key) => key !== "restrict_to_workspace");
188
+ for (const key of unsupported) {
189
+ diagnostics.push(createDiagnostic("warn", `Pi runtime option ${key} is not used yet`));
190
+ }
191
+ return diagnostics;
192
+ }
193
+ };
194
+ export const daimonAdapter = {
195
+ ...piAdapter,
196
+ name: "daimon"
197
+ };
198
+ export const PI_RUNTIME_PACKAGE = `${PI_PACKAGE_NAME}@${PI_PACKAGE_VERSION}`;
@@ -0,0 +1 @@
1
+ export declare const renderPiActivitySource: () => string;
@@ -0,0 +1,87 @@
1
+ export const renderPiActivitySource = () => String.raw `
2
+ const maxActivityEvents = 500;
3
+
4
+ const createActivityBroker = () => {
5
+ let sequence = 0;
6
+ const events = [];
7
+ const clients = new Set();
8
+
9
+ const normalizeFilter = (value) => typeof value === "string" && value.trim().length > 0
10
+ ? value.trim()
11
+ : "";
12
+ const matchesFilter = (event, filter) => {
13
+ const normalized = normalizeFilter(filter);
14
+ return normalized === "" ||
15
+ event.agent_id === normalized ||
16
+ event.agent_slug === normalized ||
17
+ event.agent_name === normalized ||
18
+ event.agent_id === "agent:" + normalized;
19
+ };
20
+ const parseTail = (value) => {
21
+ const parsed = Number(value);
22
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : maxActivityEvents;
23
+ };
24
+
25
+ const publish = (event) => {
26
+ const full = {
27
+ version: "spawnfile.activity.v1",
28
+ sequence: ++sequence,
29
+ created_at: new Date().toISOString(),
30
+ ...event
31
+ };
32
+ events.push(full);
33
+ if (events.length > maxActivityEvents) {
34
+ events.splice(0, events.length - maxActivityEvents);
35
+ }
36
+ const frame = "data: " + JSON.stringify(full) + "\n\n";
37
+ for (const client of [...clients]) {
38
+ if (!matchesFilter(full, client.filter)) {
39
+ continue;
40
+ }
41
+ try {
42
+ client.response.write(frame);
43
+ } catch {
44
+ clients.delete(client);
45
+ }
46
+ }
47
+ return full;
48
+ };
49
+
50
+ const list = (filter, tail) => {
51
+ const selected = events.filter((event) => matchesFilter(event, filter));
52
+ return selected.slice(Math.max(0, selected.length - parseTail(tail)));
53
+ };
54
+
55
+ const stream = (request, response, filter, tail) => {
56
+ response.writeHead(200, {
57
+ "cache-control": "no-cache",
58
+ "connection": "keep-alive",
59
+ "content-type": "text/event-stream"
60
+ });
61
+ response.write("event: ready\ndata: {\"status\":\"ok\"}\n\n");
62
+ for (const event of list(filter, tail)) {
63
+ response.write("data: " + JSON.stringify(event) + "\n\n");
64
+ }
65
+ const client = { filter: normalizeFilter(filter), response };
66
+ clients.add(client);
67
+ request.on("close", () => clients.delete(client));
68
+ };
69
+
70
+ return { list, publish, stream };
71
+ };
72
+
73
+ const redactActivityText = (value) => {
74
+ let redacted = String(value);
75
+ redacted = redacted.replace(/\bBearer\s+[A-Za-z0-9._~+/=-]{12,}/gi, "Bearer [REDACTED]");
76
+ redacted = redacted.replace(/\bmagt_v1_[A-Za-z0-9_-]{16,}\b/g, "[REDACTED]");
77
+ redacted = redacted.replace(/\b(?:sk|sk-proj)-[A-Za-z0-9_-]{20,}\b/g, "[REDACTED]");
78
+ redacted = redacted.replace(
79
+ /("([^"]*(?:api[_-]?key|token|secret|password)[^"]*)"\s*:\s*")([^"]+)(")/gi,
80
+ "$1[REDACTED]$4"
81
+ );
82
+ redacted = redacted.replace(/\/(?:Users|home|private|tmp|var|opt|run)\/[^\s"']+/g, "[path]");
83
+ return redacted.length > 1000 ? redacted.slice(0, 1000) + "..." : redacted;
84
+ };
85
+
86
+ const formatActivityError = (error) => redactActivityText(error instanceof Error ? error.message : String(error));
87
+ `;
@@ -0,0 +1 @@
1
+ export declare const renderPiCoreSource: () => string;