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.
- package/README.md +13 -2
- package/dist/cli/lifecycleCommands.js +101 -1
- package/dist/cli/modelCommands.js +3 -0
- package/dist/cli/resolveCommandInput.d.ts +19 -0
- package/dist/cli/resolveCommandInput.js +25 -0
- package/dist/cli/runCli.d.ts +4 -1
- package/dist/cli/runCli.js +37 -13
- package/dist/cli/runtimeCommands.js +1 -0
- package/dist/cli/statusCommand.d.ts +42 -0
- package/dist/cli/statusCommand.js +394 -0
- package/dist/cli/surfaceCommands.js +4 -0
- package/dist/compiler/agentSurfaces.js +2 -4
- package/dist/compiler/buildCompilePlanTeams.js +3 -1
- package/dist/compiler/compileProject.js +19 -10
- package/dist/compiler/compileProjectSupport.d.ts +1 -0
- package/dist/compiler/compileProjectSupport.js +1 -1
- package/dist/compiler/containerArtifacts.d.ts +1 -0
- package/dist/compiler/containerArtifacts.js +208 -32
- package/dist/compiler/containerArtifactsPlans.js +7 -4
- package/dist/compiler/containerArtifactsRender.d.ts +7 -1
- package/dist/compiler/containerArtifactsRender.js +6 -0
- package/dist/compiler/containerArtifactsTypes.d.ts +9 -0
- package/dist/compiler/containerEntrypointRender.js +18 -31
- package/dist/compiler/index.d.ts +1 -0
- package/dist/compiler/index.js +1 -0
- package/dist/compiler/moltnetArtifacts.d.ts +2 -0
- package/dist/compiler/moltnetArtifacts.js +58 -99
- package/dist/compiler/moltnetClientConfig.d.ts +2 -2
- package/dist/compiler/moltnetClientConfig.js +16 -23
- package/dist/compiler/moltnetConfigLowering.d.ts +3 -0
- package/dist/compiler/moltnetConfigLowering.js +13 -2
- package/dist/compiler/moltnetNodeConfig.d.ts +27 -0
- package/dist/compiler/moltnetNodeConfig.js +68 -0
- package/dist/compiler/moltnetResolution.js +1 -1
- package/dist/compiler/moltnetRoomMemberships.js +1 -2
- package/dist/compiler/moltnetRoomPolicyCompatibility.d.ts +4 -0
- package/dist/compiler/moltnetRoomPolicyCompatibility.js +28 -0
- package/dist/compiler/moltnetRuntimeConfig.d.ts +1 -1
- package/dist/compiler/moltnetRuntimeConfig.js +1 -13
- package/dist/compiler/networkBinding.d.ts +14 -0
- package/dist/compiler/networkBinding.js +34 -0
- package/dist/compiler/publishProject.d.ts +13 -0
- package/dist/compiler/publishProject.js +72 -0
- package/dist/compiler/runProject.d.ts +26 -12
- package/dist/compiler/runProject.js +102 -125
- package/dist/compiler/runProjectAuth.d.ts +5 -0
- package/dist/compiler/runProjectAuth.js +98 -0
- package/dist/compiler/runProjectDocker.d.ts +19 -0
- package/dist/compiler/runProjectDocker.js +57 -0
- package/dist/compiler/types.d.ts +3 -2
- package/dist/compiler/upProject.d.ts +6 -0
- package/dist/compiler/upProject.js +42 -8
- package/dist/compiler/view/buildOrganizationView.js +27 -3
- package/dist/compiler/view/declarations.d.ts +4 -0
- package/dist/compiler/view/declarations.js +104 -0
- package/dist/compiler/view/renderNetworks.js +12 -3
- package/dist/compiler/view/renderTree.js +16 -3
- package/dist/compiler/view/types.d.ts +77 -1
- package/dist/deployment/dockerInspect.d.ts +29 -0
- package/dist/deployment/dockerInspect.js +130 -0
- package/dist/deployment/dockerLabels.d.ts +16 -0
- package/dist/deployment/dockerLabels.js +32 -0
- package/dist/deployment/dockerLogs.d.ts +24 -0
- package/dist/deployment/dockerLogs.js +96 -0
- package/dist/deployment/dockerManager.d.ts +59 -0
- package/dist/deployment/dockerManager.js +76 -0
- package/dist/deployment/dockerProbeGateway.d.ts +16 -0
- package/dist/deployment/dockerProbeGateway.js +48 -0
- package/dist/deployment/homeStore.d.ts +19 -0
- package/dist/deployment/homeStore.js +130 -0
- package/dist/deployment/index.d.ts +9 -0
- package/dist/deployment/index.js +9 -0
- package/dist/deployment/names.d.ts +3 -0
- package/dist/deployment/names.js +12 -0
- package/dist/deployment/record.d.ts +76 -0
- package/dist/deployment/record.js +174 -0
- package/dist/deployment/target.d.ts +35 -0
- package/dist/deployment/target.js +96 -0
- package/dist/distribution/buildDistributionReport.d.ts +22 -0
- package/dist/distribution/buildDistributionReport.js +51 -0
- package/dist/distribution/consumeImage.d.ts +29 -0
- package/dist/distribution/consumeImage.js +254 -0
- package/dist/distribution/consumeImageSupport.d.ts +18 -0
- package/dist/distribution/consumeImageSupport.js +63 -0
- package/dist/distribution/distributionReportSchema.d.ts +84 -0
- package/dist/distribution/distributionReportSchema.js +107 -0
- package/dist/distribution/dockerRunner.d.ts +5 -0
- package/dist/distribution/dockerRunner.js +21 -0
- package/dist/distribution/extractImage.d.ts +25 -0
- package/dist/distribution/extractImage.js +96 -0
- package/dist/distribution/fingerprint.d.ts +2 -0
- package/dist/distribution/fingerprint.js +14 -0
- package/dist/distribution/imageRef.d.ts +9 -0
- package/dist/distribution/imageRef.js +65 -0
- package/dist/distribution/imageRuntimeAuth.d.ts +19 -0
- package/dist/distribution/imageRuntimeAuth.js +71 -0
- package/dist/distribution/index.d.ts +24 -0
- package/dist/distribution/index.js +16 -0
- package/dist/distribution/preflight.d.ts +11 -0
- package/dist/distribution/preflight.js +65 -0
- package/dist/distribution/projectImageView.d.ts +8 -0
- package/dist/distribution/projectImageView.js +83 -0
- package/dist/distribution/projectName.d.ts +1 -0
- package/dist/distribution/projectName.js +12 -0
- package/dist/distribution/renderImageInterface.d.ts +30 -0
- package/dist/distribution/renderImageInterface.js +86 -0
- package/dist/distribution/tarReader.d.ts +10 -0
- package/dist/distribution/tarReader.js +69 -0
- package/dist/distribution/types.d.ts +80 -0
- package/dist/distribution/types.js +4 -0
- package/dist/distribution/verifyDistributionReport.d.ts +12 -0
- package/dist/distribution/verifyDistributionReport.js +29 -0
- package/dist/filesystem/paths.d.ts +6 -0
- package/dist/filesystem/paths.js +11 -0
- package/dist/manifest/loadManifest.js +22 -2
- package/dist/manifest/renderSpawnfile.js +2 -4
- package/dist/manifest/renderSpawnfileNetworks.js +5 -0
- package/dist/manifest/schemas.d.ts +71 -41
- package/dist/manifest/surfaceSchemas.d.ts +19 -47
- package/dist/manifest/surfaceSchemas.js +3 -6
- package/dist/manifest/teamNetworkAccessSchemas.d.ts +15 -0
- package/dist/manifest/teamNetworkAccessSchemas.js +8 -0
- package/dist/manifest/teamNetworkConsoleSchemas.d.ts +7 -0
- package/dist/manifest/teamNetworkConsoleSchemas.js +19 -0
- package/dist/manifest/teamNetworkSchemas.d.ts +60 -0
- package/dist/manifest/teamNetworkSchemas.js +20 -7
- package/dist/report/createReport.d.ts +7 -1
- package/dist/report/createReport.js +28 -1
- package/dist/report/types.d.ts +43 -0
- package/dist/runtime/container.js +0 -16
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/install.d.ts +0 -10
- package/dist/runtime/install.js +0 -45
- package/dist/runtime/openclaw/adapter.js +9 -1
- package/dist/runtime/openclaw/configAuth.d.ts +15 -0
- package/dist/runtime/openclaw/configAuth.js +46 -0
- package/dist/runtime/openclaw/runAuth.d.ts +6 -0
- package/dist/runtime/openclaw/runAuth.js +7 -55
- package/dist/runtime/openclaw/statusProbes.d.ts +2 -0
- package/dist/runtime/openclaw/statusProbes.js +31 -0
- package/dist/runtime/picoclaw/adapter.js +10 -0
- package/dist/runtime/picoclaw/runAuth.d.ts +7 -0
- package/dist/runtime/picoclaw/runAuth.js +8 -68
- package/dist/runtime/picoclaw/statusProbes.d.ts +2 -0
- package/dist/runtime/picoclaw/statusProbes.js +100 -0
- package/dist/runtime/registry.d.ts +0 -5
- package/dist/runtime/registry.js +2 -12
- package/dist/runtime/statusProbes.d.ts +16 -0
- package/dist/runtime/statusProbes.js +41 -0
- package/dist/runtime/types.d.ts +52 -1
- package/dist/shared/errors.d.ts +6 -0
- package/dist/shared/errors.js +9 -0
- package/dist/status/buildStatus.d.ts +13 -0
- package/dist/status/buildStatus.js +266 -0
- package/dist/status/compileReport.d.ts +96 -0
- package/dist/status/compileReport.js +230 -0
- package/dist/status/compiledContainerObservations.d.ts +5 -0
- package/dist/status/compiledContainerObservations.js +63 -0
- package/dist/status/deploymentLogs.d.ts +12 -0
- package/dist/status/deploymentLogs.js +45 -0
- package/dist/status/deployments.d.ts +14 -0
- package/dist/status/deployments.js +128 -0
- package/dist/status/imageStatusReport.d.ts +10 -0
- package/dist/status/imageStatusReport.js +73 -0
- package/dist/status/index.d.ts +14 -0
- package/dist/status/index.js +14 -0
- package/dist/status/moltnetProbes.d.ts +21 -0
- package/dist/status/moltnetProbes.js +240 -0
- package/dist/status/registryDrift.d.ts +28 -0
- package/dist/status/registryDrift.js +119 -0
- package/dist/status/renderStatus.d.ts +2 -0
- package/dist/status/renderStatus.js +230 -0
- package/dist/status/runtimeProbes.d.ts +13 -0
- package/dist/status/runtimeProbes.js +111 -0
- package/dist/status/selectionSubjects.d.ts +8 -0
- package/dist/status/selectionSubjects.js +77 -0
- package/dist/status/selectors.d.ts +14 -0
- package/dist/status/selectors.js +90 -0
- package/dist/status/traversal.d.ts +6 -0
- package/dist/status/traversal.js +15 -0
- package/dist/status/types.d.ts +113 -0
- package/dist/status/types.js +1 -0
- package/package.json +4 -2
- package/runtimes.yaml +22 -15
- package/dist/runtime/tinyclaw/adapter.d.ts +0 -2
- package/dist/runtime/tinyclaw/adapter.js +0 -284
- package/dist/runtime/tinyclaw/runAuth.d.ts +0 -2
- package/dist/runtime/tinyclaw/runAuth.js +0 -49
- package/dist/runtime/tinyclaw/scaffold-assets/AGENTS.md +0 -160
- package/dist/runtime/tinyclaw/scaffold-assets/CLAUDE.md +0 -5
- package/dist/runtime/tinyclaw/scaffold-assets/SOUL.md +0 -177
- package/dist/runtime/tinyclaw/scaffold.d.ts +0 -2
- package/dist/runtime/tinyclaw/scaffold.js +0 -24
- package/dist/runtime/tinyclaw/schedules.d.ts +0 -9
- package/dist/runtime/tinyclaw/schedules.js +0 -62
- package/dist/runtime/tinyclaw/surfaces.d.ts +0 -8
- package/dist/runtime/tinyclaw/surfaces.js +0 -94
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { readFile, stat } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { REPORT_FILENAME } from "../shared/index.js";
|
|
4
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5
|
+
const toStringOrNull = (value) => typeof value === "string" ? value : null;
|
|
6
|
+
const toStringArray = (value) => Array.isArray(value)
|
|
7
|
+
? value.filter((entry) => typeof entry === "string")
|
|
8
|
+
: [];
|
|
9
|
+
const toNumberOrNull = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
10
|
+
const toBooleanOrNull = (value) => typeof value === "boolean" ? value : null;
|
|
11
|
+
const toNumberArray = (value) => Array.isArray(value)
|
|
12
|
+
? value.filter((entry) => typeof entry === "number" && Number.isFinite(entry))
|
|
13
|
+
: [];
|
|
14
|
+
const normalizeCapability = (value) => {
|
|
15
|
+
if (!isRecord(value)) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const key = toStringOrNull(value.key);
|
|
19
|
+
const message = toStringOrNull(value.message);
|
|
20
|
+
const outcome = toStringOrNull(value.outcome);
|
|
21
|
+
if (!key || !message || !["degraded", "supported", "unsupported"].includes(outcome ?? "")) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
return { key, message, outcome: outcome };
|
|
25
|
+
};
|
|
26
|
+
const normalizeDiagnostic = (value) => {
|
|
27
|
+
if (!isRecord(value)) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const level = toStringOrNull(value.level);
|
|
31
|
+
const message = toStringOrNull(value.message);
|
|
32
|
+
if (!message || !["error", "info", "warn"].includes(level ?? "")) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return { level: level, message };
|
|
36
|
+
};
|
|
37
|
+
const normalizeNode = (value) => {
|
|
38
|
+
if (!isRecord(value)) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const id = toStringOrNull(value.id);
|
|
42
|
+
const kind = toStringOrNull(value.kind);
|
|
43
|
+
if (!id || !["agent", "team"].includes(kind ?? "")) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
capabilities: (Array.isArray(value.capabilities) ? value.capabilities : [])
|
|
48
|
+
.map(normalizeCapability)
|
|
49
|
+
.filter((entry) => entry !== null),
|
|
50
|
+
diagnostics: (Array.isArray(value.diagnostics) ? value.diagnostics : [])
|
|
51
|
+
.map(normalizeDiagnostic)
|
|
52
|
+
.filter((entry) => entry !== null),
|
|
53
|
+
id,
|
|
54
|
+
kind: kind,
|
|
55
|
+
outputDir: toStringOrNull(value.output_dir),
|
|
56
|
+
runtime: toStringOrNull(value.runtime)
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
const normalizeRuntimeInstance = (value) => {
|
|
60
|
+
if (!isRecord(value)) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const id = toStringOrNull(value.id);
|
|
64
|
+
const runtime = toStringOrNull(value.runtime);
|
|
65
|
+
if (!id || !runtime) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
configPath: toStringOrNull(value.config_path),
|
|
70
|
+
homePath: toStringOrNull(value.home_path),
|
|
71
|
+
id,
|
|
72
|
+
internalPort: toNumberOrNull(value.internal_port),
|
|
73
|
+
nodeIds: toStringArray(value.node_ids),
|
|
74
|
+
publishedPort: toNumberOrNull(value.published_port),
|
|
75
|
+
runtime,
|
|
76
|
+
workspacePath: toStringOrNull(value.workspace_path)
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
const normalizeMoltnetRoom = (value) => {
|
|
80
|
+
if (!isRecord(value)) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
const id = toStringOrNull(value.id);
|
|
84
|
+
if (!id) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
id,
|
|
89
|
+
members: toStringArray(value.members),
|
|
90
|
+
visibility: toStringOrNull(value.visibility),
|
|
91
|
+
writePolicy: toStringOrNull(value.write_policy)
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
const normalizeMoltnetServer = (value) => {
|
|
95
|
+
if (!isRecord(value)) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const id = toStringOrNull(value.id);
|
|
99
|
+
const mode = toStringOrNull(value.mode);
|
|
100
|
+
const networkId = toStringOrNull(value.network_id);
|
|
101
|
+
const baseUrl = toStringOrNull(value.base_url);
|
|
102
|
+
if (!id || !baseUrl || !networkId || (mode !== "managed" && mode !== "external")) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
authMode: toStringOrNull(value.auth_mode),
|
|
107
|
+
baseUrl,
|
|
108
|
+
directMessages: toBooleanOrNull(value.direct_messages),
|
|
109
|
+
id,
|
|
110
|
+
mode,
|
|
111
|
+
networkId,
|
|
112
|
+
operatorTokenSecret: toStringOrNull(value.operator_token_secret),
|
|
113
|
+
port: toNumberOrNull(value.port),
|
|
114
|
+
publicRead: toBooleanOrNull(value.public_read),
|
|
115
|
+
rooms: (Array.isArray(value.rooms) ? value.rooms : [])
|
|
116
|
+
.map(normalizeMoltnetRoom)
|
|
117
|
+
.filter((entry) => entry !== null),
|
|
118
|
+
storeKind: toStringOrNull(value.store_kind)
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
const normalizePortMapping = (value) => {
|
|
122
|
+
if (!isRecord(value)) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
const internalPort = toNumberOrNull(value.internal_port);
|
|
126
|
+
const publishedPort = toNumberOrNull(value.published_port);
|
|
127
|
+
return internalPort && publishedPort ? { internalPort, publishedPort } : null;
|
|
128
|
+
};
|
|
129
|
+
const normalizePersistentMount = (value) => {
|
|
130
|
+
if (!isRecord(value)) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
const id = toStringOrNull(value.id);
|
|
134
|
+
const mountPath = toStringOrNull(value.mount_path);
|
|
135
|
+
const reason = toStringOrNull(value.reason);
|
|
136
|
+
const volumeName = toStringOrNull(value.volume_name);
|
|
137
|
+
return id && mountPath && reason && volumeName
|
|
138
|
+
? { id, mountPath, reason, volumeName }
|
|
139
|
+
: null;
|
|
140
|
+
};
|
|
141
|
+
const normalizeWorkspaceResource = (value) => {
|
|
142
|
+
if (!isRecord(value)) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
const backingPath = toStringOrNull(value.backing_path);
|
|
146
|
+
const id = toStringOrNull(value.id);
|
|
147
|
+
const kind = toStringOrNull(value.kind);
|
|
148
|
+
const linkPath = toStringOrNull(value.link_path);
|
|
149
|
+
const mode = toStringOrNull(value.mode);
|
|
150
|
+
const mount = toStringOrNull(value.mount);
|
|
151
|
+
const sharing = toStringOrNull(value.sharing);
|
|
152
|
+
return backingPath && id && kind && linkPath && mode && mount && sharing
|
|
153
|
+
? { backingPath, id, kind, linkPath, mode, mount, sharing }
|
|
154
|
+
: null;
|
|
155
|
+
};
|
|
156
|
+
const normalizeReport = (value, reportPath) => {
|
|
157
|
+
if (!isRecord(value) || !Array.isArray(value.nodes)) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
const container = isRecord(value.container) ? value.container : {};
|
|
161
|
+
const runtimeInstances = Array.isArray(container.runtime_instances)
|
|
162
|
+
? container.runtime_instances
|
|
163
|
+
: [];
|
|
164
|
+
const moltnet = isRecord(container.moltnet) ? container.moltnet : {};
|
|
165
|
+
const moltnetServers = Array.isArray(moltnet.server_plans) ? moltnet.server_plans : [];
|
|
166
|
+
return {
|
|
167
|
+
compileFingerprint: toStringOrNull(value.compile_fingerprint),
|
|
168
|
+
generatedAt: toStringOrNull(value.generated_at),
|
|
169
|
+
internalPorts: toNumberArray(container.internal_ports),
|
|
170
|
+
moltnetServers: moltnetServers
|
|
171
|
+
.map(normalizeMoltnetServer)
|
|
172
|
+
.filter((entry) => entry !== null),
|
|
173
|
+
nodes: value.nodes
|
|
174
|
+
.map(normalizeNode)
|
|
175
|
+
.filter((entry) => entry !== null),
|
|
176
|
+
outputDirectory: toStringOrNull(value.output_directory),
|
|
177
|
+
persistentMounts: (Array.isArray(container.persistent_mounts) ? container.persistent_mounts : [])
|
|
178
|
+
.map(normalizePersistentMount)
|
|
179
|
+
.filter((entry) => entry !== null),
|
|
180
|
+
portMappings: (Array.isArray(container.port_mappings) ? container.port_mappings : [])
|
|
181
|
+
.map(normalizePortMapping)
|
|
182
|
+
.filter((entry) => entry !== null),
|
|
183
|
+
publishedPorts: toNumberArray(container.published_ports ?? container.ports),
|
|
184
|
+
reportPath,
|
|
185
|
+
root: toStringOrNull(value.root),
|
|
186
|
+
runtimeInstances: runtimeInstances
|
|
187
|
+
.map(normalizeRuntimeInstance)
|
|
188
|
+
.filter((entry) => entry !== null),
|
|
189
|
+
secretsRequired: toStringArray(container.secrets_required),
|
|
190
|
+
workspaceResources: (Array.isArray(container.workspace_resources) ? container.workspace_resources : [])
|
|
191
|
+
.map(normalizeWorkspaceResource)
|
|
192
|
+
.filter((entry) => entry !== null)
|
|
193
|
+
};
|
|
194
|
+
};
|
|
195
|
+
export const resolveCompileReportPath = (outputDirectory) => path.join(outputDirectory, REPORT_FILENAME);
|
|
196
|
+
export const loadCompileReport = async (outputDirectory) => {
|
|
197
|
+
const reportPath = resolveCompileReportPath(outputDirectory);
|
|
198
|
+
try {
|
|
199
|
+
await stat(reportPath);
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
if (error.code === "ENOENT") {
|
|
203
|
+
return { kind: "missing", reportPath };
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
failure: { exitCode: 2, message: `Unable to stat compile report ${reportPath}` },
|
|
207
|
+
kind: "failure",
|
|
208
|
+
reportPath
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
let parsed;
|
|
212
|
+
try {
|
|
213
|
+
parsed = JSON.parse(await readFile(reportPath, "utf8"));
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
return {
|
|
217
|
+
failure: { exitCode: 2, message: `Unable to read compile report ${reportPath}` },
|
|
218
|
+
kind: "failure",
|
|
219
|
+
reportPath
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
const report = normalizeReport(parsed, reportPath);
|
|
223
|
+
return report
|
|
224
|
+
? { kind: "loaded", report, reportPath }
|
|
225
|
+
: {
|
|
226
|
+
failure: { exitCode: 2, message: `Malformed compile report ${reportPath}` },
|
|
227
|
+
kind: "failure",
|
|
228
|
+
reportPath
|
|
229
|
+
};
|
|
230
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const createObservation = (input) => ({
|
|
2
|
+
...input,
|
|
3
|
+
label: `${input.severity.toUpperCase()} ${input.key}`
|
|
4
|
+
});
|
|
5
|
+
export const createCompiledContainerObservations = (loaded) => {
|
|
6
|
+
const observations = [];
|
|
7
|
+
const report = loaded.report;
|
|
8
|
+
for (const instance of report.runtimeInstances) {
|
|
9
|
+
observations.push(createObservation({
|
|
10
|
+
key: "runtime.instance",
|
|
11
|
+
message: `${instance.id} emits ${instance.runtime} workspace ${instance.workspacePath ?? "unknown"}`,
|
|
12
|
+
severity: "ok",
|
|
13
|
+
source: "compile_report",
|
|
14
|
+
subject: `runtime-instance:${instance.id}`
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
for (const server of report.moltnetServers ?? []) {
|
|
18
|
+
observations.push(createObservation({
|
|
19
|
+
key: "network.compiled",
|
|
20
|
+
message: `${server.networkId} Moltnet ${server.mode} server at ${server.baseUrl}`,
|
|
21
|
+
severity: "ok",
|
|
22
|
+
source: "compile_report",
|
|
23
|
+
subject: `network:${server.networkId}`
|
|
24
|
+
}));
|
|
25
|
+
for (const room of server.rooms) {
|
|
26
|
+
observations.push(createObservation({
|
|
27
|
+
key: "network.room.compiled",
|
|
28
|
+
message: `${server.networkId}/${room.id} expects ${room.members.length} member(s)`,
|
|
29
|
+
severity: "ok",
|
|
30
|
+
source: "compile_report",
|
|
31
|
+
subject: `room:${server.networkId}:${room.id}`
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
for (const mount of report.persistentMounts ?? []) {
|
|
36
|
+
observations.push(createObservation({
|
|
37
|
+
key: "container.mount",
|
|
38
|
+
message: `${mount.id} mounted at ${mount.mountPath} using volume ${mount.volumeName}`,
|
|
39
|
+
severity: "ok",
|
|
40
|
+
source: "compile_report",
|
|
41
|
+
subject: "compile"
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
for (const resource of report.workspaceResources ?? []) {
|
|
45
|
+
observations.push(createObservation({
|
|
46
|
+
key: "workspace.resource",
|
|
47
|
+
message: `${resource.id} linked at ${resource.linkPath} from ${resource.backingPath}`,
|
|
48
|
+
severity: "ok",
|
|
49
|
+
source: "compile_report",
|
|
50
|
+
subject: "compile"
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
if ((report.internalPorts?.length ?? 0) > 0 || (report.publishedPorts?.length ?? 0) > 0) {
|
|
54
|
+
observations.push(createObservation({
|
|
55
|
+
key: "container.ports",
|
|
56
|
+
message: `internal ports: ${(report.internalPorts ?? []).join(", ") || "none"}; published ports: ${(report.publishedPorts ?? []).join(", ") || "none"}`,
|
|
57
|
+
severity: "ok",
|
|
58
|
+
source: "compile_report",
|
|
59
|
+
subject: "compile"
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
return observations;
|
|
63
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type DeploymentRecord, type DockerLogsExecFile } from "../deployment/index.js";
|
|
2
|
+
import type { LoadedCompileReport } from "./compileReport.js";
|
|
3
|
+
import type { StatusObservation } from "./types.js";
|
|
4
|
+
export interface CollectDeploymentLogOptions {
|
|
5
|
+
deployments: DeploymentRecord[];
|
|
6
|
+
dockerCommand?: string;
|
|
7
|
+
execFile?: DockerLogsExecFile;
|
|
8
|
+
loadedReport: LoadedCompileReport;
|
|
9
|
+
tail?: number;
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare const collectDeploymentLogObservations: (options: CollectDeploymentLogOptions) => Promise<StatusObservation[]>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { readDockerDeploymentLogs } from "../deployment/index.js";
|
|
2
|
+
const createObservation = (input) => ({
|
|
3
|
+
...input,
|
|
4
|
+
label: `${input.severity.toUpperCase()} ${input.key}`,
|
|
5
|
+
source: "deployment"
|
|
6
|
+
});
|
|
7
|
+
const secretValuesFor = (loadedReport) => {
|
|
8
|
+
if (loadedReport.kind !== "loaded") {
|
|
9
|
+
return [];
|
|
10
|
+
}
|
|
11
|
+
return (loadedReport.report.secretsRequired ?? [])
|
|
12
|
+
.map((secretName) => process.env[secretName])
|
|
13
|
+
.filter((value) => typeof value === "string" && value.length > 0);
|
|
14
|
+
};
|
|
15
|
+
const normalizeFailureSeverity = (severity) => severity === "error" ? "unknown" : severity;
|
|
16
|
+
export const collectDeploymentLogObservations = async (options) => {
|
|
17
|
+
const secretValues = secretValuesFor(options.loadedReport);
|
|
18
|
+
const observations = [];
|
|
19
|
+
for (const deployment of options.deployments) {
|
|
20
|
+
const logs = await readDockerDeploymentLogs(deployment, {
|
|
21
|
+
dockerCommand: options.dockerCommand,
|
|
22
|
+
execFile: options.execFile,
|
|
23
|
+
secretValues,
|
|
24
|
+
tail: options.tail,
|
|
25
|
+
timeoutMs: options.timeoutMs
|
|
26
|
+
});
|
|
27
|
+
for (const unit of deployment.units) {
|
|
28
|
+
const unitLogs = logs.get(unit.id);
|
|
29
|
+
if (!unitLogs) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
observations.push(createObservation({
|
|
33
|
+
details: {
|
|
34
|
+
container_ref: unitLogs.containerRef,
|
|
35
|
+
log_tail: unitLogs.text
|
|
36
|
+
},
|
|
37
|
+
key: "deployment.logs",
|
|
38
|
+
message: `${deployment.name}/${unit.id}: ${unitLogs.message}`,
|
|
39
|
+
severity: normalizeFailureSeverity(unitLogs.severity),
|
|
40
|
+
subject: `deployment-unit:${deployment.name}:${unit.id}`
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return observations;
|
|
45
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DeploymentRecord, DockerInspectionResult } from "../deployment/index.js";
|
|
2
|
+
import type { StatusDeploymentSummary, StatusObservation } from "./types.js";
|
|
3
|
+
export interface LoadedDeploymentRecord {
|
|
4
|
+
path: string;
|
|
5
|
+
record: DeploymentRecord;
|
|
6
|
+
}
|
|
7
|
+
export type StatusDeploymentInspections = Map<string, DockerInspectionResult>;
|
|
8
|
+
export declare const createDeploymentSummaries: (records: LoadedDeploymentRecord[], inspections?: StatusDeploymentInspections) => StatusDeploymentSummary[];
|
|
9
|
+
export declare const createDeploymentObservations: (deployments: StatusDeploymentSummary[], options: {
|
|
10
|
+
compileFingerprint: string | null;
|
|
11
|
+
liveRequested: boolean;
|
|
12
|
+
outputDirectory: string;
|
|
13
|
+
recover: boolean;
|
|
14
|
+
}) => StatusObservation[];
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
const createObservation = (input) => ({
|
|
2
|
+
...input,
|
|
3
|
+
label: `${input.severity.toUpperCase()} ${input.key}`
|
|
4
|
+
});
|
|
5
|
+
const targetLabelFor = (record) => record.target.kind === "context"
|
|
6
|
+
? `docker context ${record.target.name}`
|
|
7
|
+
: record.target.kind === "docker-context"
|
|
8
|
+
? `docker context ${record.target.context}`
|
|
9
|
+
: "docker host";
|
|
10
|
+
const liveForInspection = (inspection) => {
|
|
11
|
+
if (!inspection) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
checked: true,
|
|
16
|
+
containerId: inspection.containerId,
|
|
17
|
+
drift: [...inspection.drift],
|
|
18
|
+
exists: inspection.exists,
|
|
19
|
+
exitCode: inspection.exitCode,
|
|
20
|
+
finishedAt: inspection.finishedAt,
|
|
21
|
+
imageId: inspection.imageId,
|
|
22
|
+
message: inspection.message,
|
|
23
|
+
restartCount: inspection.restartCount,
|
|
24
|
+
running: inspection.running,
|
|
25
|
+
severity: inspection.severity,
|
|
26
|
+
startedAt: inspection.startedAt,
|
|
27
|
+
status: inspection.status
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
const unitSeverity = (live) => {
|
|
31
|
+
if (!live) {
|
|
32
|
+
return "ok";
|
|
33
|
+
}
|
|
34
|
+
if (live.severity !== "ok") {
|
|
35
|
+
return live.severity;
|
|
36
|
+
}
|
|
37
|
+
if (live.running === true) {
|
|
38
|
+
return "ok";
|
|
39
|
+
}
|
|
40
|
+
if (live.exists === false) {
|
|
41
|
+
return "warn";
|
|
42
|
+
}
|
|
43
|
+
if (live.running === false) {
|
|
44
|
+
return "error";
|
|
45
|
+
}
|
|
46
|
+
return "unknown";
|
|
47
|
+
};
|
|
48
|
+
const summarizeUnit = (unit, live) => ({
|
|
49
|
+
containerId: unit.container_id,
|
|
50
|
+
containerName: unit.container_name,
|
|
51
|
+
contains: unit.contains.map((entry) => ({ id: entry.id, kind: entry.kind })),
|
|
52
|
+
id: unit.id,
|
|
53
|
+
imageId: unit.image_id,
|
|
54
|
+
imageTag: unit.image_tag,
|
|
55
|
+
kind: unit.kind,
|
|
56
|
+
live,
|
|
57
|
+
runtimeInstances: [...unit.runtime_instances]
|
|
58
|
+
});
|
|
59
|
+
export const createDeploymentSummaries = (records, inspections = new Map()) => records.map(({ path, record }) => ({
|
|
60
|
+
authProfile: record.auth_profile,
|
|
61
|
+
compileFingerprint: record.compile_fingerprint,
|
|
62
|
+
createdAt: record.created_at,
|
|
63
|
+
manager: record.manager,
|
|
64
|
+
name: record.name,
|
|
65
|
+
recordPath: path,
|
|
66
|
+
target: targetLabelFor(record),
|
|
67
|
+
units: record.units.map((unit) => summarizeUnit(unit, liveForInspection(inspections.get(record.name)?.get(unit.id))))
|
|
68
|
+
}));
|
|
69
|
+
export const createDeploymentObservations = (deployments, options) => {
|
|
70
|
+
const observations = [];
|
|
71
|
+
if (deployments.length === 0 && options.liveRequested && !options.recover) {
|
|
72
|
+
observations.push(createObservation({
|
|
73
|
+
key: "deployment.record",
|
|
74
|
+
message: `No deployment records found under ${options.outputDirectory}`,
|
|
75
|
+
severity: "warn",
|
|
76
|
+
source: "deployment",
|
|
77
|
+
subject: "deployment"
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
if (options.recover) {
|
|
81
|
+
observations.push(createObservation({
|
|
82
|
+
key: "deployment.recover",
|
|
83
|
+
message: "Label recovery is not implemented yet; use record-backed status for live checks",
|
|
84
|
+
severity: "unknown",
|
|
85
|
+
source: "deployment",
|
|
86
|
+
subject: "deployment"
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
for (const deployment of deployments) {
|
|
90
|
+
observations.push(createObservation({
|
|
91
|
+
key: "deployment.record",
|
|
92
|
+
message: `${deployment.name} record exists at ${deployment.recordPath}`,
|
|
93
|
+
severity: "ok",
|
|
94
|
+
source: "deployment",
|
|
95
|
+
subject: `deployment:${deployment.name}`
|
|
96
|
+
}));
|
|
97
|
+
if (options.compileFingerprint && deployment.compileFingerprint !== options.compileFingerprint) {
|
|
98
|
+
observations.push(createObservation({
|
|
99
|
+
key: "deployment.compile_fingerprint",
|
|
100
|
+
message: `${deployment.name} was deployed from ${deployment.compileFingerprint}, current compile is ${options.compileFingerprint}`,
|
|
101
|
+
severity: "warn",
|
|
102
|
+
source: "deployment",
|
|
103
|
+
subject: `deployment:${deployment.name}`
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
for (const unit of deployment.units) {
|
|
107
|
+
const severity = unitSeverity(unit.live);
|
|
108
|
+
const unitSubject = `deployment-unit:${deployment.name}:${unit.id}`;
|
|
109
|
+
observations.push(createObservation({
|
|
110
|
+
key: "deployment.unit",
|
|
111
|
+
message: unit.live?.message ?? `${unit.id} recorded for ${deployment.target}`,
|
|
112
|
+
severity,
|
|
113
|
+
source: "deployment",
|
|
114
|
+
subject: unitSubject
|
|
115
|
+
}));
|
|
116
|
+
for (const entry of unit.contains) {
|
|
117
|
+
observations.push(createObservation({
|
|
118
|
+
key: "deployment.hosting",
|
|
119
|
+
message: `${entry.id} is hosted by ${deployment.name}/${unit.id}`,
|
|
120
|
+
severity,
|
|
121
|
+
source: "deployment",
|
|
122
|
+
subject: entry.id
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return observations;
|
|
128
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DistributionReport } from "../distribution/index.js";
|
|
2
|
+
import type { LoadedCompileReport, StatusReport } from "./compileReport.js";
|
|
3
|
+
/**
|
|
4
|
+
* Maps a cached distribution report (from a sourceless image deployment) into
|
|
5
|
+
* the StatusReport shape so live status can render the compiled, deployment,
|
|
6
|
+
* and runtime layers without project source. Moltnet server plans are not part
|
|
7
|
+
* of the distribution report, so the network layer falls back to `unknown`.
|
|
8
|
+
*/
|
|
9
|
+
export declare const distributionReportToStatusReport: (report: DistributionReport, reportPath: string) => StatusReport;
|
|
10
|
+
export declare const loadedImageCompileReport: (report: DistributionReport, reportPath: string) => LoadedCompileReport;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps a cached distribution report (from a sourceless image deployment) into
|
|
3
|
+
* the StatusReport shape so live status can render the compiled, deployment,
|
|
4
|
+
* and runtime layers without project source. Moltnet server plans are not part
|
|
5
|
+
* of the distribution report, so the network layer falls back to `unknown`.
|
|
6
|
+
*/
|
|
7
|
+
export const distributionReportToStatusReport = (report, reportPath) => ({
|
|
8
|
+
compileFingerprint: report.compile_fingerprint,
|
|
9
|
+
generatedAt: report.generated_at,
|
|
10
|
+
internalPorts: report.internal_ports,
|
|
11
|
+
moltnetServers: [],
|
|
12
|
+
nodes: [
|
|
13
|
+
...report.organization.agents.map((agent) => ({
|
|
14
|
+
capabilities: [],
|
|
15
|
+
diagnostics: [],
|
|
16
|
+
id: agent.id,
|
|
17
|
+
kind: "agent",
|
|
18
|
+
outputDir: null,
|
|
19
|
+
runtime: agent.runtime
|
|
20
|
+
})),
|
|
21
|
+
...report.organization.teams.map((team) => ({
|
|
22
|
+
capabilities: [],
|
|
23
|
+
diagnostics: [],
|
|
24
|
+
id: team.id,
|
|
25
|
+
kind: "team",
|
|
26
|
+
outputDir: null,
|
|
27
|
+
runtime: null
|
|
28
|
+
}))
|
|
29
|
+
],
|
|
30
|
+
outputDirectory: null,
|
|
31
|
+
persistentMounts: report.persistent_mounts.map((mount) => ({
|
|
32
|
+
id: mount.id,
|
|
33
|
+
mountPath: mount.target,
|
|
34
|
+
reason: "image persistent mount",
|
|
35
|
+
volumeName: ""
|
|
36
|
+
})),
|
|
37
|
+
portMappings: report.port_mappings.map((mapping) => ({
|
|
38
|
+
internalPort: mapping.internal_port,
|
|
39
|
+
publishedPort: mapping.published_port
|
|
40
|
+
})),
|
|
41
|
+
publishedPorts: report.ports,
|
|
42
|
+
reportPath,
|
|
43
|
+
root: null,
|
|
44
|
+
runtimeInstances: report.runtime_instances.map((instance) => ({
|
|
45
|
+
configPath: instance.config_path,
|
|
46
|
+
homePath: instance.home_path,
|
|
47
|
+
id: instance.id,
|
|
48
|
+
internalPort: instance.internal_port,
|
|
49
|
+
nodeIds: instance.node_ids,
|
|
50
|
+
publishedPort: instance.published_port,
|
|
51
|
+
runtime: instance.runtime,
|
|
52
|
+
workspacePath: instance.workspace_path
|
|
53
|
+
})),
|
|
54
|
+
secretsRequired: [
|
|
55
|
+
...new Set(["model", "project", "runtime", "surface"].flatMap((category) => report.secrets[category]
|
|
56
|
+
.filter((entry) => entry.required && !entry.generated)
|
|
57
|
+
.map((entry) => entry.name)))
|
|
58
|
+
].sort(),
|
|
59
|
+
workspaceResources: report.resources.map((resource) => ({
|
|
60
|
+
backingPath: "",
|
|
61
|
+
id: resource.id,
|
|
62
|
+
kind: resource.kind,
|
|
63
|
+
linkPath: resource.link_path,
|
|
64
|
+
mode: resource.mode,
|
|
65
|
+
mount: resource.mount,
|
|
66
|
+
sharing: resource.sharing
|
|
67
|
+
}))
|
|
68
|
+
});
|
|
69
|
+
export const loadedImageCompileReport = (report, reportPath) => ({
|
|
70
|
+
kind: "loaded",
|
|
71
|
+
report: distributionReportToStatusReport(report, reportPath),
|
|
72
|
+
reportPath
|
|
73
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./buildStatus.js";
|
|
2
|
+
export * from "./compiledContainerObservations.js";
|
|
3
|
+
export * from "./compileReport.js";
|
|
4
|
+
export * from "./deploymentLogs.js";
|
|
5
|
+
export * from "./deployments.js";
|
|
6
|
+
export * from "./moltnetProbes.js";
|
|
7
|
+
export * from "./renderStatus.js";
|
|
8
|
+
export * from "./runtimeProbes.js";
|
|
9
|
+
export * from "./selectionSubjects.js";
|
|
10
|
+
export * from "./selectors.js";
|
|
11
|
+
export * from "./traversal.js";
|
|
12
|
+
export * from "./types.js";
|
|
13
|
+
export * from "./imageStatusReport.js";
|
|
14
|
+
export * from "./registryDrift.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./buildStatus.js";
|
|
2
|
+
export * from "./compiledContainerObservations.js";
|
|
3
|
+
export * from "./compileReport.js";
|
|
4
|
+
export * from "./deploymentLogs.js";
|
|
5
|
+
export * from "./deployments.js";
|
|
6
|
+
export * from "./moltnetProbes.js";
|
|
7
|
+
export * from "./renderStatus.js";
|
|
8
|
+
export * from "./runtimeProbes.js";
|
|
9
|
+
export * from "./selectionSubjects.js";
|
|
10
|
+
export * from "./selectors.js";
|
|
11
|
+
export * from "./traversal.js";
|
|
12
|
+
export * from "./types.js";
|
|
13
|
+
export * from "./imageStatusReport.js";
|
|
14
|
+
export * from "./registryDrift.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DeploymentRecord, DockerInspectionResult, DockerProbeExecFile } from "../deployment/index.js";
|
|
2
|
+
import type { LoadedCompileReport } from "./compileReport.js";
|
|
3
|
+
import type { StatusObservation } from "./types.js";
|
|
4
|
+
export type StatusNetworkInspections = Map<string, DockerInspectionResult>;
|
|
5
|
+
export interface CollectMoltnetProbeOptions {
|
|
6
|
+
authValues?: Record<string, string>;
|
|
7
|
+
deployments: DeploymentRecord[];
|
|
8
|
+
execFile?: DockerProbeExecFile;
|
|
9
|
+
fetchJson?: MoltnetFetchJson;
|
|
10
|
+
inspections: StatusNetworkInspections;
|
|
11
|
+
loadedReport: LoadedCompileReport;
|
|
12
|
+
timeoutMs?: number;
|
|
13
|
+
}
|
|
14
|
+
export type MoltnetFetchJson = (url: string, headers: Record<string, string>, timeoutMs: number) => Promise<MoltnetProbeResponse>;
|
|
15
|
+
interface MoltnetProbeResponse {
|
|
16
|
+
error?: string;
|
|
17
|
+
json: unknown;
|
|
18
|
+
ok: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare const collectMoltnetProbeObservations: (options: CollectMoltnetProbeOptions) => Promise<StatusObservation[]>;
|
|
21
|
+
export {};
|