@foresthubai/workflow-core 0.4.3 → 0.4.4
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/LICENSE +202 -202
- package/NOTICE +14 -14
- package/README.md +63 -63
- package/dist/api/deployment.d.ts +67 -0
- package/dist/api/deployment.d.ts.map +1 -0
- package/dist/api/deployment.js +6 -0
- package/dist/api/deployment.js.map +1 -0
- package/dist/api/engine.d.ts +744 -0
- package/dist/api/engine.d.ts.map +1 -0
- package/dist/api/engine.js +6 -0
- package/dist/api/engine.js.map +1 -0
- package/dist/api/index.d.ts +4 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/workflow.d.ts +17 -1
- package/dist/api/workflow.d.ts.map +1 -1
- package/dist/channel/Channel.d.ts +1 -1
- package/dist/channel/Channel.d.ts.map +1 -1
- package/dist/channel/Channel.js +1 -1
- package/dist/channel/Channel.js.map +1 -1
- package/dist/channel/ChannelDefinition.d.ts.map +1 -1
- package/dist/channel/ChannelDefinition.js +22 -0
- package/dist/channel/ChannelDefinition.js.map +1 -1
- package/dist/channel/serialization.d.ts.map +1 -1
- package/dist/channel/serialization.js +6 -0
- package/dist/channel/serialization.js.map +1 -1
- package/dist/deploy/index.d.ts +5 -1
- package/dist/deploy/index.d.ts.map +1 -1
- package/dist/deploy/index.js +2 -1
- package/dist/deploy/index.js.map +1 -1
- package/dist/deploy/inputs.d.ts +26 -0
- package/dist/deploy/inputs.d.ts.map +1 -0
- package/dist/deploy/inputs.js +12 -0
- package/dist/deploy/inputs.js.map +1 -0
- package/dist/deploy/requirements.d.ts +24 -0
- package/dist/deploy/requirements.d.ts.map +1 -1
- package/dist/deploy/requirements.js +61 -0
- package/dist/deploy/requirements.js.map +1 -1
- package/dist/deploy/spec.d.ts +32 -0
- package/dist/deploy/spec.d.ts.map +1 -0
- package/dist/deploy/spec.js +343 -0
- package/dist/deploy/spec.js.map +1 -0
- package/dist/node/OutputNode.js +2 -2
- package/dist/node/OutputNode.js.map +1 -1
- package/package.json +2 -2
- package/src/api/deployment.ts +67 -0
- package/src/api/engine.ts +744 -0
- package/src/api/index.ts +26 -11
- package/src/api/workflow.ts +17 -1
- package/src/channel/Channel.ts +11 -11
- package/src/channel/ChannelDefinition.ts +98 -76
- package/src/channel/index.ts +6 -6
- package/src/channel/serialization.ts +74 -68
- package/src/deploy/index.ts +14 -1
- package/src/deploy/inputs.ts +41 -0
- package/src/deploy/requirements.test.ts +61 -61
- package/src/deploy/requirements.ts +156 -41
- package/src/deploy/spec.test.ts +226 -0
- package/src/deploy/spec.ts +379 -0
- package/src/diagnostics/__fixtures__/diagnosticFixtures.ts +158 -158
- package/src/diagnostics/diagnostics.test.ts +878 -878
- package/src/diagnostics/diagnostics.ts +936 -936
- package/src/diagnostics/index.ts +11 -11
- package/src/edge/Edge.ts +23 -23
- package/src/edge/EdgeDefinition.ts +45 -45
- package/src/edge/EdgeType.ts +19 -19
- package/src/edge/index.ts +8 -8
- package/src/edge/serialization.ts +83 -83
- package/src/expression/index.ts +4 -4
- package/src/expression/parser.ts +362 -362
- package/src/expression/types.ts +30 -30
- package/src/function/FunctionDeclaration.ts +54 -54
- package/src/function/index.ts +3 -3
- package/src/function/serialization.ts +40 -40
- package/src/globals.d.ts +9 -9
- package/src/id/index.ts +8 -8
- package/src/index.ts +22 -22
- package/src/memory/Memory.ts +15 -15
- package/src/memory/MemoryDefinition.ts +16 -16
- package/src/memory/MemoryFileDefinition.ts +37 -37
- package/src/memory/MemoryRegistry.ts +35 -35
- package/src/memory/VectorDatabaseDefinition.ts +21 -21
- package/src/memory/index.ts +8 -8
- package/src/memory/serialization.ts +47 -47
- package/src/migration/index.ts +4 -4
- package/src/migration/migrate.test.ts +44 -44
- package/src/migration/migrate.ts +58 -58
- package/src/migration/migrations.ts +24 -24
- package/src/migration/version.ts +9 -9
- package/src/model/LLMModelDefinition.ts +12 -12
- package/src/model/Model.ts +39 -39
- package/src/model/ModelDefinition.ts +15 -15
- package/src/model/ModelRegistry.ts +33 -33
- package/src/model/index.ts +7 -7
- package/src/model/serialization.ts +30 -30
- package/src/node/AgentNode.ts +82 -82
- package/src/node/DataNode.ts +41 -41
- package/src/node/FunctionNode.ts +76 -76
- package/src/node/InputNode.ts +185 -185
- package/src/node/LogicNode.ts +33 -33
- package/src/node/MqttNode.ts +127 -127
- package/src/node/Node.ts +61 -61
- package/src/node/NodeDefinition.ts +37 -37
- package/src/node/NodeRegistry.ts +85 -85
- package/src/node/OutputNode.ts +87 -87
- package/src/node/ToolNode.ts +32 -32
- package/src/node/TriggerNode.ts +272 -272
- package/src/node/constants.ts +16 -16
- package/src/node/index.ts +26 -26
- package/src/node/methods.ts +278 -278
- package/src/node/serialization.ts +544 -544
- package/src/parameter/OutputParameter.ts +68 -68
- package/src/parameter/Parameter.ts +243 -243
- package/src/parameter/index.ts +33 -33
- package/src/variable/Variable.ts +10 -10
- package/src/variable/index.ts +16 -16
- package/src/variable/operations.ts +106 -106
- package/src/workflow/Workflow.ts +41 -41
- package/src/workflow/index.ts +3 -3
- package/src/workflow/serialization.test.ts +240 -240
- package/src/workflow/serialization.ts +242 -242
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
// The spec resolver: (workflow + bindings) -> DeploymentSpec. The shared
|
|
2
|
+
// "packaging library" the migration doc calls for — component-set derivation
|
|
3
|
+
// and device-grant resolution computed once here, frozen into the contract spec,
|
|
4
|
+
// so neither renderer (OSS one-shot CLI, paid ranger) re-derives them.
|
|
5
|
+
//
|
|
6
|
+
// Every produced field is typed against the generated deployment contract, so a
|
|
7
|
+
// contract change stops this compiling — the drift guard for the spec.
|
|
8
|
+
import { serialize } from "../workflow";
|
|
9
|
+
import { deriveRequirements } from "./requirements";
|
|
10
|
+
// Mount path for the engine's memory volume — matches the image's ENGINE_MEMORY_DIR
|
|
11
|
+
// default, so the renderer mounts here without wiring an env var.
|
|
12
|
+
const ENGINE_MEMORY_PATH = "/var/lib/foresthub/memory";
|
|
13
|
+
// Hands out stable, collision-free ref names. Same dedup key -> same ref (the
|
|
14
|
+
// engine builds that resource once); distinct keys preferring the same name get
|
|
15
|
+
// suffixed (-2, -3, ...) so the flat ref namespace stays unambiguous.
|
|
16
|
+
class RefAllocator {
|
|
17
|
+
byKey = new Map();
|
|
18
|
+
used = new Set();
|
|
19
|
+
alloc(key, hint) {
|
|
20
|
+
const existing = this.byKey.get(key);
|
|
21
|
+
if (existing)
|
|
22
|
+
return existing;
|
|
23
|
+
let ref = hint;
|
|
24
|
+
for (let n = 2; this.used.has(ref); n++)
|
|
25
|
+
ref = `${hint}-${n}`;
|
|
26
|
+
this.used.add(ref);
|
|
27
|
+
this.byKey.set(key, ref);
|
|
28
|
+
return ref;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Last path/URL segment, reduced to a safe ref token.
|
|
32
|
+
// "/dev/gpiochip0" -> "gpiochip0", ".../iio:device0" -> "iio:device0".
|
|
33
|
+
function basename(p) {
|
|
34
|
+
const tail = p.replace(/\/+$/, "").split("/").pop() ?? p;
|
|
35
|
+
return tail.replace(/[^A-Za-z0-9._:-]/g, "-") || "res";
|
|
36
|
+
}
|
|
37
|
+
// Host of a broker URL, for a readable ref. "mqtt" when unparseable.
|
|
38
|
+
function brokerHost(url) {
|
|
39
|
+
try {
|
|
40
|
+
return new URL(url).hostname || "mqtt";
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return "mqtt";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Compose/container service name for an on-device model's llama-server sidecar.
|
|
47
|
+
// Single source of truth: the resolver derives the provider URL from it and the
|
|
48
|
+
// renderer emits a service with the same name — they must agree or the URL
|
|
49
|
+
// points at a service that doesn't exist.
|
|
50
|
+
export function sidecarServiceName(modelId) {
|
|
51
|
+
const slug = modelId
|
|
52
|
+
.toLowerCase()
|
|
53
|
+
.replace(/[^a-z0-9._-]+/g, "-")
|
|
54
|
+
.replace(/^-+|-+$/g, "");
|
|
55
|
+
return `llama-${slug || "model"}`;
|
|
56
|
+
}
|
|
57
|
+
// Why an on-device model filename is unacceptable, or null when fine. A name
|
|
58
|
+
// check only — the file doesn't exist yet at spec time. Shared with the prompts
|
|
59
|
+
// so input collection and the resolver reject the same input.
|
|
60
|
+
export function ggufNameError(name) {
|
|
61
|
+
const t = (name ?? "").trim();
|
|
62
|
+
if (!t)
|
|
63
|
+
return "a model filename is required";
|
|
64
|
+
if (!t.toLowerCase().endsWith(".gguf"))
|
|
65
|
+
return "must be a .gguf file (llama-server only loads GGUF)";
|
|
66
|
+
if (t.includes("/"))
|
|
67
|
+
return "just the filename, not a path — the file goes in ./models/";
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
// A physical address belongs to exactly one channel — the engine doesn't police
|
|
71
|
+
// this and would silently let the last claimer win. Same key = collision;
|
|
72
|
+
// sharing just a chip path is fine (one chip, many lines), except serial where
|
|
73
|
+
// the path IS the device. Exported so input collection (prompts) can reject a
|
|
74
|
+
// duplicate at entry with the same identity the resolver validates against.
|
|
75
|
+
export function hardwareAddressKey(family, chipOrDevice, index) {
|
|
76
|
+
const dev = chipOrDevice.trim();
|
|
77
|
+
return family === "serial" ? `serial:${dev}` : `${family}:${dev}:${index}`;
|
|
78
|
+
}
|
|
79
|
+
// The same address phrased for an error message: "/dev/gpiochip0 line 17".
|
|
80
|
+
export function hardwareAddressLabel(family, chipOrDevice, index) {
|
|
81
|
+
const dev = chipOrDevice.trim();
|
|
82
|
+
if (family === "serial")
|
|
83
|
+
return dev;
|
|
84
|
+
return `${dev} ${family === "gpio" ? "line" : "channel"} ${index}`;
|
|
85
|
+
}
|
|
86
|
+
// One message per channel whose address an earlier channel already claimed.
|
|
87
|
+
// Incomplete bindings are skipped (completeness is checked separately).
|
|
88
|
+
export function hardwareConflicts(channels, bindings) {
|
|
89
|
+
const conflicts = [];
|
|
90
|
+
const claimed = new Map(); // address key -> channel id holding it
|
|
91
|
+
for (const ch of channels) {
|
|
92
|
+
const b = bindings[ch.id];
|
|
93
|
+
if (!b?.chipOrDevice || (ch.addressable && b.index === undefined))
|
|
94
|
+
continue;
|
|
95
|
+
const key = hardwareAddressKey(ch.family, b.chipOrDevice, b.index);
|
|
96
|
+
const holder = claimed.get(key);
|
|
97
|
+
if (holder) {
|
|
98
|
+
conflicts.push(`hardware "${ch.id}": ${hardwareAddressLabel(ch.family, b.chipOrDevice, b.index)} is already used by "${holder}"`);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
claimed.set(key, ch.id);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return conflicts;
|
|
105
|
+
}
|
|
106
|
+
// One message per binding carrying a field its family doesn't have (`baud` is
|
|
107
|
+
// serial-only, `index` is everything-but-serial). Usually a mixed-up channel id
|
|
108
|
+
// in a machine-written binding set — reject loudly instead of ignoring.
|
|
109
|
+
export function familyMismatches(channels, bindings) {
|
|
110
|
+
const mismatches = [];
|
|
111
|
+
for (const ch of channels) {
|
|
112
|
+
const b = bindings[ch.id];
|
|
113
|
+
if (!b)
|
|
114
|
+
continue;
|
|
115
|
+
if (ch.family !== "serial" && b.baud !== undefined) {
|
|
116
|
+
mismatches.push(`hardware "${ch.id}": "baud" only applies to serial channels (this is a ${ch.family} channel)`);
|
|
117
|
+
}
|
|
118
|
+
if (ch.family === "serial" && b.index !== undefined) {
|
|
119
|
+
mismatches.push(`hardware "${ch.id}": "index" does not apply to serial channels (the device path is the full address)`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return mismatches;
|
|
123
|
+
}
|
|
124
|
+
// Exhaustiveness guard over HardwareFamily — a new family breaks compilation
|
|
125
|
+
// here until handled.
|
|
126
|
+
function assertNeverFamily(f) {
|
|
127
|
+
throw new Error(`unhandled hardware family: ${String(f)}`);
|
|
128
|
+
}
|
|
129
|
+
// Mirror of the engine's deploy-layer validation: every declared resource must
|
|
130
|
+
// carry a binding or the engine fatals at boot. Collects ALL gaps so a caller
|
|
131
|
+
// sees them at once. Throws on any gap — the last guard before a dead spec.
|
|
132
|
+
export function assertDeployable(req, inputs) {
|
|
133
|
+
const missing = [];
|
|
134
|
+
for (const ch of req.hardwareChannels) {
|
|
135
|
+
const b = inputs.hardware[ch.id];
|
|
136
|
+
if (!b?.chipOrDevice)
|
|
137
|
+
missing.push(`hardware "${ch.id}": device path`);
|
|
138
|
+
else if (ch.addressable && b.index === undefined)
|
|
139
|
+
missing.push(`hardware "${ch.id}": index`);
|
|
140
|
+
}
|
|
141
|
+
for (const ch of req.mqttChannels) {
|
|
142
|
+
if (!inputs.mqtt[ch.id]?.brokerUrl)
|
|
143
|
+
missing.push(`mqtt "${ch.id}": broker URL`);
|
|
144
|
+
}
|
|
145
|
+
for (const m of req.customModels) {
|
|
146
|
+
const b = inputs.models[m.id];
|
|
147
|
+
if (b?.location === "device") {
|
|
148
|
+
const err = ggufNameError(b.modelFile);
|
|
149
|
+
if (err)
|
|
150
|
+
missing.push(`model "${m.id}": ${err}`);
|
|
151
|
+
}
|
|
152
|
+
else if (!b?.url) {
|
|
153
|
+
missing.push(`model "${m.id}": endpoint URL`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
missing.push(...hardwareConflicts(req.hardwareChannels, inputs.hardware));
|
|
157
|
+
missing.push(...familyMismatches(req.hardwareChannels, inputs.hardware));
|
|
158
|
+
if (missing.length > 0) {
|
|
159
|
+
throw new Error(`invalid deploy config:\n - ${missing.join("\n - ")}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// One compose service per name: a duplicate name would collapse two components
|
|
163
|
+
// onto one service and silently drop the loser. Names only — same image under
|
|
164
|
+
// different names is legitimate (e.g. two grafanas).
|
|
165
|
+
function assertNoNameCollisions(components) {
|
|
166
|
+
const seen = new Set();
|
|
167
|
+
for (const c of components) {
|
|
168
|
+
if (seen.has(c.name))
|
|
169
|
+
throw new Error(`duplicate component name "${c.name}"`);
|
|
170
|
+
seen.add(c.name);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// buildDeploymentSpec resolves a workflow plus its bindings into a complete,
|
|
174
|
+
// contract-defined DeploymentSpec. Throws (via assertDeployable) if any declared
|
|
175
|
+
// resource is unbound. The embedded engine config carries the serialized (and
|
|
176
|
+
// thereby pruned) workflow; device grants and privileged are resolved here.
|
|
177
|
+
// customComponents are operator-authored containers, merged in verbatim.
|
|
178
|
+
export function buildDeploymentSpec(workflow, inputs, meta, customComponents = []) {
|
|
179
|
+
const req = deriveRequirements(workflow);
|
|
180
|
+
assertDeployable(req, inputs);
|
|
181
|
+
const refs = new RefAllocator();
|
|
182
|
+
const resourceSecrets = {};
|
|
183
|
+
// DeviceManifest is split per family; accumulate each separately, attach only
|
|
184
|
+
// the non-empty ones (all slots optional).
|
|
185
|
+
const gpios = {};
|
|
186
|
+
const adcs = {};
|
|
187
|
+
const dacs = {};
|
|
188
|
+
const pwms = {};
|
|
189
|
+
const serials = {};
|
|
190
|
+
const externalResources = {};
|
|
191
|
+
const mapping = {};
|
|
192
|
+
// Container-level hardware access, resolved once: cdev nodes (GPIO, UART) map
|
|
193
|
+
// one-to-one into the engine component's devices; sysfs families (ADC/DAC/PWM)
|
|
194
|
+
// have no single node, so the engine container runs privileged.
|
|
195
|
+
const cdev = new Set();
|
|
196
|
+
let privileged = false;
|
|
197
|
+
// Hardware: one driver instance per distinct device path (dedup by
|
|
198
|
+
// family+path); one mapping per channel carrying its per-channel index.
|
|
199
|
+
for (const ch of req.hardwareChannels) {
|
|
200
|
+
const b = inputs.hardware[ch.id];
|
|
201
|
+
if (!b)
|
|
202
|
+
throw new Error(`unbound hardware channel ${ch.id}`); // unreachable after assertDeployable
|
|
203
|
+
const dev = b.chipOrDevice;
|
|
204
|
+
const ref = refs.alloc(`hw:${ch.family}:${dev}`, basename(dev));
|
|
205
|
+
switch (ch.family) {
|
|
206
|
+
case "gpio":
|
|
207
|
+
gpios[ref] = { chip: dev };
|
|
208
|
+
cdev.add(dev);
|
|
209
|
+
break;
|
|
210
|
+
case "serial":
|
|
211
|
+
serials[ref] = b.baud ? { device: dev, baud: b.baud } : { device: dev };
|
|
212
|
+
cdev.add(dev);
|
|
213
|
+
break;
|
|
214
|
+
case "pwm":
|
|
215
|
+
pwms[ref] = { chip: dev };
|
|
216
|
+
privileged = true;
|
|
217
|
+
break;
|
|
218
|
+
case "adc":
|
|
219
|
+
adcs[ref] = { device: dev };
|
|
220
|
+
privileged = true;
|
|
221
|
+
break;
|
|
222
|
+
case "dac":
|
|
223
|
+
dacs[ref] = { device: dev };
|
|
224
|
+
privileged = true;
|
|
225
|
+
break;
|
|
226
|
+
default:
|
|
227
|
+
return assertNeverFamily(ch.family);
|
|
228
|
+
}
|
|
229
|
+
if (ch.addressable && b.index !== undefined)
|
|
230
|
+
mapping[ch.id] = { ref, index: b.index };
|
|
231
|
+
else
|
|
232
|
+
mapping[ch.id] = { ref };
|
|
233
|
+
}
|
|
234
|
+
// MQTT: one connection per distinct config (dedup by full content — same
|
|
235
|
+
// broker, different creds is a different resource). No index.
|
|
236
|
+
for (const ch of req.mqttChannels) {
|
|
237
|
+
const b = inputs.mqtt[ch.id];
|
|
238
|
+
if (!b)
|
|
239
|
+
throw new Error(`unbound mqtt channel ${ch.id}`); // unreachable
|
|
240
|
+
const conn = { type: "mqtt", brokerUrl: b.brokerUrl };
|
|
241
|
+
if (b.username)
|
|
242
|
+
conn.username = b.username;
|
|
243
|
+
// The password is a secret — kept out of conn (and thus the spec). It still
|
|
244
|
+
// participates in the dedup key, so two channels differing only by password
|
|
245
|
+
// don't collapse onto one ref (and one shared secret).
|
|
246
|
+
const ref = refs.alloc(`mqtt:${JSON.stringify(conn)}:${b.password ?? ""}`, `mqtt-${brokerHost(b.brokerUrl)}`);
|
|
247
|
+
externalResources[ref] = conn;
|
|
248
|
+
mapping[ch.id] = { ref };
|
|
249
|
+
if (b.password)
|
|
250
|
+
resourceSecrets[ref] = { ...resourceSecrets[ref], password: b.password };
|
|
251
|
+
}
|
|
252
|
+
// Custom models: one self-hosted provider per model id. A device model points
|
|
253
|
+
// at the sidecar we run (over the container network, no key) and gets its own
|
|
254
|
+
// llama-server component; a network model points at the operator's endpoint and
|
|
255
|
+
// runs no component here. `model` is left off — the endpoint serves under the
|
|
256
|
+
// workflow id (no upstream-name aliasing yet).
|
|
257
|
+
const llamaComponents = [];
|
|
258
|
+
for (const m of req.customModels) {
|
|
259
|
+
const b = inputs.models[m.id];
|
|
260
|
+
if (!b)
|
|
261
|
+
throw new Error(`unbound model ${m.id}`); // unreachable after assertDeployable
|
|
262
|
+
const ref = refs.alloc(`model:${m.id}`, basename(m.id));
|
|
263
|
+
mapping[m.id] = { ref };
|
|
264
|
+
if (b.location === "device") {
|
|
265
|
+
const port = b.port ?? 8080;
|
|
266
|
+
const service = sidecarServiceName(m.id);
|
|
267
|
+
externalResources[ref] = { type: "selfhosted", url: `http://${service}:${port}` };
|
|
268
|
+
// The whole config is CLI flags, so it rides in `command` (no config blob).
|
|
269
|
+
// ctx-size is frozen here — retuning it is a re-deploy, not an env edit.
|
|
270
|
+
llamaComponents.push({
|
|
271
|
+
name: service,
|
|
272
|
+
image: meta.llamaServerImage,
|
|
273
|
+
command: [
|
|
274
|
+
"--model",
|
|
275
|
+
`/models/${b.modelFile}`,
|
|
276
|
+
"--host",
|
|
277
|
+
"0.0.0.0",
|
|
278
|
+
"--port",
|
|
279
|
+
String(port),
|
|
280
|
+
"--ctx-size",
|
|
281
|
+
String(b.ctxSize ?? 4096),
|
|
282
|
+
],
|
|
283
|
+
volumes: ["./models:/models:ro"],
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
externalResources[ref] = { type: "selfhosted", url: b.url };
|
|
288
|
+
// The endpoint bearer is a secret — out of the spec, returned separately.
|
|
289
|
+
if (b.apiKey)
|
|
290
|
+
resourceSecrets[ref] = { apiKey: b.apiKey };
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
const manifest = {};
|
|
294
|
+
if (Object.keys(gpios).length)
|
|
295
|
+
manifest.gpios = gpios;
|
|
296
|
+
if (Object.keys(adcs).length)
|
|
297
|
+
manifest.adcs = adcs;
|
|
298
|
+
if (Object.keys(dacs).length)
|
|
299
|
+
manifest.dacs = dacs;
|
|
300
|
+
if (Object.keys(pwms).length)
|
|
301
|
+
manifest.pwms = pwms;
|
|
302
|
+
if (Object.keys(serials).length)
|
|
303
|
+
manifest.serials = serials;
|
|
304
|
+
// The engine's boot input. workflow is serialized (and thereby pruned) from
|
|
305
|
+
// the domain. The optional sections attach only when non-empty — an absent
|
|
306
|
+
// section is correct, not a gap, and matches what the engine skips.
|
|
307
|
+
const config = { workflow: serialize(workflow) };
|
|
308
|
+
if (Object.keys(mapping).length)
|
|
309
|
+
config.mapping = mapping;
|
|
310
|
+
if (Object.keys(externalResources).length)
|
|
311
|
+
config.externalResources = externalResources;
|
|
312
|
+
if (Object.keys(manifest).length)
|
|
313
|
+
config.manifest = manifest;
|
|
314
|
+
// The engine component. configPath is omitted (the image reads the convention
|
|
315
|
+
// path it defaults to); the config blob is mounted there by the renderer. cdev
|
|
316
|
+
// nodes pass through as devices; sysfs families force privileged; either case
|
|
317
|
+
// needs root to open the root-owned nodes the nonroot image otherwise can't.
|
|
318
|
+
const engine = {
|
|
319
|
+
name: "engine",
|
|
320
|
+
image: meta.engineImage,
|
|
321
|
+
pull: "never", // built locally before deploy, in no registry
|
|
322
|
+
config,
|
|
323
|
+
volumes: [`engine-memory:${ENGINE_MEMORY_PATH}`],
|
|
324
|
+
};
|
|
325
|
+
if (cdev.size > 0)
|
|
326
|
+
engine.devices = [...cdev];
|
|
327
|
+
if (privileged)
|
|
328
|
+
engine.privileged = true;
|
|
329
|
+
if (cdev.size > 0 || privileged)
|
|
330
|
+
engine.user = "0:0";
|
|
331
|
+
const components = [engine, ...llamaComponents, ...customComponents];
|
|
332
|
+
assertNoNameCollisions(components);
|
|
333
|
+
const spec = {
|
|
334
|
+
schemaVersion: 1,
|
|
335
|
+
id: meta.id,
|
|
336
|
+
status: meta.status,
|
|
337
|
+
components,
|
|
338
|
+
};
|
|
339
|
+
if (meta.createdAt)
|
|
340
|
+
spec.createdAt = meta.createdAt;
|
|
341
|
+
return { spec, resourceSecrets };
|
|
342
|
+
}
|
|
343
|
+
//# sourceMappingURL=spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/deploy/spec.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,6EAA6E;AAC7E,iFAAiF;AACjF,uEAAuE;AACvE,EAAE;AACF,gFAAgF;AAChF,uEAAuE;AAGvE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAUpD,oFAAoF;AACpF,kEAAkE;AAClE,MAAM,kBAAkB,GAAG,2BAA2B,CAAC;AA8BvD,8EAA8E;AAC9E,gFAAgF;AAChF,sEAAsE;AACtE,MAAM,YAAY;IACC,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IAClC,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE1C,KAAK,CAAC,GAAW,EAAE,IAAY;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC9B,IAAI,GAAG,GAAG,IAAI,CAAC;QACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,GAAG,GAAG,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC;QAC9D,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACzB,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAED,sDAAsD;AACtD,uEAAuE;AACvE,SAAS,QAAQ,CAAC,CAAS;IACzB,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACzD,OAAO,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,GAAG,CAAC,IAAI,KAAK,CAAC;AACzD,CAAC;AAED,qEAAqE;AACrE,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,IAAI,MAAM,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC;IAChB,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,gFAAgF;AAChF,2EAA2E;AAC3E,0CAA0C;AAC1C,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,MAAM,IAAI,GAAG,OAAO;SACjB,WAAW,EAAE;SACb,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC;SAC9B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC3B,OAAO,SAAS,IAAI,IAAI,OAAO,EAAE,CAAC;AACpC,CAAC;AAED,6EAA6E;AAC7E,gFAAgF;AAChF,8DAA8D;AAC9D,MAAM,UAAU,aAAa,CAAC,IAAwB;IACpD,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,CAAC;QAAE,OAAO,8BAA8B,CAAC;IAC9C,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,qDAAqD,CAAC;IACrG,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,4DAA4D,CAAC;IACzF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,gFAAgF;AAChF,0EAA0E;AAC1E,+EAA+E;AAC/E,8EAA8E;AAC9E,4EAA4E;AAC5E,MAAM,UAAU,kBAAkB,CAAC,MAAsB,EAAE,YAAoB,EAAE,KAAc;IAC7F,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC;IAChC,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;AAC7E,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,oBAAoB,CAAC,MAAsB,EAAE,YAAoB,EAAE,KAAc;IAC/F,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,MAAM,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IACpC,OAAO,GAAG,GAAG,IAAI,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,IAAI,KAAK,EAAE,CAAC;AACrE,CAAC;AAED,4EAA4E;AAC5E,wEAAwE;AACxE,MAAM,UAAU,iBAAiB,CAAC,QAA2B,EAAE,QAAyC;IACtG,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAC,uCAAuC;IAClF,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC,CAAC,EAAE,YAAY,IAAI,CAAC,EAAE,CAAC,WAAW,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC;YAAE,SAAS;QAC5E,MAAM,GAAG,GAAG,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QACnE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,MAAM,EAAE,CAAC;YACX,SAAS,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,wBAAwB,MAAM,GAAG,CAAC,CAAC;QACpI,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,8EAA8E;AAC9E,gFAAgF;AAChF,wEAAwE;AACxE,MAAM,UAAU,gBAAgB,CAAC,QAA2B,EAAE,QAAyC;IACrG,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,IAAI,EAAE,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACnD,UAAU,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,EAAE,wDAAwD,EAAE,CAAC,MAAM,WAAW,CAAC,CAAC;QAClH,CAAC;QACD,IAAI,EAAE,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YACpD,UAAU,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,EAAE,oFAAoF,CAAC,CAAC;QAC1H,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,6EAA6E;AAC7E,sBAAsB;AACtB,SAAS,iBAAiB,CAAC,CAAQ;IACjC,MAAM,IAAI,KAAK,CAAC,8BAA8B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED,+EAA+E;AAC/E,8EAA8E;AAC9E,4EAA4E;AAC5E,MAAM,UAAU,gBAAgB,CAAC,GAAuB,EAAE,MAAwB;IAChF,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACjC,IAAI,CAAC,CAAC,EAAE,YAAY;YAAE,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,EAAE,gBAAgB,CAAC,CAAC;aAClE,IAAI,EAAE,CAAC,WAAW,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IAC/F,CAAC;IACD,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,EAAE,eAAe,CAAC,CAAC;IAClF,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,EAAE,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACvC,IAAI,GAAG;gBAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC;QACnD,CAAC;aAAM,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1E,OAAO,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,+BAA+B,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,8EAA8E;AAC9E,qDAAqD;AACrD,SAAS,sBAAsB,CAAC,UAA6B;IAC3D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;QAC9E,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,6EAA6E;AAC7E,iFAAiF;AACjF,8EAA8E;AAC9E,4EAA4E;AAC5E,yEAAyE;AACzE,MAAM,UAAU,mBAAmB,CACjC,QAAkB,EAClB,MAAwB,EACxB,IAAwB,EACxB,mBAAsC,EAAE;IAExC,MAAM,GAAG,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACzC,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAE9B,MAAM,IAAI,GAAG,IAAI,YAAY,EAAE,CAAC;IAChC,MAAM,eAAe,GAAoB,EAAE,CAAC;IAE5C,8EAA8E;IAC9E,2CAA2C;IAC3C,MAAM,KAAK,GAAgD,EAAE,CAAC;IAC9D,MAAM,IAAI,GAA+C,EAAE,CAAC;IAC5D,MAAM,IAAI,GAA+C,EAAE,CAAC;IAC5D,MAAM,IAAI,GAA+C,EAAE,CAAC;IAC5D,MAAM,OAAO,GAAkD,EAAE,CAAC;IAElE,MAAM,iBAAiB,GAAuC,EAAE,CAAC;IACjE,MAAM,OAAO,GAAuC,EAAE,CAAC;IAEvD,8EAA8E;IAC9E,+EAA+E;IAC/E,gEAAgE;IAChE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,UAAU,GAAG,KAAK,CAAC;IAEvB,mEAAmE;IACnE,wEAAwE;IACxE,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,gBAAgB,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACjC,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,qCAAqC;QACnG,MAAM,GAAG,GAAG,CAAC,CAAC,YAAY,CAAC;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,MAAM,IAAI,GAAG,EAAE,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QAEhE,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC;YAClB,KAAK,MAAM;gBACT,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;gBAC3B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACd,MAAM;YACR,KAAK,QAAQ;gBACX,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;gBACxE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACd,MAAM;YACR,KAAK,KAAK;gBACR,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;gBAC1B,UAAU,GAAG,IAAI,CAAC;gBAClB,MAAM;YACR,KAAK,KAAK;gBACR,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;gBAC5B,UAAU,GAAG,IAAI,CAAC;gBAClB,MAAM;YACR,KAAK,KAAK;gBACR,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;gBAC5B,UAAU,GAAG,IAAI,CAAC;gBAClB,MAAM;YACR;gBACE,OAAO,iBAAiB,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,EAAE,CAAC,WAAW,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS;YAAE,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;;YACjF,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;IAChC,CAAC;IAED,yEAAyE;IACzE,8DAA8D;IAC9D,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC7B,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc;QACxE,MAAM,IAAI,GAAoC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC;QACvF,IAAI,CAAC,CAAC,QAAQ;YAAE,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC;QAC3C,4EAA4E;QAC5E,4EAA4E;QAC5E,uDAAuD;QACvD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,IAAI,EAAE,EAAE,EAAE,QAAQ,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAC9G,iBAAiB,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;QAC9B,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,QAAQ;YAAE,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,eAAe,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC3F,CAAC;IAED,8EAA8E;IAC9E,8EAA8E;IAC9E,gFAAgF;IAChF,8EAA8E;IAC9E,+CAA+C;IAC/C,MAAM,eAAe,GAAsB,EAAE,CAAC;IAC9C,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,qCAAqC;QACvF,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACxD,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;QAExB,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC;YAC5B,MAAM,OAAO,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACzC,iBAAiB,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,UAAU,OAAO,IAAI,IAAI,EAAE,EAAE,CAAC;YAClF,4EAA4E;YAC5E,yEAAyE;YACzE,eAAe,CAAC,IAAI,CAAC;gBACnB,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,IAAI,CAAC,gBAAgB;gBAC5B,OAAO,EAAE;oBACP,SAAS;oBACT,WAAW,CAAC,CAAC,SAAS,EAAE;oBACxB,QAAQ;oBACR,SAAS;oBACT,QAAQ;oBACR,MAAM,CAAC,IAAI,CAAC;oBACZ,YAAY;oBACZ,MAAM,CAAC,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC;iBAC1B;gBACD,OAAO,EAAE,CAAC,qBAAqB,CAAC;aACjC,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,iBAAiB,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;YAC5D,0EAA0E;YAC1E,IAAI,CAAC,CAAC,MAAM;gBAAE,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAoC,EAAE,CAAC;IACrD,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM;QAAE,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC;IACtD,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM;QAAE,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC;IACnD,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM;QAAE,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC;IACnD,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM;QAAE,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC;IACnD,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM;QAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC;IAE5D,4EAA4E;IAC5E,2EAA2E;IAC3E,oEAAoE;IACpE,MAAM,MAAM,GAAiB,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC/D,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM;QAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IAC1D,IAAI,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,MAAM;QAAE,MAAM,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;IACxF,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM;QAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAE7D,8EAA8E;IAC9E,+EAA+E;IAC/E,8EAA8E;IAC9E,6EAA6E;IAC7E,MAAM,MAAM,GAAoB;QAC9B,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,IAAI,CAAC,WAAW;QACvB,IAAI,EAAE,OAAO,EAAE,8CAA8C;QAC7D,MAAM;QACN,OAAO,EAAE,CAAC,iBAAiB,kBAAkB,EAAE,CAAC;KACjD,CAAC;IACF,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC;QAAE,MAAM,CAAC,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IAC9C,IAAI,UAAU;QAAE,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC;IACzC,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,UAAU;QAAE,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC;IAErD,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,GAAG,eAAe,EAAE,GAAG,gBAAgB,CAAC,CAAC;IACrE,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAEnC,MAAM,IAAI,GAAmB;QAC3B,aAAa,EAAE,CAAC;QAChB,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,UAAU;KACX,CAAC;IACF,IAAI,IAAI,CAAC,SAAS;QAAE,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IACpD,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;AACnC,CAAC"}
|
package/dist/node/OutputNode.js
CHANGED
|
@@ -45,9 +45,9 @@ export const SerialWriteNodeDefinition = {
|
|
|
45
45
|
{
|
|
46
46
|
id: "portReference",
|
|
47
47
|
label: "Port",
|
|
48
|
-
description: "Serial port to write to",
|
|
48
|
+
description: "Serial port or log channel to write to",
|
|
49
49
|
type: "channelSelect",
|
|
50
|
-
channelType: ["UART"],
|
|
50
|
+
channelType: ["UART", "LOG"],
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
id: "value",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OutputNode.js","sourceRoot":"","sources":["../../src/node/OutputNode.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAuBpD,mBAAmB;AAEnB,MAAM,CAAC,MAAM,sBAAsB,GAAmB;IACpD,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,WAAW;IAClB,QAAQ,EAAE,YAAY,CAAC,MAAM;IAC7B,IAAI,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;IACnB,WAAW,EAAE,qBAAqB;IAClC,UAAU,EAAE;QACV;YACE,EAAE,EAAE,cAAc;YAClB,KAAK,EAAE,KAAK;YACZ,WAAW,EAAE,oBAAoB;YACjC,IAAI,EAAE,eAAe;YACrB,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAE,IAAkC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;SACrH;QACD;YACE,EAAE,EAAE,YAAY;YAChB,KAAK,EAAE,aAAa;YACpB,WAAW,EAAE,gBAAgB;YAC7B,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,SAAS;YAClB,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;gBACtC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;aACrC;SACF;QACD;YACE,EAAE,EAAE,OAAO;YACX,KAAK,EAAE,OAAO;YACd,WAAW,EAAE,gCAAgC;YAC7C,IAAI,EAAE,YAAY;YAClB,cAAc,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAE,IAAkC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;YACzG,OAAO,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE;SAC9D;KACF;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAmB;IACvD,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,cAAc;IACrB,QAAQ,EAAE,YAAY,CAAC,MAAM;IAC7B,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;IACtB,WAAW,EAAE,6BAA6B;IAC1C,UAAU,EAAE;QACV;YACE,EAAE,EAAE,eAAe;YACnB,KAAK,EAAE,MAAM;YACb,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"OutputNode.js","sourceRoot":"","sources":["../../src/node/OutputNode.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAuBpD,mBAAmB;AAEnB,MAAM,CAAC,MAAM,sBAAsB,GAAmB;IACpD,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,WAAW;IAClB,QAAQ,EAAE,YAAY,CAAC,MAAM;IAC7B,IAAI,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;IACnB,WAAW,EAAE,qBAAqB;IAClC,UAAU,EAAE;QACV;YACE,EAAE,EAAE,cAAc;YAClB,KAAK,EAAE,KAAK;YACZ,WAAW,EAAE,oBAAoB;YACjC,IAAI,EAAE,eAAe;YACrB,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAE,IAAkC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;SACrH;QACD;YACE,EAAE,EAAE,YAAY;YAChB,KAAK,EAAE,aAAa;YACpB,WAAW,EAAE,gBAAgB;YAC7B,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,SAAS;YAClB,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;gBACtC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;aACrC;SACF;QACD;YACE,EAAE,EAAE,OAAO;YACX,KAAK,EAAE,OAAO;YACd,WAAW,EAAE,gCAAgC;YAC7C,IAAI,EAAE,YAAY;YAClB,cAAc,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAE,IAAkC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;YACzG,OAAO,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE;SAC9D;KACF;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAmB;IACvD,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,cAAc;IACrB,QAAQ,EAAE,YAAY,CAAC,MAAM;IAC7B,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;IACtB,WAAW,EAAE,6BAA6B;IAC1C,UAAU,EAAE;QACV;YACE,EAAE,EAAE,eAAe;YACnB,KAAK,EAAE,MAAM;YACb,WAAW,EAAE,wCAAwC;YACrD,IAAI,EAAE,eAAe;YACrB,WAAW,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC;SAC7B;QACD;YACE,EAAE,EAAE,OAAO;YACX,KAAK,EAAE,OAAO;YACd,WAAW,EAAE,mCAAmC;YAChD,IAAI,EAAE,YAAY;YAClB,cAAc,EAAE,QAAQ;YACxB,OAAO,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE;SAChE;KACF;CACF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foresthubai/workflow-core",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "Headless workflow types + serialization + pure validator. No React, no browser.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"access": "public"
|
|
90
90
|
},
|
|
91
91
|
"scripts": {
|
|
92
|
-
"generate": "openapi-typescript ../../contract/workflow.yaml -o src/api/workflow.ts",
|
|
92
|
+
"generate": "openapi-typescript ../../contract/workflow.yaml -o src/api/workflow.ts && openapi-typescript ../../contract/deployment.yaml -o src/api/deployment.ts && openapi-typescript ../../contract/engine.yaml -o src/api/engine.ts",
|
|
93
93
|
"build": "tsc -b",
|
|
94
94
|
"prepublishOnly": "npm run build",
|
|
95
95
|
"test": "vitest run"
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file was auto-generated by openapi-typescript.
|
|
3
|
+
* Do not make direct changes to the file.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type paths = Record<string, never>;
|
|
7
|
+
export type webhooks = Record<string, never>;
|
|
8
|
+
export interface components {
|
|
9
|
+
schemas: {
|
|
10
|
+
/** @description The resolved set of components to run on one device for one deployment, plus its identity and lifecycle status. Every decision (which components run, their images, device access, config file content) is computed once by the packaging step and frozen here, so a renderer renders it without re-deriving anything. The spec is the self-contained, restartable source of truth: spec + cached images + device-local env files are all a device needs to (re)start offline. */
|
|
11
|
+
DeploymentSpec: {
|
|
12
|
+
/** @description Spec format version. Bumped when the spec shape changes incompatibly. */
|
|
13
|
+
schemaVersion: number;
|
|
14
|
+
/** @description Stable identifier for this deployment, used as the rollback/history key. */
|
|
15
|
+
id: string;
|
|
16
|
+
/**
|
|
17
|
+
* Format: date-time
|
|
18
|
+
* @description When the packaging step produced this spec. Stamped by the producer; drives deployment history ordering.
|
|
19
|
+
*/
|
|
20
|
+
createdAt?: string;
|
|
21
|
+
/**
|
|
22
|
+
* @description Whether this spec is the one a device should currently be running. The active spec is the reconcile/render target; inactive specs are history or rollback candidates.
|
|
23
|
+
* @enum {string}
|
|
24
|
+
*/
|
|
25
|
+
status: "active" | "inactive";
|
|
26
|
+
/** @description The components to run for this deployment, each a fully resolved container. The list is unordered: components do not declare dependencies on one another. Coupling between components (e.g. the engine reaching an on-device model) is expressed as a URL the consumer connects to at runtime with retry, never as a start-ordering edge, so the model works identically whether the dependency runs on this device or another one. The packaging step expands any one-to-many component (e.g. one llama-server image per on-device model) into separate concrete entries here. */
|
|
27
|
+
components: components["schemas"]["DeployComponent"][];
|
|
28
|
+
};
|
|
29
|
+
/** @description One resolved container to run as part of a deployment. Generic by design: it carries only runtime-neutral container knobs the renderer passes through, never a component-typed config schema. A component's own config shape lives in that component's contract (e.g. the engine's EngineConfig in engine.yaml), referenced directly by whoever produces and consumes that config; this spec only transports the rendered config content as opaque file bytes. Adding a component, OSS or paid, means producing one of these, not editing this contract. */
|
|
30
|
+
DeployComponent: {
|
|
31
|
+
/** @description Unique component name within the deployment. Doubles as the container/service name the renderer emits, the basename of any device-local env file the operator supplies ("<name>.env"), and the address other components reach this one by over the container network. */
|
|
32
|
+
name: string;
|
|
33
|
+
/** @description OCI image reference, frozen at packaging time. OSS: a local convention tag built before deploy, e.g. "foresthub/engine:local". Paid: a registry-qualified, digest-pinned ref the ranger resolves and freezes, e.g. "ghcr.io/foresthubai/engine:1.2.0@sha256:abc123...". Which registry and how the daemon authenticates to it are device-side config, not part of this string. */
|
|
34
|
+
image: string;
|
|
35
|
+
/**
|
|
36
|
+
* @description Image pull policy, emitted as the renderer's pull_policy. Omit to default to "missing" (pull only if absent locally — correct for any registry image). Use "never" for an image built locally and present in no registry (the OSS engine); "always" re-pulls on every start.
|
|
37
|
+
* @enum {string}
|
|
38
|
+
*/
|
|
39
|
+
pull?: "always" | "missing" | "never";
|
|
40
|
+
/** @description Overrides the image's default command/entrypoint arguments, in exec form — one token per element, e.g. ["--model", "/models/x.gguf", "--ctx-size", "4096"]. Runtime-neutral: every runtime can override a container's command. Lets a CLI-flag-configured image (llama-server and many third-party servers) run unwrapped — the packaging step puts the flags here instead of baking a JSON-to-flags translation into a wrapper image. Omit to use the image's own default command. */
|
|
41
|
+
command?: string[];
|
|
42
|
+
/** @description Structured config for the component, frozen at packaging time. The renderer serializes it to JSON, writes it to a device-local file, bind-mounts that file read-only at configPath, and hashes it into a recreate trigger (compose does not track bind-mount content). How the component interprets the file — read it as JSON, convert it to CLI args, expand it into several native config files — is the image's entrypoint, not this spec; a non-JSON image is wrapped with a thin entrypoint that converts. Omit for a component configured only by its image defaults and its device-local env. Never contains secrets; those arrive as environment variables from the device-local env file. */
|
|
43
|
+
config?: {
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
};
|
|
46
|
+
/** @description Absolute in-container path to mount the config file at. Omit to use the convention default "/etc/foresthub/config.json", which first-party components read by default. Set it to drop in a JSON-configured third-party image that reads its config elsewhere, e.g. "/app/config.json". Ignored when config is absent. */
|
|
47
|
+
configPath?: string;
|
|
48
|
+
/** @description Persistent or host volume mounts in compose short form, e.g. "engine-memory:/var/lib/foresthub/memory" or "./models:/models:ro". Empty when the component is stateless and mounts nothing beyond its config files. */
|
|
49
|
+
volumes?: string[];
|
|
50
|
+
/** @description Resolved host device nodes to pass into the container, e.g. "/dev/gpiochip0", "/dev/ttyUSB0". One entry per distinct cdev node the component binds, computed once from the workflow's hardware against the device manifest. Empty when the component uses no cdev hardware; ADC/DAC/PWM have no single node and go through privileged instead. */
|
|
51
|
+
devices?: string[];
|
|
52
|
+
/** @description Host port publishings in compose short form, e.g. "1883:1883". Empty when the component is reached only over the internal container network (the common case: components address each other by name, no host exposure needed). */
|
|
53
|
+
ports?: string[];
|
|
54
|
+
/** @description Run the container privileged. Required for hardware with no single device node to grant (ADC/DAC/PWM use sysfs paths like /sys/class/pwm, /sys/bus/iio). False when the component uses only cdev hardware (use devices) or none. */
|
|
55
|
+
privileged?: boolean;
|
|
56
|
+
/** @description Container user as "UID[:GID]", e.g. "0:0" for root. The renderer passes it through verbatim. Needed when a nonroot image must reach root-owned resources: the engine image runs nonroot but has to open the root-owned device nodes / sysfs files granted via devices/privileged, so its component sets "0:0". Omit to use the image's own default user. */
|
|
57
|
+
user?: string;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
responses: never;
|
|
61
|
+
parameters: never;
|
|
62
|
+
requestBodies: never;
|
|
63
|
+
headers: never;
|
|
64
|
+
pathItems: never;
|
|
65
|
+
}
|
|
66
|
+
export type $defs = Record<string, never>;
|
|
67
|
+
export type operations = Record<string, never>;
|