spawnfile 0.1.4 → 0.1.6

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 (74) hide show
  1. package/dist/cli/lifecycleCommands.d.ts +3 -0
  2. package/dist/cli/lifecycleCommands.js +80 -0
  3. package/dist/cli/runCli.d.ts +2 -1
  4. package/dist/cli/runCli.js +4 -48
  5. package/dist/compiler/buildCompilePlan.js +12 -202
  6. package/dist/compiler/buildCompilePlanRuntime.d.ts +6 -1
  7. package/dist/compiler/buildCompilePlanRuntime.js +9 -0
  8. package/dist/compiler/buildCompilePlanTeams.js +16 -10
  9. package/dist/compiler/buildCompilePlanTraversal.d.ts +16 -0
  10. package/dist/compiler/buildCompilePlanTraversal.js +214 -0
  11. package/dist/compiler/buildCompilePlanTraversalHelpers.d.ts +18 -0
  12. package/dist/compiler/buildCompilePlanTraversalHelpers.js +22 -0
  13. package/dist/compiler/compilePlanHelpers.d.ts +3 -1
  14. package/dist/compiler/compilePlanHelpers.js +37 -1
  15. package/dist/compiler/compileProject.js +14 -0
  16. package/dist/compiler/containerArtifacts.js +18 -3
  17. package/dist/compiler/containerArtifactsPlans.js +32 -0
  18. package/dist/compiler/containerArtifactsRender.js +86 -3
  19. package/dist/compiler/containerArtifactsTypes.d.ts +7 -3
  20. package/dist/compiler/containerEntrypointRender.d.ts +1 -1
  21. package/dist/compiler/containerEntrypointRender.js +34 -24
  22. package/dist/compiler/containerTargetResources.d.ts +4 -0
  23. package/dist/compiler/containerTargetResources.js +54 -0
  24. package/dist/compiler/containerWorkspaceResourceRender.d.ts +3 -0
  25. package/dist/compiler/containerWorkspaceResourceRender.js +128 -0
  26. package/dist/compiler/executionDefaults.js +0 -3
  27. package/dist/compiler/helpers.d.ts +1 -1
  28. package/dist/compiler/index.d.ts +1 -0
  29. package/dist/compiler/index.js +1 -0
  30. package/dist/compiler/moltnetArtifacts.d.ts +11 -5
  31. package/dist/compiler/moltnetArtifacts.js +133 -117
  32. package/dist/compiler/moltnetClientConfig.js +8 -2
  33. package/dist/compiler/moltnetConfigLowering.d.ts +36 -0
  34. package/dist/compiler/moltnetConfigLowering.js +125 -0
  35. package/dist/compiler/moltnetRuntimeConfig.d.ts +2 -0
  36. package/dist/compiler/moltnetRuntimeConfig.js +69 -0
  37. package/dist/compiler/surfaces.d.ts +3 -13
  38. package/dist/compiler/surfaces.js +1 -6
  39. package/dist/compiler/syncProjectAuth.js +14 -0
  40. package/dist/compiler/types.d.ts +16 -1
  41. package/dist/compiler/upProject.d.ts +19 -0
  42. package/dist/compiler/upProject.js +37 -0
  43. package/dist/compiler/view/buildOrganizationView.js +22 -2
  44. package/dist/compiler/view/renderNetworks.js +14 -3
  45. package/dist/compiler/view/renderTree.js +8 -2
  46. package/dist/compiler/view/types.d.ts +18 -3
  47. package/dist/compiler/workspaceResources.d.ts +34 -0
  48. package/dist/compiler/workspaceResources.js +120 -0
  49. package/dist/filesystem/paths.js +1 -10
  50. package/dist/manifest/executionSchemas.d.ts +106 -0
  51. package/dist/manifest/executionSchemas.js +140 -0
  52. package/dist/manifest/loadManifest.js +15 -27
  53. package/dist/manifest/renderSpawnfile.js +44 -52
  54. package/dist/manifest/renderSpawnfileNetworks.d.ts +2 -0
  55. package/dist/manifest/renderSpawnfileNetworks.js +63 -0
  56. package/dist/manifest/renderSpawnfileWorkspace.d.ts +2 -0
  57. package/dist/manifest/renderSpawnfileWorkspace.js +47 -0
  58. package/dist/manifest/scaffold.js +12 -6
  59. package/dist/manifest/scheduleSchemas.d.ts +15 -0
  60. package/dist/manifest/scheduleSchemas.js +26 -0
  61. package/dist/manifest/schemas.d.ts +626 -368
  62. package/dist/manifest/schemas.js +51 -191
  63. package/dist/manifest/teamNetworkSchemas.d.ts +228 -0
  64. package/dist/manifest/teamNetworkSchemas.js +295 -0
  65. package/dist/manifest/workspaceSchemas.d.ts +96 -0
  66. package/dist/manifest/workspaceSchemas.js +166 -0
  67. package/dist/report/types.d.ts +10 -0
  68. package/dist/runtime/common.d.ts +2 -1
  69. package/dist/runtime/common.js +3 -3
  70. package/dist/runtime/tinyclaw/adapter.js +9 -2
  71. package/dist/runtime/tinyclaw/schedules.d.ts +9 -0
  72. package/dist/runtime/tinyclaw/schedules.js +62 -0
  73. package/dist/runtime/types.d.ts +1 -0
  74. package/package.json +2 -1
@@ -0,0 +1,3 @@
1
+ import type { Command } from "commander";
2
+ import type { CliHandlers, CliStreams } from "./runCli.js";
3
+ export declare const registerLifecycleCommands: (program: Command, handlers: CliHandlers, streams: CliStreams) => void;
@@ -0,0 +1,80 @@
1
+ export const registerLifecycleCommands = (program, handlers, streams) => {
2
+ program
3
+ .command("compile")
4
+ .argument("[path]", "Project directory or Spawnfile path", process.cwd())
5
+ .option("-o, --out <directory>", "Output directory")
6
+ .action(async (inputPath, options) => {
7
+ const result = await handlers.compileProject(inputPath, { outputDirectory: options.out });
8
+ streams.stdout(`compiled to ${result.outputDirectory}`);
9
+ streams.stdout(`report: ${result.reportPath}`);
10
+ });
11
+ program
12
+ .command("build")
13
+ .argument("[path]", "Project directory or Spawnfile path", process.cwd())
14
+ .option("--docker-command <command>", "Docker command")
15
+ .option("-o, --out <directory>", "Output directory")
16
+ .option("-t, --tag <image>", "Docker image tag")
17
+ .action(async (inputPath, options) => {
18
+ const result = await handlers.buildProject(inputPath, {
19
+ dockerCommand: options.dockerCommand,
20
+ imageTag: options.tag,
21
+ outputDirectory: options.out
22
+ });
23
+ streams.stdout(`built image ${result.imageTag}`);
24
+ streams.stdout(`compiled to ${result.outputDirectory}`);
25
+ streams.stdout(`report: ${result.reportPath}`);
26
+ });
27
+ program
28
+ .command("run")
29
+ .argument("[path]", "Project directory or Spawnfile path", process.cwd())
30
+ .option("-o, --out <directory>", "Output directory")
31
+ .option("-t, --tag <image>", "Docker image tag")
32
+ .option("--auth-profile <name>", "Local Spawnfile auth profile")
33
+ .option("--docker-command <command>", "Docker command")
34
+ .option("--name <container>", "Docker container name")
35
+ .option("--env-file <file>", "Path to an env file for runtime secrets")
36
+ .option("-d, --detach", "Run the container in detached mode")
37
+ .action(async (inputPath, options) => {
38
+ const result = await handlers.runProject(inputPath, {
39
+ authProfile: options.authProfile,
40
+ containerName: options.name,
41
+ detach: options.detach,
42
+ dockerCommand: options.dockerCommand,
43
+ envFilePath: options.envFile,
44
+ imageTag: options.tag,
45
+ outputDirectory: options.out
46
+ });
47
+ if (options.detach) {
48
+ streams.stdout(`running container ${result.containerName ?? "unknown"}`);
49
+ streams.stdout(`image: ${result.imageTag}`);
50
+ }
51
+ });
52
+ program
53
+ .command("up")
54
+ .argument("[path]", "Project directory or Spawnfile path", process.cwd())
55
+ .option("-o, --out <directory>", "Output directory")
56
+ .option("-t, --tag <image>", "Docker image tag")
57
+ .option("--auth-profile <name>", "Local Spawnfile auth profile")
58
+ .option("--docker-command <command>", "Docker command")
59
+ .option("--name <container>", "Docker container name")
60
+ .option("--env-file <file>", "Path to an env file for runtime secrets")
61
+ .option("-d, --detach", "Run the container in detached mode")
62
+ .action(async (inputPath, options) => {
63
+ const result = await handlers.upProject(inputPath, {
64
+ authProfile: options.authProfile,
65
+ containerName: options.name,
66
+ detach: options.detach,
67
+ dockerCommand: options.dockerCommand,
68
+ envFilePath: options.envFile,
69
+ imageTag: options.tag,
70
+ outputDirectory: options.out
71
+ });
72
+ streams.stdout(`built image ${result.imageTag}`);
73
+ streams.stdout(`compiled to ${result.outputDirectory}`);
74
+ streams.stdout(`report: ${result.reportPath}`);
75
+ if (options.detach) {
76
+ streams.stdout(`running container ${result.containerName ?? "unknown"}`);
77
+ streams.stdout(`image: ${result.imageTag}`);
78
+ }
79
+ });
80
+ };
@@ -1,5 +1,5 @@
1
1
  import { importClaudeCodeAuth, importCodexAuth, importEnvFile, requireAuthProfile } from "../auth/index.js";
2
- import { addAgentProject, addProjectSurface, addProjectModelFallback, addSubagentProject, addTeamProject, buildOrganizationView, buildCompilePlan, buildProject, clearProjectModelFallbacks, compileProject, initProject, removeProjectSurface, runProject, setProjectPrimaryModel, setProjectRuntime, setProjectSurfaceAccess, showProjectSurfaces, syncProjectAuth } from "../compiler/index.js";
2
+ import { addAgentProject, addProjectSurface, addProjectModelFallback, addSubagentProject, addTeamProject, buildOrganizationView, buildCompilePlan, buildProject, clearProjectModelFallbacks, compileProject, initProject, upProject, removeProjectSurface, runProject, setProjectPrimaryModel, setProjectRuntime, setProjectSurfaceAccess, showProjectSurfaces, syncProjectAuth } from "../compiler/index.js";
3
3
  import { listRuntimeAdapters } from "../runtime/index.js";
4
4
  export interface CliStreams {
5
5
  stderr: (message: string) => void;
@@ -29,6 +29,7 @@ export interface CliHandlers {
29
29
  removeProjectSurface: typeof removeProjectSurface;
30
30
  requireAuthProfile: typeof requireAuthProfile;
31
31
  runProject: typeof runProject;
32
+ upProject: typeof upProject;
32
33
  setProjectPrimaryModel: typeof setProjectPrimaryModel;
33
34
  setProjectRuntime: typeof setProjectRuntime;
34
35
  setProjectSurfaceAccess: typeof setProjectSurfaceAccess;
@@ -1,8 +1,9 @@
1
1
  import { Command } from "commander";
2
2
  import { importClaudeCodeAuth, importCodexAuth, importEnvFile, requireAuthProfile } from "../auth/index.js";
3
- import { addAgentProject, addProjectSurface, addProjectModelFallback, addSubagentProject, addTeamProject, buildOrganizationView, buildCompilePlan, buildProject, clearProjectModelFallbacks, compileProject, initProject, removeProjectSurface, runProject, setProjectPrimaryModel, setProjectRuntime, setProjectSurfaceAccess, showProjectSurfaces, syncProjectAuth } from "../compiler/index.js";
3
+ import { addAgentProject, addProjectSurface, addProjectModelFallback, addSubagentProject, addTeamProject, buildOrganizationView, buildCompilePlan, buildProject, clearProjectModelFallbacks, compileProject, initProject, upProject, removeProjectSurface, runProject, setProjectPrimaryModel, setProjectRuntime, setProjectSurfaceAccess, showProjectSurfaces, syncProjectAuth } from "../compiler/index.js";
4
4
  import { isSpawnfileError } from "../shared/index.js";
5
5
  import { listRuntimeAdapters } from "../runtime/index.js";
6
+ import { registerLifecycleCommands } from "./lifecycleCommands.js";
6
7
  import { registerModelCommands } from "./modelCommands.js";
7
8
  import { registerRuntimeCommands } from "./runtimeCommands.js";
8
9
  import { registerSurfaceCommands } from "./surfaceCommands.js";
@@ -22,7 +23,7 @@ const createDefaultHandlers = () => ({
22
23
  addSubagentProject, addTeamProject, clearProjectModelFallbacks,
23
24
  importClaudeCodeAuth, importCodexAuth, importEnvFile,
24
25
  initProject, listRuntimeAdapters, removeProjectSurface, requireAuthProfile,
25
- runProject, setProjectPrimaryModel, setProjectRuntime,
26
+ runProject, setProjectPrimaryModel, setProjectRuntime, upProject,
26
27
  setProjectSurfaceAccess, showProjectSurfaces, syncProjectAuth
27
28
  });
28
29
  const isCliStreams = (value) => {
@@ -83,52 +84,7 @@ export const runCli = async (argv, optionsOrStreams, handlerOverrides = {}) => {
83
84
  writeErr: (message) => writeCommanderOutput(streams.stderr, message),
84
85
  writeOut: (message) => writeCommanderOutput(streams.stdout, message)
85
86
  });
86
- program
87
- .command("compile")
88
- .argument("[path]", "Project directory or Spawnfile path", process.cwd())
89
- .option("-o, --out <directory>", "Output directory")
90
- .action(async (inputPath, options) => {
91
- const result = await handlers.compileProject(inputPath, { outputDirectory: options.out });
92
- streams.stdout(`compiled to ${result.outputDirectory}`);
93
- streams.stdout(`report: ${result.reportPath}`);
94
- });
95
- program
96
- .command("build")
97
- .argument("[path]", "Project directory or Spawnfile path", process.cwd())
98
- .option("-o, --out <directory>", "Output directory")
99
- .option("-t, --tag <image>", "Docker image tag")
100
- .action(async (inputPath, options) => {
101
- const result = await handlers.buildProject(inputPath, {
102
- imageTag: options.tag,
103
- outputDirectory: options.out
104
- });
105
- streams.stdout(`built image ${result.imageTag}`);
106
- streams.stdout(`compiled to ${result.outputDirectory}`);
107
- streams.stdout(`report: ${result.reportPath}`);
108
- });
109
- program
110
- .command("run")
111
- .argument("[path]", "Project directory or Spawnfile path", process.cwd())
112
- .option("-o, --out <directory>", "Output directory")
113
- .option("-t, --tag <image>", "Docker image tag")
114
- .option("--auth-profile <name>", "Local Spawnfile auth profile")
115
- .option("--name <container>", "Docker container name")
116
- .option("--env-file <file>", "Path to an env file for runtime secrets")
117
- .option("-d, --detach", "Run the container in detached mode")
118
- .action(async (inputPath, options) => {
119
- const result = await handlers.runProject(inputPath, {
120
- authProfile: options.authProfile,
121
- containerName: options.name,
122
- detach: options.detach,
123
- envFilePath: options.envFile,
124
- imageTag: options.tag,
125
- outputDirectory: options.out
126
- });
127
- if (options.detach) {
128
- streams.stdout(`running container ${result.containerName ?? "unknown"}`);
129
- streams.stdout(`image: ${result.imageTag}`);
130
- }
131
- });
87
+ registerLifecycleCommands(program, handlers, streams);
132
88
  program
133
89
  .command("init")
134
90
  .argument("[path]", "Directory to initialize", process.cwd())
@@ -1,17 +1,10 @@
1
- import { getCanonicalManifestPath, getManifestPath, resolveProjectPath } from "../filesystem/index.js";
2
- import { isAgentManifest, isTeamManifest, loadManifest, mergeExecution } from "../manifest/index.js";
3
- import { SpawnfileError } from "../shared/index.js";
4
- import { getAgentFingerprint, getMcpNames, getTeamFingerprint, validateEffectiveSkillRequirements } from "./compilePlanHelpers.js";
5
- import { resolveAgentSurfaces } from "./agentSurfaces.js";
1
+ import { getCanonicalManifestPath, getManifestPath } from "../filesystem/index.js";
2
+ import { loadManifest, isAgentManifest } from "../manifest/index.js";
6
3
  import { assignStableNodeIds } from "./helpers.js";
7
- import { loadResolvedDocuments, mergeResolvedSkills, loadResolvedSkills, mergeSharedSurface } from "./surfaces.js";
8
- import { assertRuntimeSupportsExecutionModelAuth } from "./modelAuth.js";
9
- import { assertRuntimeSupportsAgentSurfaces } from "./surfaceSupport.js";
10
- import { applyExecutionDefaults } from "./executionDefaults.js";
11
4
  import { resolvePlanMoltnetAttachments } from "./moltnetResolution.js";
12
5
  import { resolveMoltnetRoomMemberships } from "./moltnetRoomMemberships.js";
13
- import { normalizeDescription, resolveDescription, resolveRuntime } from "./buildCompilePlanRuntime.js";
14
- import { resolveTeamExternalIds, resolveTeamNetworks, validateTeamNetworkRooms } from "./buildCompilePlanTeams.js";
6
+ import { createRuntimeGroups } from "./buildCompilePlanRuntime.js";
7
+ import { createCompilePlanTraversal } from "./buildCompilePlanTraversal.js";
15
8
  export const buildCompilePlan = async (inputPath) => {
16
9
  const rootManifestPath = getCanonicalManifestPath(getManifestPath(inputPath));
17
10
  const loadCache = new Map();
@@ -19,7 +12,6 @@ export const buildCompilePlan = async (inputPath) => {
19
12
  const fingerprintCache = new Map();
20
13
  const edges = [];
21
14
  const memberships = new Map();
22
- const visitStack = [];
23
15
  const getLoadedManifest = (manifestPath) => {
24
16
  const canonicalPath = getCanonicalManifestPath(manifestPath);
25
17
  const cached = loadCache.get(canonicalPath);
@@ -30,186 +22,13 @@ export const buildCompilePlan = async (inputPath) => {
30
22
  loadCache.set(canonicalPath, promise);
31
23
  return promise;
32
24
  };
33
- const visitAgent = async (manifestPath, context) => {
34
- const canonicalPath = getCanonicalManifestPath(manifestPath);
35
- if (visitStack.includes(canonicalPath)) {
36
- throw new SpawnfileError("compile_error", `Cycle detected while visiting ${canonicalPath}`);
37
- }
38
- const loadedManifest = await getLoadedManifest(canonicalPath);
39
- if (!isAgentManifest(loadedManifest.manifest)) {
40
- throw new SpawnfileError("compile_error", `Expected agent manifest, got ${loadedManifest.manifest.kind} at ${canonicalPath}`);
41
- }
42
- const runtime = await resolveRuntime(loadedManifest.manifest, context);
43
- const execution = applyExecutionDefaults(context.isSubagent
44
- ? mergeExecution(context.inheritedExecution, loadedManifest.manifest.execution)
45
- : loadedManifest.manifest.execution);
46
- assertRuntimeSupportsExecutionModelAuth(runtime.name, execution, loadedManifest.manifest.name);
47
- const sharedSurface = mergeSharedSurface(context.inheritedShared?.surface, {
48
- env: loadedManifest.manifest.env,
49
- mcpServers: loadedManifest.manifest.mcp_servers,
50
- secrets: loadedManifest.manifest.secrets,
51
- skills: loadedManifest.manifest.skills
52
- });
53
- const inheritedSkills = context.inheritedShared
54
- ? await loadResolvedSkills(context.inheritedShared.manifestPath, context.inheritedShared.surface?.skills)
55
- : [];
56
- const localSkills = await loadResolvedSkills(canonicalPath, loadedManifest.manifest.skills);
57
- const skills = mergeResolvedSkills(inheritedSkills, localSkills);
58
- validateEffectiveSkillRequirements(loadedManifest.manifest.name, getMcpNames(sharedSurface.mcpServers), skills);
59
- const docs = await loadResolvedDocuments(canonicalPath, loadedManifest.manifest.docs);
60
- const candidate = {
61
- description: resolveDescription(loadedManifest.manifest.description, docs),
62
- docs,
63
- env: sharedSurface.env,
64
- execution,
65
- expose: loadedManifest.manifest.expose ?? false,
66
- kind: "agent",
67
- mcpServers: sharedSurface.mcpServers,
68
- name: loadedManifest.manifest.name,
69
- policyMode: loadedManifest.manifest.policy?.mode ?? null,
70
- policyOnDegrade: loadedManifest.manifest.policy?.on_degrade ?? null,
71
- runtime,
72
- secrets: sharedSurface.secrets,
73
- skills,
74
- source: canonicalPath,
75
- surfaces: resolveAgentSurfaces(loadedManifest.manifest.surfaces),
76
- subagents: []
77
- };
78
- assertRuntimeSupportsAgentSurfaces(runtime.name, candidate.surfaces, loadedManifest.manifest.name);
79
- const fingerprint = getAgentFingerprint(candidate);
80
- const existingFingerprint = fingerprintCache.get(canonicalPath);
81
- if (existingFingerprint && existingFingerprint !== fingerprint) {
82
- throw new SpawnfileError("compile_error", `Manifest ${canonicalPath} resolves differently across compile contexts`);
83
- }
84
- const cachedNode = nodeCache.get(canonicalPath);
85
- if (cachedNode) {
86
- return cachedNode.value;
87
- }
88
- fingerprintCache.set(canonicalPath, fingerprint);
89
- nodeCache.set(canonicalPath, {
90
- runtimeName: runtime.name,
91
- source: canonicalPath,
92
- value: candidate
93
- });
94
- visitStack.push(canonicalPath);
95
- for (const subagent of loadedManifest.manifest.subagents ?? []) {
96
- const childManifestPath = getManifestPath(resolveProjectPath(canonicalPath, subagent.ref));
97
- const resolvedSubagent = await visitAgent(childManifestPath, {
98
- inheritedExecution: execution,
99
- inheritedRuntime: runtime,
100
- isSubagent: true
101
- });
102
- candidate.subagents.push({
103
- id: subagent.id,
104
- nodeSource: resolvedSubagent.source
105
- });
106
- edges.push({
107
- from: canonicalPath,
108
- kind: "subagent",
109
- label: subagent.id,
110
- to: resolvedSubagent.source
111
- });
112
- }
113
- visitStack.pop();
114
- return candidate;
115
- };
116
- const visitTeam = async (manifestPath) => {
117
- const canonicalPath = getCanonicalManifestPath(manifestPath);
118
- if (visitStack.includes(canonicalPath)) {
119
- throw new SpawnfileError("compile_error", `Cycle detected while visiting ${canonicalPath}`);
120
- }
121
- const loadedManifest = await getLoadedManifest(canonicalPath);
122
- if (!isTeamManifest(loadedManifest.manifest)) {
123
- throw new SpawnfileError("compile_error", `Expected team manifest, got ${loadedManifest.manifest.kind} at ${canonicalPath}`);
124
- }
125
- const sharedSkills = await loadResolvedSkills(canonicalPath, loadedManifest.manifest.shared?.skills);
126
- validateEffectiveSkillRequirements(loadedManifest.manifest.name, getMcpNames(loadedManifest.manifest.shared?.mcp_servers ?? []), sharedSkills);
127
- const manifest = loadedManifest.manifest;
128
- const resolvedExternal = resolveTeamExternalIds(manifest);
129
- const docs = await loadResolvedDocuments(canonicalPath, manifest.docs);
130
- const candidate = {
131
- description: manifest.description ? normalizeDescription(manifest.description) : "",
132
- docs,
133
- external: resolvedExternal,
134
- externalExplicit: manifest.external !== undefined,
135
- kind: "team",
136
- lead: manifest.lead ?? null,
137
- members: [],
138
- mode: manifest.mode,
139
- name: manifest.name,
140
- networks: resolveTeamNetworks(manifest),
141
- policyMode: manifest.policy?.mode ?? null,
142
- policyOnDegrade: manifest.policy?.on_degrade ?? null,
143
- shared: {
144
- env: manifest.shared?.env ?? {},
145
- mcpServers: manifest.shared?.mcp_servers ?? [],
146
- secrets: manifest.shared?.secrets ?? [],
147
- skills: sharedSkills
148
- },
149
- source: canonicalPath,
150
- };
151
- const fingerprint = getTeamFingerprint(candidate);
152
- const existingFingerprint = fingerprintCache.get(canonicalPath);
153
- if (existingFingerprint && existingFingerprint !== fingerprint) {
154
- throw new SpawnfileError("compile_error", `Team manifest ${canonicalPath} resolves differently across compile contexts`);
155
- }
156
- const cachedNode = nodeCache.get(canonicalPath);
157
- if (cachedNode) {
158
- return cachedNode.value;
159
- }
160
- fingerprintCache.set(canonicalPath, fingerprint);
161
- nodeCache.set(canonicalPath, {
162
- runtimeName: null,
163
- source: canonicalPath,
164
- value: candidate
165
- });
166
- visitStack.push(canonicalPath);
167
- for (const member of loadedManifest.manifest.members) {
168
- const childManifestPath = getManifestPath(resolveProjectPath(canonicalPath, member.ref));
169
- const childManifest = await getLoadedManifest(childManifestPath);
170
- let resolvedMember;
171
- if (isAgentManifest(childManifest.manifest)) {
172
- const resolvedAgent = await visitAgent(childManifestPath, {
173
- inheritedShared: {
174
- manifestPath: canonicalPath,
175
- surface: loadedManifest.manifest.shared
176
- },
177
- isSubagent: false
178
- });
179
- resolvedMember = {
180
- id: member.id,
181
- kind: "agent",
182
- nodeSource: resolvedAgent.source,
183
- runtimeName: resolvedAgent.runtime.name
184
- };
185
- memberships.set(`${canonicalPath}::${member.id}::${resolvedAgent.source}`, {
186
- agentSource: resolvedAgent.source,
187
- memberId: member.id,
188
- teamName: candidate.name,
189
- teamSource: canonicalPath
190
- });
191
- }
192
- else {
193
- const resolvedTeam = await visitTeam(childManifestPath);
194
- resolvedMember = {
195
- id: member.id,
196
- kind: "team",
197
- nodeSource: resolvedTeam.source,
198
- runtimeName: null
199
- };
200
- }
201
- candidate.members.push(resolvedMember);
202
- edges.push({
203
- from: canonicalPath,
204
- kind: "team_member",
205
- label: member.id,
206
- to: resolvedMember.nodeSource
207
- });
208
- }
209
- validateTeamNetworkRooms(candidate);
210
- visitStack.pop();
211
- return candidate;
212
- };
25
+ const { visitAgent, visitTeam } = createCompilePlanTraversal({
26
+ getLoadedManifest,
27
+ nodeCache,
28
+ edges,
29
+ fingerprintCache,
30
+ memberships
31
+ });
213
32
  const rootLoadedManifest = await getLoadedManifest(rootManifestPath);
214
33
  if (isAgentManifest(rootLoadedManifest.manifest)) {
215
34
  await visitAgent(rootManifestPath, { isSubagent: false });
@@ -234,21 +53,12 @@ export const buildCompilePlan = async (inputPath) => {
234
53
  from: idBySource.get(edge.from) ?? edge.from,
235
54
  to: idBySource.get(edge.to) ?? edge.to
236
55
  }));
237
- const runtimes = compilePlanNodes.reduce((groups, node) => {
238
- if (!node.runtimeName) {
239
- return groups;
240
- }
241
- const group = groups[node.runtimeName] ?? { nodeIds: [] };
242
- group.nodeIds.push(node.id);
243
- groups[node.runtimeName] = group;
244
- return groups;
245
- }, {});
246
56
  const compilePlan = {
247
57
  edges: compilePlanEdges,
248
58
  memberships: [...memberships.values()].sort((left, right) => `${left.agentSource}:${left.teamSource}:${left.memberId}`.localeCompare(`${right.agentSource}:${right.teamSource}:${right.memberId}`)),
249
59
  nodes: compilePlanNodes,
250
60
  root: rootManifestPath,
251
- runtimes
61
+ runtimes: createRuntimeGroups(compilePlanNodes)
252
62
  };
253
63
  compilePlan.moltnetRoomMemberships = resolveMoltnetRoomMemberships(compilePlan);
254
64
  resolvePlanMoltnetAttachments(compilePlan);
@@ -1,7 +1,9 @@
1
1
  import { type AgentManifest, type ExecutionBlock, type SharedSurface } from "../manifest/index.js";
2
- import type { ResolvedDocument, ResolvedRuntime } from "./types.js";
2
+ import type { CompilePlanNode, ResolvedDocument, ResolvedRuntime } from "./types.js";
3
+ import type { ResolvedWorkspaceResource } from "./workspaceResources.js";
3
4
  export interface AgentVisitContext {
4
5
  inheritedExecution?: ExecutionBlock;
6
+ inheritedResources?: ResolvedWorkspaceResource[];
5
7
  inheritedShared?: {
6
8
  manifestPath: string;
7
9
  surface: SharedSurface | undefined;
@@ -12,3 +14,6 @@ export interface AgentVisitContext {
12
14
  export declare const resolveRuntime: (manifest: AgentManifest, context: AgentVisitContext) => Promise<ResolvedRuntime>;
13
15
  export declare const normalizeDescription: (description: string) => string;
14
16
  export declare const resolveDescription: (description: string | undefined, docs: ResolvedDocument[]) => string;
17
+ export declare const createRuntimeGroups: (nodes: CompilePlanNode[]) => Record<string, {
18
+ nodeIds: string[];
19
+ }>;
@@ -37,3 +37,12 @@ const deriveDescriptionFromDocs = (docs) => {
37
37
  export const resolveDescription = (description, docs) => description !== undefined
38
38
  ? normalizeDescription(description)
39
39
  : deriveDescriptionFromDocs(docs);
40
+ export const createRuntimeGroups = (nodes) => nodes.reduce((groups, node) => {
41
+ if (!node.runtimeName) {
42
+ return groups;
43
+ }
44
+ const group = groups[node.runtimeName] ?? { nodeIds: [] };
45
+ group.nodeIds.push(node.id);
46
+ groups[node.runtimeName] = group;
47
+ return groups;
48
+ }, {});
@@ -14,16 +14,22 @@ export const resolveTeamExternalIds = (manifest) => {
14
14
  ? [manifest.lead]
15
15
  : memberIds);
16
16
  };
17
- export const resolveTeamNetworks = (manifest) => (manifest.networks ?? []).map((network) => ({
18
- expose: network.expose ?? false,
19
- id: network.id,
20
- name: network.name ?? network.id,
21
- provider: network.provider,
22
- rooms: network.rooms.map((room) => ({
23
- id: room.id,
24
- members: [...room.members]
25
- }))
26
- }));
17
+ export const resolveTeamNetworks = (manifest) => (manifest.networks ?? []).map((network) => {
18
+ const resolved = {
19
+ id: network.id,
20
+ name: network.name ?? network.id,
21
+ provider: network.provider,
22
+ rooms: network.rooms.map((room) => ({
23
+ id: room.id,
24
+ members: [...room.members],
25
+ ...(room.name ? { name: room.name } : {})
26
+ }))
27
+ };
28
+ if (network.server) {
29
+ resolved.server = network.server;
30
+ }
31
+ return resolved;
32
+ });
27
33
  export const validateTeamNetworkRooms = (teamNode) => {
28
34
  for (const network of teamNode.networks ?? []) {
29
35
  for (const room of network.rooms) {
@@ -0,0 +1,16 @@
1
+ import { LoadedManifest } from "../manifest/index.js";
2
+ import { CompilePlanEdge, ResolvedAgentNode, ResolvedTeamMembershipContext, ResolvedTeamNode } from "./types.js";
3
+ import { type AgentVisitContext } from "./buildCompilePlanRuntime.js";
4
+ import { type InternalNode } from "./buildCompilePlanTraversalHelpers.js";
5
+ type BuildCompilePlanTraversalDeps = {
6
+ getLoadedManifest: (manifestPath: string) => Promise<LoadedManifest>;
7
+ nodeCache: Map<string, InternalNode>;
8
+ fingerprintCache: Map<string, string>;
9
+ edges: CompilePlanEdge[];
10
+ memberships: Map<string, ResolvedTeamMembershipContext>;
11
+ };
12
+ export declare const createCompilePlanTraversal: ({ getLoadedManifest, nodeCache, fingerprintCache, edges, memberships }: BuildCompilePlanTraversalDeps) => {
13
+ visitAgent: (manifestPath: string, context: AgentVisitContext) => Promise<ResolvedAgentNode>;
14
+ visitTeam: (manifestPath: string, inheritedResources?: ResolvedAgentNode["workspaceResources"]) => Promise<ResolvedTeamNode>;
15
+ };
16
+ export type { InternalNode };