@foresthubai/workflow-cli 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 +661 -661
- package/NOTICE +23 -23
- package/README.md +137 -137
- package/dist/assets/index-CiLOHdeR.css +1 -0
- package/dist/assets/{index-LJpK2FES.js → index-D7a-pqL0.js} +11 -11
- package/dist/index.html +14 -14
- package/dist-cli/cli.js +1232 -483
- package/dist-cli/deployment.yaml +83 -0
- package/dist-cli/llmproxy.yaml +300 -300
- package/dist-cli/workflow.yaml +912 -895
- package/package.json +2 -3
- package/dist/assets/index-CnM-MQ9w.css +0 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
openapi: 3.0.3
|
|
2
|
+
info:
|
|
3
|
+
title: ForestHub Deployment Spec Contract
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
description: "Resolved, contract-defined description of a device's component set for one deployment (types only). Produced once by a packaging step (the CLI for the OSS path, the FE/backend for the paid path) and consumed two ways: the OSS one-shot CLI renders it to containers and exits; the paid ranger reconciles desired-vs-actual against it. Components are generic: the spec never names engine, llama-server, or any specific component, so a new OSS or paid component is added without touching this contract."
|
|
6
|
+
|
|
7
|
+
paths: {}
|
|
8
|
+
components:
|
|
9
|
+
schemas:
|
|
10
|
+
DeploymentSpec:
|
|
11
|
+
type: object
|
|
12
|
+
required: [schemaVersion, id, status, components]
|
|
13
|
+
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."
|
|
14
|
+
properties:
|
|
15
|
+
schemaVersion:
|
|
16
|
+
type: integer
|
|
17
|
+
minimum: 1
|
|
18
|
+
description: "Spec format version. Bumped when the spec shape changes incompatibly."
|
|
19
|
+
id:
|
|
20
|
+
type: string
|
|
21
|
+
description: "Stable identifier for this deployment, used as the rollback/history key."
|
|
22
|
+
createdAt:
|
|
23
|
+
type: string
|
|
24
|
+
format: date-time
|
|
25
|
+
description: "When the packaging step produced this spec. Stamped by the producer; drives deployment history ordering."
|
|
26
|
+
status:
|
|
27
|
+
type: string
|
|
28
|
+
enum: [active, inactive]
|
|
29
|
+
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."
|
|
30
|
+
components:
|
|
31
|
+
type: array
|
|
32
|
+
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."
|
|
33
|
+
items:
|
|
34
|
+
$ref: "#/components/schemas/DeployComponent"
|
|
35
|
+
|
|
36
|
+
DeployComponent:
|
|
37
|
+
type: object
|
|
38
|
+
required: [name, image]
|
|
39
|
+
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."
|
|
40
|
+
properties:
|
|
41
|
+
name:
|
|
42
|
+
type: string
|
|
43
|
+
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.'
|
|
44
|
+
image:
|
|
45
|
+
type: string
|
|
46
|
+
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.'
|
|
47
|
+
pull:
|
|
48
|
+
type: string
|
|
49
|
+
enum: [always, missing, never]
|
|
50
|
+
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.'
|
|
51
|
+
command:
|
|
52
|
+
type: array
|
|
53
|
+
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.'
|
|
54
|
+
items:
|
|
55
|
+
type: string
|
|
56
|
+
config:
|
|
57
|
+
type: object
|
|
58
|
+
additionalProperties: true
|
|
59
|
+
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."
|
|
60
|
+
configPath:
|
|
61
|
+
type: string
|
|
62
|
+
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.'
|
|
63
|
+
volumes:
|
|
64
|
+
type: array
|
|
65
|
+
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.'
|
|
66
|
+
items:
|
|
67
|
+
type: string
|
|
68
|
+
devices:
|
|
69
|
+
type: array
|
|
70
|
+
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.'
|
|
71
|
+
items:
|
|
72
|
+
type: string
|
|
73
|
+
ports:
|
|
74
|
+
type: array
|
|
75
|
+
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).'
|
|
76
|
+
items:
|
|
77
|
+
type: string
|
|
78
|
+
privileged:
|
|
79
|
+
type: boolean
|
|
80
|
+
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."
|
|
81
|
+
user:
|
|
82
|
+
type: string
|
|
83
|
+
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.'
|