@ours.network/install 1.1.1 → 1.2.0-nightly.2
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 +196 -6
- package/assets/Dockerfile +41 -0
- package/assets/docker-compose.yaml +222 -0
- package/assets/scripts/README.md +20 -0
- package/assets/scripts/build/README.md +39 -0
- package/assets/scripts/build/build-common.mjs +37 -0
- package/assets/scripts/build/build-cowork.mjs +2 -0
- package/assets/scripts/build/build-fleet.mjs +2 -0
- package/assets/scripts/build/build-mcp.mjs +9 -0
- package/assets/scripts/build/build-messenger.mjs +2 -0
- package/assets/scripts/build/build-sdk.mjs +9 -0
- package/assets/scripts/build/build-telegram.mjs +2 -0
- package/assets/scripts/build/build.mjs +49 -0
- package/assets/scripts/build/record-build.mjs +31 -0
- package/assets/scripts/maintenance/README.md +35 -0
- package/assets/scripts/maintenance/build-context.mjs +162 -0
- package/assets/scripts/maintenance/docker-layout-conversion.mjs +238 -0
- package/assets/scripts/maintenance/provenance-compare.mjs +160 -0
- package/assets/scripts/maintenance/state-archive.mjs +238 -0
- package/assets/scripts/maintenance/state-native.mjs +56 -0
- package/assets/scripts/maintenance/state-operation.mjs +249 -0
- package/assets/scripts/runtime/README.md +24 -0
- package/assets/scripts/runtime/check-client.mjs +21 -0
- package/assets/scripts/runtime/check-start.mjs +15 -0
- package/assets/scripts/runtime/client-setup.mjs +197 -0
- package/assets/scripts/runtime/entrypoint.sh +13 -0
- package/assets/scripts/runtime/health-cowork.sh +11 -0
- package/assets/scripts/runtime/health-messenger.mjs +6 -0
- package/assets/scripts/runtime/health-telegram.sh +8 -0
- package/assets/scripts/runtime/healthcheck.mjs +17 -0
- package/assets/scripts/runtime/runtime-common.mjs +47 -0
- package/assets/scripts/runtime/start-cowork.sh +6 -0
- package/assets/scripts/runtime/start-messenger.sh +6 -0
- package/assets/scripts/runtime/start-telegram.sh +6 -0
- package/assets/sources.json +21 -0
- package/install.sh +2 -1
- package/lib/build-transition.mjs +56 -0
- package/lib/docker-conversion-runtime.mjs +96 -0
- package/lib/docker-layout-installation.mjs +62 -0
- package/lib/effects.mjs +945 -11
- package/lib/extras.mjs +23 -68
- package/lib/layout-conversion.mjs +297 -0
- package/lib/orchestrate-uninstall.mjs +30 -1
- package/lib/orchestrate.mjs +265 -18
- package/lib/plan.mjs +194 -1
- package/lib/target.mjs +100 -0
- package/lib/usage.mjs +27 -2
- package/package.json +9 -2
- package/uninstall.sh +2 -0
package/README.md
CHANGED
|
@@ -42,10 +42,9 @@ connector from another daemon still require explicit confirmation.
|
|
|
42
42
|
installations.
|
|
43
43
|
- Configures and starts cowork as a durable shim over the shared daemon.
|
|
44
44
|
- Configures and starts Telegram as a durable shim over the same daemon.
|
|
45
|
-
- Runs Fleet's
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
`~/fleet.yaml` is never overwritten.
|
|
45
|
+
- Runs Fleet's native initialization through prepared settings or its interactive wizard. Fleet owns and
|
|
46
|
+
publishes its v2 configuration, including subscriptions, models, roles,
|
|
47
|
+
templates, and permissions. The installer does not start Fleet roles.
|
|
49
48
|
|
|
50
49
|
The operator CLI owns daemon configuration, lifecycle, and boot persistence.
|
|
51
50
|
The MCP package is only the stdio adapter spawned by agent harnesses; the
|
|
@@ -66,7 +65,7 @@ managed service and old state, then initialize the new major. The default answer
|
|
|
66
65
|
Only Fleet is intentionally not started. Review and activate it when ready:
|
|
67
66
|
|
|
68
67
|
```sh
|
|
69
|
-
# After reviewing ~/fleet.yaml:
|
|
68
|
+
# After completing Fleet's wizard and reviewing ~/fleet.yaml:
|
|
70
69
|
ours-fleet doctor
|
|
71
70
|
ours-fleet config
|
|
72
71
|
ours-fleet up
|
|
@@ -97,6 +96,16 @@ cannot store an environment value; for those harnesses the installer prints the
|
|
|
97
96
|
exact `export OURS_CONFIG=...` line that must be added to the shell profile
|
|
98
97
|
before starting the harness. There is no per-application daemon.
|
|
99
98
|
|
|
99
|
+
`OURS_CONFIG` may also name a prepared private host profile containing the
|
|
100
|
+
complete `endpoint`, `expectedInstanceId`, and absolute `credentialPath` tuple.
|
|
101
|
+
The profile and credential must already be regular current-user files with
|
|
102
|
+
private permissions. In this mode the installer verifies `/selection` before
|
|
103
|
+
sending the credential to `/version`, installs only MCP, detected Claude/Codex
|
|
104
|
+
plugins, and Fleet client support, and never creates, starts, stops, or services
|
|
105
|
+
a host daemon. Telegram, cowork, messenger, daemon voice, and daemon state stay
|
|
106
|
+
Compose-owned. If `OURS_CONFIG` is unset, the same profile is discovered at
|
|
107
|
+
`~/.ours/config.json`; a legacy config there keeps the existing local behavior.
|
|
108
|
+
|
|
100
109
|
## Uninstall
|
|
101
110
|
|
|
102
111
|
```sh
|
|
@@ -108,6 +117,10 @@ The uninstaller delegates service and daemon removal to the `ours` CLI. Identity
|
|
|
108
117
|
state is retained by default. Purging requires the existing destructive gates and
|
|
109
118
|
targets only the explicit state directory.
|
|
110
119
|
|
|
120
|
+
When `OURS_CONFIG` selects a host profile, uninstall removes only selected
|
|
121
|
+
client attachments. The operator-owned profile and shared credential are kept
|
|
122
|
+
even with `--purge`, and no Compose daemon, service, or state is touched.
|
|
123
|
+
|
|
111
124
|
## Release channel
|
|
112
125
|
|
|
113
126
|
`OURS_CHANNEL=nightly` (or `OURS_INSTALL_CHANNEL`) selects the packages' nightly
|
|
@@ -120,6 +133,183 @@ both channels.
|
|
|
120
133
|
- `OURS_ASSUME_YES=1`: accept safe defaults without prompting.
|
|
121
134
|
- `OURS_INSTALL_DRY_RUN=1`: preview without mutation.
|
|
122
135
|
- `OURS_NPM`: npm executable.
|
|
123
|
-
- `OURS_CONFIG`: explicit daemon
|
|
136
|
+
- `OURS_CONFIG`: explicit legacy daemon config or prepared private host profile.
|
|
124
137
|
- `OURS_STATE_DIR`: explicit daemon state directory.
|
|
125
138
|
- `OURS_CHANNEL`: `latest` or `nightly`.
|
|
139
|
+
|
|
140
|
+
## Selected network installations (2.0)
|
|
141
|
+
|
|
142
|
+
The installed package carries its compatible `assets/sources.json` policy.
|
|
143
|
+
`--sources` remains available as an explicit development override. Feature
|
|
144
|
+
revisions in the testing delivery remain unpublished; local build evidence does
|
|
145
|
+
not prove remote fetchability or compatibility of a replacement source set.
|
|
146
|
+
|
|
147
|
+
```sh
|
|
148
|
+
ours-install server install --mode docker --state-dir /private/ours-install
|
|
149
|
+
ours-install server install --mode packages --state-dir /private/ours-install
|
|
150
|
+
ours-install server status --state-dir /private/ours-install
|
|
151
|
+
ours-install server stop --state-dir /private/ours-install
|
|
152
|
+
ours-install server start --state-dir /private/ours-install
|
|
153
|
+
ours-install server restart --state-dir /private/ours-install
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Choose one mode for a private installation root. The private `installation.json`
|
|
157
|
+
records mode, instance selection, configuration/source paths and service selection;
|
|
158
|
+
it never records master bytes or an issued-token registry. The selected policy
|
|
159
|
+
is resolved to an exact, role-filtered `sources.json` before acquisition.
|
|
160
|
+
Repeated installation retains that concrete selection,
|
|
161
|
+
settings and state and repairs credential delivery without rotating the master.
|
|
162
|
+
Conflicting modes or source mappings are refused. Docker Compose is an internal
|
|
163
|
+
diagnostic artifact under the root's `runtime` directory; all installer calls use
|
|
164
|
+
an explicit project directory, Compose file, project name and selected environment.
|
|
165
|
+
Assets resolve from the installed package, independently of the working directory.
|
|
166
|
+
|
|
167
|
+
Package mode requires Node.js 22+, npm and a working systemd user manager on
|
|
168
|
+
Linux/WSL or a launchd GUI user domain on macOS. Source builds also require Git,
|
|
169
|
+
Python 3, a C/C++ toolchain, make, and the selected repositories' own prerequisites.
|
|
170
|
+
Docker mode requires a working Docker engine and Compose 2.35+; its build image
|
|
171
|
+
contains the source-build prerequisites. No bind or Docker socket mounts are used.
|
|
172
|
+
Server runtime installation selects SDK/CLI, main MCP, Telegram, Cowork and
|
|
173
|
+
Messenger. Main MCP is injected into the daemon, not started as a second daemon.
|
|
174
|
+
The daemon starts first; consumers are checked through their owning readiness
|
|
175
|
+
interfaces. Messenger uses its existing identity prerequisite and never creates an
|
|
176
|
+
identity. Its failure is reported after attempting unrelated consumers. Package
|
|
177
|
+
mode uses an installer-owned per-installation systemd/launchd Messenger service
|
|
178
|
+
for `ours-messenger-server serve`; other services use their owning CLIs.
|
|
179
|
+
Native daemon stop invokes the owning CLI's guarded `uninstall-service --yes`
|
|
180
|
+
before its process/endpoint stop and verifies the selected job is unloaded or
|
|
181
|
+
inactive. This removes its boot-service definition so the manager cannot respawn
|
|
182
|
+
a writer during authority operations. A later selected start uses the owning
|
|
183
|
+
`install-service --yes` to recreate it. Replacement/restart restore only previously
|
|
184
|
+
running services; an excluded stopped daemon keeps its service removed.
|
|
185
|
+
|
|
186
|
+
```sh
|
|
187
|
+
ours-install server access-issue --state-dir /private/ours-install --output /private/client/credential
|
|
188
|
+
ours-install server access-replace --state-dir /private/ours-install --confirm
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Fresh Docker preparation leaves daemon state containing only its selected config.
|
|
192
|
+
Only after owning `access-init` succeeds are daemon provenance and MCP profile
|
|
193
|
+
files materialized, so fresh setup never needs an inferred migration.
|
|
194
|
+
Initial setup calls owning CLI `access-init`, then `access-issue --replace` for
|
|
195
|
+
managed credential destinations. Explicit legacy migration adds `--migrate` to
|
|
196
|
+
`server install`; migration is never inferred. Global replacement stops consumers
|
|
197
|
+
and the daemon, calls `access-replace` once, repairs managed credential delivery,
|
|
198
|
+
and restarts only previously running services. If delivery/startup fails after
|
|
199
|
+
replacement, the new master remains authoritative and setup is reported incomplete.
|
|
200
|
+
Repeat ordinary `server install` to repair delivery without another rotation.
|
|
201
|
+
Separately configured clients need newly issued credentials after replacement.
|
|
202
|
+
Docker issuance copies only a newly issued file from an administrative container
|
|
203
|
+
into private host staging, publishes to an absent protected destination and removes
|
|
204
|
+
the temporary administrative container. It never transfers the master.
|
|
205
|
+
|
|
206
|
+
For client-only installation, supply a private complete network profile with
|
|
207
|
+
client-owned installer settings:
|
|
208
|
+
|
|
209
|
+
```json
|
|
210
|
+
{
|
|
211
|
+
"endpoint": "http://server:3050",
|
|
212
|
+
"expectedInstanceId": "12345678-1234-1234-1234-123456789abc",
|
|
213
|
+
"credentialPath": "/private/client/credential",
|
|
214
|
+
"installer": {
|
|
215
|
+
"integrations": ["codex", "claude-code", "fleet"],
|
|
216
|
+
"fleetSettingsPath": "fleet-settings.json"
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
```sh
|
|
222
|
+
ours-install client install --config /private/client/profile.json
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Optional `sourcesPath` and `fleetSettingsPath` values are absolute or resolved
|
|
226
|
+
relative to the profile file. Select any nonempty subset of integrations; Fleet is optional.
|
|
227
|
+
When Fleet settings are supplied, the installer passes them to Fleet's strict
|
|
228
|
+
noninteractive `init --settings`; otherwise it opens Fleet's existing wizard.
|
|
229
|
+
Fleet validates and publishes its own configuration. Client setup verifies the selected
|
|
230
|
+
daemon and packaged OURS MCP before registering native integrations. It acquires
|
|
231
|
+
only selected integration packages and their actual client dependencies. It does
|
|
232
|
+
not install main MCP, administer daemon state or invoke Docker. Exact npm client
|
|
233
|
+
installation needs no Python; Git source builds use the supplied source recipes
|
|
234
|
+
and their build prerequisites. Normal native clients need neither Docker nor
|
|
235
|
+
server maintenance tools.
|
|
236
|
+
|
|
237
|
+
Installer imports the profile, issued token, source manifest and optional Fleet
|
|
238
|
+
settings into `~/.ours-client/` (directory 0700, files 0600). The saved profile is
|
|
239
|
+
`profile.json`, referencing the imported `credential`. Original input files are
|
|
240
|
+
left untouched and may be moved or removed after setup. Ordinary new Codex,
|
|
241
|
+
Claude and Fleet invocations discover the saved server without an environment
|
|
242
|
+
export. Explicit `OURS_CONFIG` still overrides new invocations; installer reports
|
|
243
|
+
an existing override and does not edit shell configuration or running sessions.
|
|
244
|
+
|
|
245
|
+
Repeat with `ours-install client install` to reuse imported inputs and installed
|
|
246
|
+
package records. Existing settings and Fleet-generated files are preserved. A
|
|
247
|
+
prepared profile for the same endpoint/instance may supply a valid replacement
|
|
248
|
+
issued token; another server is refused without changing the default. Invalid
|
|
249
|
+
server access is rejected before import. An acquisition or component failure
|
|
250
|
+
reports incomplete setup and keeps the saved configuration for retry. Selected
|
|
251
|
+
native integrations whose executable is unavailable are incomplete, not installed.
|
|
252
|
+
Source repositories or registry access remain prerequisites when packages still
|
|
253
|
+
need to be acquired; they are not runtime configuration dependencies.
|
|
254
|
+
|
|
255
|
+
Interactive no-argument installation asks for package/Docker server mode, a
|
|
256
|
+
prepared client profile, or `client`. Client setup offers the saved server when
|
|
257
|
+
present. On first setup it asks for the server HTTP endpoint, issued-token file,
|
|
258
|
+
source manifest and integration choices, obtains the instance UUID from
|
|
259
|
+
`/selection`, displays it, then checks authenticated daemon and MCP access before
|
|
260
|
+
saving anything. No UUID must be entered manually. The 2.0 HTTP flow assumes the
|
|
261
|
+
approved trusted same-host deployment; selection metadata is not cryptographic
|
|
262
|
+
server authentication. Fleet collects missing setup answers through its own wizard.
|
|
263
|
+
This network flow never
|
|
264
|
+
creates a Human identity. Legacy explicitly selected local flows are retained.
|
|
265
|
+
|
|
266
|
+
For a managed server, maintenance runs on the server machine through the installer:
|
|
267
|
+
|
|
268
|
+
```sh
|
|
269
|
+
ours-install server backup server snapshot --state-dir /path/to/installation
|
|
270
|
+
ours-install server restore server snapshot --state-dir /path/to/installation
|
|
271
|
+
ours-install server rebuild --state-dir /path/to/installation
|
|
272
|
+
ours-install server update --state-dir /path/to/installation --compatible
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
Backup and restore support the full server or an individual `daemon`, `telegram`,
|
|
276
|
+
`cowork`, or `messenger` domain. Reset requires an individual domain and `--confirm`.
|
|
277
|
+
The installer stops affected writers and preserves a validated pre-operation
|
|
278
|
+
backup before restore, reset, or update. Restore retains current access authority.
|
|
279
|
+
|
|
280
|
+
Rebuild uses the saved exact source selection. Update resolves the packaged policy,
|
|
281
|
+
or an explicitly supplied development override, into a retained replacement.
|
|
282
|
+
Preparation does not replace the active runtime. Rebuild requires the same selected sources and equivalent verified dependency records.
|
|
283
|
+
Different JSON ordering is harmless; different package bytes or dependency edges refuse
|
|
284
|
+
rebuild. Fresh builds record the verified vendor archive bindings so staging paths
|
|
285
|
+
can differ without ignoring package integrity.
|
|
286
|
+
Changed sources require reviewed storage compatibility through explicit update with `--compatible`; this flag
|
|
287
|
+
attests to external evidence and does not establish compatibility by itself.
|
|
288
|
+
Services stop before state/runtime publication, and only previously running services
|
|
289
|
+
resume. Credentials and identities are not regenerated.
|
|
290
|
+
|
|
291
|
+
If activation fails, repeat the same update/rebuild command and retain its input
|
|
292
|
+
manifest. The installer resumes its saved candidate rather than fetching another
|
|
293
|
+
build. `server status` reports the pending phase; `server stop` remains available.
|
|
294
|
+
Other mutations refuse until activation completes. There is no automatic rollback
|
|
295
|
+
of application state after publication.
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
New builds retain `build-context.json` alongside their original lockfile and dependency
|
|
299
|
+
tree. The context binds the original record bytes to verified vendor tar names,
|
|
300
|
+
versions and integrity. Only proven top-level vendor staging paths are normalized;
|
|
301
|
+
lockfile integrity and other dependency references remain unchanged. An invalid or
|
|
302
|
+
unknown context is an error, including with `--compatible`.
|
|
303
|
+
|
|
304
|
+
Older records without a context retain their conservative comparison. If a rebuild
|
|
305
|
+
is refused because historical staging evidence is unavailable, use a reviewed
|
|
306
|
+
`server update --compatible` to establish a newly verified context; this operation
|
|
307
|
+
preserves the original record set in the pre-update backup. The flag is an explicit
|
|
308
|
+
storage-compatibility attestation, not proof of compatibility or a way to reconstruct
|
|
309
|
+
missing historic evidence. Startup never adds a context to existing legacy markers.
|
|
310
|
+
|
|
311
|
+
Backups with a context use archive format2; legacy backups remain format1. Updated
|
|
312
|
+
maintenance reads both formats. Format2 is not readable by older maintenance tools,
|
|
313
|
+
so this change does not promise executable downgrade support. Restore validates the
|
|
314
|
+
original archive records unchanged, then writes markers for the active target runtime.
|
|
315
|
+
Mixed/incomplete context and component record sets are refused before activation.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# syntax=docker/dockerfile:1
|
|
2
|
+
FROM node:24 AS toolchain
|
|
3
|
+
RUN apt-get update && apt-get install -y --no-install-recommends build-essential python3 ca-certificates git && rm -rf /var/lib/apt/lists/*
|
|
4
|
+
FROM toolchain AS build
|
|
5
|
+
WORKDIR /opt/ours
|
|
6
|
+
COPY sources.json /opt/ours/sources.json
|
|
7
|
+
COPY scripts/build/*.mjs /build-scripts/
|
|
8
|
+
COPY scripts/maintenance/build-context.mjs scripts/maintenance/provenance-compare.mjs /maintenance/
|
|
9
|
+
RUN --mount=type=secret,id=github_token --mount=type=cache,id=ours-dist-2-npm,target=/root/.npm,sharing=locked node /build-scripts/build.mjs
|
|
10
|
+
# Testing delivery: npm resolves transitive versions afresh; repeat builds may differ.
|
|
11
|
+
# build.mjs creates package.json once from the sources.json selections.
|
|
12
|
+
# Keep npm's generated lock and resolved tree in the image for this build's provenance.
|
|
13
|
+
RUN --mount=type=cache,id=ours-dist-2-npm,target=/root/.npm,sharing=locked npm install --omit=dev --no-audit --no-fund
|
|
14
|
+
RUN node /build-scripts/record-build.mjs
|
|
15
|
+
# Build provenance is non-secret, root-owned image content; arbitrary runtime UIDs
|
|
16
|
+
# must be able to read it. Protected state/host copies retain private ownership.
|
|
17
|
+
RUN chmod 755 /opt/ours /opt/ours/docker /opt/ours/docker/vendor && chmod 644 package.json package-lock.json dependency-tree.json build-context.json docker/vendor/*.tgz
|
|
18
|
+
LABEL network.ours.build-context="1"
|
|
19
|
+
COPY scripts/maintenance/build-context.mjs scripts/maintenance/provenance-compare.mjs /opt/ours/maintenance/
|
|
20
|
+
COPY scripts/runtime/runtime-common.mjs /opt/ours/docker/runtime-common.mjs
|
|
21
|
+
COPY scripts/runtime/check-client.mjs /opt/ours/docker/check-client.mjs
|
|
22
|
+
COPY scripts/runtime/check-start.mjs /opt/ours/docker/check-start.mjs
|
|
23
|
+
COPY scripts/runtime/client-setup.mjs /opt/ours/docker/client-setup.mjs
|
|
24
|
+
COPY scripts/runtime/entrypoint.sh /opt/ours/docker/entrypoint.sh
|
|
25
|
+
COPY scripts/runtime/healthcheck.mjs /opt/ours/docker/healthcheck.mjs
|
|
26
|
+
COPY scripts/runtime/start-telegram.sh scripts/runtime/health-telegram.sh scripts/runtime/start-cowork.sh scripts/runtime/health-cowork.sh scripts/runtime/start-messenger.sh scripts/runtime/health-messenger.mjs /opt/ours/docker/
|
|
27
|
+
FROM node:24 AS maintenance
|
|
28
|
+
LABEL network.ours.build-context="1"
|
|
29
|
+
WORKDIR /opt/ours
|
|
30
|
+
COPY --from=build /opt/ours /opt/ours
|
|
31
|
+
COPY scripts/maintenance/*.mjs /opt/ours/docker/
|
|
32
|
+
COPY --chmod=644 scripts/maintenance/package.json /opt/ours/docker/package.json
|
|
33
|
+
RUN --mount=type=cache,id=ours-dist-2-npm,target=/root/.npm,sharing=locked npm install --prefix /opt/ours/docker --omit=dev --ignore-scripts --no-audit --no-fund
|
|
34
|
+
USER 1000:1000
|
|
35
|
+
ENTRYPOINT ["node", "/opt/ours/docker/state-operation.mjs"]
|
|
36
|
+
FROM node:24 AS runtime
|
|
37
|
+
LABEL network.ours.build-context="1"
|
|
38
|
+
WORKDIR /opt/ours
|
|
39
|
+
COPY --from=build /opt/ours /opt/ours
|
|
40
|
+
USER 1000:1000
|
|
41
|
+
ENTRYPOINT ["/bin/sh", "/opt/ours/docker/entrypoint.sh"]
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# OURS 2.0 source delivery. Build input: Dockerfile, sources.json and scripts/ in this delivery directory.
|
|
2
|
+
# Pinned feature commits must be available in their upstream repositories before building.
|
|
3
|
+
# Docker Compose 2.35+ with BuildKit; current upstream MUFL compiler: linux/amd64.
|
|
4
|
+
# Set OURS_DAEMON_ID to one retained lowercase UUID before the first start.
|
|
5
|
+
# Private SDK source access: export OURS_BUILD_GITHUB_TOKEN with read access to
|
|
6
|
+
# adapt-toolkit/ours-sdk. Passed only as a BuildKit secret, never an image ARG.
|
|
7
|
+
# Supported setup/start entrypoint: ours-install server install --mode docker ...
|
|
8
|
+
# The installer calls prepare, then owning HMAC access-init/access-issue, then
|
|
9
|
+
# starts daemon and consumers in dependency order. Compose is diagnostic only.
|
|
10
|
+
# Protected optional Telegram JSON can use the prepare service telegram-input.
|
|
11
|
+
# No bot settings are required to start the connector without a configured bot.
|
|
12
|
+
# Fleet and the Codex/Claude integrations stay on the host; main MCP executes in Docker.
|
|
13
|
+
# Host clients use the same pinned feature revisions documented in README.md.
|
|
14
|
+
|
|
15
|
+
x-build: &source-build
|
|
16
|
+
context: .
|
|
17
|
+
target: runtime
|
|
18
|
+
secrets: [github_token]
|
|
19
|
+
dockerfile: Dockerfile
|
|
20
|
+
|
|
21
|
+
x-runtime: &runtime
|
|
22
|
+
build: *source-build
|
|
23
|
+
platform: linux/amd64
|
|
24
|
+
image: "${OURS_IMAGE:-ours-compose-2-runtime:local}"
|
|
25
|
+
user: "${OURS_UID:-1000}:${OURS_GID:-1000}"
|
|
26
|
+
init: true
|
|
27
|
+
read_only: true
|
|
28
|
+
cap_drop: [ALL]
|
|
29
|
+
security_opt: [no-new-privileges:true]
|
|
30
|
+
tmpfs: ["/tmp:rw,nosuid,nodev,noexec,size=64m,mode=1777"]
|
|
31
|
+
networks: [ours]
|
|
32
|
+
stop_grace_period: 30s
|
|
33
|
+
|
|
34
|
+
x-owner-environment: &owner-environment
|
|
35
|
+
HOME: /tmp
|
|
36
|
+
OURS_CONFIG: /var/lib/ours/config.json
|
|
37
|
+
OURS_STATE_DIR: /var/lib/ours
|
|
38
|
+
OURS_PORT: "3050"
|
|
39
|
+
OURS_LISTEN_HOST: 0.0.0.0
|
|
40
|
+
OURS_API_VISIBILITY: owner
|
|
41
|
+
OURS_DAEMON_ID: "${OURS_DAEMON_ID:?Set a stable daemon UUID}"
|
|
42
|
+
OURS_ACCESS_MIGRATE: "${OURS_ACCESS_MIGRATE:-0}"
|
|
43
|
+
OURS_MESSENGER_IDENTITY: "${OURS_MESSENGER_IDENTITY:-}"
|
|
44
|
+
|
|
45
|
+
x-owner-volumes: &owner-volumes
|
|
46
|
+
- {type: volume, source: server-storage, target: /var/lib/ours, volume: {nocopy: true, subpath: state/daemon}}
|
|
47
|
+
- {type: volume, source: server-storage, target: /var/lib/ours-mcp, volume: {nocopy: true, subpath: state/mcp}}
|
|
48
|
+
- {type: volume, source: server-storage, target: /credentials/telegram, volume: {nocopy: true, subpath: state/credentials/telegram}}
|
|
49
|
+
- {type: volume, source: server-storage, target: /credentials/cowork, volume: {nocopy: true, subpath: state/credentials/cowork}}
|
|
50
|
+
- {type: volume, source: server-storage, target: /credentials/messenger, volume: {nocopy: true, subpath: state/credentials/messenger}}
|
|
51
|
+
- type: volume
|
|
52
|
+
source: owner-locks
|
|
53
|
+
target: "/tmp/ours-${OURS_UID:-1000}"
|
|
54
|
+
volume: {nocopy: true}
|
|
55
|
+
|
|
56
|
+
x-client-order: &client-order
|
|
57
|
+
daemon: {condition: service_healthy}
|
|
58
|
+
|
|
59
|
+
services:
|
|
60
|
+
prepare:
|
|
61
|
+
profiles: [administration]
|
|
62
|
+
build: *source-build
|
|
63
|
+
platform: linux/amd64
|
|
64
|
+
image: "${OURS_IMAGE:-ours-compose-2-runtime:local}"
|
|
65
|
+
user: "0:0"
|
|
66
|
+
read_only: true
|
|
67
|
+
network_mode: none
|
|
68
|
+
cap_drop: [ALL]
|
|
69
|
+
cap_add: [CHOWN, DAC_OVERRIDE, SETUID, SETGID]
|
|
70
|
+
security_opt: [no-new-privileges:true]
|
|
71
|
+
entrypoint: [node, /opt/ours/docker/client-setup.mjs]
|
|
72
|
+
command: [prepare]
|
|
73
|
+
environment:
|
|
74
|
+
OURS_UID: "${OURS_UID:-1000}"
|
|
75
|
+
OURS_GID: "${OURS_GID:-1000}"
|
|
76
|
+
OURS_DAEMON_ID: "${OURS_DAEMON_ID:?Set a stable daemon UUID}"
|
|
77
|
+
OURS_COWORK_REST_PORT: "${OURS_COWORK_PORT:-3052}"
|
|
78
|
+
OURS_MESSENGER_IDENTITY: "${OURS_MESSENGER_IDENTITY:-}"
|
|
79
|
+
OURS_BROKER_URL: "${OURS_BROKER_URL:-}"
|
|
80
|
+
volumes:
|
|
81
|
+
- {type: volume, source: server-storage, target: /storage, volume: {nocopy: true}}
|
|
82
|
+
- {type: volume, source: owner-locks, target: /owner-locks, volume: {nocopy: true}}
|
|
83
|
+
|
|
84
|
+
daemon:
|
|
85
|
+
<<: *runtime
|
|
86
|
+
environment: *owner-environment
|
|
87
|
+
volumes:
|
|
88
|
+
- {type: volume, source: server-storage, target: /var/lib/ours, volume: {nocopy: true, subpath: state/daemon}}
|
|
89
|
+
- {type: volume, source: server-storage, target: /var/lib/ours-mcp, volume: {nocopy: true, subpath: state/mcp}}
|
|
90
|
+
- {type: volume, source: owner-locks, target: "/tmp/ours-${OURS_UID:-1000}", volume: {nocopy: true}}
|
|
91
|
+
ports:
|
|
92
|
+
- {target: 3050, published: "${OURS_HOST_PORT:-3050}", host_ip: 127.0.0.1}
|
|
93
|
+
healthcheck:
|
|
94
|
+
test: [CMD, node, /opt/ours/docker/healthcheck.mjs]
|
|
95
|
+
interval: 5s
|
|
96
|
+
timeout: 4s
|
|
97
|
+
start_period: 30s
|
|
98
|
+
retries: 12
|
|
99
|
+
|
|
100
|
+
access:
|
|
101
|
+
<<: *runtime
|
|
102
|
+
environment: *owner-environment
|
|
103
|
+
volumes: *owner-volumes
|
|
104
|
+
entrypoint: [node, /opt/ours/docker/client-setup.mjs]
|
|
105
|
+
command: [access-init]
|
|
106
|
+
profiles: [administration]
|
|
107
|
+
|
|
108
|
+
telegram:
|
|
109
|
+
<<: *runtime
|
|
110
|
+
entrypoint: [/bin/sh, -e, /opt/ours/docker/start-telegram.sh]
|
|
111
|
+
environment:
|
|
112
|
+
HOME: /tmp
|
|
113
|
+
OURS_TG_CONFIG: /var/lib/ours-telegram/config.json
|
|
114
|
+
OURS_TG_STATE_DIR: /var/lib/ours-telegram
|
|
115
|
+
OURS_TG_CONTROL_PORT: "3051"
|
|
116
|
+
OURS_TG_DAEMON_URL: http://daemon:3050
|
|
117
|
+
OURS_TG_DAEMON_ID: "${OURS_DAEMON_ID:?Set a stable daemon UUID}"
|
|
118
|
+
OURS_TG_DAEMON_CREDENTIAL_PATH: /credentials/telegram/daemon-token
|
|
119
|
+
volumes:
|
|
120
|
+
- {type: volume, source: server-storage, target: /var/lib/ours-telegram, volume: {nocopy: true, subpath: state/telegram}}
|
|
121
|
+
- {type: volume, source: server-storage, target: /credentials/telegram, read_only: true, volume: {nocopy: true, subpath: state/credentials/telegram}}
|
|
122
|
+
depends_on: *client-order
|
|
123
|
+
healthcheck:
|
|
124
|
+
test: [CMD, /bin/sh, /opt/ours/docker/health-telegram.sh]
|
|
125
|
+
interval: 5s
|
|
126
|
+
timeout: 4s
|
|
127
|
+
start_period: 30s
|
|
128
|
+
retries: 12
|
|
129
|
+
|
|
130
|
+
cowork:
|
|
131
|
+
<<: *runtime
|
|
132
|
+
entrypoint: [/bin/sh, -e, /opt/ours/docker/start-cowork.sh]
|
|
133
|
+
environment:
|
|
134
|
+
HOME: /tmp
|
|
135
|
+
OURS_COWORK_CONFIG: /var/lib/ours-cowork/config.json
|
|
136
|
+
OURS_COWORK_STATE_DIR: /var/lib/ours-cowork
|
|
137
|
+
OURS_COWORK_REST_PORT: "${OURS_COWORK_PORT:-3052}"
|
|
138
|
+
OURS_DAEMON_URL: http://daemon:3050
|
|
139
|
+
OURS_DAEMON_ID: "${OURS_DAEMON_ID:?Set a stable daemon UUID}"
|
|
140
|
+
OURS_DAEMON_CREDENTIAL_PATH: /credentials/cowork/daemon-token
|
|
141
|
+
volumes:
|
|
142
|
+
- {type: volume, source: server-storage, target: /var/lib/ours-cowork, volume: {nocopy: true, subpath: state/cowork}}
|
|
143
|
+
- {type: volume, source: server-storage, target: /credentials/cowork, read_only: true, volume: {nocopy: true, subpath: state/credentials/cowork}}
|
|
144
|
+
ports:
|
|
145
|
+
- {target: "${OURS_COWORK_PORT:-3052}", published: "${OURS_COWORK_PORT:-3052}", host_ip: 127.0.0.1}
|
|
146
|
+
depends_on: *client-order
|
|
147
|
+
healthcheck:
|
|
148
|
+
test: [CMD, /bin/sh, /opt/ours/docker/health-cowork.sh]
|
|
149
|
+
interval: 5s
|
|
150
|
+
timeout: 15s
|
|
151
|
+
start_period: 30s
|
|
152
|
+
retries: 12
|
|
153
|
+
|
|
154
|
+
messenger:
|
|
155
|
+
<<: *runtime
|
|
156
|
+
entrypoint: [/bin/sh, -e, /opt/ours/docker/start-messenger.sh]
|
|
157
|
+
environment:
|
|
158
|
+
HOME: /tmp
|
|
159
|
+
OURS_DAEMON_URL: http://daemon:3050
|
|
160
|
+
OURS_DAEMON_ID: "${OURS_DAEMON_ID:?Set a stable daemon UUID}"
|
|
161
|
+
OURS_DAEMON_CREDENTIAL_PATH: /credentials/messenger/daemon-token
|
|
162
|
+
OURS_MESSENGER_IDENTITY: "${OURS_MESSENGER_IDENTITY:-}"
|
|
163
|
+
OURS_MESSENGER_HOST: 0.0.0.0
|
|
164
|
+
OURS_MESSENGER_PORT: "8420"
|
|
165
|
+
OURS_MESSENGER_PUBLIC_ORIGIN: "http://127.0.0.1:${OURS_MESSENGER_PORT:-8420}"
|
|
166
|
+
OURS_MESSENGER_STATE_DIR: /var/lib/ours-messenger
|
|
167
|
+
volumes:
|
|
168
|
+
- {type: volume, source: server-storage, target: /var/lib/ours-messenger, volume: {nocopy: true, subpath: state/messenger}}
|
|
169
|
+
- {type: volume, source: server-storage, target: /credentials/messenger, read_only: true, volume: {nocopy: true, subpath: state/credentials/messenger}}
|
|
170
|
+
ports:
|
|
171
|
+
- {target: 8420, published: "${OURS_MESSENGER_PORT:-8420}", host_ip: 127.0.0.1}
|
|
172
|
+
depends_on: *client-order
|
|
173
|
+
healthcheck:
|
|
174
|
+
test: [CMD, node, /opt/ours/docker/health-messenger.mjs]
|
|
175
|
+
interval: 5s
|
|
176
|
+
timeout: 4s
|
|
177
|
+
start_period: 30s
|
|
178
|
+
retries: 12
|
|
179
|
+
|
|
180
|
+
state-operation:
|
|
181
|
+
profiles: [maintenance]
|
|
182
|
+
build:
|
|
183
|
+
<<: *source-build
|
|
184
|
+
target: maintenance
|
|
185
|
+
platform: linux/amd64
|
|
186
|
+
image: "${OURS_MAINTENANCE_IMAGE:-ours-compose-2-maintenance:local}"
|
|
187
|
+
user: "${OURS_UID:-1000}:${OURS_GID:-1000}"
|
|
188
|
+
network_mode: none
|
|
189
|
+
read_only: true
|
|
190
|
+
cap_drop: [ALL]
|
|
191
|
+
security_opt: [no-new-privileges:true]
|
|
192
|
+
command: [--help]
|
|
193
|
+
environment:
|
|
194
|
+
OURS_STATE_DOMAIN: "${OURS_STATE_DOMAIN:-daemon}"
|
|
195
|
+
OURS_STATE_ROOT: /storage
|
|
196
|
+
OURS_LIVE_ROOT: "${OURS_LIVE_ROOT:-/storage/state}"
|
|
197
|
+
OURS_BUILD_ROOT: /opt/ours
|
|
198
|
+
OURS_CLI_PATH: /opt/ours/node_modules/.bin/ours
|
|
199
|
+
OURS_DAEMON_CONFIG: /var/lib/ours/config.json
|
|
200
|
+
OURS_COWORK_CLI_PATH: /opt/ours/node_modules/.bin/ours-cowork
|
|
201
|
+
OURS_COWORK_CONFIG: /var/lib/ours-cowork/config.json
|
|
202
|
+
OURS_COWORK_STATE_DIR: /var/lib/ours-cowork
|
|
203
|
+
OURS_DAEMON_ID: "${OURS_DAEMON_ID:?Set a stable daemon UUID}"
|
|
204
|
+
OURS_COWORK_REST_PORT: "${OURS_COWORK_PORT:-3052}"
|
|
205
|
+
OURS_BROKER_URL: "${OURS_BROKER_URL:-}"
|
|
206
|
+
volumes:
|
|
207
|
+
- {type: volume, source: server-storage, target: /storage, volume: {nocopy: true}}
|
|
208
|
+
- {type: volume, source: server-storage, target: /var/lib/ours, volume: {nocopy: true, subpath: state/daemon}}
|
|
209
|
+
- {type: volume, source: server-storage, target: /var/lib/ours-mcp, volume: {nocopy: true, subpath: state/mcp}}
|
|
210
|
+
- {type: volume, source: server-storage, target: /var/lib/ours-cowork, volume: {nocopy: true, subpath: state/cowork}}
|
|
211
|
+
|
|
212
|
+
volumes:
|
|
213
|
+
server-storage:
|
|
214
|
+
owner-locks:
|
|
215
|
+
|
|
216
|
+
networks:
|
|
217
|
+
ours:
|
|
218
|
+
driver: bridge
|
|
219
|
+
|
|
220
|
+
secrets:
|
|
221
|
+
github_token:
|
|
222
|
+
environment: OURS_BUILD_GITHUB_TOKEN
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Installer assets
|
|
2
|
+
|
|
3
|
+
| Directory | Purpose | Caller |
|
|
4
|
+
|---|---|---|
|
|
5
|
+
| [build](build/README.md) | Fetch selected sources, build and package npm packages | Dockerfile or installer |
|
|
6
|
+
| [runtime](runtime/README.md) | Prepare selected storage and settings, start services and check readiness | Installer and Compose |
|
|
7
|
+
| [maintenance](maintenance/README.md) | Back up and restore stopped state using owning package interfaces | Installer |
|
|
8
|
+
|
|
9
|
+
These are internal assets of `ours-install`; users do not invoke the scripts
|
|
10
|
+
manually. Installer materializes Docker assets into the selected installation's
|
|
11
|
+
runtime directory. Package mode uses the same build coordinator and the installed
|
|
12
|
+
maintenance implementation.
|
|
13
|
+
|
|
14
|
+
Build scripts run under Node.js. Source builds may additionally need native build
|
|
15
|
+
tools, including Python for third-party dependencies. Archive and state maintenance
|
|
16
|
+
do not require Python.
|
|
17
|
+
|
|
18
|
+
The Dockerfile copies build scripts to `/build-scripts/` and runtime/maintenance
|
|
19
|
+
scripts to `/opt/ours/docker/`. Runtime services receive only their selected state
|
|
20
|
+
subdirectories; maintenance operates on the installation's shared state tree.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Build
|
|
2
|
+
|
|
3
|
+
Inputs: [sources.json](../../sources.json), access to selected Git/npm sources and,
|
|
4
|
+
when needed, the BuildKit secret `github_token`. Docker builds run these scripts
|
|
5
|
+
inside the image build; package installations run them in installer-selected
|
|
6
|
+
staging on the host. Outputs: npm archives and one package.json under
|
|
7
|
+
`OURS_BUILD_ROOT` (default `/opt/ours`) for the final installation.
|
|
8
|
+
|
|
9
|
+
| File | Responsibility |
|
|
10
|
+
|---|---|
|
|
11
|
+
| `build.mjs` | Fetch sources, run required recipes in order and generate the final manifest |
|
|
12
|
+
| `build-sdk.mjs` | Build SDK and CLI from one repository, including MUFL |
|
|
13
|
+
| `build-mcp.mjs` | Build selected packages from the MCP monorepo |
|
|
14
|
+
| `build-telegram.mjs`, `build-cowork.mjs`, `build-messenger.mjs`, `build-fleet.mjs` | Build the corresponding repository with the selected SDK/CLI |
|
|
15
|
+
| `record-build.mjs` | Finalize a fresh npm installation: record the resolved tree, protect owned inputs and verify/publish vendor context |
|
|
16
|
+
| `build-common.mjs` | Shared archive naming and dispatch to consumer-owned build recipes |
|
|
17
|
+
|
|
18
|
+
The Dockerfile invokes `node /build-scripts/build.mjs`; no manual script calls are
|
|
19
|
+
needed. Each Git repository is built once. Selected published npm packages are
|
|
20
|
+
retrieved without rebuilding them. Archives are created inside the image; prebuilt
|
|
21
|
+
dependencies are not included in the delivery directory.
|
|
22
|
+
|
|
23
|
+
Telegram, Cowork, Messenger and Fleet own `scripts/build-selected.mjs`. The
|
|
24
|
+
assembler passes the actual selected SDK and CLI archives with `--sdk PATH --cli
|
|
25
|
+
PATH --out-dir PATH`, reads the JSON `filename`, verifies the packed package name,
|
|
26
|
+
and collects it using the existing archive naming convention. The owning recipe
|
|
27
|
+
handles disposable dependency preparation, build and portable packing. Consumer
|
|
28
|
+
source manifests and locks are not rewritten by the assembler. Missing owner
|
|
29
|
+
recipes or selected SDK/CLI archives fail explicitly; there is no fallback build.
|
|
30
|
+
SDK and MCP retain their existing repository build owners.
|
|
31
|
+
|
|
32
|
+
After the final npm install, the owning installer/Dockerfile runs `record-build.mjs`.
|
|
33
|
+
It requires a fresh output with no retained dependency tree/context, verifies actual
|
|
34
|
+
archive bytes and lock/tree bindings, and writes context privately. An existing
|
|
35
|
+
context is never regenerated as historical evidence. Image export makes non-secret
|
|
36
|
+
provenance root-owned and readable for configured runtime UIDs; host/state copies
|
|
37
|
+
remain private. Docker images carrying context are labelled
|
|
38
|
+
`network.ours.build-context=1`; a missing/copy-failed context on such an image aborts
|
|
39
|
+
preparation instead of treating it as legacy.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** Shared npm operations for the six fixed repository recipes. */
|
|
2
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync } from 'node:fs';
|
|
3
|
+
import { join, basename, resolve } from 'node:path';
|
|
4
|
+
import { execFileSync } from 'node:child_process';
|
|
5
|
+
|
|
6
|
+
export const ROOT = resolve(process.env.OURS_BUILD_ROOT || '/opt/ours');
|
|
7
|
+
export const SOURCE_ROOT = resolve(process.env.OURS_SOURCE_ROOT || '/src');
|
|
8
|
+
export const OUT = join(ROOT, 'docker/vendor');
|
|
9
|
+
export const CONFIG = JSON.parse(readFileSync(join(ROOT, 'sources.json'), 'utf8'));
|
|
10
|
+
export const SELECTED = new Set((process.env.OURS_BUILD_PACKAGES || 'sdk,cli,mcp,tg-connector,cowork,messenger-server').split(',').map(name => '@ours.network/' + name));
|
|
11
|
+
export const inheritedLock = process.env.OURS_INSTALLER_LOCK_FD === '3' ? [3] : [];
|
|
12
|
+
export const run = (args, cwd) => execFileSync(args[0], args.slice(1), { cwd, stdio: ['inherit', 'inherit', 'inherit', ...inheritedLock] });
|
|
13
|
+
export const capture = (args, cwd, env = process.env) => execFileSync(args[0], args.slice(1), { cwd, env, encoding: 'utf8', stdio: ['ignore', 'pipe', 'inherit', ...inheritedLock] });
|
|
14
|
+
export const archive = packageName => join(OUT, `ours.network-${packageName.replace(/^@ours\.network\//, '')}.tgz`);
|
|
15
|
+
// npm already owns package archive interpretation; no second tar parser here.
|
|
16
|
+
export const manifest = path => JSON.parse(capture(['npm', 'pack', '--dry-run', '--ignore-scripts', '--json', path], ROOT))[0];
|
|
17
|
+
export function pack(cwd, packageName, source) {
|
|
18
|
+
if (!SELECTED.has(packageName) || CONFIG.packages[packageName]?.source !== source) return;
|
|
19
|
+
const result = JSON.parse(capture(['npm', 'pack', '--ignore-scripts', '--json', '--pack-destination', OUT], cwd))[0];
|
|
20
|
+
renameSync(join(OUT, result.filename), archive(packageName));
|
|
21
|
+
}
|
|
22
|
+
export function buildConsumer(source, packageName) {
|
|
23
|
+
if (!SELECTED.has(packageName) || CONFIG.packages[packageName]?.source !== source) return;
|
|
24
|
+
const directory = join(SOURCE_ROOT, source);
|
|
25
|
+
const recipe = join(directory, 'scripts/build-selected.mjs');
|
|
26
|
+
const sdk = archive('@ours.network/sdk'), cli = archive('@ours.network/cli');
|
|
27
|
+
for (const input of [recipe, sdk, cli]) if (!existsSync(input)) throw Error(`${packageName}: required build input missing: ${input}`);
|
|
28
|
+
mkdirSync(OUT, { recursive: true });
|
|
29
|
+
const output = mkdtempSync(join(OUT, source + '-'));
|
|
30
|
+
try {
|
|
31
|
+
const result = JSON.parse(capture([process.execPath, recipe, '--sdk', sdk, '--cli', cli, '--out-dir', output], directory));
|
|
32
|
+
if (typeof result.filename !== 'string' || basename(result.filename) !== result.filename) throw Error(`${packageName}: recipe must return an archive filename`);
|
|
33
|
+
const packed = join(output, result.filename);
|
|
34
|
+
if (manifest(packed).name !== packageName) throw Error(`Packed output does not match selection: ${packageName}`);
|
|
35
|
+
renameSync(packed, archive(packageName));
|
|
36
|
+
} finally { rmSync(output, { recursive: true, force: true }); }
|
|
37
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { SOURCE_ROOT, SELECTED, pack, run } from './build-common.mjs';
|
|
3
|
+
const source = join(SOURCE_ROOT, 'mcp');
|
|
4
|
+
run(['npm', 'ci', '--ignore-scripts', '--no-audit', '--no-fund'], source);
|
|
5
|
+
for (const [directory, name] of [['core', 'mcp'], ['codex', 'codex'], ['claude-code', 'claude-code'], ['installer', 'install']]) {
|
|
6
|
+
if (!SELECTED.has('@ours.network/' + name)) continue;
|
|
7
|
+
if (name !== 'install') run(['npm', 'run', 'build', '--workspace', '@ours.network/' + name], source);
|
|
8
|
+
pack(join(source, 'packages', directory), '@ours.network/' + name, 'mcp');
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { SOURCE_ROOT, SELECTED, pack, run } from './build-common.mjs';
|
|
3
|
+
const source = join(SOURCE_ROOT, 'sdk');
|
|
4
|
+
run(['npm', 'ci', '--no-audit', '--no-fund'], source);
|
|
5
|
+
run(['bash', 'scripts/compile-mufl.sh'], source);
|
|
6
|
+
run(['npm', 'run', 'build'], source);
|
|
7
|
+
if (SELECTED.has('@ours.network/cli')) run(['npm', 'run', 'build:cli'], source);
|
|
8
|
+
pack(source, '@ours.network/sdk', 'sdk');
|
|
9
|
+
pack(join(source, 'packages/cli'), '@ours.network/cli', 'sdk');
|