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
@@ -0,0 +1,180 @@
1
+ import path from "node:path";
2
+ import { SpawnfileError } from "../../shared/index.js";
3
+ import { buildCompilePlan } from "../buildCompilePlan.js";
4
+ import { resolveMoltnetRoomMemberships } from "../moltnetRoomMemberships.js";
5
+ const createNameCounts = (plan) => {
6
+ const counts = new Map();
7
+ for (const node of plan.nodes) {
8
+ const key = `${node.kind}:${node.value.name}`;
9
+ counts.set(key, (counts.get(key) ?? 0) + 1);
10
+ }
11
+ return counts;
12
+ };
13
+ const formatDisplayName = (node, nameCounts) => {
14
+ const key = `${node.kind}:${node.value.name}`;
15
+ return (nameCounts.get(key) ?? 0) > 1
16
+ ? `${node.value.name} [${node.id}]`
17
+ : node.value.name;
18
+ };
19
+ const groupEdgesBySource = (edges) => {
20
+ const groups = new Map();
21
+ for (const edge of edges) {
22
+ const group = groups.get(edge.from) ?? [];
23
+ group.push(edge);
24
+ groups.set(edge.from, group);
25
+ }
26
+ return groups;
27
+ };
28
+ const buildTreeNetworkSummaries = (node) => {
29
+ if (node.value.kind !== "team") {
30
+ return [];
31
+ }
32
+ return (node.value.networks ?? []).map((network) => ({
33
+ expose: network.expose ?? false,
34
+ id: network.id,
35
+ name: network.name,
36
+ provider: network.provider,
37
+ rooms: network.rooms.map((room) => ({
38
+ declaredMembers: [...room.members],
39
+ id: room.id
40
+ }))
41
+ }));
42
+ };
43
+ const buildTreeNode = (node, nodeById, edgesBySource, nameCounts, ancestors = []) => {
44
+ if (ancestors.includes(node.id)) {
45
+ throw new SpawnfileError("compile_error", `Cycle detected while building view tree for ${node.id}`);
46
+ }
47
+ const children = (edgesBySource.get(node.id) ?? []).map((edge) => {
48
+ const child = nodeById.get(edge.to);
49
+ if (!child) {
50
+ throw new SpawnfileError("compile_error", `Unable to find view node ${edge.to}`);
51
+ }
52
+ return {
53
+ label: edge.label,
54
+ node: buildTreeNode(child, nodeById, edgesBySource, nameCounts, [...ancestors, node.id]),
55
+ relation: edge.kind
56
+ };
57
+ });
58
+ return {
59
+ children,
60
+ displayName: formatDisplayName(node, nameCounts),
61
+ ...(node.value.kind === "team"
62
+ ? {
63
+ external: [...node.value.external],
64
+ lead: node.value.lead,
65
+ mode: node.value.mode
66
+ }
67
+ : {}),
68
+ id: node.id,
69
+ kind: node.kind,
70
+ name: node.value.name,
71
+ networks: buildTreeNetworkSummaries(node),
72
+ runtimeName: node.runtimeName,
73
+ source: node.value.source
74
+ };
75
+ };
76
+ const sortNetworkMembers = (declaredMembers, members) => {
77
+ const declaredOrder = new Map(declaredMembers.map((member, index) => [member, index]));
78
+ return [...members].sort((left, right) => (declaredOrder.get(left.declaredSlot) ?? Number.MAX_SAFE_INTEGER)
79
+ - (declaredOrder.get(right.declaredSlot) ?? Number.MAX_SAFE_INTEGER)
80
+ || (left.representativePath ?? []).join("/").localeCompare((right.representativePath ?? []).join("/"))
81
+ || left.concreteMemberId.localeCompare(right.concreteMemberId));
82
+ };
83
+ const toNetworkMemberView = (membership) => ({
84
+ agentName: membership.agentName,
85
+ agentSource: membership.agentSource,
86
+ concreteMemberId: membership.concreteMemberId,
87
+ declaredSlot: membership.declaredSlot,
88
+ directTeamName: membership.directTeamName,
89
+ directTeamSource: membership.directTeamSource,
90
+ ...(membership.policy ? { policy: { ...membership.policy } } : {}),
91
+ ...(membership.representedSlot ? { representedSlot: membership.representedSlot } : {}),
92
+ ...(membership.representedTeamName
93
+ ? { representedTeamName: membership.representedTeamName }
94
+ : {}),
95
+ ...(membership.representedTeamSource
96
+ ? { representedTeamSource: membership.representedTeamSource }
97
+ : {}),
98
+ ...(membership.representativePath
99
+ ? { representativePath: [...membership.representativePath] }
100
+ : {})
101
+ });
102
+ const createNetworkKey = (provider, networkId) => `${provider}::${networkId}`;
103
+ const buildNetworkDeclaration = (teamNode, network, roomMemberships) => ({
104
+ declaringTeamName: teamNode.name,
105
+ declaringTeamSource: teamNode.source,
106
+ expose: network.expose ?? false,
107
+ name: network.name,
108
+ rooms: network.rooms.map((room) => {
109
+ const members = roomMemberships
110
+ .filter((membership) => membership.declaringTeamSource === teamNode.source
111
+ && membership.networkId === network.id
112
+ && membership.roomId === room.id)
113
+ .map(toNetworkMemberView);
114
+ return {
115
+ declaredMembers: [...room.members],
116
+ id: room.id,
117
+ members: sortNetworkMembers(room.members, members)
118
+ };
119
+ })
120
+ });
121
+ const buildNetworks = (plan) => {
122
+ const roomMemberships = plan.moltnetRoomMemberships
123
+ ?? resolveMoltnetRoomMemberships(plan);
124
+ const groups = new Map();
125
+ for (const node of plan.nodes) {
126
+ if (node.value.kind !== "team") {
127
+ continue;
128
+ }
129
+ const teamNode = node.value;
130
+ for (const network of teamNode.networks ?? []) {
131
+ const key = createNetworkKey(network.provider, network.id);
132
+ const declaration = buildNetworkDeclaration(teamNode, network, roomMemberships);
133
+ const existing = groups.get(key);
134
+ if (existing) {
135
+ existing.declarations = [...(existing.declarations ?? []), declaration];
136
+ continue;
137
+ }
138
+ groups.set(key, {
139
+ declaringTeamName: declaration.declaringTeamName,
140
+ declaringTeamSource: declaration.declaringTeamSource,
141
+ declarations: [declaration],
142
+ expose: declaration.expose,
143
+ id: network.id,
144
+ name: declaration.name,
145
+ provider: network.provider,
146
+ rooms: declaration.rooms
147
+ });
148
+ }
149
+ }
150
+ const networks = [...groups.values()];
151
+ for (const network of networks) {
152
+ const firstDeclaration = network.declarations?.[0];
153
+ if (firstDeclaration) {
154
+ network.declaringTeamName = firstDeclaration.declaringTeamName;
155
+ network.declaringTeamSource = firstDeclaration.declaringTeamSource;
156
+ network.expose = firstDeclaration.expose;
157
+ network.name = firstDeclaration.name;
158
+ network.rooms = firstDeclaration.rooms;
159
+ }
160
+ }
161
+ return networks;
162
+ };
163
+ export const buildOrganizationView = async (inputPath) => {
164
+ const plan = await buildCompilePlan(inputPath);
165
+ const rootNode = plan.nodes.find((node) => node.value.source === plan.root);
166
+ if (!rootNode) {
167
+ throw new SpawnfileError("compile_error", `Unable to find root view node for ${plan.root}`);
168
+ }
169
+ const nodeById = new Map(plan.nodes.map((node) => [node.id, node]));
170
+ const root = buildTreeNode(rootNode, nodeById, groupEdgesBySource(plan.edges), createNameCounts(plan));
171
+ return {
172
+ contexts: [],
173
+ diagnostics: [],
174
+ inputPath,
175
+ networks: buildNetworks(plan),
176
+ projectRoot: path.dirname(plan.root),
177
+ root,
178
+ runtimes: []
179
+ };
180
+ };
@@ -0,0 +1,4 @@
1
+ export * from "./buildOrganizationView.js";
2
+ export * from "./renderNetworks.js";
3
+ export * from "./renderTree.js";
4
+ export * from "./types.js";
@@ -0,0 +1,4 @@
1
+ export * from "./buildOrganizationView.js";
2
+ export * from "./renderNetworks.js";
3
+ export * from "./renderTree.js";
4
+ export * from "./types.js";
@@ -0,0 +1,2 @@
1
+ import type { OrganizationView, RenderOrganizationViewOptions } from "./types.js";
2
+ export declare const renderOrganizationNetworks: (view: OrganizationView, options?: RenderOrganizationViewOptions) => string;
@@ -0,0 +1,93 @@
1
+ import { formatSourceMeta } from "./sourcePaths.js";
2
+ const color = (value, code, options) => options.color ? `\u001b[${code}m${value}\u001b[0m` : value;
3
+ const glyphsFor = (options) => options.ascii
4
+ ? { branch: "|-- ", last: "`-- ", pipe: "| ", space: " " }
5
+ : { branch: "├── ", last: "└── ", pipe: "│ ", space: " " };
6
+ const formatPolicy = (member) => {
7
+ if (!member.policy) {
8
+ return [];
9
+ }
10
+ return [
11
+ member.policy.read ? `read=${member.policy.read}` : undefined,
12
+ member.policy.reply ? `reply=${member.policy.reply}` : undefined
13
+ ].filter((entry) => entry !== undefined);
14
+ };
15
+ const formatMember = (member, options, projectRoot) => {
16
+ const metadata = member.representedSlot
17
+ ? [
18
+ `represents=${member.representedSlot}`,
19
+ member.representedTeamName && member.representedTeamName !== member.representedSlot
20
+ ? `team=${member.representedTeamName}`
21
+ : undefined,
22
+ `member=${member.concreteMemberId}`
23
+ ]
24
+ : [
25
+ `team=${member.directTeamName}`,
26
+ `member=${member.concreteMemberId}`
27
+ ];
28
+ const source = options.paths
29
+ ? formatSourceMeta("source", member.agentSource, projectRoot)
30
+ : "";
31
+ const details = [
32
+ ...metadata,
33
+ ...formatPolicy(member)
34
+ ].filter((entry) => entry !== undefined);
35
+ return `${member.agentName} ${details.join(" ")}${source}`;
36
+ };
37
+ const formatNetwork = (network, options) => {
38
+ const id = color(network.id, "36", options);
39
+ return `${network.provider} ${id}`;
40
+ };
41
+ const getDeclarations = (network) => network.declarations ?? [
42
+ {
43
+ declaringTeamName: network.declaringTeamName,
44
+ declaringTeamSource: network.declaringTeamSource,
45
+ expose: network.expose,
46
+ name: network.name,
47
+ rooms: network.rooms
48
+ }
49
+ ];
50
+ const formatDeclaration = (network, declaration, options, projectRoot) => {
51
+ const exposed = declaration.expose ? " exposed" : "";
52
+ const source = options.paths
53
+ ? formatSourceMeta("declared_source", declaration.declaringTeamSource, projectRoot)
54
+ : "";
55
+ return `${network.id} "${declaration.name}" on ${declaration.declaringTeamName}${exposed}${source}`;
56
+ };
57
+ export const renderOrganizationNetworks = (view, options = {}) => {
58
+ if (view.networks.length === 0) {
59
+ return "No Moltnet networks.";
60
+ }
61
+ const glyphs = glyphsFor(options);
62
+ const lines = ["Moltnet networks"];
63
+ view.networks.forEach((network, networkIndex) => {
64
+ const networkLast = networkIndex === view.networks.length - 1;
65
+ const networkPrefix = networkLast ? glyphs.space : glyphs.pipe;
66
+ lines.push(`${networkLast ? glyphs.last : glyphs.branch}${formatNetwork(network, options)}`);
67
+ const declarations = getDeclarations(network);
68
+ declarations.forEach((declaration, declarationIndex) => {
69
+ const declarationLast = declarationIndex === declarations.length - 1;
70
+ const declarationPrefix = `${networkPrefix}${declarationLast ? glyphs.space : glyphs.pipe}`;
71
+ lines.push(`${networkPrefix}${declarationLast ? glyphs.last : glyphs.branch}${formatDeclaration(network, declaration, options, view.projectRoot)}`);
72
+ declaration.rooms.forEach((room, roomIndex) => {
73
+ const roomLast = roomIndex === declaration.rooms.length - 1;
74
+ const roomPrefix = `${declarationPrefix}${roomLast ? glyphs.space : glyphs.pipe}`;
75
+ const legacyDeclared = options.declared && !view.projectRoot
76
+ ? ` room ${room.id} declared [${room.declaredMembers.join(", ")}]`
77
+ : "";
78
+ lines.push(`${declarationPrefix}${roomLast ? glyphs.last : glyphs.branch}#${room.id}${legacyDeclared}`);
79
+ if (options.declared) {
80
+ const declaredMembers = room.declaredMembers.length > 0
81
+ ? room.declaredMembers.join(", ")
82
+ : "(none)";
83
+ lines.push(`${roomPrefix}${glyphs.branch}declared members: ${declaredMembers}`);
84
+ }
85
+ room.members.forEach((member, memberIndex) => {
86
+ const memberLast = memberIndex === room.members.length - 1;
87
+ lines.push(`${roomPrefix}${memberLast ? glyphs.last : glyphs.branch}${formatMember(member, options, view.projectRoot)}`);
88
+ });
89
+ });
90
+ });
91
+ });
92
+ return lines.join("\n");
93
+ };
@@ -0,0 +1,2 @@
1
+ import type { OrganizationView, RenderOrganizationViewOptions } from "./types.js";
2
+ export declare const renderOrganizationTree: (view: OrganizationView, options?: RenderOrganizationViewOptions) => string;
@@ -0,0 +1,59 @@
1
+ import { formatSourceMeta } from "./sourcePaths.js";
2
+ const color = (value, code, options) => options.color ? `\u001b[${code}m${value}\u001b[0m` : value;
3
+ const formatNode = (node, options, projectRoot) => {
4
+ const kind = color(node.kind, node.kind === "team" ? "36" : "32", options);
5
+ const metadata = node.kind === "team"
6
+ ? [
7
+ node.mode ? `mode=${node.mode}` : undefined,
8
+ node.lead ? `lead=${node.lead}` : undefined,
9
+ node.external && node.external.length > 0
10
+ ? `external=${node.external.join(",")}`
11
+ : undefined
12
+ ]
13
+ : [
14
+ node.runtimeName ? `[${node.runtimeName}]` : undefined,
15
+ node.runtimeName ? `runtime=${node.runtimeName}` : undefined
16
+ ];
17
+ const details = metadata.filter((entry) => entry !== undefined);
18
+ const source = options.paths ? formatSourceMeta("source", node.source, projectRoot) : "";
19
+ const separator = details[0]?.startsWith("[") ? " " : " ";
20
+ return `${kind} ${node.displayName}${details.length > 0 ? `${separator}${details.join(" ")}` : ""}${source}`;
21
+ };
22
+ const formatEdgeLabel = (edge) => edge.relation === "subagent"
23
+ ? `subagent ${edge.label}`
24
+ : edge.label;
25
+ const formatNetworkSummary = (network, options) => {
26
+ const id = color(network.id, "36", options);
27
+ const exposed = network.expose ? " exposed" : "";
28
+ const rooms = network.rooms
29
+ .map((room) => `${room.id} [${room.declaredMembers.join(", ")}]`)
30
+ .join("; ");
31
+ return `network ${id} "${network.name}"${exposed}: ${rooms}`;
32
+ };
33
+ const renderChildren = (node, options, projectRoot, prefix = "") => {
34
+ const glyphs = options.ascii
35
+ ? { branch: "|-- ", last: "`-- ", pipe: "| ", space: " " }
36
+ : { branch: "├── ", last: "└── ", pipe: "│ ", space: " " };
37
+ const items = [
38
+ ...(node.networks ?? []).map((network) => ({ kind: "network", network })),
39
+ ...node.children.map((edge) => ({ kind: "edge", edge }))
40
+ ];
41
+ return items.flatMap((item, index) => {
42
+ const isLast = index === items.length - 1;
43
+ const connector = isLast ? glyphs.last : glyphs.branch;
44
+ const nextPrefix = `${prefix}${isLast ? glyphs.space : glyphs.pipe}`;
45
+ if (item.kind === "network") {
46
+ return [`${prefix}${connector}${formatNetworkSummary(item.network, options)}`];
47
+ }
48
+ const edge = item.edge;
49
+ const line = `${prefix}${connector}${formatEdgeLabel(edge)}: ${formatNode(edge.node, options, projectRoot)}`;
50
+ return [
51
+ line,
52
+ ...renderChildren(edge.node, options, projectRoot, nextPrefix)
53
+ ];
54
+ });
55
+ };
56
+ export const renderOrganizationTree = (view, options = {}) => [
57
+ formatNode(view.root, options, view.projectRoot),
58
+ ...renderChildren(view.root, options, view.projectRoot)
59
+ ].join("\n");
@@ -0,0 +1,2 @@
1
+ export declare const formatSourcePath: (sourcePath: string, projectRoot: string | undefined) => string;
2
+ export declare const formatSourceMeta: (label: string, sourcePath: string, projectRoot: string | undefined) => string;
@@ -0,0 +1,19 @@
1
+ import path from "node:path";
2
+ export const formatSourcePath = (sourcePath, projectRoot) => {
3
+ if (!projectRoot || !path.isAbsolute(sourcePath) || !path.isAbsolute(projectRoot)) {
4
+ return sourcePath;
5
+ }
6
+ const relativePath = path.relative(projectRoot, sourcePath);
7
+ if (relativePath === ""
8
+ || relativePath.startsWith("..")
9
+ || path.isAbsolute(relativePath)) {
10
+ return sourcePath;
11
+ }
12
+ return relativePath.split(path.sep).join("/");
13
+ };
14
+ export const formatSourceMeta = (label, sourcePath, projectRoot) => {
15
+ const formattedPath = formatSourcePath(sourcePath, projectRoot);
16
+ return projectRoot
17
+ ? ` ${label}=${formattedPath}`
18
+ : ` <${formattedPath}>`;
19
+ };
@@ -0,0 +1,80 @@
1
+ import type { ResolvedMoltnetRoomPolicy } from "../types.js";
2
+ export interface OrganizationViewTreeNode {
3
+ children: OrganizationViewTreeEdge[];
4
+ displayName: string;
5
+ external?: string[];
6
+ id: string;
7
+ kind: "agent" | "team";
8
+ lead?: string | null;
9
+ mode?: "hierarchical" | "swarm";
10
+ name: string;
11
+ networks?: OrganizationTreeNetworkSummary[];
12
+ runtimeName: string | null;
13
+ source: string;
14
+ }
15
+ export interface OrganizationTreeNetworkRoomSummary {
16
+ declaredMembers: string[];
17
+ id: string;
18
+ }
19
+ export interface OrganizationTreeNetworkSummary {
20
+ expose: boolean;
21
+ id: string;
22
+ name: string;
23
+ provider: "moltnet";
24
+ rooms: OrganizationTreeNetworkRoomSummary[];
25
+ }
26
+ export interface OrganizationViewTreeEdge {
27
+ label: string;
28
+ node: OrganizationViewTreeNode;
29
+ relation: "subagent" | "team_member";
30
+ }
31
+ export interface OrganizationNetworkMemberView {
32
+ agentName: string;
33
+ agentSource: string;
34
+ concreteMemberId: string;
35
+ declaredSlot: string;
36
+ directTeamName: string;
37
+ directTeamSource: string;
38
+ policy?: ResolvedMoltnetRoomPolicy;
39
+ representedSlot?: string;
40
+ representedTeamName?: string;
41
+ representedTeamSource?: string;
42
+ representativePath?: string[];
43
+ }
44
+ export interface OrganizationNetworkDeclarationView {
45
+ declaringTeamName: string;
46
+ declaringTeamSource: string;
47
+ expose: boolean;
48
+ name: string;
49
+ rooms: OrganizationNetworkRoomView[];
50
+ }
51
+ export interface OrganizationNetworkRoomView {
52
+ declaredMembers: string[];
53
+ id: string;
54
+ members: OrganizationNetworkMemberView[];
55
+ }
56
+ export interface OrganizationNetworkView {
57
+ declaringTeamName: string;
58
+ declaringTeamSource: string;
59
+ expose: boolean;
60
+ id: string;
61
+ name: string;
62
+ provider: "moltnet";
63
+ rooms: OrganizationNetworkRoomView[];
64
+ declarations?: OrganizationNetworkDeclarationView[];
65
+ }
66
+ export interface OrganizationView {
67
+ contexts: [];
68
+ diagnostics: [];
69
+ inputPath: string;
70
+ networks: OrganizationNetworkView[];
71
+ projectRoot?: string;
72
+ root: OrganizationViewTreeNode;
73
+ runtimes: [];
74
+ }
75
+ export interface RenderOrganizationViewOptions {
76
+ ascii?: boolean;
77
+ color?: boolean;
78
+ declared?: boolean;
79
+ paths?: boolean;
80
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -102,12 +102,12 @@ const validateLocalTeamManifest = async (manifestPath, manifest) => {
102
102
  await validateManifestRefs(manifestPath, manifest.members.map((member) => member.ref), "Member");
103
103
  validateSkillRequirements(manifest.shared?.skills, getSharedMcpNames(manifest.shared));
104
104
  const memberIds = new Set(manifest.members.map((member) => member.id));
105
- if (manifest.structure.leader && !memberIds.has(manifest.structure.leader)) {
106
- throw new SpawnfileError("validation_error", `Structure leader is not a declared team member: ${manifest.structure.leader}`);
105
+ if (manifest.lead && !memberIds.has(manifest.lead)) {
106
+ throw new SpawnfileError("validation_error", `Lead is not a declared team member: ${manifest.lead}`);
107
107
  }
108
- for (const id of manifest.structure.external ?? []) {
108
+ for (const id of manifest.external ?? []) {
109
109
  if (!memberIds.has(id)) {
110
- throw new SpawnfileError("validation_error", `Structure external references undeclared member: ${id}`);
110
+ throw new SpawnfileError("validation_error", `External references undeclared member: ${id}`);
111
111
  }
112
112
  }
113
113
  };
@@ -29,7 +29,8 @@ const orderDiscordSurface = (surface) => {
29
29
  }
30
30
  return withDefinedEntries([
31
31
  ["access", orderDiscordSurfaceAccess(surface.access)],
32
- ["bot_token_secret", surface.bot_token_secret]
32
+ ["bot_token_secret", surface.bot_token_secret],
33
+ ["identity", surface.identity]
33
34
  ]);
34
35
  };
35
36
  const orderDiscordSurfaceAccess = (access) => {
@@ -49,7 +50,8 @@ const orderTelegramSurface = (surface) => {
49
50
  }
50
51
  return withDefinedEntries([
51
52
  ["access", orderTelegramSurfaceAccess(surface.access)],
52
- ["bot_token_secret", surface.bot_token_secret]
53
+ ["bot_token_secret", surface.bot_token_secret],
54
+ ["identity", surface.identity]
53
55
  ]);
54
56
  };
55
57
  const orderTelegramSurfaceAccess = (access) => {
@@ -62,11 +64,55 @@ const orderTelegramSurfaceAccess = (access) => {
62
64
  ["chats", access.chats]
63
65
  ]);
64
66
  };
67
+ const orderWebhookSurface = (surface) => {
68
+ if (!surface) {
69
+ return undefined;
70
+ }
71
+ return withDefinedEntries([
72
+ ["url", surface.url],
73
+ ["signing_secret", surface.signing_secret]
74
+ ]);
75
+ };
76
+ const orderMoltnetRoomBehavior = (behavior) => {
77
+ if (!behavior) {
78
+ return undefined;
79
+ }
80
+ return withDefinedEntries([
81
+ ["read", behavior.read],
82
+ ["reply", behavior.reply]
83
+ ]);
84
+ };
85
+ const orderMoltnetDm = (dms) => {
86
+ if (!dms) {
87
+ return undefined;
88
+ }
89
+ return withDefinedEntries([
90
+ ["enabled", dms.enabled],
91
+ ["read", dms.read],
92
+ ["reply", dms.reply]
93
+ ]);
94
+ };
95
+ const orderMoltnetAttachment = (attachment) => withDefinedEntries([
96
+ ["network", attachment.network],
97
+ [
98
+ "rooms",
99
+ attachment.rooms
100
+ ? Object.fromEntries(Object.entries(attachment.rooms)
101
+ .sort(([left], [right]) => left.localeCompare(right))
102
+ .map(([roomId, behavior]) => [roomId, orderMoltnetRoomBehavior(behavior)]))
103
+ : undefined
104
+ ],
105
+ ["dms", orderMoltnetDm(attachment.dms)]
106
+ ]);
107
+ const orderMoltnetSurface = (surface) => surface?.map(orderMoltnetAttachment);
65
108
  const orderWhatsAppSurface = (surface) => {
66
109
  if (!surface) {
67
110
  return undefined;
68
111
  }
69
- return withDefinedEntries([["access", orderWhatsAppSurfaceAccess(surface.access)]]);
112
+ return withDefinedEntries([
113
+ ["access", orderWhatsAppSurfaceAccess(surface.access)],
114
+ ["identity", surface.identity]
115
+ ]);
70
116
  };
71
117
  const orderWhatsAppSurfaceAccess = (access) => {
72
118
  if (!access) {
@@ -85,7 +131,8 @@ const orderSlackSurface = (surface) => {
85
131
  return withDefinedEntries([
86
132
  ["access", orderSlackSurfaceAccess(surface.access)],
87
133
  ["bot_token_secret", surface.bot_token_secret],
88
- ["app_token_secret", surface.app_token_secret]
134
+ ["app_token_secret", surface.app_token_secret],
135
+ ["identity", surface.identity]
89
136
  ]);
90
137
  };
91
138
  const orderSlackSurfaceAccess = (access) => {
@@ -156,9 +203,24 @@ const orderSurfaces = (surfaces) => {
156
203
  ["discord", orderDiscordSurface(surfaces.discord)],
157
204
  ["telegram", orderTelegramSurface(surfaces.telegram)],
158
205
  ["whatsapp", orderWhatsAppSurface(surfaces.whatsapp)],
159
- ["slack", orderSlackSurface(surfaces.slack)]
206
+ ["slack", orderSlackSurface(surfaces.slack)],
207
+ ["webhook", orderWebhookSurface(surfaces.webhook)],
208
+ ["moltnet", orderMoltnetSurface(surfaces.moltnet)]
160
209
  ]);
161
210
  };
211
+ const orderTeamNetworks = (networks) => networks?.map((network) => withDefinedEntries([
212
+ ["id", network.id],
213
+ ["provider", network.provider],
214
+ ["name", network.name],
215
+ ["expose", network.expose],
216
+ [
217
+ "rooms",
218
+ network.rooms.map((room) => withDefinedEntries([
219
+ ["id", room.id],
220
+ ["members", room.members]
221
+ ]))
222
+ ]
223
+ ]));
162
224
  const renderSections = (sections) => sections
163
225
  .filter(hasEntries)
164
226
  .map((section) => YAML.stringify(section))
@@ -167,7 +229,8 @@ const orderAgentManifestSections = (manifest) => [
167
229
  withDefinedEntries([
168
230
  ["spawnfile_version", manifest.spawnfile_version],
169
231
  ["kind", manifest.kind],
170
- ["name", manifest.name]
232
+ ["name", manifest.name],
233
+ ["expose", manifest.expose]
171
234
  ]),
172
235
  withDefinedEntries([["runtime", orderRuntimeBinding(manifest.runtime)]]),
173
236
  withDefinedEntries([["execution", orderExecution(manifest.execution)]]),
@@ -192,7 +255,8 @@ const orderTeamManifestSections = (manifest) => [
192
255
  withDefinedEntries([["execution", orderExecution(manifest.execution)]]),
193
256
  withDefinedEntries([
194
257
  ["docs", orderDocs(manifest.docs)],
195
- ["shared", orderSharedSurface(manifest.shared)]
258
+ ["shared", orderSharedSurface(manifest.shared)],
259
+ ["networks", orderTeamNetworks(manifest.networks)]
196
260
  ]),
197
261
  withDefinedEntries([
198
262
  ["skills", manifest.skills],
@@ -203,7 +267,9 @@ const orderTeamManifestSections = (manifest) => [
203
267
  ]),
204
268
  withDefinedEntries([
205
269
  ["members", manifest.members],
206
- ["structure", manifest.structure]
270
+ ["mode", manifest.mode],
271
+ ["lead", manifest.lead],
272
+ ["external", manifest.external]
207
273
  ])
208
274
  ];
209
275
  export const renderSpawnfile = (manifest) => renderSections(manifest.kind === "agent"
@@ -35,7 +35,5 @@ export const createTeamScaffoldManifest = () => ({
35
35
  system: "TEAM.md"
36
36
  },
37
37
  members: [],
38
- structure: {
39
- mode: "swarm"
40
- }
38
+ mode: "swarm"
41
39
  });