spawnfile 0.1.11 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/README.md +21 -3
  2. package/dist/auth/runtimeCredentials.js +18 -2
  3. package/dist/cli/devCommands.d.ts +3 -0
  4. package/dist/cli/devCommands.js +115 -0
  5. package/dist/cli/lifecycleCommands.js +103 -1
  6. package/dist/cli/modelCommands.js +3 -0
  7. package/dist/cli/resolveCommandInput.d.ts +19 -0
  8. package/dist/cli/resolveCommandInput.js +25 -0
  9. package/dist/cli/runCli.d.ts +10 -1
  10. package/dist/cli/runCli.js +41 -13
  11. package/dist/cli/runtimeCommands.js +1 -0
  12. package/dist/cli/statusCommand.d.ts +43 -0
  13. package/dist/cli/statusCommand.js +428 -0
  14. package/dist/cli/surfaceCommands.js +4 -0
  15. package/dist/compiler/agentSurfaces.js +2 -4
  16. package/dist/compiler/buildProject.d.ts +9 -1
  17. package/dist/compiler/buildProject.js +44 -5
  18. package/dist/compiler/compileProject.d.ts +2 -0
  19. package/dist/compiler/compileProject.js +22 -11
  20. package/dist/compiler/containerArtifacts.d.ts +1 -0
  21. package/dist/compiler/containerArtifacts.js +208 -32
  22. package/dist/compiler/containerArtifactsPlans.js +7 -4
  23. package/dist/compiler/containerArtifactsRender.d.ts +7 -1
  24. package/dist/compiler/containerArtifactsRender.js +31 -69
  25. package/dist/compiler/containerArtifactsTypes.d.ts +9 -0
  26. package/dist/compiler/containerEntrypointRender.js +22 -32
  27. package/dist/compiler/containerPackageRender.d.ts +15 -0
  28. package/dist/compiler/containerPackageRender.js +63 -0
  29. package/dist/compiler/containerTargetResources.js +3 -1
  30. package/dist/compiler/index.d.ts +1 -0
  31. package/dist/compiler/index.js +1 -0
  32. package/dist/compiler/moltnetArtifacts.js +21 -1
  33. package/dist/compiler/moltnetBinaries.d.ts +4 -1
  34. package/dist/compiler/moltnetBinaries.js +24 -3
  35. package/dist/compiler/moltnetClientConfig.d.ts +1 -1
  36. package/dist/compiler/moltnetClientConfig.js +14 -16
  37. package/dist/compiler/moltnetNodeConfig.js +2 -4
  38. package/dist/compiler/moltnetResolution.js +1 -1
  39. package/dist/compiler/moltnetRoomMemberships.js +1 -2
  40. package/dist/compiler/moltnetRuntimeConfig.d.ts +1 -1
  41. package/dist/compiler/moltnetRuntimeConfig.js +9 -10
  42. package/dist/compiler/networkBinding.d.ts +14 -0
  43. package/dist/compiler/networkBinding.js +34 -0
  44. package/dist/compiler/publishProject.d.ts +13 -0
  45. package/dist/compiler/publishProject.js +72 -0
  46. package/dist/compiler/runProject.d.ts +26 -12
  47. package/dist/compiler/runProject.js +109 -126
  48. package/dist/compiler/runProjectAuth.d.ts +5 -0
  49. package/dist/compiler/runProjectAuth.js +98 -0
  50. package/dist/compiler/runProjectDocker.d.ts +19 -0
  51. package/dist/compiler/runProjectDocker.js +202 -0
  52. package/dist/compiler/types.d.ts +1 -2
  53. package/dist/compiler/upProject.d.ts +6 -0
  54. package/dist/compiler/upProject.js +43 -8
  55. package/dist/compiler/view/buildOrganizationView.js +4 -1
  56. package/dist/compiler/view/declarations.d.ts +4 -0
  57. package/dist/compiler/view/declarations.js +104 -0
  58. package/dist/compiler/view/renderNetworks.js +1 -2
  59. package/dist/compiler/view/renderTree.js +6 -2
  60. package/dist/compiler/view/types.d.ts +64 -1
  61. package/dist/deployment/dockerInspect.d.ts +29 -0
  62. package/dist/deployment/dockerInspect.js +130 -0
  63. package/dist/deployment/dockerLabels.d.ts +16 -0
  64. package/dist/deployment/dockerLabels.js +32 -0
  65. package/dist/deployment/dockerLogs.d.ts +24 -0
  66. package/dist/deployment/dockerLogs.js +96 -0
  67. package/dist/deployment/dockerManager.d.ts +59 -0
  68. package/dist/deployment/dockerManager.js +76 -0
  69. package/dist/deployment/dockerProbeGateway.d.ts +16 -0
  70. package/dist/deployment/dockerProbeGateway.js +48 -0
  71. package/dist/deployment/dockerRecover.d.ts +17 -0
  72. package/dist/deployment/dockerRecover.js +129 -0
  73. package/dist/deployment/homeStore.d.ts +19 -0
  74. package/dist/deployment/homeStore.js +130 -0
  75. package/dist/deployment/index.d.ts +10 -0
  76. package/dist/deployment/index.js +10 -0
  77. package/dist/deployment/names.d.ts +3 -0
  78. package/dist/deployment/names.js +12 -0
  79. package/dist/deployment/record.d.ts +76 -0
  80. package/dist/deployment/record.js +174 -0
  81. package/dist/deployment/target.d.ts +35 -0
  82. package/dist/deployment/target.js +96 -0
  83. package/dist/dev/activity.d.ts +14 -0
  84. package/dist/dev/activity.js +48 -0
  85. package/dist/dev/docker.d.ts +16 -0
  86. package/dist/dev/docker.js +71 -0
  87. package/dist/dev/index.d.ts +2 -0
  88. package/dist/dev/index.js +2 -0
  89. package/dist/dev/project.d.ts +35 -0
  90. package/dist/dev/project.js +164 -0
  91. package/dist/distribution/buildDistributionReport.d.ts +22 -0
  92. package/dist/distribution/buildDistributionReport.js +51 -0
  93. package/dist/distribution/consumeImage.d.ts +29 -0
  94. package/dist/distribution/consumeImage.js +254 -0
  95. package/dist/distribution/consumeImageSupport.d.ts +18 -0
  96. package/dist/distribution/consumeImageSupport.js +63 -0
  97. package/dist/distribution/distributionReportSchema.d.ts +84 -0
  98. package/dist/distribution/distributionReportSchema.js +107 -0
  99. package/dist/distribution/dockerRunner.d.ts +5 -0
  100. package/dist/distribution/dockerRunner.js +21 -0
  101. package/dist/distribution/extractImage.d.ts +25 -0
  102. package/dist/distribution/extractImage.js +96 -0
  103. package/dist/distribution/fingerprint.d.ts +2 -0
  104. package/dist/distribution/fingerprint.js +14 -0
  105. package/dist/distribution/imageRef.d.ts +9 -0
  106. package/dist/distribution/imageRef.js +65 -0
  107. package/dist/distribution/imageRuntimeAuth.d.ts +19 -0
  108. package/dist/distribution/imageRuntimeAuth.js +71 -0
  109. package/dist/distribution/index.d.ts +24 -0
  110. package/dist/distribution/index.js +16 -0
  111. package/dist/distribution/preflight.d.ts +11 -0
  112. package/dist/distribution/preflight.js +65 -0
  113. package/dist/distribution/projectImageView.d.ts +8 -0
  114. package/dist/distribution/projectImageView.js +83 -0
  115. package/dist/distribution/projectName.d.ts +1 -0
  116. package/dist/distribution/projectName.js +12 -0
  117. package/dist/distribution/renderImageInterface.d.ts +30 -0
  118. package/dist/distribution/renderImageInterface.js +86 -0
  119. package/dist/distribution/tarReader.d.ts +10 -0
  120. package/dist/distribution/tarReader.js +69 -0
  121. package/dist/distribution/types.d.ts +80 -0
  122. package/dist/distribution/types.js +4 -0
  123. package/dist/distribution/verifyDistributionReport.d.ts +12 -0
  124. package/dist/distribution/verifyDistributionReport.js +29 -0
  125. package/dist/filesystem/paths.d.ts +6 -0
  126. package/dist/filesystem/paths.js +11 -0
  127. package/dist/manifest/loadManifest.js +22 -2
  128. package/dist/manifest/renderSpawnfile.js +2 -4
  129. package/dist/manifest/schemas.d.ts +17 -41
  130. package/dist/manifest/surfaceSchemas.d.ts +19 -47
  131. package/dist/manifest/surfaceSchemas.js +3 -6
  132. package/dist/report/createReport.d.ts +7 -1
  133. package/dist/report/createReport.js +28 -1
  134. package/dist/report/types.d.ts +43 -0
  135. package/dist/runtime/common.d.ts +2 -0
  136. package/dist/runtime/common.js +1 -1
  137. package/dist/runtime/container.d.ts +1 -0
  138. package/dist/runtime/container.js +82 -15
  139. package/dist/runtime/index.d.ts +1 -0
  140. package/dist/runtime/index.js +1 -0
  141. package/dist/runtime/install.d.ts +1 -11
  142. package/dist/runtime/install.js +27 -30
  143. package/dist/runtime/openclaw/adapter.js +9 -1
  144. package/dist/runtime/openclaw/configAuth.d.ts +15 -0
  145. package/dist/runtime/openclaw/configAuth.js +46 -0
  146. package/dist/runtime/openclaw/runAuth.d.ts +6 -0
  147. package/dist/runtime/openclaw/runAuth.js +7 -55
  148. package/dist/runtime/openclaw/statusProbes.d.ts +2 -0
  149. package/dist/runtime/openclaw/statusProbes.js +31 -0
  150. package/dist/runtime/pi/adapter.d.ts +4 -0
  151. package/dist/runtime/pi/adapter.js +198 -0
  152. package/dist/runtime/pi/appActivitySource.d.ts +1 -0
  153. package/dist/runtime/pi/appActivitySource.js +87 -0
  154. package/dist/runtime/pi/appCoreSource.d.ts +1 -0
  155. package/dist/runtime/pi/appCoreSource.js +354 -0
  156. package/dist/runtime/pi/appPreludeSource.d.ts +1 -0
  157. package/dist/runtime/pi/appPreludeSource.js +103 -0
  158. package/dist/runtime/pi/appSource.d.ts +1 -0
  159. package/dist/runtime/pi/appSource.js +8 -0
  160. package/dist/runtime/pi/appTemplate.d.ts +28 -0
  161. package/dist/runtime/pi/appTemplate.js +144 -0
  162. package/dist/runtime/pi/runAuth.d.ts +2 -0
  163. package/dist/runtime/pi/runAuth.js +68 -0
  164. package/dist/runtime/picoclaw/adapter.js +10 -0
  165. package/dist/runtime/picoclaw/runAuth.d.ts +7 -0
  166. package/dist/runtime/picoclaw/runAuth.js +8 -68
  167. package/dist/runtime/picoclaw/statusProbes.d.ts +2 -0
  168. package/dist/runtime/picoclaw/statusProbes.js +100 -0
  169. package/dist/runtime/registry.d.ts +0 -5
  170. package/dist/runtime/registry.js +5 -12
  171. package/dist/runtime/statusProbes.d.ts +16 -0
  172. package/dist/runtime/statusProbes.js +41 -0
  173. package/dist/runtime/types.d.ts +53 -1
  174. package/dist/shared/errors.d.ts +6 -0
  175. package/dist/shared/errors.js +9 -0
  176. package/dist/status/buildStatus.d.ts +13 -0
  177. package/dist/status/buildStatus.js +266 -0
  178. package/dist/status/compileReport.d.ts +96 -0
  179. package/dist/status/compileReport.js +230 -0
  180. package/dist/status/compiledContainerObservations.d.ts +5 -0
  181. package/dist/status/compiledContainerObservations.js +63 -0
  182. package/dist/status/deploymentLogs.d.ts +12 -0
  183. package/dist/status/deploymentLogs.js +45 -0
  184. package/dist/status/deployments.d.ts +14 -0
  185. package/dist/status/deployments.js +121 -0
  186. package/dist/status/imageStatusReport.d.ts +10 -0
  187. package/dist/status/imageStatusReport.js +73 -0
  188. package/dist/status/index.d.ts +14 -0
  189. package/dist/status/index.js +14 -0
  190. package/dist/status/moltnetProbes.d.ts +21 -0
  191. package/dist/status/moltnetProbes.js +240 -0
  192. package/dist/status/registryDrift.d.ts +28 -0
  193. package/dist/status/registryDrift.js +119 -0
  194. package/dist/status/renderStatus.d.ts +2 -0
  195. package/dist/status/renderStatus.js +230 -0
  196. package/dist/status/runtimeProbes.d.ts +13 -0
  197. package/dist/status/runtimeProbes.js +111 -0
  198. package/dist/status/selectionSubjects.d.ts +8 -0
  199. package/dist/status/selectionSubjects.js +77 -0
  200. package/dist/status/selectors.d.ts +14 -0
  201. package/dist/status/selectors.js +90 -0
  202. package/dist/status/traversal.d.ts +6 -0
  203. package/dist/status/traversal.js +15 -0
  204. package/dist/status/types.d.ts +113 -0
  205. package/dist/status/types.js +1 -0
  206. package/package.json +9 -2
  207. package/runtimes.yaml +44 -21
  208. package/dist/runtime/tinyclaw/adapter.d.ts +0 -2
  209. package/dist/runtime/tinyclaw/adapter.js +0 -284
  210. package/dist/runtime/tinyclaw/runAuth.d.ts +0 -2
  211. package/dist/runtime/tinyclaw/runAuth.js +0 -49
  212. package/dist/runtime/tinyclaw/scaffold-assets/AGENTS.md +0 -160
  213. package/dist/runtime/tinyclaw/scaffold-assets/CLAUDE.md +0 -5
  214. package/dist/runtime/tinyclaw/scaffold-assets/SOUL.md +0 -177
  215. package/dist/runtime/tinyclaw/scaffold.d.ts +0 -2
  216. package/dist/runtime/tinyclaw/scaffold.js +0 -24
  217. package/dist/runtime/tinyclaw/schedules.d.ts +0 -9
  218. package/dist/runtime/tinyclaw/schedules.js +0 -62
  219. package/dist/runtime/tinyclaw/surfaces.d.ts +0 -8
  220. package/dist/runtime/tinyclaw/surfaces.js +0 -94
@@ -0,0 +1,202 @@
1
+ import { execFile as execFileCallback, spawn } from "node:child_process";
2
+ import path from "node:path";
3
+ import { promisify } from "node:util";
4
+ import { SpawnfileError } from "../shared/index.js";
5
+ const execFile = promisify(execFileCallback);
6
+ const parseDockerContextHost = (stdout) => {
7
+ const trimmed = stdout.trim();
8
+ if (!trimmed) {
9
+ return null;
10
+ }
11
+ try {
12
+ const parsed = JSON.parse(trimmed);
13
+ return typeof parsed === "string" ? parsed : null;
14
+ }
15
+ catch {
16
+ return trimmed;
17
+ }
18
+ };
19
+ const resolveSshDockerContext = async (invocation) => {
20
+ if (!invocation.dockerContext) {
21
+ return null;
22
+ }
23
+ const { stdout } = await execFile(invocation.command, [
24
+ "context",
25
+ "inspect",
26
+ invocation.dockerContext,
27
+ "--format",
28
+ "{{json .Endpoints.docker.Host}}"
29
+ ], { cwd: invocation.cwd, timeout: 10_000 });
30
+ const host = parseDockerContextHost(stdout);
31
+ if (!host?.startsWith("ssh://")) {
32
+ return null;
33
+ }
34
+ const url = new URL(host);
35
+ const user = decodeURIComponent(url.username);
36
+ const targetHost = url.hostname;
37
+ return {
38
+ host,
39
+ ...(url.port ? { port: url.port } : {}),
40
+ target: user ? `${user}@${targetHost}` : targetHost
41
+ };
42
+ };
43
+ const sshArgs = (context, command) => [
44
+ ...(context.port ? ["-p", context.port] : []),
45
+ context.target,
46
+ command
47
+ ];
48
+ const scpArgs = (context, source, target) => [
49
+ ...(context.port ? ["-P", context.port] : []),
50
+ "-r",
51
+ source,
52
+ `${context.target}:${target}`
53
+ ];
54
+ const shellQuote = (value) => `'${value.replace(/'/g, `'\"'\"'`)}'`;
55
+ const createRemoteDirectory = async (context) => {
56
+ const { stdout } = await execFile("ssh", sshArgs(context, "mktemp -d /tmp/spawnfile-run-XXXXXX"), {
57
+ timeout: 10_000
58
+ });
59
+ return stdout.trim();
60
+ };
61
+ const copyPathToRemote = async (context, sourcePath, remotePath) => {
62
+ await execFile("scp", scpArgs(context, sourcePath, remotePath), { timeout: 120_000 });
63
+ };
64
+ const removeRemoteDirectory = async (context, remoteDirectory) => {
65
+ await execFile("ssh", sshArgs(context, `rm -rf ${shellQuote(remoteDirectory)}`), {
66
+ timeout: 10_000
67
+ });
68
+ };
69
+ const splitVolumeSpec = (spec) => {
70
+ const delimiter = spec.indexOf(":");
71
+ if (delimiter <= 0) {
72
+ return null;
73
+ }
74
+ return {
75
+ rest: spec.slice(delimiter),
76
+ source: spec.slice(0, delimiter)
77
+ };
78
+ };
79
+ const collectBindMountSources = (args) => {
80
+ const sources = new Set();
81
+ for (let index = 0; index < args.length; index += 1) {
82
+ if (args[index] !== "-v" && args[index] !== "--volume") {
83
+ continue;
84
+ }
85
+ const volume = args[index + 1];
86
+ if (!volume) {
87
+ continue;
88
+ }
89
+ const parsed = splitVolumeSpec(volume);
90
+ if (parsed && path.isAbsolute(parsed.source)) {
91
+ sources.add(parsed.source);
92
+ }
93
+ index += 1;
94
+ }
95
+ return [...sources].sort();
96
+ };
97
+ const rewriteBindMountSources = (args, replacements) => args.map((arg, index) => {
98
+ const previous = args[index - 1];
99
+ if (previous !== "-v" && previous !== "--volume") {
100
+ return arg;
101
+ }
102
+ const parsed = splitVolumeSpec(arg);
103
+ if (!parsed) {
104
+ return arg;
105
+ }
106
+ const replacement = replacements.get(parsed.source);
107
+ return replacement ? `${replacement}${parsed.rest}` : arg;
108
+ });
109
+ const prepareRemoteBindMounts = async (invocation) => {
110
+ const context = await resolveSshDockerContext(invocation);
111
+ if (!context) {
112
+ return { cleanup: async () => undefined, invocation };
113
+ }
114
+ const sources = collectBindMountSources(invocation.args);
115
+ if (sources.length === 0) {
116
+ return { cleanup: async () => undefined, invocation };
117
+ }
118
+ const remoteDirectory = await createRemoteDirectory(context);
119
+ const replacements = new Map();
120
+ for (const [index, source] of sources.entries()) {
121
+ const remotePath = `${remoteDirectory}/${index}-${path.basename(source) || "mount"}`;
122
+ await copyPathToRemote(context, source, remotePath);
123
+ replacements.set(source, remotePath);
124
+ }
125
+ return {
126
+ cleanup: invocation.detach
127
+ ? async () => undefined
128
+ : async () => removeRemoteDirectory(context, remoteDirectory),
129
+ invocation: {
130
+ ...invocation,
131
+ args: rewriteBindMountSources(invocation.args, replacements)
132
+ }
133
+ };
134
+ };
135
+ const inspectImageArgs = (invocation, containerId) => {
136
+ const base = invocation.dockerContext
137
+ ? ["--context", invocation.dockerContext, "inspect"]
138
+ : invocation.dockerHost
139
+ ? ["--host", invocation.dockerHost, "inspect"]
140
+ : ["inspect"];
141
+ return [...base, "--format", "{{.Image}}", containerId];
142
+ };
143
+ const inspectDetachedImageId = async (invocation, containerId) => {
144
+ try {
145
+ const { stdout } = await execFile(invocation.command, inspectImageArgs(invocation, containerId), {
146
+ cwd: invocation.cwd,
147
+ timeout: 10_000
148
+ });
149
+ return stdout.trim() || undefined;
150
+ }
151
+ catch (error) {
152
+ const message = error instanceof Error ? error.message : String(error);
153
+ throw new SpawnfileError("runtime_error", `Unable to inspect detached container ${containerId} image id: ${message}`);
154
+ }
155
+ };
156
+ const runPreparedDockerContainer = (prepared) => new Promise((resolve, reject) => {
157
+ let stdout = "";
158
+ const child = spawn(prepared.invocation.command, prepared.invocation.args, {
159
+ cwd: prepared.invocation.cwd,
160
+ stdio: prepared.invocation.detach ? ["ignore", "pipe", "inherit"] : "inherit"
161
+ });
162
+ const settle = (finish) => {
163
+ prepared.cleanup().then(finish, reject);
164
+ };
165
+ const rejectAfterCleanup = (error) => {
166
+ prepared.cleanup().then(() => reject(error), reject);
167
+ };
168
+ if (prepared.invocation.detach && child.stdout) {
169
+ child.stdout.setEncoding("utf8");
170
+ child.stdout.on("data", (chunk) => {
171
+ stdout += chunk;
172
+ });
173
+ }
174
+ child.once("error", (error) => {
175
+ rejectAfterCleanup(new SpawnfileError("runtime_error", `Unable to start docker run for ${prepared.invocation.imageTag}: ${error.message}`));
176
+ });
177
+ child.once("exit", (code, signal) => {
178
+ if (code === 0) {
179
+ const containerId = stdout.trim().split(/\s+/)[0];
180
+ if (!prepared.invocation.detach || !containerId) {
181
+ settle(() => resolve(undefined));
182
+ return;
183
+ }
184
+ inspectDetachedImageId(prepared.invocation, containerId)
185
+ .then((imageId) => resolve({ containerId, ...(imageId ? { imageId } : {}) }))
186
+ .catch(reject);
187
+ return;
188
+ }
189
+ rejectAfterCleanup(new SpawnfileError("runtime_error", signal
190
+ ? `Docker run for ${prepared.invocation.imageTag} exited from signal ${signal}`
191
+ : `Docker run for ${prepared.invocation.imageTag} failed with exit code ${code ?? "unknown"}`));
192
+ });
193
+ });
194
+ export const runDockerContainer = (invocation) => {
195
+ if (!invocation.dockerContext || collectBindMountSources(invocation.args).length === 0) {
196
+ return runPreparedDockerContainer({
197
+ cleanup: async () => undefined,
198
+ invocation
199
+ });
200
+ }
201
+ return prepareRemoteBindMounts(invocation).then(runPreparedDockerContainer);
202
+ };
@@ -82,8 +82,7 @@ export interface ResolvedHttpSurface {
82
82
  port?: number;
83
83
  }
84
84
  export interface ResolvedMoltnetRoomPolicy {
85
- read?: "all" | "mentions" | "thread_only";
86
- reply?: "auto" | "never";
85
+ wake?: "all" | "mentions" | "thread_only" | "never";
87
86
  }
88
87
  export interface ResolvedMoltnetDMConfig extends ResolvedMoltnetRoomPolicy {
89
88
  enabled: boolean;
@@ -1,3 +1,4 @@
1
+ import { type DockerTargetExecFile } from "../deployment/index.js";
1
2
  import { type BuildProjectResult, type DockerBuildRunner } from "./buildProject.js";
2
3
  import { type DockerRunRunner } from "./runProject.js";
3
4
  import { CompileProjectOptions } from "./compileProject.js";
@@ -6,14 +7,19 @@ export interface UpProjectOptions extends CompileProjectOptions {
6
7
  buildRunner?: DockerBuildRunner;
7
8
  containerName?: string;
8
9
  detach?: boolean;
10
+ deploymentName?: string;
9
11
  dockerCommand?: string;
12
+ dockerContext?: string;
13
+ dockerHost?: string;
10
14
  envFilePath?: string;
11
15
  imageTag?: string;
12
16
  runRunner?: DockerRunRunner;
17
+ targetExecFile?: DockerTargetExecFile;
13
18
  }
14
19
  export interface UpProjectResult extends BuildProjectResult {
15
20
  authProfileName: string | null;
16
21
  containerName: string | null;
22
+ deploymentRecordPath?: string | null;
17
23
  supportDirectory: string | null;
18
24
  }
19
25
  export declare const upProject: (inputPath: string, options?: UpProjectOptions) => Promise<UpProjectResult>;
@@ -1,37 +1,72 @@
1
+ import path from "node:path";
1
2
  import { removeDirectory } from "../filesystem/index.js";
3
+ import { writeDockerDeploymentRecordForRun } from "../deployment/index.js";
2
4
  import { buildProject } from "./buildProject.js";
3
- import { createDockerRunInvocation, runDockerContainer } from "./runProject.js";
5
+ import { createDockerRunInvocation, resolveDetachedDeploymentOptions, runDockerContainer } from "./runProject.js";
4
6
  import { requireAuthProfile } from "../auth/index.js";
7
+ import { DEFAULT_OUTPUT_DIRECTORY } from "../shared/index.js";
5
8
  export const upProject = async (inputPath, options = {}) => {
9
+ const resolvedOptions = await resolveDetachedDeploymentOptions(path.resolve(options.outputDirectory ?? DEFAULT_OUTPUT_DIRECTORY), {
10
+ authProfile: options.authProfile,
11
+ containerName: options.containerName,
12
+ deploymentName: options.deploymentName,
13
+ detach: options.detach,
14
+ dockerCommand: options.dockerCommand,
15
+ dockerContext: options.dockerContext,
16
+ dockerHost: options.dockerHost,
17
+ envFilePath: options.envFilePath,
18
+ imageTag: options.imageTag,
19
+ targetExecFile: options.targetExecFile
20
+ });
6
21
  const buildResult = await buildProject(inputPath, {
7
22
  buildRunner: options.buildRunner,
8
23
  clean: options.clean,
24
+ dockerContext: resolvedOptions.dockerContext,
9
25
  dockerCommand: options.dockerCommand,
10
- imageTag: options.imageTag,
26
+ imageTag: resolvedOptions.imageTag,
11
27
  outputDirectory: options.outputDirectory
12
28
  });
13
- const authProfile = options.authProfile
14
- ? await requireAuthProfile(options.authProfile)
29
+ const authProfile = resolvedOptions.authProfile
30
+ ? await requireAuthProfile(resolvedOptions.authProfile)
15
31
  : null;
16
- const invocation = await createDockerRunInvocation(buildResult, buildResult.imageTag, {
32
+ const imageTag = resolvedOptions.imageTag ?? buildResult.imageTag;
33
+ const invocation = await createDockerRunInvocation(buildResult, imageTag, {
17
34
  authProfile,
18
- containerName: options.containerName,
35
+ containerName: resolvedOptions.containerName,
19
36
  detach: options.detach,
37
+ deploymentName: resolvedOptions.deploymentName,
20
38
  dockerCommand: options.dockerCommand,
21
- envFilePath: options.envFilePath
39
+ dockerContext: resolvedOptions.dockerContext,
40
+ dockerHost: resolvedOptions.dockerHost,
41
+ envFilePath: resolvedOptions.envFilePath
22
42
  });
43
+ let runMetadata;
23
44
  try {
24
- await (options.runRunner ?? runDockerContainer)(invocation);
45
+ runMetadata = await (options.runRunner ?? runDockerContainer)(invocation);
25
46
  }
26
47
  finally {
27
48
  if (!invocation.detach) {
28
49
  await removeDirectory(invocation.supportDirectory);
29
50
  }
30
51
  }
52
+ const deploymentRecordPath = invocation.detach && invocation.deploymentName
53
+ ? await writeDockerDeploymentRecordForRun({
54
+ authProfileName: authProfile?.name ?? null,
55
+ envFilePath: resolvedOptions.envFilePath,
56
+ imageTag,
57
+ invocation,
58
+ outputDirectory: buildResult.outputDirectory,
59
+ report: buildResult.report,
60
+ runMetadata: runMetadata ?? undefined,
61
+ targetExecFile: options.targetExecFile
62
+ })
63
+ : null;
31
64
  return {
32
65
  ...buildResult,
33
66
  authProfileName: authProfile?.name ?? null,
34
67
  containerName: invocation.containerName,
68
+ deploymentRecordPath,
69
+ imageTag,
35
70
  supportDirectory: invocation.supportDirectory
36
71
  };
37
72
  };
@@ -2,6 +2,7 @@ import path from "node:path";
2
2
  import { SpawnfileError } from "../../shared/index.js";
3
3
  import { buildCompilePlan } from "../buildCompilePlan.js";
4
4
  import { resolveMoltnetRoomMemberships } from "../moltnetRoomMemberships.js";
5
+ import { buildDeclaredNodeView, buildRuntimeViews } from "./declarations.js";
5
6
  const createNameCounts = (plan) => {
6
7
  const counts = new Map();
7
8
  for (const node of plan.nodes) {
@@ -82,7 +83,9 @@ const buildTreeNode = (node, nodeById, edgesBySource, nameCounts, ancestors = []
82
83
  kind: node.kind,
83
84
  name: node.value.name,
84
85
  networks: buildTreeNetworkSummaries(node),
86
+ declared: buildDeclaredNodeView(node),
85
87
  runtimeName: node.runtimeName,
88
+ slug: node.slug,
86
89
  source: node.value.source
87
90
  };
88
91
  };
@@ -219,6 +222,6 @@ export const buildOrganizationView = async (inputPath) => {
219
222
  networks: buildNetworks(plan),
220
223
  projectRoot: path.dirname(plan.root),
221
224
  root,
222
- runtimes: []
225
+ runtimes: buildRuntimeViews(plan)
223
226
  };
224
227
  };
@@ -0,0 +1,4 @@
1
+ import type { CompilePlan, CompilePlanNode } from "../types.js";
2
+ import type { OrganizationRuntimeView, OrganizationViewDeclaredSummary } from "./types.js";
3
+ export declare const buildDeclaredNodeView: (node: CompilePlanNode) => OrganizationViewDeclaredSummary;
4
+ export declare const buildRuntimeViews: (plan: CompilePlan) => OrganizationRuntimeView[];
@@ -0,0 +1,104 @@
1
+ import { resolveEffectiveModelTarget } from "../modelEnv.js";
2
+ import { listInteractiveSurfaceScopes } from "../interactiveSurfaceScopes.js";
3
+ const summarizeModel = (node) => {
4
+ if (node.value.kind !== "agent" || !node.value.execution?.model?.primary) {
5
+ return null;
6
+ }
7
+ const target = resolveEffectiveModelTarget(node.value.execution.model.primary, node.value.execution);
8
+ return {
9
+ authMethod: target.auth.method,
10
+ name: target.name,
11
+ provider: target.provider
12
+ };
13
+ };
14
+ const summarizeSchedule = (node) => {
15
+ if (node.value.kind !== "agent" || !node.value.schedule) {
16
+ return null;
17
+ }
18
+ const schedule = node.value.schedule;
19
+ if (schedule.kind === "cron") {
20
+ return {
21
+ expression: schedule.cron,
22
+ kind: schedule.kind,
23
+ ...(schedule.timezone ? { timezone: schedule.timezone } : {})
24
+ };
25
+ }
26
+ if (schedule.kind === "every") {
27
+ return {
28
+ expression: schedule.every,
29
+ kind: schedule.kind,
30
+ ...(schedule.timezone ? { timezone: schedule.timezone } : {})
31
+ };
32
+ }
33
+ return { kind: schedule.kind };
34
+ };
35
+ const surfaceSummaryFor = (name, surfaces) => {
36
+ if (!surfaces[name]) {
37
+ return null;
38
+ }
39
+ const scopes = name === "moltnet"
40
+ ? listInteractiveSurfaceScopes(surfaces).filter((scope) => scope.startsWith("moltnet:"))
41
+ : listInteractiveSurfaceScopes(surfaces).filter((scope) => scope === name);
42
+ return {
43
+ name,
44
+ scopes: scopes.length > 0 ? scopes : [name]
45
+ };
46
+ };
47
+ const summarizeSurfaces = (node) => {
48
+ const surfaces = node.value.kind === "agent" ? node.value.surfaces : undefined;
49
+ if (!surfaces) {
50
+ return [];
51
+ }
52
+ return ["discord", "http", "moltnet", "slack", "telegram", "webhook", "whatsapp"]
53
+ .map((name) => surfaceSummaryFor(name, surfaces))
54
+ .filter((surface) => surface !== null);
55
+ };
56
+ const summarizePackages = (node) => {
57
+ const packages = node.value.kind === "agent"
58
+ ? node.value.packages ?? []
59
+ : node.value.shared.packages ?? [];
60
+ return packages.map((pkg) => ({
61
+ id: pkg.id,
62
+ manager: pkg.manager,
63
+ name: pkg.name,
64
+ ...(pkg.scope ? { scope: pkg.scope } : {}),
65
+ ...(pkg.version ? { version: pkg.version } : {})
66
+ }));
67
+ };
68
+ const summarizeResources = (node) => (node.value.workspaceResources ?? []).map((resource) => ({
69
+ id: resource.id,
70
+ kind: resource.kind,
71
+ mode: resource.mode,
72
+ mount: resource.mount,
73
+ sharing: resource.sharing
74
+ }));
75
+ export const buildDeclaredNodeView = (node) => {
76
+ const skills = node.value.kind === "agent" ? node.value.skills : node.value.shared.skills;
77
+ const mcpServers = node.value.kind === "agent"
78
+ ? node.value.mcpServers
79
+ : node.value.shared.mcpServers;
80
+ return {
81
+ docs: node.value.docs.map((doc) => ({ role: doc.role, source: doc.sourcePath })),
82
+ mcpServers: mcpServers.map((server) => ({
83
+ name: server.name,
84
+ transport: server.transport
85
+ })),
86
+ model: summarizeModel(node),
87
+ packages: summarizePackages(node),
88
+ policy: {
89
+ mode: node.value.policyMode,
90
+ onDegrade: node.value.policyOnDegrade
91
+ },
92
+ resources: summarizeResources(node),
93
+ schedule: summarizeSchedule(node),
94
+ skills: skills.map((skill) => ({
95
+ name: skill.name,
96
+ ref: skill.ref,
97
+ requiresMcp: [...skill.requiresMcp]
98
+ })),
99
+ surfaces: summarizeSurfaces(node)
100
+ };
101
+ };
102
+ export const buildRuntimeViews = (plan) => Object.entries(plan.runtimes)
103
+ .map(([name, runtime]) => ({ name, nodeIds: [...runtime.nodeIds].sort() }))
104
+ .sort((left, right) => left.name.localeCompare(right.name));
@@ -8,8 +8,7 @@ const formatPolicy = (member) => {
8
8
  return [];
9
9
  }
10
10
  return [
11
- member.policy.read ? `read=${member.policy.read}` : undefined,
12
- member.policy.reply ? `reply=${member.policy.reply}` : undefined
11
+ member.policy.wake ? `wake=${member.policy.wake}` : undefined
13
12
  ].filter((entry) => entry !== undefined);
14
13
  };
15
14
  const formatMember = (member, options, projectRoot) => {
@@ -1,5 +1,9 @@
1
1
  import { formatSourceMeta } from "./sourcePaths.js";
2
2
  const color = (value, code, options) => options.color ? `\u001b[${code}m${value}\u001b[0m` : value;
3
+ const formatAnnotations = (subjectKey, options) => {
4
+ const annotations = options.annotationFor?.(subjectKey) ?? [];
5
+ return annotations.length > 0 ? ` ${annotations.join(" ")}` : "";
6
+ };
3
7
  const formatNode = (node, options, projectRoot) => {
4
8
  const kind = color(node.kind, node.kind === "team" ? "36" : "32", options);
5
9
  const metadata = node.kind === "team"
@@ -17,7 +21,7 @@ const formatNode = (node, options, projectRoot) => {
17
21
  const details = metadata.filter((entry) => entry !== undefined);
18
22
  const source = options.paths ? formatSourceMeta("source", node.source, projectRoot) : "";
19
23
  const separator = details[0]?.startsWith("[") ? " " : " ";
20
- return `${kind} ${node.displayName}${details.length > 0 ? `${separator}${details.join(" ")}` : ""}${source}`;
24
+ return `${kind} ${node.displayName}${details.length > 0 ? `${separator}${details.join(" ")}` : ""}${source}${formatAnnotations(node.id, options)}`;
21
25
  };
22
26
  const formatEdgeLabel = (edge) => edge.relation === "subagent"
23
27
  ? `subagent ${edge.label}`
@@ -44,7 +48,7 @@ const formatNetworkSummary = (network, options) => {
44
48
  return `${room.id}${roomMetadata.length > 0 ? ` ${roomMetadata.join(" ")}` : ""} [${room.declaredMembers.join(", ")}]`;
45
49
  })
46
50
  .join("; ");
47
- return `network ${id} "${network.name}"${metadata.length > 0 ? ` ${metadata.join(" ")}` : ""}: ${rooms}`;
51
+ return `network ${id} "${network.name}"${metadata.length > 0 ? ` ${metadata.join(" ")}` : ""}: ${rooms}${formatAnnotations(`network:${network.id}`, options)}`;
48
52
  };
49
53
  const renderChildren = (node, options, projectRoot, prefix = "") => {
50
54
  const glyphs = options.ascii
@@ -1,6 +1,63 @@
1
1
  import type { ResolvedMoltnetRoomPolicy } from "../types.js";
2
+ export interface OrganizationViewDocSummary {
3
+ role: string;
4
+ source: string;
5
+ }
6
+ export interface OrganizationViewSkillSummary {
7
+ name: string;
8
+ ref: string;
9
+ requiresMcp: string[];
10
+ }
11
+ export interface OrganizationViewResourceSummary {
12
+ id: string;
13
+ kind: "git" | "volume";
14
+ mode: "mutable" | "readonly";
15
+ mount: string;
16
+ sharing: "per_agent" | "team";
17
+ }
18
+ export interface OrganizationViewPackageSummary {
19
+ id: string;
20
+ manager: string;
21
+ name: string;
22
+ scope?: string;
23
+ version?: string;
24
+ }
25
+ export interface OrganizationViewMcpSummary {
26
+ name: string;
27
+ transport: "sse" | "stdio" | "streamable_http";
28
+ }
29
+ export interface OrganizationViewModelSummary {
30
+ authMethod: string;
31
+ name: string;
32
+ provider: string;
33
+ }
34
+ export interface OrganizationViewScheduleSummary {
35
+ expression?: string;
36
+ kind: "cron" | "disabled" | "every";
37
+ timezone?: string;
38
+ }
39
+ export interface OrganizationViewSurfaceSummary {
40
+ name: string;
41
+ scopes: string[];
42
+ }
43
+ export interface OrganizationViewPolicySummary {
44
+ mode: string | null;
45
+ onDegrade: string | null;
46
+ }
47
+ export interface OrganizationViewDeclaredSummary {
48
+ docs: OrganizationViewDocSummary[];
49
+ mcpServers: OrganizationViewMcpSummary[];
50
+ model: OrganizationViewModelSummary | null;
51
+ packages: OrganizationViewPackageSummary[];
52
+ policy: OrganizationViewPolicySummary;
53
+ resources: OrganizationViewResourceSummary[];
54
+ schedule: OrganizationViewScheduleSummary | null;
55
+ skills: OrganizationViewSkillSummary[];
56
+ surfaces: OrganizationViewSurfaceSummary[];
57
+ }
2
58
  export interface OrganizationViewTreeNode {
3
59
  children: OrganizationViewTreeEdge[];
60
+ declared?: OrganizationViewDeclaredSummary;
4
61
  displayName: string;
5
62
  external?: string[];
6
63
  id: string;
@@ -10,6 +67,7 @@ export interface OrganizationViewTreeNode {
10
67
  name: string;
11
68
  networks?: OrganizationTreeNetworkSummary[];
12
69
  runtimeName: string | null;
70
+ slug?: string;
13
71
  source: string;
14
72
  }
15
73
  export interface OrganizationTreeNetworkRoomSummary {
@@ -94,6 +152,10 @@ export interface OrganizationNetworkView {
94
152
  url?: string;
95
153
  declarations?: OrganizationNetworkDeclarationView[];
96
154
  }
155
+ export interface OrganizationRuntimeView {
156
+ name: string;
157
+ nodeIds: string[];
158
+ }
97
159
  export interface OrganizationView {
98
160
  contexts: [];
99
161
  diagnostics: [];
@@ -101,9 +163,10 @@ export interface OrganizationView {
101
163
  networks: OrganizationNetworkView[];
102
164
  projectRoot?: string;
103
165
  root: OrganizationViewTreeNode;
104
- runtimes: [];
166
+ runtimes: OrganizationRuntimeView[];
105
167
  }
106
168
  export interface RenderOrganizationViewOptions {
169
+ annotationFor?: (subjectKey: string) => string[];
107
170
  ascii?: boolean;
108
171
  color?: boolean;
109
172
  declared?: boolean;
@@ -0,0 +1,29 @@
1
+ import type { DeploymentRecord } from "./record.js";
2
+ export type DockerInspectExecFile = (file: string, args: string[], options: {
3
+ timeout: number;
4
+ }) => Promise<{
5
+ stderr: string;
6
+ stdout: string;
7
+ }>;
8
+ export interface DockerUnitInspection {
9
+ containerId: string | null;
10
+ drift: string[];
11
+ exists: boolean | null;
12
+ exitCode: number | null;
13
+ finishedAt: string | null;
14
+ imageId: string | null;
15
+ message: string;
16
+ restartCount: number | null;
17
+ running: boolean | null;
18
+ severity: "error" | "ok" | "unknown" | "warn";
19
+ startedAt: string | null;
20
+ status: string | null;
21
+ unitId: string;
22
+ }
23
+ export type DockerInspectionResult = Map<string, DockerUnitInspection>;
24
+ export interface DockerInspectOptions {
25
+ dockerCommand?: string;
26
+ execFile?: DockerInspectExecFile;
27
+ timeoutMs?: number;
28
+ }
29
+ export declare const inspectDockerDeployment: (record: DeploymentRecord, options?: DockerInspectOptions) => Promise<DockerInspectionResult>;