ai-fly 0.4.0 → 0.6.0-alpha.1
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 +161 -2
- package/dist/ai-fly.js +9 -6
- package/dist/app/main.js +4230 -3173
- package/dist/{common-CanLn0Qt.mjs → common-9KRvrs5f.mjs} +1 -1
- package/dist/{common-C51SAE5f.mjs → common-DqSyhR6F.mjs} +25 -23
- package/dist/{daemon-BWgyJMyB.mjs → daemon-D5J50r7U.mjs} +4 -4
- package/dist/{forget-B3KRkHho.mjs → forget-DGJwF3Gy.mjs} +2 -2
- package/dist/{group-BdnvRD2t.mjs → group-Dh64zhKn.mjs} +6 -6
- package/dist/hooks-BztmB61b.mjs +243 -0
- package/dist/http-errors-BA_8giMK.mjs +175 -0
- package/dist/{import-CTkKGPsa.mjs → import-DN8bNBJU.mjs} +5 -5
- package/dist/{join-d-pqyf8e.mjs → join-CLD4fdCf.mjs} +3 -3
- package/dist/{join-BRow9_3-.mjs → join-D5QUz8mh.mjs} +14 -10
- package/dist/{key-CTL_AXOh.mjs → key-Cpw-HzT4.mjs} +5 -5
- package/dist/{key-D_66hrWW.mjs → key-JLJewbw9.mjs} +3 -3
- package/dist/{local-test-BZHGo22F.mjs → local-test-BGgTbZC7.mjs} +1 -1
- package/dist/{models-dev-CDEyd2k3.mjs → models-dev-BNxZl4yw.mjs} +170 -8
- package/dist/{ports-TQ4tWmiJ.mjs → ports-DmBKgLSi.mjs} +2 -2
- package/dist/{presets-DleOUQiT.mjs → presets-BwkVV7E2.mjs} +2 -2
- package/dist/{revoke-DTFW_EF1.mjs → revoke-DMx9hZUH.mjs} +2 -2
- package/dist/{rewrite-CEzfYH9n.mjs → rewrite-BMXvJYE1.mjs} +120 -134
- package/dist/{route-test-D2LQyX7c.mjs → route-test-D7kj9-Xf.mjs} +4 -4
- package/dist/{rpc-contract-cB5SuyQ_.mjs → rpc-contract-BAz-C8fx.mjs} +572 -94
- package/dist/{run-D8kgXdId.mjs → run-C-CxjlLu.mjs} +68 -5
- package/dist/{runtime-C_pLA5F0.mjs → runtime-DKmrkfNT.mjs} +409 -409
- package/dist/{secret-P2RgHy2h.mjs → secret-BrfkuRkP.mjs} +9 -9
- package/dist/{secrets-1Hmddmwy.mjs → secrets-AGbk6IRp.mjs} +17 -21
- package/dist/secrets-CmkG0pM4.mjs +2 -0
- package/dist/serve-BB6-4Ixd.mjs +1793 -0
- package/dist/{serve-B51lmr9M.mjs → serve-DJ8id2Qo.mjs} +3 -2
- package/dist/{service-D6TNolyh.mjs → service-P-vz61tx.mjs} +138 -41
- package/dist/services-Deh7Gxwa.mjs +100 -0
- package/dist/{settings-Rq1zLoxY.mjs → settings-15j9BB6j.mjs} +1 -1
- package/dist/{settings-XCvAzDK8.mjs → settings-DtjTKZfl.mjs} +2 -2
- package/dist/{share-DdtbAylA.mjs → share-mozydAfj.mjs} +9 -6
- package/dist/{status-uE2-kOyK.mjs → status-BlvQvxGW.mjs} +14 -6
- package/dist/{status-DSVQ3YHm.mjs → status-DsFpGrzC.mjs} +8 -4
- package/dist/{store-DOFDy1rY.mjs → store-Bu4I1rNj.mjs} +103 -10
- package/dist/store-CmHtxOCd.mjs +1353 -0
- package/dist/{test-DW4BF7xJ.mjs → test-ChqaPwHA.mjs} +2 -2
- package/hooks/codex.cjs +58 -9
- package/hooks/env.cjs +4 -3
- package/hooks/file.cjs +7 -7
- package/hooks/rust-fetch.cjs +179 -0
- package/hooks/secret.cjs +4 -4
- package/package.json +4 -3
- package/webui/dist/assets/index-DQr5cBwc.js +67 -0
- package/webui/dist/assets/index-Dne1d-yC.css +2 -0
- package/webui/dist/index.html +2 -2
- package/dist/frames-BDz8buix.mjs +0 -386
- package/dist/hook-CvAMGts4.mjs +0 -228
- package/dist/hooks-DUrXA7PL.mjs +0 -142
- package/dist/mux-BaIDugDq.mjs +0 -630
- package/dist/secrets-C9IYp93v.mjs +0 -2
- package/dist/serve-CY7ZFOFM.mjs +0 -1254
- package/dist/store-EGzVd-dn.mjs +0 -654
- package/webui/dist/assets/index-B5lnC-QV.js +0 -71
- package/webui/dist/assets/index-DqLIOzIY.css +0 -2
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Share any HTTP/WebSocket upstream (ollama / vllm / LM Studio, an internal gatewa
|
|
|
8
8
|
Consumer machine Provider machine
|
|
9
9
|
Agent ──► http://127.0.0.1:11434/… ollama :11434 (or any HTTP/WS upstream)
|
|
10
10
|
──► ws://127.0.0.1:11434/… ▲ provider engine
|
|
11
|
-
consumer engine │ match set +
|
|
11
|
+
consumer engine │ match set + lifecycle hooks (auth/headers)
|
|
12
12
|
│ AUTH keyring / catalog │ quotas (per key)
|
|
13
13
|
└────── OpenDWeb fabric ──────┘ (identity / invites / QUIC + relay)
|
|
14
14
|
```
|
|
@@ -38,15 +38,122 @@ credential injection impossible without MITM).
|
|
|
38
38
|
```bash
|
|
39
39
|
# Provider
|
|
40
40
|
ai-fly serve --upstream http://127.0.0.1:11434 # run + manage services/groups
|
|
41
|
+
ai-fly service stop ollama # pause exposure (catalog drops it, config kept)
|
|
42
|
+
ai-fly service start ollama # resume; consumers see it again
|
|
41
43
|
ai-fly key issue --group friends # sk-aifly-… keys
|
|
42
44
|
ai-fly share --group friends --ttl 30m # aifly1.… link (token + key)
|
|
43
45
|
|
|
44
46
|
# Consumer
|
|
45
47
|
ai-fly import <link> --run # join + keyring + start gateway
|
|
46
48
|
ai-fly key add <sk-aifly-…> --provider <id> # bare key into an existing ring
|
|
49
|
+
ai-fly services # list services across groups (state + ports)
|
|
50
|
+
ai-fly services stop <provider> # stop ALL of a provider's services (revivable)
|
|
51
|
+
ai-fly services stop <provider> <service> # stop one service's local listener (live)
|
|
52
|
+
ai-fly services rm <provider> # remove the whole provider (= forget: keyring + fabric identity)
|
|
53
|
+
ai-fly services start <provider> [<service>] # re-enable (per-service stops persist across ring stops)
|
|
47
54
|
ai-fly status --verbose # ports, providers, service details
|
|
48
55
|
```
|
|
49
56
|
|
|
57
|
+
Service lifecycle: a stopped provider service disappears from the consumer catalog
|
|
58
|
+
(local listener closes, in-flight requests abort, requests get 404); a stopped
|
|
59
|
+
consumer service is "removed but revivable" — the provider's catalog sync still
|
|
60
|
+
updates the entry, it just never re-materializes a local port until you start it
|
|
61
|
+
back. The running gateway daemon picks these changes up live (keyring watch); the
|
|
62
|
+
dashboard's port table exposes the same start/stop/remove actions.
|
|
63
|
+
|
|
64
|
+
## Request lifecycle (hooks v2)
|
|
65
|
+
|
|
66
|
+
Every service runs a four-stage pipeline around the upstream call:
|
|
67
|
+
|
|
68
|
+
`onRequestBearerAuthentication (1) -> onRequestHeaders (2) -> onRequest (3) -> onResponse (4)`
|
|
69
|
+
|
|
70
|
+
- `service.auth` (stage 1) — Authorization header source: `{secret: <name>}`,
|
|
71
|
+
`{script: <name>, args?}` or `{literal: <value>}` (literals accept `$env:<VAR>` /
|
|
72
|
+
`$secret:<name>` indirection, resolved per request), plus `bearer: false` to drop
|
|
73
|
+
the default `Bearer ` prefix.
|
|
74
|
+
- `service.headers` (stage 2) — `remove: [...]`, `set: {name: literal}` and an
|
|
75
|
+
optional whole-stage `script: {name, args?}` returning `{set?, remove?}` (script
|
|
76
|
+
output wins over the declared set).
|
|
77
|
+
- `service.request` (stage 3) — takes over the outbound call entirely; ctx is
|
|
78
|
+
`{url, method, headers, body, signal}`, returns `{status, headers, body?}`.
|
|
79
|
+
- `service.response` (stage 4) — post-processes the response; ctx is
|
|
80
|
+
`{status, headers, body, signal}`, returns `{status?, headers?, body?}`.
|
|
81
|
+
|
|
82
|
+
Hook scripts export one function per stage they implement — the export name is the
|
|
83
|
+
stage name. Builtin library: `codex` (reads `$CODEX_HOME/auth.json`, falling back to
|
|
84
|
+
`~/.codex/auth.json` — read-only, ai-fly never writes credential files; set
|
|
85
|
+
`CODEX_HOME` when your `~/.codex` holds a different Codex CLI config), plus `env` /
|
|
86
|
+
`file` / `secret` bridges for stage 1.
|
|
87
|
+
All stage fns receive `{homedir, args, secrets, env}`; stages 1-2 additionally get
|
|
88
|
+
the request-level `{method, path, headers}`. Returned streams (3/4 bodies) are
|
|
89
|
+
cancelled when the engine aborts the request.
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# --secret -> auth = {secret: mykey}; --headers-script -> stage-2 whole-stage
|
|
93
|
+
# script; --request-script/--response-script -> stage 3/4 bindings
|
|
94
|
+
ai-fly service add myapi --upstream https://api.example.com --match suffix:api.example.com \
|
|
95
|
+
--secret mykey \
|
|
96
|
+
--header-set x-org=acme --header-remove x-internal \
|
|
97
|
+
--headers-script hdrfix \
|
|
98
|
+
--request-script mock-up --response-script log
|
|
99
|
+
ai-fly hooks list # stage matrix per script
|
|
100
|
+
ai-fly hooks run codex --stage onRequestBearerAuthentication
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Breaking changes (hooks-lifecycle v2)**
|
|
104
|
+
|
|
105
|
+
- Old hook scripts must be rewritten, not just renamed: export names changed
|
|
106
|
+
(`authHeader` -> `onRequestBearerAuthentication`, etc.) and the runtime contract
|
|
107
|
+
is new — request-scoped ctx, 3/4 object return shapes, stream cancellation.
|
|
108
|
+
- v1 `services.json` (pre-`version: 2`) is invalid: the store enters a legacy
|
|
109
|
+
read-only state (`ai-fly service list` and `status --verbose` show the stale
|
|
110
|
+
names); remove them with `ai-fly service remove <name>`, then re-add services
|
|
111
|
+
to rebuild a clean v2 store (groups and share keys are not carried over).
|
|
112
|
+
- The v1 string form `--hooks "<script>"` became an object slot in preset mode:
|
|
113
|
+
`--hooks <name>` binds one whole-script lifecycle (see below), mutually
|
|
114
|
+
exclusive with per-stage flags; `--secret` fills `auth.secret`; `--header-set`
|
|
115
|
+
values accept literals and `$env:`/`$secret:` references only (per-header hook
|
|
116
|
+
objects are gone — bind a stage script with `--headers-script` instead).
|
|
117
|
+
|
|
118
|
+
## Lifecycle binding modes & rust-fetch
|
|
119
|
+
|
|
120
|
+
Lifecycle config has two **mutually exclusive** modes (Owner ruling 2026-09-15):
|
|
121
|
+
|
|
122
|
+
- **custom** — pick per-stage scripts or inline config (auth secret/literal,
|
|
123
|
+
header set/remove, …). The default.
|
|
124
|
+
- **preset** — bind one hook-js with `hooks: {script}` (CLI `--hooks <name>`);
|
|
125
|
+
the script's stage exports form the whole lifecycle. Stages without an export
|
|
126
|
+
fall back to defaults (stage 3 unbound = js-backend-fetch — the current JS
|
|
127
|
+
runtime backend's fetch, Node/Deno/Bun alike).
|
|
128
|
+
|
|
129
|
+
The `codex` preset runs in preset mode: the built-in `codex` script provides the
|
|
130
|
+
complete lifecycle — ① auth token from `$CODEX_HOME/auth.json` (falling back to
|
|
131
|
+
`~/.codex/auth.json`, read-only), ② the codex CLI header set (`chatgpt-account-id`,
|
|
132
|
+
`originator`, `openai-beta`, user-agent), ③ outbound via the **rust-fetch** sidecar.
|
|
133
|
+
Launch e.g. `CODEX_HOME=~/.ai-fly/codex-home pnpm app:dev` to keep that credential
|
|
134
|
+
copy fully isolated from your own `~/.codex`.
|
|
135
|
+
|
|
136
|
+
`rust-fetch` (rustls TLS + HTTP/2, a client stack distinct from
|
|
137
|
+
js-backend-fetch) replaces the outbound HTTPS call — empirical A/B against
|
|
138
|
+
chatgpt.com: GET /rate_limits via js-backend-fetch → 403 (Cloudflare, 0/13
|
|
139
|
+
historically) vs rust-fetch → 404 (passes CF, reaches the backend); POST
|
|
140
|
+
/responses with a real subscription → 200 + SSE through the full pipeline.
|
|
141
|
+
|
|
142
|
+
Build & install the sidecar (not shipped in the repo) — **required before the
|
|
143
|
+
codex preset can serve**; without it every request fails with a masked
|
|
144
|
+
`hook_failed` (the daemon logs a one-line install hint to its stderr):
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
pnpm sidecar:install # cargo build --release + copy to ~/.aifly/sidecars/rust-fetch/
|
|
148
|
+
# or point AIFLY_RUST_FETCH_BIN at the binary when starting the daemon
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Bind it per service (custom mode, stage 3 only) with `--request-script
|
|
152
|
+
rust-fetch` (or the stage-3 selector in the WebUI); the codex preset carries it
|
|
153
|
+
automatically. Per-request process spawn (no pooling yet); env proxies
|
|
154
|
+
(HTTPS_PROXY/…) follow the Rust stack's defaults. stdio protocol is frozen in
|
|
155
|
+
`openspec/changes/rust-fetch-sidecar`.
|
|
156
|
+
|
|
50
157
|
## Development
|
|
51
158
|
|
|
52
159
|
```bash
|
|
@@ -61,6 +168,35 @@ Node >= 20. License: MIT OR Apache-2.0. The fabric dependency
|
|
|
61
168
|
`@jixo/opendweb-client-sdk` ships native binaries for darwin-arm64 and win32-x64
|
|
62
169
|
(no Linux yet).
|
|
63
170
|
|
|
171
|
+
### Local link development against the opendweb kernel
|
|
172
|
+
|
|
173
|
+
The consumer/provider data plane rides the opendweb session-continuity kernel
|
|
174
|
+
(`Fabric.openSession` / `fetchHttp` / `serveHttp`; the aifly envelope wire
|
|
175
|
+
protocol is retired). While iterating against the opendweb workspace, link the
|
|
176
|
+
SDK instead of installing from the registry:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# one-time, inside the opendweb workspace
|
|
180
|
+
cd /path/to/opendweb/packages/client-sdk && npm link
|
|
181
|
+
|
|
182
|
+
# then in this repo (replaces the registry install with a symlink)
|
|
183
|
+
npm link @jixo/opendweb-client-sdk
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Notes:
|
|
187
|
+
|
|
188
|
+
- Do **not** run `pnpm install` in this repo while the link is in place — it
|
|
189
|
+
resolves the symlink back to the registry version. Add new dependencies in a
|
|
190
|
+
separate step and re-link afterwards.
|
|
191
|
+
- `test/e2e/kernel-migration.test.mjs` is the real-kernel acceptance suite
|
|
192
|
+
(dual in-process fabrics + serveHttp/fetchHttp; SSE mid-stream resume, dead
|
|
193
|
+
semantics, provider restart, WS tunnel). It runs via
|
|
194
|
+
`node --import tsx --test --test-force-exit ...` (the native runtime keeps
|
|
195
|
+
the event loop alive; force-exit is required, mirroring the SDK's own test
|
|
196
|
+
script).
|
|
197
|
+
- The `package.json` version stays on the published semver (`^0.5.0` line once
|
|
198
|
+
the dual-release milestone lands); the link is a dev-time override only.
|
|
199
|
+
|
|
64
200
|
## Manual regression checklist
|
|
65
201
|
|
|
66
202
|
Desktop-shell behaviors that automated suites do not cover. Run before any
|
|
@@ -95,7 +231,7 @@ strings below are exactly what the UI shows.
|
|
|
95
231
|
plain browser tab the layout must look identical (zero inset fallback).
|
|
96
232
|
9. **Secrets panel** — Advanced > secrets: add a key-value pair, pick it in
|
|
97
233
|
the share wizard's "api key" selector, generate a service; the saved
|
|
98
|
-
|
|
234
|
+
service shows the auth slot `secret <name>`; values never re-display
|
|
99
235
|
after saving; removing a secret referenced by a service is allowed but the
|
|
100
236
|
service then fails with `secret_missing` until re-added.
|
|
101
237
|
10. **Connectivity test** — in the share wizard (with a secret picked) or a
|
|
@@ -103,3 +239,26 @@ strings below are exactly what the UI shows.
|
|
|
103
239
|
picked by default, the dropdown lists models sorted by price, and the
|
|
104
240
|
result line shows `ok · <ms> · <model>` or the upstream error (an
|
|
105
241
|
upstream 401 with an invalid key is a PASS — the network is proven).
|
|
242
|
+
11. **Service lifecycle** — with a running gateway, stop a service from the
|
|
243
|
+
dashboard's port table (or `ai-fly services stop`): its local port
|
|
244
|
+
refuses connections within ~a second and the row flips to disabled;
|
|
245
|
+
start restores the same port. Stop it on the *provider* (`ai-fly service
|
|
246
|
+
stop <name>`): the consumer's row disappears (catalog sync); start brings
|
|
247
|
+
it back. Remove on the consumer keeps the entry hidden-but-revivable —
|
|
248
|
+
`ai-fly services` still lists it as `disabled`, and starting it again
|
|
249
|
+
works without re-importing.
|
|
250
|
+
12. **Codex e2e through the gateway** — with a provider exposing a codex
|
|
251
|
+
subscription service and a consumer gateway running, point Codex CLI at
|
|
252
|
+
the mapped port (`OPENAI_BASE_URL=http://127.0.0.1:<port>/v1` with the
|
|
253
|
+
group key): a chat completion streams through, tool calls round-trip, and
|
|
254
|
+
`ai-fly status --verbose` shows the served count climbing.
|
|
255
|
+
13. **SSE mid-stream connection swap (kernel continuity)** — start a long
|
|
256
|
+
streaming request through the gateway (e.g. a slow/long codex response),
|
|
257
|
+
then kill the provider's network path mid-stream (`ai-fly` fabric reset
|
|
258
|
+
injection or simply restart the provider process within the recovery
|
|
259
|
+
window): the stream continues in order with **no duplicated tokens**, the
|
|
260
|
+
upstream request is NOT re-executed (provider logs show one execution),
|
|
261
|
+
and `ai-fly status` shows the provider flipping to offline then back —
|
|
262
|
+
the client never sees an error. Kill the provider for longer than the
|
|
263
|
+
recovery window: in-flight requests fail with a network error and only
|
|
264
|
+
*new* requests get 503 `provider_offline`.
|
package/dist/ai-fly.js
CHANGED
|
@@ -37,6 +37,9 @@ Consumer:
|
|
|
37
37
|
ai-fly test [--data <dir>] [--service <name>] [--form …] [--content <text>]
|
|
38
38
|
single AI request through the local gateway
|
|
39
39
|
ai-fly key add <sk-aifly-key> --provider <id> bare key into an existing ring
|
|
40
|
+
ai-fly services [list] services across groups (state + ports)
|
|
41
|
+
ai-fly services stop|start <provider> [<service>] provider- or service-level lifecycle (live)
|
|
42
|
+
ai-fly services rm <provider> [<service>] rm provider (= forget) or one service
|
|
40
43
|
ai-fly forget <endpointId|8-char-prefix> drop an imported provider
|
|
41
44
|
|
|
42
45
|
Config:
|
|
@@ -63,7 +66,7 @@ async function dispatch(command, rest) {
|
|
|
63
66
|
const lazy = (load) => {
|
|
64
67
|
return (argv, ctx) => load().then((m) => m.run([...argv], ctx));
|
|
65
68
|
};
|
|
66
|
-
return match(command).with("serve", () => lazy(() => import("./serve-
|
|
69
|
+
return match(command).with("serve", () => lazy(() => import("./serve-DJ8id2Qo.mjs"))(rest)).with("app", async () => {
|
|
67
70
|
const { join, dirname } = await import("node:path");
|
|
68
71
|
const { fileURLToPath } = await import("node:url");
|
|
69
72
|
const { spawn } = await import("node:child_process");
|
|
@@ -78,17 +81,17 @@ async function dispatch(command, rest) {
|
|
|
78
81
|
return await new Promise((resolve) => {
|
|
79
82
|
child.once("exit", (c) => resolve(c ?? 0));
|
|
80
83
|
});
|
|
81
|
-
}).with("daemon", () => lazy(() => import("./daemon-
|
|
82
|
-
if (rest[0] === "add") return lazy(() => import("./key-
|
|
83
|
-
return lazy(() => import("./key-
|
|
84
|
+
}).with("daemon", () => lazy(() => import("./daemon-D5J50r7U.mjs"))(rest)).with("presets", () => lazy(() => import("./presets-BwkVV7E2.mjs"))(rest)).with("hooks", () => lazy(() => import("./hooks-BztmB61b.mjs"))(rest)).with("secret", () => lazy(() => import("./secret-BrfkuRkP.mjs"))(rest)).with("settings", async () => (await import("./settings-15j9BB6j.mjs")).runAsSettings(rest, {})).with("relay", async () => (await import("./settings-15j9BB6j.mjs")).runAsRelay(rest, {})).with("test", () => lazy(() => import("./test-ChqaPwHA.mjs"))(rest)).with("service", () => lazy(() => import("./service-P-vz61tx.mjs"))(rest)).with("group", () => lazy(() => import("./group-Dh64zhKn.mjs"))(rest)).with("share", () => lazy(() => import("./share-mozydAfj.mjs"))(rest)).with("revoke", () => lazy(() => import("./revoke-DMx9hZUH.mjs"))(rest)).with("join", () => lazy(() => import("./join-CLD4fdCf.mjs"))(rest)).with("import", () => lazy(() => import("./import-DN8bNBJU.mjs"))(rest)).with("run", () => lazy(() => import("./run-C-CxjlLu.mjs"))(rest)).with("ports", () => lazy(() => import("./ports-DmBKgLSi.mjs"))(rest)).with("forget", () => lazy(() => import("./forget-DGJwF3Gy.mjs"))(rest)).with("services", () => lazy(() => import("./services-Deh7Gxwa.mjs"))(rest)).with("key", () => {
|
|
85
|
+
if (rest[0] === "add") return lazy(() => import("./key-JLJewbw9.mjs"))(rest);
|
|
86
|
+
return lazy(() => import("./key-Cpw-HzT4.mjs"))(rest);
|
|
84
87
|
}).with("status", async () => {
|
|
85
88
|
const [scope, ...tail] = rest;
|
|
86
89
|
const wantProvider = scope === "provider" || scope !== "consumer" && providerDirExists();
|
|
87
90
|
const wantConsumer = scope === "consumer" || scope !== "provider" && consumersRootExists();
|
|
88
91
|
const argv = scope === "provider" || scope === "consumer" ? tail : rest;
|
|
89
92
|
let code = 0;
|
|
90
|
-
if (wantProvider) code = Math.max(code, await lazy(() => import("./status-
|
|
91
|
-
if (wantConsumer) code = Math.max(code, await lazy(() => import("./status-
|
|
93
|
+
if (wantProvider) code = Math.max(code, await lazy(() => import("./status-DsFpGrzC.mjs"))(argv));
|
|
94
|
+
if (wantConsumer) code = Math.max(code, await lazy(() => import("./status-BlvQvxGW.mjs"))(argv));
|
|
92
95
|
if (!wantProvider && !wantConsumer) process.stdout.write("nothing to report: no provider storage and no imported consumers\n");
|
|
93
96
|
return code;
|
|
94
97
|
}).otherwise(() => {
|