spawnfile 0.1.1 → 0.1.3

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 (102) hide show
  1. package/README.md +80 -396
  2. package/dist/cli/index.js +0 -0
  3. package/dist/cli/modelCommands.d.ts +3 -0
  4. package/dist/cli/modelCommands.js +68 -0
  5. package/dist/cli/runCli.d.ts +23 -2
  6. package/dist/cli/runCli.js +78 -122
  7. package/dist/cli/runtimeCommands.d.ts +3 -0
  8. package/dist/cli/runtimeCommands.js +20 -0
  9. package/dist/cli/surfaceCommands.d.ts +3 -0
  10. package/dist/cli/surfaceCommands.js +98 -0
  11. package/dist/cli/viewCommand.d.ts +3 -0
  12. package/dist/cli/viewCommand.js +87 -0
  13. package/dist/compiler/agentSurfaces.js +51 -5
  14. package/dist/compiler/buildCompilePlan.js +38 -40
  15. package/dist/compiler/buildCompilePlanRuntime.d.ts +14 -0
  16. package/dist/compiler/buildCompilePlanRuntime.js +39 -0
  17. package/dist/compiler/buildCompilePlanTeams.d.ts +5 -0
  18. package/dist/compiler/buildCompilePlanTeams.js +38 -0
  19. package/dist/compiler/compilePlanHelpers.js +4 -1
  20. package/dist/compiler/compileProject.js +62 -13
  21. package/dist/compiler/compileProjectSupport.d.ts +17 -0
  22. package/dist/compiler/compileProjectSupport.js +136 -0
  23. package/dist/compiler/containerArtifacts.d.ts +6 -1
  24. package/dist/compiler/containerArtifacts.js +26 -4
  25. package/dist/compiler/containerArtifactsPlans.js +16 -1
  26. package/dist/compiler/containerArtifactsRender.d.ts +4 -2
  27. package/dist/compiler/containerArtifactsRender.js +21 -126
  28. package/dist/compiler/containerArtifactsTypes.d.ts +7 -0
  29. package/dist/compiler/containerEntrypointRender.d.ts +12 -0
  30. package/dist/compiler/containerEntrypointRender.js +186 -0
  31. package/dist/compiler/index.d.ts +4 -0
  32. package/dist/compiler/index.js +4 -0
  33. package/dist/compiler/interactiveSurfaceScopes.d.ts +2 -0
  34. package/dist/compiler/interactiveSurfaceScopes.js +21 -0
  35. package/dist/compiler/moltnetArtifacts.d.ts +27 -0
  36. package/dist/compiler/moltnetArtifacts.js +208 -0
  37. package/dist/compiler/moltnetBinaries.d.ts +4 -0
  38. package/dist/compiler/moltnetBinaries.js +103 -0
  39. package/dist/compiler/moltnetClientConfig.d.ts +11 -0
  40. package/dist/compiler/moltnetClientConfig.js +89 -0
  41. package/dist/compiler/moltnetRepresentativeResolution.d.ts +16 -0
  42. package/dist/compiler/moltnetRepresentativeResolution.js +86 -0
  43. package/dist/compiler/moltnetResolution.d.ts +3 -0
  44. package/dist/compiler/moltnetResolution.js +182 -0
  45. package/dist/compiler/moltnetRoomMemberships.d.ts +3 -0
  46. package/dist/compiler/moltnetRoomMemberships.js +140 -0
  47. package/dist/compiler/runProject.js +1 -1
  48. package/dist/compiler/surfaceDefinitions.d.ts +55 -0
  49. package/dist/compiler/surfaceDefinitions.js +204 -0
  50. package/dist/compiler/teamContextHelpers.d.ts +18 -0
  51. package/dist/compiler/teamContextHelpers.js +112 -0
  52. package/dist/compiler/teamContextSupport.d.ts +4 -0
  53. package/dist/compiler/teamContextSupport.js +264 -0
  54. package/dist/compiler/teamContextSupport.testHelpers.d.ts +16 -0
  55. package/dist/compiler/teamContextSupport.testHelpers.js +68 -0
  56. package/dist/compiler/teamContextTypes.d.ts +28 -0
  57. package/dist/compiler/teamContextTypes.js +1 -0
  58. package/dist/compiler/teamRoster.d.ts +12 -0
  59. package/dist/compiler/teamRoster.js +48 -0
  60. package/dist/compiler/teamRosterEntries.d.ts +13 -0
  61. package/dist/compiler/teamRosterEntries.js +230 -0
  62. package/dist/compiler/teamRosterTypes.d.ts +45 -0
  63. package/dist/compiler/teamRosterTypes.js +1 -0
  64. package/dist/compiler/types.d.ts +90 -6
  65. package/dist/compiler/updateProjectRuntime.d.ts +9 -0
  66. package/dist/compiler/updateProjectRuntime.js +67 -0
  67. package/dist/compiler/updateProjectSurfaces.d.ts +8 -0
  68. package/dist/compiler/updateProjectSurfaces.js +106 -0
  69. package/dist/compiler/view/buildOrganizationView.d.ts +2 -0
  70. package/dist/compiler/view/buildOrganizationView.js +180 -0
  71. package/dist/compiler/view/index.d.ts +4 -0
  72. package/dist/compiler/view/index.js +4 -0
  73. package/dist/compiler/view/renderNetworks.d.ts +2 -0
  74. package/dist/compiler/view/renderNetworks.js +93 -0
  75. package/dist/compiler/view/renderTree.d.ts +2 -0
  76. package/dist/compiler/view/renderTree.js +59 -0
  77. package/dist/compiler/view/sourcePaths.d.ts +2 -0
  78. package/dist/compiler/view/sourcePaths.js +19 -0
  79. package/dist/compiler/view/types.d.ts +80 -0
  80. package/dist/compiler/view/types.js +1 -0
  81. package/dist/manifest/loadManifest.js +4 -4
  82. package/dist/manifest/renderSpawnfile.js +74 -8
  83. package/dist/manifest/scaffold.js +1 -3
  84. package/dist/manifest/schemas.d.ts +227 -17
  85. package/dist/manifest/schemas.js +62 -20
  86. package/dist/manifest/surfaceSchemas.d.ts +154 -0
  87. package/dist/manifest/surfaceSchemas.js +77 -5
  88. package/dist/runtime/common.js +3 -0
  89. package/dist/runtime/openclaw/adapter.js +38 -5
  90. package/dist/runtime/openclaw/moltnet.d.ts +12 -0
  91. package/dist/runtime/openclaw/moltnet.js +124 -0
  92. package/dist/runtime/openclaw/surfaces.js +3 -0
  93. package/dist/runtime/picoclaw/adapter.js +27 -8
  94. package/dist/runtime/picoclaw/pico.d.ts +2 -0
  95. package/dist/runtime/picoclaw/pico.js +2 -0
  96. package/dist/runtime/picoclaw/surfaces.js +11 -0
  97. package/dist/runtime/tinyclaw/adapter.js +22 -8
  98. package/dist/runtime/tinyclaw/runAuth.js +28 -1
  99. package/dist/runtime/tinyclaw/surfaces.js +8 -0
  100. package/dist/runtime/types.d.ts +11 -0
  101. package/package.json +5 -3
  102. package/runtimes.yaml +4 -4
@@ -1,4 +1,5 @@
1
1
  import { SpawnfileError } from "../../shared/index.js";
2
+ import { PICOCLAW_INTERNAL_PICO_TOKEN } from "./pico.js";
2
3
  export const buildPicoClawChannelConfig = (surfaces) => {
3
4
  if (!surfaces) {
4
5
  return {};
@@ -41,6 +42,13 @@ export const buildPicoClawChannelConfig = (surfaces) => {
41
42
  }
42
43
  };
43
44
  }
45
+ if (surfaces.moltnet) {
46
+ channels.pico = {
47
+ allow_token_query: true,
48
+ enabled: true,
49
+ token: PICOCLAW_INTERNAL_PICO_TOKEN
50
+ };
51
+ }
44
52
  return channels;
45
53
  };
46
54
  export const buildPicoClawSurfaceEnvBindings = (surfaces) => {
@@ -72,6 +80,9 @@ export const buildPicoClawSurfaceEnvBindings = (surfaces) => {
72
80
  return bindings.length > 0 ? bindings : undefined;
73
81
  };
74
82
  export const assertSupportedPicoClawSurfaces = (surfaces) => {
83
+ if (surfaces?.http) {
84
+ throw new SpawnfileError("validation_error", "PicoClaw does not support portable HTTP surfaces in Spawnfile v0.1");
85
+ }
75
86
  const discordAccess = surfaces?.discord?.access;
76
87
  if (discordAccess) {
77
88
  if (discordAccess.mode === "pairing") {
@@ -5,6 +5,7 @@ import { prepareTinyClawRuntimeAuth } from "./runAuth.js";
5
5
  import { createTinyClawAgentScaffold } from "./scaffold.js";
6
6
  import { assertSupportedTinyClawSurfaces, buildTinyClawChannels, resolveTinyClawSurfaceTokenBindings } from "./surfaces.js";
7
7
  const WORKSPACE_PLACEHOLDER = "<workspace-path>";
8
+ const SUPPORTED_TINYCLAW_OPENAI_MODEL_PREFIXES = ["gpt-5"];
8
9
  const TINYCLAW_START_SCRIPT = `
9
10
  set -euo pipefail
10
11
  PIDS=()
@@ -55,6 +56,7 @@ for pid in "\${PIDS[@]}"; do
55
56
  done
56
57
  exit "$status"
57
58
  `.trim();
59
+ const isSupportedTinyClawOpenAiModel = (modelName) => SUPPORTED_TINYCLAW_OPENAI_MODEL_PREFIXES.some((prefix) => modelName.startsWith(prefix));
58
60
  const buildTinyClawSettings = (node) => {
59
61
  const [primary] = listEffectiveExecutionModelTargets(node.execution);
60
62
  const agentEntry = {
@@ -168,12 +170,15 @@ export const tinyClawAdapter = {
168
170
  throw new SpawnfileError("validation_error", "TinyClaw custom or local endpoints are not supported in Spawnfile v0.1");
169
171
  }
170
172
  if (target.provider === "anthropic") {
171
- if (target.auth.method === "claude-code") {
173
+ if (target.auth.method === "claude-code" || target.auth.method === "api_key") {
172
174
  return;
173
175
  }
174
176
  }
175
177
  else if (target.provider === "openai") {
176
- if (target.auth.method === "codex") {
178
+ if (!isSupportedTinyClawOpenAiModel(target.name)) {
179
+ throw new SpawnfileError("validation_error", `TinyClaw OpenAI models must use the runtime's Codex/GPT-5 path; received ${target.name}`);
180
+ }
181
+ if (target.auth.method === "codex" || target.auth.method === "api_key") {
177
182
  return;
178
183
  }
179
184
  }
@@ -190,11 +195,11 @@ export const tinyClawAdapter = {
190
195
  configEnvBindings: [
191
196
  {
192
197
  envName: "ANTHROPIC_API_KEY",
193
- jsonPath: "models.anthropic.auth_token"
198
+ jsonPath: "models.anthropic.api_key"
194
199
  },
195
200
  {
196
201
  envName: "OPENAI_API_KEY",
197
- jsonPath: "models.openai.auth_token"
202
+ jsonPath: "models.openai.api_key"
198
203
  }
199
204
  ],
200
205
  homeEnv: "TINYAGI_HOME",
@@ -210,6 +215,12 @@ export const tinyClawAdapter = {
210
215
  startCommand: ["bash", "-lc", TINYCLAW_START_SCRIPT],
211
216
  systemDeps: ["bash", "ca-certificates", "curl", "g++", "make", "python3", "tar"]
212
217
  },
218
+ systemInstructionSurface: {
219
+ placement: "append_pointer",
220
+ resolvePath({ node }) {
221
+ return `workspace/${node.name}/AGENTS.md`;
222
+ }
223
+ },
213
224
  async compileAgent(node) {
214
225
  return {
215
226
  capabilities: createAgentCapabilities(node, {
@@ -234,17 +245,20 @@ export const tinyClawAdapter = {
234
245
  const agentIds = node.members
235
246
  .filter((member) => member.kind === "agent")
236
247
  .map((member) => member.id);
248
+ const leadAgent = node.lead
249
+ ? node.members.find((member) => member.id === node.lead && member.kind === "agent")
250
+ : null;
237
251
  const teamConfig = {
238
252
  name: node.name,
239
253
  agents: agentIds,
240
- leader_agent: node.structure.leader ?? agentIds[0] ?? "leader"
254
+ ...(leadAgent ? { leader_agent: leadAgent.id } : {})
241
255
  };
242
256
  return {
243
257
  capabilities: [
244
258
  createCapability("team.members", "supported"),
245
- createCapability("team.structure.mode", node.structure.mode === "hierarchical" ? "supported" : "degraded", "TinyClaw only supports leader-led teams"),
246
- createCapability("team.structure.leader", node.structure.leader ? "supported" : "degraded", "TinyClaw requires a leader_agent"),
247
- createCapability("team.structure.external", "degraded", "TinyClaw does not enforce external boundary"),
259
+ createCapability("team.mode", node.mode === "hierarchical" ? "supported" : "degraded", "TinyClaw only supports leader-led teams"),
260
+ createCapability("team.lead", leadAgent ? "supported" : "degraded", leadAgent ? "" : "TinyClaw requires a concrete leader_agent"),
261
+ createCapability("team.external", "degraded", "TinyClaw does not enforce external boundary"),
248
262
  createCapability("team.shared", "supported"),
249
263
  createCapability("team.nested", "degraded", "TinyClaw nested teams flatten in v0.1")
250
264
  ],
@@ -1,4 +1,20 @@
1
+ import path from "node:path";
1
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("/"));
5
+ const createMountArgs = (hostPath, containerPath) => [
6
+ "-v",
7
+ `${hostPath}:${containerPath}`
8
+ ];
9
+ const writeRuntimeAuthFile = async (input, relativePath, content) => {
10
+ const hostPath = path.join(input.tempRoot, "runtime-auth", "tinyclaw", input.instance.id, ...relativePath.split("/"));
11
+ await ensureDirectory(path.dirname(hostPath));
12
+ await writeUtf8File(hostPath, content);
13
+ return hostPath;
14
+ };
15
+ const writePatchedSettings = async (input, config) => {
16
+ return writeRuntimeAuthFile(input, "settings.json", `${JSON.stringify(config, null, 2)}\n`);
17
+ };
2
18
  export const prepareTinyClawRuntimeAuth = async (input) => {
3
19
  const coveredModelSecrets = [];
4
20
  const claudeCode = input.authProfile.imports["claude-code"]
@@ -15,8 +31,19 @@ export const prepareTinyClawRuntimeAuth = async (input) => {
15
31
  codex) {
16
32
  coveredModelSecrets.push("OPENAI_API_KEY");
17
33
  }
34
+ const sourceConfig = JSON.parse(await readUtf8File(resolveRootfsSourcePath(input.outputDirectory, input.instance.config_path)));
35
+ const patchedConfigPath = await writePatchedSettings(input, sourceConfig);
36
+ const mountArgs = createMountArgs(patchedConfigPath, input.instance.config_path);
37
+ if (input.instance.home_path && input.instance.model_auth_methods.anthropic === "claude-code" && claudeCode) {
38
+ const mountedClaudePath = await writeRuntimeAuthFile(input, ".claude/.credentials.json", await readUtf8File(path.join(input.authProfile.imports["claude-code"].path, ".credentials.json")));
39
+ mountArgs.push(...createMountArgs(mountedClaudePath, path.posix.join(input.instance.home_path, ".claude", ".credentials.json")));
40
+ }
41
+ if (input.instance.home_path && input.instance.model_auth_methods.openai === "codex" && codex) {
42
+ const mountedAuthPath = await writeRuntimeAuthFile(input, ".codex/auth.json", await readUtf8File(path.join(input.authProfile.imports.codex.path, "auth.json")));
43
+ mountArgs.push(...createMountArgs(mountedAuthPath, path.posix.join(input.instance.home_path, ".codex", "auth.json")));
44
+ }
18
45
  return {
19
46
  coveredModelSecrets,
20
- mountArgs: []
47
+ mountArgs
21
48
  };
22
49
  };
@@ -1,3 +1,4 @@
1
+ import { listInteractiveSurfaceScopes } from "../../compiler/interactiveSurfaceScopes.js";
1
2
  import { SpawnfileError } from "../../shared/index.js";
2
3
  export const buildTinyClawChannels = (surfaces) => {
3
4
  const enabled = [];
@@ -51,6 +52,9 @@ export const resolveTinyClawSurfaceTokenBindings = (inputs) => {
51
52
  return bindings.length > 0 ? bindings : undefined;
52
53
  };
53
54
  export const assertSupportedTinyClawSurfaces = (surfaces) => {
55
+ if (surfaces?.http) {
56
+ throw new SpawnfileError("validation_error", "TinyClaw does not support portable HTTP surfaces in Spawnfile v0.1");
57
+ }
54
58
  const discordAccess = surfaces?.discord?.access;
55
59
  if (discordAccess) {
56
60
  if (discordAccess.mode !== "pairing") {
@@ -83,4 +87,8 @@ export const assertSupportedTinyClawSurfaces = (surfaces) => {
83
87
  if (surfaces?.slack) {
84
88
  throw new SpawnfileError("validation_error", "TinyClaw does not support Slack in Spawnfile v0.1");
85
89
  }
90
+ const interactiveScopes = listInteractiveSurfaceScopes(surfaces);
91
+ if (interactiveScopes.length > 1) {
92
+ throw new SpawnfileError("validation_error", `TinyClaw preserves only one interactive conversation scope in Spawnfile v0.1; declared ${interactiveScopes.join(", ")}`);
93
+ }
86
94
  };
@@ -5,6 +5,7 @@ import type { CapabilityReport, DiagnosticReport } from "../report/index.js";
5
5
  import type { ContainerRuntimeInstanceReport } from "../report/index.js";
6
6
  export interface EmittedFile {
7
7
  content: string;
8
+ mode?: number;
8
9
  path: string;
9
10
  }
10
11
  export interface RuntimeAgentScaffold {
@@ -51,6 +52,7 @@ export interface RuntimeContainerMeta {
51
52
  instancePaths: RuntimeContainerInstancePaths;
52
53
  globalNpmPackages?: string[];
53
54
  port?: number;
55
+ portStride?: number;
54
56
  portEnv?: string;
55
57
  standaloneBaseImage: string;
56
58
  startCommand: string[];
@@ -68,6 +70,14 @@ export interface RuntimeAuthPreparationResult {
68
70
  coveredModelSecrets: string[];
69
71
  mountArgs: string[];
70
72
  }
73
+ export interface RuntimeSystemInstructionSurfaceInput {
74
+ node: ResolvedAgentNode;
75
+ }
76
+ export type RuntimeSystemInstructionPlacement = "append_pointer" | "append_inline" | "replace_generated_block";
77
+ export interface RuntimeSystemInstructionSurface {
78
+ placement: RuntimeSystemInstructionPlacement;
79
+ resolvePath(input: RuntimeSystemInstructionSurfaceInput): string;
80
+ }
71
81
  export interface AdapterCompileResult {
72
82
  capabilities: CapabilityReport[];
73
83
  diagnostics: DiagnosticReport[];
@@ -83,5 +93,6 @@ export interface RuntimeAdapter {
83
93
  name: string;
84
94
  prepareRuntimeAuth?(input: RuntimeAuthPreparationInput): Promise<RuntimeAuthPreparationResult>;
85
95
  scaffoldAgentProject?(): RuntimeAgentScaffold;
96
+ systemInstructionSurface?: RuntimeSystemInstructionSurface;
86
97
  validateRuntimeOptions?(options: Record<string, unknown>): DiagnosticReport[];
87
98
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spawnfile",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Canonical source compiler for autonomous agents and teams.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "scripts": {
18
18
  "blueprints": "./scripts/blueprints.sh",
19
- "build": "rm -rf dist && tsc --project tsconfig.build.json && node ./scripts/copy-runtime-scaffold-assets.mjs",
19
+ "build": "rm -rf dist && tsc --project tsconfig.build.json && chmod +x dist/cli/index.js && node ./scripts/copy-runtime-scaffold-assets.mjs",
20
20
  "clean": "rm -rf coverage dist",
21
21
  "coverage": "vitest run --coverage",
22
22
  "dev": "tsx src/cli/index.ts",
@@ -28,6 +28,7 @@
28
28
  "runtimes": "./scripts/runtimes.sh",
29
29
  "runtimes:sync": "./scripts/runtimes.sh && ./scripts/blueprints.sh",
30
30
  "test:e2e:docker-auth": "tsx src/e2e/cli.ts",
31
+ "test:e2e:moltnet-team-chat": "tsx src/e2e/cli.ts moltnet-team-chat",
31
32
  "test": "vitest run",
32
33
  "typecheck": "tsc --project tsconfig.json --noEmit"
33
34
  },
@@ -42,5 +43,6 @@
42
43
  "tsx": "^4.20.6",
43
44
  "typescript": "^5.9.3",
44
45
  "vitest": "^3.2.4"
45
- }
46
+ },
47
+ "packageManager": "pnpm@10.32.1+sha512.a706938f0e89ac1456b6563eab4edf1d1faf3368d1191fc5c59790e96dc918e4456ab2e67d613de1043d2e8c81f87303e6b40d4ffeca9df15ef1ad567348f2be"
46
48
  }
package/runtimes.yaml CHANGED
@@ -26,12 +26,12 @@ runtimes:
26
26
 
27
27
  picoclaw:
28
28
  remote: git@github.com:sipeed/picoclaw.git
29
- ref: v0.2.3
29
+ ref: v0.2.5
30
30
  default_branch: main
31
31
  install:
32
32
  kind: github_release_archive
33
33
  repository: sipeed/picoclaw
34
- tag: v0.2.3
34
+ tag: v0.2.5
35
35
  binary: picoclaw
36
36
  assets:
37
37
  linux_amd64: picoclaw_Linux_x86_64.tar.gz
@@ -40,12 +40,12 @@ runtimes:
40
40
 
41
41
  tinyclaw:
42
42
  remote: git@github.com:TinyAGI/tinyclaw.git
43
- ref: v0.0.15
43
+ ref: v0.0.20
44
44
  default_branch: main
45
45
  install:
46
46
  kind: github_release_bundle
47
47
  repository: TinyAGI/tinyagi
48
- tag: v0.0.15
48
+ tag: v0.0.20
49
49
  asset: tinyagi-bundle.tar.gz
50
50
  status: active
51
51