spawnfile 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/README.md +13 -2
  2. package/dist/cli/lifecycleCommands.js +101 -1
  3. package/dist/cli/modelCommands.js +3 -0
  4. package/dist/cli/resolveCommandInput.d.ts +19 -0
  5. package/dist/cli/resolveCommandInput.js +25 -0
  6. package/dist/cli/runCli.d.ts +4 -1
  7. package/dist/cli/runCli.js +37 -13
  8. package/dist/cli/runtimeCommands.js +1 -0
  9. package/dist/cli/statusCommand.d.ts +42 -0
  10. package/dist/cli/statusCommand.js +394 -0
  11. package/dist/cli/surfaceCommands.js +4 -0
  12. package/dist/compiler/agentSurfaces.js +2 -4
  13. package/dist/compiler/buildCompilePlanTeams.js +3 -1
  14. package/dist/compiler/compileProject.js +19 -10
  15. package/dist/compiler/compileProjectSupport.d.ts +1 -0
  16. package/dist/compiler/compileProjectSupport.js +1 -1
  17. package/dist/compiler/containerArtifacts.d.ts +1 -0
  18. package/dist/compiler/containerArtifacts.js +208 -32
  19. package/dist/compiler/containerArtifactsPlans.js +7 -4
  20. package/dist/compiler/containerArtifactsRender.d.ts +7 -1
  21. package/dist/compiler/containerArtifactsRender.js +6 -0
  22. package/dist/compiler/containerArtifactsTypes.d.ts +9 -0
  23. package/dist/compiler/containerEntrypointRender.js +18 -31
  24. package/dist/compiler/index.d.ts +1 -0
  25. package/dist/compiler/index.js +1 -0
  26. package/dist/compiler/moltnetArtifacts.d.ts +2 -0
  27. package/dist/compiler/moltnetArtifacts.js +58 -99
  28. package/dist/compiler/moltnetClientConfig.d.ts +2 -2
  29. package/dist/compiler/moltnetClientConfig.js +16 -23
  30. package/dist/compiler/moltnetConfigLowering.d.ts +3 -0
  31. package/dist/compiler/moltnetConfigLowering.js +13 -2
  32. package/dist/compiler/moltnetNodeConfig.d.ts +27 -0
  33. package/dist/compiler/moltnetNodeConfig.js +68 -0
  34. package/dist/compiler/moltnetResolution.js +1 -1
  35. package/dist/compiler/moltnetRoomMemberships.js +1 -2
  36. package/dist/compiler/moltnetRoomPolicyCompatibility.d.ts +4 -0
  37. package/dist/compiler/moltnetRoomPolicyCompatibility.js +28 -0
  38. package/dist/compiler/moltnetRuntimeConfig.d.ts +1 -1
  39. package/dist/compiler/moltnetRuntimeConfig.js +1 -13
  40. package/dist/compiler/networkBinding.d.ts +14 -0
  41. package/dist/compiler/networkBinding.js +34 -0
  42. package/dist/compiler/publishProject.d.ts +13 -0
  43. package/dist/compiler/publishProject.js +72 -0
  44. package/dist/compiler/runProject.d.ts +26 -12
  45. package/dist/compiler/runProject.js +102 -125
  46. package/dist/compiler/runProjectAuth.d.ts +5 -0
  47. package/dist/compiler/runProjectAuth.js +98 -0
  48. package/dist/compiler/runProjectDocker.d.ts +19 -0
  49. package/dist/compiler/runProjectDocker.js +57 -0
  50. package/dist/compiler/types.d.ts +3 -2
  51. package/dist/compiler/upProject.d.ts +6 -0
  52. package/dist/compiler/upProject.js +42 -8
  53. package/dist/compiler/view/buildOrganizationView.js +27 -3
  54. package/dist/compiler/view/declarations.d.ts +4 -0
  55. package/dist/compiler/view/declarations.js +104 -0
  56. package/dist/compiler/view/renderNetworks.js +12 -3
  57. package/dist/compiler/view/renderTree.js +16 -3
  58. package/dist/compiler/view/types.d.ts +77 -1
  59. package/dist/deployment/dockerInspect.d.ts +29 -0
  60. package/dist/deployment/dockerInspect.js +130 -0
  61. package/dist/deployment/dockerLabels.d.ts +16 -0
  62. package/dist/deployment/dockerLabels.js +32 -0
  63. package/dist/deployment/dockerLogs.d.ts +24 -0
  64. package/dist/deployment/dockerLogs.js +96 -0
  65. package/dist/deployment/dockerManager.d.ts +59 -0
  66. package/dist/deployment/dockerManager.js +76 -0
  67. package/dist/deployment/dockerProbeGateway.d.ts +16 -0
  68. package/dist/deployment/dockerProbeGateway.js +48 -0
  69. package/dist/deployment/homeStore.d.ts +19 -0
  70. package/dist/deployment/homeStore.js +130 -0
  71. package/dist/deployment/index.d.ts +9 -0
  72. package/dist/deployment/index.js +9 -0
  73. package/dist/deployment/names.d.ts +3 -0
  74. package/dist/deployment/names.js +12 -0
  75. package/dist/deployment/record.d.ts +76 -0
  76. package/dist/deployment/record.js +174 -0
  77. package/dist/deployment/target.d.ts +35 -0
  78. package/dist/deployment/target.js +96 -0
  79. package/dist/distribution/buildDistributionReport.d.ts +22 -0
  80. package/dist/distribution/buildDistributionReport.js +51 -0
  81. package/dist/distribution/consumeImage.d.ts +29 -0
  82. package/dist/distribution/consumeImage.js +254 -0
  83. package/dist/distribution/consumeImageSupport.d.ts +18 -0
  84. package/dist/distribution/consumeImageSupport.js +63 -0
  85. package/dist/distribution/distributionReportSchema.d.ts +84 -0
  86. package/dist/distribution/distributionReportSchema.js +107 -0
  87. package/dist/distribution/dockerRunner.d.ts +5 -0
  88. package/dist/distribution/dockerRunner.js +21 -0
  89. package/dist/distribution/extractImage.d.ts +25 -0
  90. package/dist/distribution/extractImage.js +96 -0
  91. package/dist/distribution/fingerprint.d.ts +2 -0
  92. package/dist/distribution/fingerprint.js +14 -0
  93. package/dist/distribution/imageRef.d.ts +9 -0
  94. package/dist/distribution/imageRef.js +65 -0
  95. package/dist/distribution/imageRuntimeAuth.d.ts +19 -0
  96. package/dist/distribution/imageRuntimeAuth.js +71 -0
  97. package/dist/distribution/index.d.ts +24 -0
  98. package/dist/distribution/index.js +16 -0
  99. package/dist/distribution/preflight.d.ts +11 -0
  100. package/dist/distribution/preflight.js +65 -0
  101. package/dist/distribution/projectImageView.d.ts +8 -0
  102. package/dist/distribution/projectImageView.js +83 -0
  103. package/dist/distribution/projectName.d.ts +1 -0
  104. package/dist/distribution/projectName.js +12 -0
  105. package/dist/distribution/renderImageInterface.d.ts +30 -0
  106. package/dist/distribution/renderImageInterface.js +86 -0
  107. package/dist/distribution/tarReader.d.ts +10 -0
  108. package/dist/distribution/tarReader.js +69 -0
  109. package/dist/distribution/types.d.ts +80 -0
  110. package/dist/distribution/types.js +4 -0
  111. package/dist/distribution/verifyDistributionReport.d.ts +12 -0
  112. package/dist/distribution/verifyDistributionReport.js +29 -0
  113. package/dist/filesystem/paths.d.ts +6 -0
  114. package/dist/filesystem/paths.js +11 -0
  115. package/dist/manifest/loadManifest.js +22 -2
  116. package/dist/manifest/renderSpawnfile.js +2 -4
  117. package/dist/manifest/renderSpawnfileNetworks.js +5 -0
  118. package/dist/manifest/schemas.d.ts +71 -41
  119. package/dist/manifest/surfaceSchemas.d.ts +19 -47
  120. package/dist/manifest/surfaceSchemas.js +3 -6
  121. package/dist/manifest/teamNetworkAccessSchemas.d.ts +15 -0
  122. package/dist/manifest/teamNetworkAccessSchemas.js +8 -0
  123. package/dist/manifest/teamNetworkConsoleSchemas.d.ts +7 -0
  124. package/dist/manifest/teamNetworkConsoleSchemas.js +19 -0
  125. package/dist/manifest/teamNetworkSchemas.d.ts +60 -0
  126. package/dist/manifest/teamNetworkSchemas.js +20 -7
  127. package/dist/report/createReport.d.ts +7 -1
  128. package/dist/report/createReport.js +28 -1
  129. package/dist/report/types.d.ts +43 -0
  130. package/dist/runtime/container.js +0 -16
  131. package/dist/runtime/index.d.ts +1 -0
  132. package/dist/runtime/index.js +1 -0
  133. package/dist/runtime/install.d.ts +0 -10
  134. package/dist/runtime/install.js +0 -45
  135. package/dist/runtime/openclaw/adapter.js +9 -1
  136. package/dist/runtime/openclaw/configAuth.d.ts +15 -0
  137. package/dist/runtime/openclaw/configAuth.js +46 -0
  138. package/dist/runtime/openclaw/runAuth.d.ts +6 -0
  139. package/dist/runtime/openclaw/runAuth.js +7 -55
  140. package/dist/runtime/openclaw/statusProbes.d.ts +2 -0
  141. package/dist/runtime/openclaw/statusProbes.js +31 -0
  142. package/dist/runtime/picoclaw/adapter.js +10 -0
  143. package/dist/runtime/picoclaw/runAuth.d.ts +7 -0
  144. package/dist/runtime/picoclaw/runAuth.js +8 -68
  145. package/dist/runtime/picoclaw/statusProbes.d.ts +2 -0
  146. package/dist/runtime/picoclaw/statusProbes.js +100 -0
  147. package/dist/runtime/registry.d.ts +0 -5
  148. package/dist/runtime/registry.js +2 -12
  149. package/dist/runtime/statusProbes.d.ts +16 -0
  150. package/dist/runtime/statusProbes.js +41 -0
  151. package/dist/runtime/types.d.ts +52 -1
  152. package/dist/shared/errors.d.ts +6 -0
  153. package/dist/shared/errors.js +9 -0
  154. package/dist/status/buildStatus.d.ts +13 -0
  155. package/dist/status/buildStatus.js +266 -0
  156. package/dist/status/compileReport.d.ts +96 -0
  157. package/dist/status/compileReport.js +230 -0
  158. package/dist/status/compiledContainerObservations.d.ts +5 -0
  159. package/dist/status/compiledContainerObservations.js +63 -0
  160. package/dist/status/deploymentLogs.d.ts +12 -0
  161. package/dist/status/deploymentLogs.js +45 -0
  162. package/dist/status/deployments.d.ts +14 -0
  163. package/dist/status/deployments.js +128 -0
  164. package/dist/status/imageStatusReport.d.ts +10 -0
  165. package/dist/status/imageStatusReport.js +73 -0
  166. package/dist/status/index.d.ts +14 -0
  167. package/dist/status/index.js +14 -0
  168. package/dist/status/moltnetProbes.d.ts +21 -0
  169. package/dist/status/moltnetProbes.js +240 -0
  170. package/dist/status/registryDrift.d.ts +28 -0
  171. package/dist/status/registryDrift.js +119 -0
  172. package/dist/status/renderStatus.d.ts +2 -0
  173. package/dist/status/renderStatus.js +230 -0
  174. package/dist/status/runtimeProbes.d.ts +13 -0
  175. package/dist/status/runtimeProbes.js +111 -0
  176. package/dist/status/selectionSubjects.d.ts +8 -0
  177. package/dist/status/selectionSubjects.js +77 -0
  178. package/dist/status/selectors.d.ts +14 -0
  179. package/dist/status/selectors.js +90 -0
  180. package/dist/status/traversal.d.ts +6 -0
  181. package/dist/status/traversal.js +15 -0
  182. package/dist/status/types.d.ts +113 -0
  183. package/dist/status/types.js +1 -0
  184. package/package.json +4 -2
  185. package/runtimes.yaml +22 -15
  186. package/dist/runtime/tinyclaw/adapter.d.ts +0 -2
  187. package/dist/runtime/tinyclaw/adapter.js +0 -284
  188. package/dist/runtime/tinyclaw/runAuth.d.ts +0 -2
  189. package/dist/runtime/tinyclaw/runAuth.js +0 -49
  190. package/dist/runtime/tinyclaw/scaffold-assets/AGENTS.md +0 -160
  191. package/dist/runtime/tinyclaw/scaffold-assets/CLAUDE.md +0 -5
  192. package/dist/runtime/tinyclaw/scaffold-assets/SOUL.md +0 -177
  193. package/dist/runtime/tinyclaw/scaffold.d.ts +0 -2
  194. package/dist/runtime/tinyclaw/scaffold.js +0 -24
  195. package/dist/runtime/tinyclaw/schedules.d.ts +0 -9
  196. package/dist/runtime/tinyclaw/schedules.js +0 -62
  197. package/dist/runtime/tinyclaw/surfaces.d.ts +0 -8
  198. package/dist/runtime/tinyclaw/surfaces.js +0 -94
@@ -0,0 +1,69 @@
1
+ import { SpawnfileError } from "../shared/index.js";
2
+ const BLOCK_SIZE = 512;
3
+ const parseOctal = (buffer, offset, length) => {
4
+ const raw = buffer
5
+ .subarray(offset, offset + length)
6
+ .toString("ascii")
7
+ .replace(/\0.*$/, "")
8
+ .trim();
9
+ if (raw === "") {
10
+ return 0;
11
+ }
12
+ const parsed = Number.parseInt(raw, 8);
13
+ if (!Number.isFinite(parsed) || parsed < 0) {
14
+ throw new SpawnfileError("validation_error", "Malformed tar header: invalid numeric field");
15
+ }
16
+ return parsed;
17
+ };
18
+ const isZeroBlock = (block) => block.every((byte) => byte === 0);
19
+ /**
20
+ * Extracts exactly one regular file from a (single-file) tar stream such as the
21
+ * output of `docker cp <container>:<file> -`. Rejects symlinks, hardlinks,
22
+ * directories, path traversal, and oversized payloads, because the stream is
23
+ * untrusted input pulled from a registry.
24
+ */
25
+ export const extractSingleFileFromTar = (tar, options) => {
26
+ let offset = 0;
27
+ let result = null;
28
+ while (offset + BLOCK_SIZE <= tar.length) {
29
+ const header = tar.subarray(offset, offset + BLOCK_SIZE);
30
+ if (isZeroBlock(header)) {
31
+ break;
32
+ }
33
+ offset += BLOCK_SIZE;
34
+ const name = header.subarray(0, 100).toString("ascii").replace(/\0.*$/, "");
35
+ const size = parseOctal(header, 124, 12);
36
+ const typeFlag = String.fromCharCode(header[156] ?? 0);
37
+ if (typeFlag === "5") {
38
+ throw new SpawnfileError("validation_error", `Refusing tar directory entry: ${name}`);
39
+ }
40
+ if (typeFlag === "2" || typeFlag === "1") {
41
+ throw new SpawnfileError("validation_error", `Refusing tar link entry: ${name}`);
42
+ }
43
+ if (typeFlag !== "0" && typeFlag !== "\0") {
44
+ // Skip metadata entries (pax headers, global headers) without treating
45
+ // them as the payload.
46
+ offset += Math.ceil(size / BLOCK_SIZE) * BLOCK_SIZE;
47
+ continue;
48
+ }
49
+ if (name.includes("..")) {
50
+ throw new SpawnfileError("validation_error", `Refusing tar entry with traversal: ${name}`);
51
+ }
52
+ if (size > options.maxBytes) {
53
+ throw new SpawnfileError("validation_error", `Embedded report exceeds the ${options.maxBytes}-byte size cap`);
54
+ }
55
+ if (result) {
56
+ throw new SpawnfileError("validation_error", "Expected a single-file tar stream but found multiple file entries");
57
+ }
58
+ const contentEnd = offset + size;
59
+ if (contentEnd > tar.length) {
60
+ throw new SpawnfileError("validation_error", "Truncated tar stream");
61
+ }
62
+ result = Buffer.from(tar.subarray(offset, contentEnd));
63
+ offset += Math.ceil(size / BLOCK_SIZE) * BLOCK_SIZE;
64
+ }
65
+ if (!result) {
66
+ throw new SpawnfileError("validation_error", "No file entry found in tar stream");
67
+ }
68
+ return result;
69
+ };
@@ -0,0 +1,80 @@
1
+ import type { ModelAuthMethod } from "../shared/index.js";
2
+ export type DistributionSecretCategory = "model" | "project" | "runtime" | "surface";
3
+ export interface DistributionSecretEntry {
4
+ generated: boolean;
5
+ name: string;
6
+ required: boolean;
7
+ }
8
+ export interface DistributionAgentSummary {
9
+ id: string;
10
+ name: string;
11
+ runtime: string | null;
12
+ teams: string[];
13
+ }
14
+ export interface DistributionTeamSummary {
15
+ agents: string[];
16
+ id: string;
17
+ name: string;
18
+ }
19
+ export interface DistributionOrganizationSummary {
20
+ agents: DistributionAgentSummary[];
21
+ project: string;
22
+ teams: DistributionTeamSummary[];
23
+ }
24
+ export interface DistributionPersistentMount {
25
+ durability: "persistent";
26
+ id: string;
27
+ kind: "volume";
28
+ target: string;
29
+ }
30
+ export interface DistributionWorkspaceResource {
31
+ id: string;
32
+ kind: "git" | "volume";
33
+ link_path: string;
34
+ mode: "mutable" | "readonly";
35
+ mount: string;
36
+ sharing: "per_agent" | "team";
37
+ }
38
+ export interface DistributionRuntimeInstance {
39
+ config_path: string;
40
+ home_path: string | null;
41
+ id: string;
42
+ internal_port: number | null;
43
+ model_auth_methods: Record<string, ModelAuthMethod>;
44
+ model_secrets_required: string[];
45
+ node_ids: string[];
46
+ published_port: number | null;
47
+ runtime: string;
48
+ workspace_path: string;
49
+ }
50
+ export interface DistributionMoltnetNetwork {
51
+ binding: "env";
52
+ id: string;
53
+ server_mode: "external" | "managed";
54
+ }
55
+ export interface DistributionPortMapping {
56
+ internal_port: number;
57
+ published_port: number;
58
+ }
59
+ export interface DistributionReport {
60
+ compile_fingerprint: string;
61
+ generated_at: string;
62
+ internal_ports: number[];
63
+ model_auth_methods: Record<string, ModelAuthMethod>;
64
+ moltnet: {
65
+ networks: DistributionMoltnetNetwork[];
66
+ };
67
+ organization: DistributionOrganizationSummary;
68
+ persistent_mounts: DistributionPersistentMount[];
69
+ port_mappings: DistributionPortMapping[];
70
+ ports: number[];
71
+ resources: DistributionWorkspaceResource[];
72
+ runtime_instances: DistributionRuntimeInstance[];
73
+ secrets: Record<DistributionSecretCategory, DistributionSecretEntry[]>;
74
+ version: "spawnfile.distribution-report.v1";
75
+ }
76
+ export declare const DISTRIBUTION_REPORT_VERSION = "spawnfile.distribution-report.v1";
77
+ export declare const DISTRIBUTION_REPORT_IMAGE_PATH = "/spawnfile/spawnfile-report.json";
78
+ export declare const DISTRIBUTION_REPORT_OUTPUT_FILE = "distribution-report.json";
79
+ export declare const IMAGE_CONTRACT_VERSION = "spawnfile.image.v1";
80
+ export type DistributionImageLabels = Record<"com.spawnfile.compile_fingerprint" | "com.spawnfile.image_contract" | "com.spawnfile.project" | "com.spawnfile.report", string> & Record<string, string>;
@@ -0,0 +1,4 @@
1
+ export const DISTRIBUTION_REPORT_VERSION = "spawnfile.distribution-report.v1";
2
+ export const DISTRIBUTION_REPORT_IMAGE_PATH = "/spawnfile/spawnfile-report.json";
3
+ export const DISTRIBUTION_REPORT_OUTPUT_FILE = "distribution-report.json";
4
+ export const IMAGE_CONTRACT_VERSION = "spawnfile.image.v1";
@@ -0,0 +1,12 @@
1
+ import type { DistributionReport } from "./types.js";
2
+ export interface VerifyDistributionReportInput {
3
+ forbiddenPathFragments?: string[];
4
+ report: unknown;
5
+ }
6
+ /**
7
+ * Pre-push verification for a published image's distribution report. Confirms
8
+ * the report parses, is free of creator host-path fragments, and that every
9
+ * secret entry carries the required/generated markers. Throws on any violation
10
+ * so publishing refuses to ship a leaky or malformed image.
11
+ */
12
+ export declare const verifyDistributionReport: (input: VerifyDistributionReportInput) => DistributionReport;
@@ -0,0 +1,29 @@
1
+ import { parseDistributionReport } from "./distributionReportSchema.js";
2
+ import { SpawnfileError } from "../shared/index.js";
3
+ /**
4
+ * Pre-push verification for a published image's distribution report. Confirms
5
+ * the report parses, is free of creator host-path fragments, and that every
6
+ * secret entry carries the required/generated markers. Throws on any violation
7
+ * so publishing refuses to ship a leaky or malformed image.
8
+ */
9
+ export const verifyDistributionReport = (input) => {
10
+ const report = parseDistributionReport(input.report, "distribution report for publish");
11
+ const serialized = JSON.stringify(report);
12
+ for (const fragment of input.forbiddenPathFragments ?? []) {
13
+ const trimmed = fragment.trim();
14
+ if (trimmed.length > 0 && serialized.includes(trimmed)) {
15
+ throw new SpawnfileError("validation_error", `Distribution report leaks a creator path fragment and must not be published: ${trimmed}`);
16
+ }
17
+ }
18
+ if (serialized.includes("/Users/") || serialized.includes("\\Users\\")) {
19
+ throw new SpawnfileError("validation_error", "Distribution report contains an absolute home path and must not be published");
20
+ }
21
+ for (const category of ["model", "project", "runtime", "surface"]) {
22
+ for (const entry of report.secrets[category]) {
23
+ if (typeof entry.required !== "boolean" || typeof entry.generated !== "boolean") {
24
+ throw new SpawnfileError("validation_error", `Secret ${entry.name} is missing required/generated markers`);
25
+ }
26
+ }
27
+ }
28
+ return report;
29
+ };
@@ -2,5 +2,11 @@ export declare const assertPortableRelativePath: (inputPath: string) => void;
2
2
  export declare const getCanonicalManifestPath: (filePath: string) => string;
3
3
  export declare const getManifestPath: (inputPath: string) => string;
4
4
  export declare const getProjectRoot: (manifestPath: string) => string;
5
+ /**
6
+ * Resolves the output/record directory for a project argument. An explicit
7
+ * `--out` is honored as given; otherwise the default lives under the resolved
8
+ * project root, not the process working directory.
9
+ */
10
+ export declare const resolveProjectOutputDirectory: (inputPath: string, outOption: string | undefined, defaultOutputName: string) => string;
5
11
  export declare const resolveProjectPath: (manifestPath: string, relativePath: string) => string;
6
12
  export declare const toPosixPath: (value: string) => string;
@@ -13,6 +13,17 @@ export const getManifestPath = (inputPath) => path.basename(inputPath) === "Spaw
13
13
  ? path.resolve(inputPath)
14
14
  : path.resolve(inputPath, "Spawnfile");
15
15
  export const getProjectRoot = (manifestPath) => path.dirname(manifestPath);
16
+ /**
17
+ * Resolves the output/record directory for a project argument. An explicit
18
+ * `--out` is honored as given; otherwise the default lives under the resolved
19
+ * project root, not the process working directory.
20
+ */
21
+ export const resolveProjectOutputDirectory = (inputPath, outOption, defaultOutputName) => {
22
+ if (outOption) {
23
+ return path.resolve(outOption);
24
+ }
25
+ return path.join(getProjectRoot(getManifestPath(inputPath)), defaultOutputName);
26
+ };
16
27
  export const resolveProjectPath = (manifestPath, relativePath) => {
17
28
  assertPortableRelativePath(relativePath);
18
29
  const projectRoot = getProjectRoot(manifestPath);
@@ -115,8 +115,18 @@ const validateLocalTeamManifest = async (manifestPath, manifest) => {
115
115
  }
116
116
  };
117
117
  const parseManifest = (source) => {
118
+ let parsed;
118
119
  try {
119
- return manifestSchema.parse(parseYaml(source));
120
+ parsed = parseYaml(source);
121
+ }
122
+ catch (error) {
123
+ // A YAML syntax error is a malformed manifest, not a runtime failure — wrap
124
+ // it so it exits as a usage error instead of leaking the parser's wording.
125
+ const reason = error instanceof Error ? error.message : String(error);
126
+ throw new SpawnfileError("invalid_manifest", `Invalid Spawnfile manifest: ${reason}`);
127
+ }
128
+ try {
129
+ return manifestSchema.parse(parsed);
120
130
  }
121
131
  catch (error) {
122
132
  if (error instanceof z.ZodError) {
@@ -127,7 +137,17 @@ const parseManifest = (source) => {
127
137
  }
128
138
  };
129
139
  export const loadManifest = async (manifestPath) => {
130
- const source = await readUtf8File(manifestPath);
140
+ let source;
141
+ try {
142
+ source = await readUtf8File(manifestPath);
143
+ }
144
+ catch (error) {
145
+ if (error.code === "ENOENT") {
146
+ // A missing Spawnfile is a usage/input error, not a runtime failure.
147
+ throw new SpawnfileError("validation_error", `No Spawnfile found at ${manifestPath}. Pass a project directory or Spawnfile path, or run 'spawnfile init'.`);
148
+ }
149
+ throw error;
150
+ }
131
151
  const manifest = parseManifest(source);
132
152
  if (isAgentManifest(manifest)) {
133
153
  await validateLocalAgentManifest(manifestPath, manifest);
@@ -67,8 +67,7 @@ const orderMoltnetRoomBehavior = (behavior) => {
67
67
  return undefined;
68
68
  }
69
69
  return withDefinedEntries([
70
- ["read", behavior.read],
71
- ["reply", behavior.reply]
70
+ ["wake", behavior.wake]
72
71
  ]);
73
72
  };
74
73
  const orderMoltnetDm = (dms) => {
@@ -77,8 +76,7 @@ const orderMoltnetDm = (dms) => {
77
76
  }
78
77
  return withDefinedEntries([
79
78
  ["enabled", dms.enabled],
80
- ["read", dms.read],
81
- ["reply", dms.reply]
79
+ ["wake", dms.wake]
82
80
  ]);
83
81
  };
84
82
  const orderMoltnetAttachment = (attachment) => withDefinedEntries([
@@ -35,6 +35,8 @@ const orderTeamAuth = (server) => withDefinedEntries([
35
35
  "auth",
36
36
  withDefinedEntries([
37
37
  ["mode", server.auth.mode],
38
+ ["public_read", server.auth.public_read],
39
+ ["agent_registration", server.auth.agent_registration],
38
40
  ["tokens", server.auth.tokens?.map(orderTeamAuthToken)],
39
41
  [
40
42
  "client",
@@ -49,6 +51,7 @@ const orderTeamAuth = (server) => withDefinedEntries([
49
51
  ]
50
52
  ])
51
53
  ],
54
+ ["console", server.mode === "managed" ? server.console : undefined],
52
55
  ["store", orderTeamStore(server)],
53
56
  [
54
57
  "pairings",
@@ -75,6 +78,8 @@ export const orderTeamNetworks = (networks) => networks?.map((network) => withDe
75
78
  network.rooms.map((room) => withDefinedEntries([
76
79
  ["id", room.id],
77
80
  ["name", room.name],
81
+ ["visibility", room.visibility],
82
+ ["write_policy", room.write_policy],
78
83
  ["members", room.members]
79
84
  ]))
80
85
  ]
@@ -258,27 +258,21 @@ declare const agentManifestSchema: z.ZodObject<{
258
258
  moltnet: z.ZodOptional<z.ZodArray<z.ZodObject<{
259
259
  dms: z.ZodOptional<z.ZodObject<{
260
260
  enabled: z.ZodBoolean;
261
- read: z.ZodOptional<z.ZodEnum<{
261
+ wake: z.ZodOptional<z.ZodEnum<{
262
+ never: "never";
262
263
  all: "all";
263
264
  mentions: "mentions";
264
265
  thread_only: "thread_only";
265
266
  }>>;
266
- reply: z.ZodOptional<z.ZodEnum<{
267
- never: "never";
268
- auto: "auto";
269
- }>>;
270
267
  }, z.core.$strict>>;
271
268
  network: z.ZodString;
272
269
  rooms: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
273
- read: z.ZodOptional<z.ZodEnum<{
270
+ wake: z.ZodOptional<z.ZodEnum<{
271
+ never: "never";
274
272
  all: "all";
275
273
  mentions: "mentions";
276
274
  thread_only: "thread_only";
277
275
  }>>;
278
- reply: z.ZodOptional<z.ZodEnum<{
279
- never: "never";
280
- auto: "auto";
281
- }>>;
282
276
  }, z.core.$strict>>>;
283
277
  }, z.core.$strict>>>;
284
278
  slack: z.ZodOptional<z.ZodObject<{
@@ -536,27 +530,21 @@ declare const teamManifestSchema: z.ZodObject<{
536
530
  moltnet: z.ZodOptional<z.ZodArray<z.ZodObject<{
537
531
  dms: z.ZodOptional<z.ZodObject<{
538
532
  enabled: z.ZodBoolean;
539
- read: z.ZodOptional<z.ZodEnum<{
533
+ wake: z.ZodOptional<z.ZodEnum<{
534
+ never: "never";
540
535
  all: "all";
541
536
  mentions: "mentions";
542
537
  thread_only: "thread_only";
543
538
  }>>;
544
- reply: z.ZodOptional<z.ZodEnum<{
545
- never: "never";
546
- auto: "auto";
547
- }>>;
548
539
  }, z.core.$strict>>;
549
540
  network: z.ZodString;
550
541
  rooms: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
551
- read: z.ZodOptional<z.ZodEnum<{
542
+ wake: z.ZodOptional<z.ZodEnum<{
543
+ never: "never";
552
544
  all: "all";
553
545
  mentions: "mentions";
554
546
  thread_only: "thread_only";
555
547
  }>>;
556
- reply: z.ZodOptional<z.ZodEnum<{
557
- never: "never";
558
- auto: "auto";
559
- }>>;
560
548
  }, z.core.$strict>>>;
561
549
  }, z.core.$strict>>>;
562
550
  slack: z.ZodOptional<z.ZodObject<{
@@ -630,10 +618,24 @@ declare const teamManifestSchema: z.ZodObject<{
630
618
  id: z.ZodString;
631
619
  members: z.ZodArray<z.ZodString>;
632
620
  name: z.ZodOptional<z.ZodString>;
621
+ visibility: z.ZodOptional<z.ZodEnum<{
622
+ public: "public";
623
+ private: "private";
624
+ }>>;
625
+ write_policy: z.ZodOptional<z.ZodEnum<{
626
+ members: "members";
627
+ registered_agents: "registered_agents";
628
+ operators: "operators";
629
+ }>>;
633
630
  }, z.core.$strict>>;
634
631
  server: z.ZodDiscriminatedUnion<[z.ZodObject<{
635
632
  allowed_origins: z.ZodOptional<z.ZodArray<z.ZodString>>;
636
633
  auth: z.ZodObject<{
634
+ agent_registration: z.ZodOptional<z.ZodEnum<{
635
+ token: "token";
636
+ disabled: "disabled";
637
+ open: "open";
638
+ }>>;
637
639
  client: z.ZodOptional<z.ZodObject<{
638
640
  static_token: z.ZodOptional<z.ZodBoolean>;
639
641
  token_env: z.ZodOptional<z.ZodString>;
@@ -645,6 +647,7 @@ declare const teamManifestSchema: z.ZodObject<{
645
647
  open: "open";
646
648
  bearer: "bearer";
647
649
  }>;
650
+ public_read: z.ZodOptional<z.ZodBoolean>;
648
651
  tokens: z.ZodOptional<z.ZodArray<z.ZodObject<{
649
652
  agents: z.ZodOptional<z.ZodArray<z.ZodString>>;
650
653
  id: z.ZodString;
@@ -658,6 +661,12 @@ declare const teamManifestSchema: z.ZodObject<{
658
661
  }>>;
659
662
  }, z.core.$strict>>>;
660
663
  }, z.core.$strict>;
664
+ console: z.ZodOptional<z.ZodObject<{
665
+ analytics: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
666
+ provider: z.ZodLiteral<"google">;
667
+ measurement_id: z.ZodString;
668
+ }, z.core.$strict>], "provider">>;
669
+ }, z.core.$strict>>;
661
670
  debug_events: z.ZodOptional<z.ZodBoolean>;
662
671
  direct_messages: z.ZodOptional<z.ZodBoolean>;
663
672
  human_ingress: z.ZodOptional<z.ZodBoolean>;
@@ -705,6 +714,11 @@ declare const teamManifestSchema: z.ZodObject<{
705
714
  url: z.ZodOptional<z.ZodString>;
706
715
  }, z.core.$strict>, z.ZodObject<{
707
716
  auth: z.ZodObject<{
717
+ agent_registration: z.ZodOptional<z.ZodEnum<{
718
+ token: "token";
719
+ disabled: "disabled";
720
+ open: "open";
721
+ }>>;
708
722
  client: z.ZodOptional<z.ZodObject<{
709
723
  static_token: z.ZodOptional<z.ZodBoolean>;
710
724
  token_env: z.ZodOptional<z.ZodString>;
@@ -716,6 +730,7 @@ declare const teamManifestSchema: z.ZodObject<{
716
730
  open: "open";
717
731
  bearer: "bearer";
718
732
  }>;
733
+ public_read: z.ZodOptional<z.ZodBoolean>;
719
734
  tokens: z.ZodOptional<z.ZodArray<z.ZodObject<{
720
735
  agents: z.ZodOptional<z.ZodArray<z.ZodString>>;
721
736
  id: z.ZodString;
@@ -915,27 +930,21 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
915
930
  moltnet: z.ZodOptional<z.ZodArray<z.ZodObject<{
916
931
  dms: z.ZodOptional<z.ZodObject<{
917
932
  enabled: z.ZodBoolean;
918
- read: z.ZodOptional<z.ZodEnum<{
933
+ wake: z.ZodOptional<z.ZodEnum<{
934
+ never: "never";
919
935
  all: "all";
920
936
  mentions: "mentions";
921
937
  thread_only: "thread_only";
922
938
  }>>;
923
- reply: z.ZodOptional<z.ZodEnum<{
924
- never: "never";
925
- auto: "auto";
926
- }>>;
927
939
  }, z.core.$strict>>;
928
940
  network: z.ZodString;
929
941
  rooms: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
930
- read: z.ZodOptional<z.ZodEnum<{
942
+ wake: z.ZodOptional<z.ZodEnum<{
943
+ never: "never";
931
944
  all: "all";
932
945
  mentions: "mentions";
933
946
  thread_only: "thread_only";
934
947
  }>>;
935
- reply: z.ZodOptional<z.ZodEnum<{
936
- never: "never";
937
- auto: "auto";
938
- }>>;
939
948
  }, z.core.$strict>>>;
940
949
  }, z.core.$strict>>>;
941
950
  slack: z.ZodOptional<z.ZodObject<{
@@ -1192,27 +1201,21 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1192
1201
  moltnet: z.ZodOptional<z.ZodArray<z.ZodObject<{
1193
1202
  dms: z.ZodOptional<z.ZodObject<{
1194
1203
  enabled: z.ZodBoolean;
1195
- read: z.ZodOptional<z.ZodEnum<{
1204
+ wake: z.ZodOptional<z.ZodEnum<{
1205
+ never: "never";
1196
1206
  all: "all";
1197
1207
  mentions: "mentions";
1198
1208
  thread_only: "thread_only";
1199
1209
  }>>;
1200
- reply: z.ZodOptional<z.ZodEnum<{
1201
- never: "never";
1202
- auto: "auto";
1203
- }>>;
1204
1210
  }, z.core.$strict>>;
1205
1211
  network: z.ZodString;
1206
1212
  rooms: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
1207
- read: z.ZodOptional<z.ZodEnum<{
1213
+ wake: z.ZodOptional<z.ZodEnum<{
1214
+ never: "never";
1208
1215
  all: "all";
1209
1216
  mentions: "mentions";
1210
1217
  thread_only: "thread_only";
1211
1218
  }>>;
1212
- reply: z.ZodOptional<z.ZodEnum<{
1213
- never: "never";
1214
- auto: "auto";
1215
- }>>;
1216
1219
  }, z.core.$strict>>>;
1217
1220
  }, z.core.$strict>>>;
1218
1221
  slack: z.ZodOptional<z.ZodObject<{
@@ -1286,10 +1289,24 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1286
1289
  id: z.ZodString;
1287
1290
  members: z.ZodArray<z.ZodString>;
1288
1291
  name: z.ZodOptional<z.ZodString>;
1292
+ visibility: z.ZodOptional<z.ZodEnum<{
1293
+ public: "public";
1294
+ private: "private";
1295
+ }>>;
1296
+ write_policy: z.ZodOptional<z.ZodEnum<{
1297
+ members: "members";
1298
+ registered_agents: "registered_agents";
1299
+ operators: "operators";
1300
+ }>>;
1289
1301
  }, z.core.$strict>>;
1290
1302
  server: z.ZodDiscriminatedUnion<[z.ZodObject<{
1291
1303
  allowed_origins: z.ZodOptional<z.ZodArray<z.ZodString>>;
1292
1304
  auth: z.ZodObject<{
1305
+ agent_registration: z.ZodOptional<z.ZodEnum<{
1306
+ token: "token";
1307
+ disabled: "disabled";
1308
+ open: "open";
1309
+ }>>;
1293
1310
  client: z.ZodOptional<z.ZodObject<{
1294
1311
  static_token: z.ZodOptional<z.ZodBoolean>;
1295
1312
  token_env: z.ZodOptional<z.ZodString>;
@@ -1301,6 +1318,7 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1301
1318
  open: "open";
1302
1319
  bearer: "bearer";
1303
1320
  }>;
1321
+ public_read: z.ZodOptional<z.ZodBoolean>;
1304
1322
  tokens: z.ZodOptional<z.ZodArray<z.ZodObject<{
1305
1323
  agents: z.ZodOptional<z.ZodArray<z.ZodString>>;
1306
1324
  id: z.ZodString;
@@ -1314,6 +1332,12 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1314
1332
  }>>;
1315
1333
  }, z.core.$strict>>>;
1316
1334
  }, z.core.$strict>;
1335
+ console: z.ZodOptional<z.ZodObject<{
1336
+ analytics: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
1337
+ provider: z.ZodLiteral<"google">;
1338
+ measurement_id: z.ZodString;
1339
+ }, z.core.$strict>], "provider">>;
1340
+ }, z.core.$strict>>;
1317
1341
  debug_events: z.ZodOptional<z.ZodBoolean>;
1318
1342
  direct_messages: z.ZodOptional<z.ZodBoolean>;
1319
1343
  human_ingress: z.ZodOptional<z.ZodBoolean>;
@@ -1361,6 +1385,11 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1361
1385
  url: z.ZodOptional<z.ZodString>;
1362
1386
  }, z.core.$strict>, z.ZodObject<{
1363
1387
  auth: z.ZodObject<{
1388
+ agent_registration: z.ZodOptional<z.ZodEnum<{
1389
+ token: "token";
1390
+ disabled: "disabled";
1391
+ open: "open";
1392
+ }>>;
1364
1393
  client: z.ZodOptional<z.ZodObject<{
1365
1394
  static_token: z.ZodOptional<z.ZodBoolean>;
1366
1395
  token_env: z.ZodOptional<z.ZodString>;
@@ -1372,6 +1401,7 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1372
1401
  open: "open";
1373
1402
  bearer: "bearer";
1374
1403
  }>;
1404
+ public_read: z.ZodOptional<z.ZodBoolean>;
1375
1405
  tokens: z.ZodOptional<z.ZodArray<z.ZodObject<{
1376
1406
  agents: z.ZodOptional<z.ZodArray<z.ZodString>>;
1377
1407
  id: z.ZodString;
@@ -1486,6 +1516,6 @@ export type SkillReference = z.infer<typeof skillReferenceSchema>;
1486
1516
  export type TeamManifest = z.infer<typeof teamManifestSchema>;
1487
1517
  export type { ExecutionBlock, ModelEndpoint, ModelEntryAuth, ModelTarget } from "./executionSchemas.js";
1488
1518
  export type { TeamNetwork, TeamNetworkRoom, TeamNetworkServer, TeamWorkspace, TeamWorkspaceResource } from "./teamNetworkSchemas.js";
1489
- export type { DiscordSurface, DiscordSurfaceAccess, HttpSurface, HttpSurfaceAccess, HttpSurfaceAuth, MoltnetAttachment, MoltnetDM, MoltnetRead, MoltnetReply, MoltnetRoomBehavior, MoltnetSurface, SlackSurface, SlackSurfaceAccess, SurfacesBlock, TelegramSurface, TelegramSurfaceAccess, WebhookSurface, WhatsAppSurface, WhatsAppSurfaceAccess } from "./surfaceSchemas.js";
1519
+ export type { DiscordSurface, DiscordSurfaceAccess, HttpSurface, HttpSurfaceAccess, HttpSurfaceAuth, MoltnetAttachment, MoltnetDM, MoltnetRoomBehavior, MoltnetSurface, MoltnetWake, SlackSurface, SlackSurfaceAccess, SurfacesBlock, TelegramSurface, TelegramSurfaceAccess, WebhookSurface, WhatsAppSurface, WhatsAppSurfaceAccess } from "./surfaceSchemas.js";
1490
1520
  export declare const isAgentManifest: (manifest: Manifest) => manifest is AgentManifest;
1491
1521
  export declare const isTeamManifest: (manifest: Manifest) => manifest is TeamManifest;