@the-open-engine/zeroshot 6.28.0 → 6.29.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 +3 -3
- package/cli/index.js +20 -224
- package/docker/zeroshot-cluster/Dockerfile +2 -3
- package/lib/cluster/client.cjs +30 -7
- package/lib/cluster/client.d.cts +52 -0
- package/lib/cluster/client.d.mts +52 -0
- package/lib/cluster/client.d.ts +4 -6
- package/lib/cluster/client.mjs +32 -9
- package/lib/cluster/connection-state.cjs +25 -0
- package/lib/cluster/connection-state.d.cts +13 -0
- package/lib/cluster/connection-state.d.mts +13 -0
- package/lib/cluster/connection-state.d.ts +13 -0
- package/lib/cluster/connection-state.mjs +21 -0
- package/lib/cluster/connection-types.cjs +2 -0
- package/lib/cluster/connection-types.d.cts +33 -0
- package/lib/cluster/connection-types.d.mts +33 -0
- package/lib/cluster/connection-types.d.ts +33 -0
- package/lib/cluster/connection-types.mjs +1 -0
- package/lib/cluster/connection.cjs +18 -46
- package/lib/cluster/connection.d.cts +26 -0
- package/lib/cluster/connection.d.mts +26 -0
- package/lib/cluster/connection.d.ts +7 -25
- package/lib/cluster/connection.mjs +12 -42
- package/lib/cluster/errors.cjs +9 -1
- package/lib/cluster/errors.d.cts +29 -0
- package/lib/cluster/errors.d.mts +29 -0
- package/lib/cluster/errors.d.ts +4 -0
- package/lib/cluster/errors.mjs +7 -0
- package/lib/cluster/frames.d.cts +12 -0
- package/lib/cluster/frames.d.mts +12 -0
- package/lib/cluster/generated/protocol-schema.d.cts +1 -0
- package/lib/cluster/generated/protocol-schema.d.mts +1 -0
- package/lib/cluster/generated/protocol.d.cts +781 -0
- package/lib/cluster/generated/protocol.d.mts +781 -0
- package/lib/cluster/index.cjs +2 -2
- package/lib/cluster/index.d.cts +13 -0
- package/lib/cluster/index.d.mts +13 -0
- package/lib/cluster/index.d.ts +3 -3
- package/lib/cluster/index.mjs +2 -2
- package/lib/cluster/json-source.cjs +1 -0
- package/lib/cluster/json-source.d.cts +5 -0
- package/lib/cluster/json-source.d.mts +5 -0
- package/lib/cluster/json-source.d.ts +1 -0
- package/lib/cluster/json-source.mjs +1 -0
- package/lib/cluster/payload-value.cjs +1 -0
- package/lib/cluster/payload-value.d.cts +8 -0
- package/lib/cluster/payload-value.d.mts +8 -0
- package/lib/cluster/payload-value.d.ts +1 -0
- package/lib/cluster/payload-value.mjs +1 -0
- package/lib/cluster/queue.d.cts +15 -0
- package/lib/cluster/queue.d.mts +15 -0
- package/lib/cluster/socket.cjs +8 -0
- package/lib/cluster/socket.d.cts +13 -0
- package/lib/cluster/socket.d.mts +13 -0
- package/lib/cluster/socket.d.ts +2 -0
- package/lib/cluster/socket.mjs +7 -0
- package/lib/cluster/subscriptions.d.cts +73 -0
- package/lib/cluster/subscriptions.d.mts +73 -0
- package/lib/cluster/subscriptions.d.ts +5 -1
- package/lib/cluster/validators.cjs +1 -0
- package/lib/cluster/validators.d.cts +7 -0
- package/lib/cluster/validators.d.mts +7 -0
- package/lib/cluster/validators.d.ts +1 -0
- package/lib/cluster/validators.mjs +1 -0
- package/lib/cluster-worker/engine-adapter.js +1 -11
- package/lib/cluster-worker/engine-input.js +14 -0
- package/lib/hosted-session/authority.cjs +61 -0
- package/lib/hosted-session/authority.d.cts +3 -0
- package/lib/hosted-session/authority.d.mts +3 -0
- package/lib/hosted-session/authority.d.ts +3 -0
- package/lib/hosted-session/authority.mjs +57 -0
- package/lib/hosted-session/coordinator.cjs +78 -51
- package/lib/hosted-session/coordinator.d.cts +11 -0
- package/lib/hosted-session/coordinator.d.mts +11 -0
- package/lib/hosted-session/coordinator.d.ts +4 -2
- package/lib/hosted-session/coordinator.mjs +75 -51
- package/lib/hosted-session/errors.cjs +25 -0
- package/lib/hosted-session/errors.d.cts +10 -0
- package/lib/hosted-session/errors.d.mts +10 -0
- package/lib/hosted-session/errors.d.ts +10 -0
- package/lib/hosted-session/errors.mjs +19 -0
- package/lib/hosted-session/index.cjs +4 -1
- package/lib/hosted-session/index.d.cts +2 -0
- package/lib/hosted-session/index.d.mts +2 -0
- package/lib/hosted-session/index.d.ts +2 -2
- package/lib/hosted-session/index.mjs +1 -1
- package/lib/hosted-session/reconnecting-watch.cjs +131 -0
- package/lib/hosted-session/reconnecting-watch.d.cts +13 -0
- package/lib/hosted-session/reconnecting-watch.d.mts +13 -0
- package/lib/hosted-session/reconnecting-watch.d.ts +13 -0
- package/lib/hosted-session/reconnecting-watch.mjs +127 -0
- package/lib/hosted-session/types.d.cts +32 -0
- package/lib/hosted-session/types.d.mts +32 -0
- package/lib/hosted-session/types.d.ts +19 -7
- package/lib/hosted-target/access-url.cjs +44 -0
- package/lib/hosted-target/access-url.d.cts +2 -0
- package/lib/hosted-target/access-url.d.mts +2 -0
- package/lib/hosted-target/access-url.d.ts +2 -0
- package/lib/hosted-target/access-url.mjs +41 -0
- package/lib/hosted-target/adapter-request.cjs +12 -0
- package/lib/hosted-target/adapter-request.d.cts +17 -0
- package/lib/hosted-target/adapter-request.d.mts +17 -0
- package/lib/hosted-target/adapter-request.d.ts +17 -0
- package/lib/hosted-target/adapter-request.mjs +9 -0
- package/lib/hosted-target/adapter-types.cjs +2 -0
- package/lib/hosted-target/adapter-types.d.cts +27 -0
- package/lib/hosted-target/adapter-types.d.mts +27 -0
- package/lib/hosted-target/adapter-types.d.ts +27 -0
- package/lib/hosted-target/adapter-types.mjs +1 -0
- package/lib/hosted-target/bounds.cjs +10 -0
- package/lib/hosted-target/bounds.d.cts +7 -0
- package/lib/hosted-target/bounds.d.mts +7 -0
- package/lib/hosted-target/bounds.d.ts +7 -0
- package/lib/hosted-target/bounds.mjs +7 -0
- package/lib/hosted-target/capsule-error-response.cjs +76 -0
- package/lib/hosted-target/capsule-error-response.d.cts +2 -0
- package/lib/hosted-target/capsule-error-response.d.mts +2 -0
- package/lib/hosted-target/capsule-error-response.d.ts +2 -0
- package/lib/hosted-target/capsule-error-response.mjs +73 -0
- package/lib/hosted-target/errors.cjs +88 -0
- package/lib/hosted-target/errors.d.cts +36 -0
- package/lib/hosted-target/errors.d.mts +36 -0
- package/lib/hosted-target/errors.d.ts +36 -0
- package/lib/hosted-target/errors.mjs +75 -0
- package/lib/hosted-target/index.cjs +16 -0
- package/lib/hosted-target/index.d.cts +3 -0
- package/lib/hosted-target/index.d.mts +3 -0
- package/lib/hosted-target/index.d.ts +3 -0
- package/lib/hosted-target/index.mjs +2 -0
- package/lib/hosted-target/response-validation.cjs +169 -0
- package/lib/hosted-target/response-validation.d.cts +5 -0
- package/lib/hosted-target/response-validation.d.mts +5 -0
- package/lib/hosted-target/response-validation.d.ts +5 -0
- package/lib/hosted-target/response-validation.mjs +163 -0
- package/lib/hosted-target/retry-executor.cjs +51 -0
- package/lib/hosted-target/retry-executor.d.cts +8 -0
- package/lib/hosted-target/retry-executor.d.mts +8 -0
- package/lib/hosted-target/retry-executor.d.ts +8 -0
- package/lib/hosted-target/retry-executor.mjs +48 -0
- package/lib/hosted-target/retry.cjs +78 -0
- package/lib/hosted-target/retry.d.cts +9 -0
- package/lib/hosted-target/retry.d.mts +9 -0
- package/lib/hosted-target/retry.d.ts +9 -0
- package/lib/hosted-target/retry.mjs +73 -0
- package/lib/hosted-target/target-adapter.cjs +10 -0
- package/lib/hosted-target/target-adapter.d.cts +3 -0
- package/lib/hosted-target/target-adapter.d.mts +3 -0
- package/lib/hosted-target/target-adapter.d.ts +3 -0
- package/lib/hosted-target/target-adapter.mjs +7 -0
- package/lib/hosted-target/types.cjs +4 -0
- package/lib/hosted-target/types.d.cts +50 -0
- package/lib/hosted-target/types.d.mts +50 -0
- package/lib/hosted-target/types.d.ts +50 -0
- package/lib/hosted-target/types.mjs +1 -0
- package/lib/hosted-target/zero-cloud-v1-adapter.cjs +185 -0
- package/lib/hosted-target/zero-cloud-v1-adapter.d.cts +13 -0
- package/lib/hosted-target/zero-cloud-v1-adapter.d.mts +13 -0
- package/lib/hosted-target/zero-cloud-v1-adapter.d.ts +13 -0
- package/lib/hosted-target/zero-cloud-v1-adapter.mjs +181 -0
- package/lib/target/bounded-response.cjs +51 -0
- package/lib/target/bounded-response.d.cts +1 -0
- package/lib/target/bounded-response.d.mts +1 -0
- package/lib/target/bounded-response.d.ts +1 -0
- package/lib/target/bounded-response.js +51 -0
- package/lib/target/bounded-response.mjs +48 -0
- package/lib/target/credential-lock.js +1 -3
- package/lib/target/credential-store.js +9 -4
- package/lib/target/device-flow.cjs +213 -0
- package/lib/target/device-flow.d.cts +54 -0
- package/lib/target/device-flow.d.mts +54 -0
- package/lib/target/device-flow.d.ts +26 -10
- package/lib/target/device-flow.js +162 -53
- package/lib/target/device-flow.mjs +203 -0
- package/lib/target/discovery-errors.cjs +10 -0
- package/lib/target/discovery-errors.d.cts +3 -0
- package/lib/target/discovery-errors.d.mts +3 -0
- package/lib/target/discovery-errors.d.ts +3 -0
- package/lib/target/discovery-errors.js +10 -0
- package/lib/target/discovery-errors.mjs +6 -0
- package/lib/target/discovery-sections.cjs +191 -0
- package/lib/target/discovery-sections.d.cts +52 -0
- package/lib/target/discovery-sections.d.mts +52 -0
- package/lib/target/discovery-sections.d.ts +52 -0
- package/lib/target/discovery-sections.js +191 -0
- package/lib/target/discovery-sections.mjs +179 -0
- package/lib/target/discovery-validation.cjs +109 -0
- package/lib/target/discovery-validation.d.cts +28 -0
- package/lib/target/discovery-validation.d.mts +28 -0
- package/lib/target/discovery-validation.d.ts +28 -0
- package/lib/target/discovery-validation.js +109 -0
- package/lib/target/discovery-validation.mjs +99 -0
- package/lib/target/discovery.cjs +112 -0
- package/lib/target/discovery.d.cts +74 -0
- package/lib/target/discovery.d.mts +74 -0
- package/lib/target/discovery.d.ts +68 -5
- package/lib/target/discovery.js +93 -101
- package/lib/target/discovery.mjs +105 -0
- package/lib/target/index.d.ts +6 -6
- package/lib/target/index.js +36 -36
- package/lib/target/oauth-http.d.ts +2 -0
- package/lib/target/oauth-http.js +25 -0
- package/lib/target/refresh-exchange.d.ts +11 -0
- package/lib/target/refresh-exchange.js +24 -0
- package/lib/target/refresh-revocation.d.ts +8 -0
- package/lib/target/refresh-revocation.js +19 -0
- package/lib/target/route-template.cjs +85 -0
- package/lib/target/route-template.d.cts +7 -0
- package/lib/target/route-template.d.mts +7 -0
- package/lib/target/route-template.d.ts +7 -0
- package/lib/target/route-template.js +85 -0
- package/lib/target/route-template.mjs +81 -0
- package/lib/target/session-errors.d.ts +4 -0
- package/lib/target/session-errors.js +12 -0
- package/lib/target/session-verification.d.ts +10 -0
- package/lib/target/session-verification.js +42 -0
- package/lib/target/target-registry.d.ts +7 -3
- package/lib/target/target-registry.js +41 -10
- package/lib/target/target-session-manager.d.ts +48 -0
- package/lib/target/target-session-manager.js +226 -0
- package/lib/target/target-session.d.ts +39 -31
- package/lib/target/target-session.js +63 -150
- package/lib/target/token-response.cjs +51 -0
- package/lib/target/token-response.d.cts +7 -0
- package/lib/target/token-response.d.mts +7 -0
- package/lib/target/token-response.d.ts +7 -0
- package/lib/target/token-response.js +51 -0
- package/lib/target/token-response.mjs +48 -0
- package/package.json +16 -6
- package/scripts/audit-production-dependencies.js +150 -0
- package/scripts/build-cluster.js +23 -3
- package/scripts/opcore-agent-gate.js +159 -0
- package/scripts/opcore-agent-tool-overlays.js +154 -0
- package/scripts/opcore-introduced-check.js +288 -0
- package/src/cluster/client.ts +42 -15
- package/src/cluster/connection-state.ts +33 -0
- package/src/cluster/connection-types.ts +28 -0
- package/src/cluster/connection.ts +37 -68
- package/src/cluster/errors.ts +5 -0
- package/src/cluster/index.ts +3 -1
- package/src/cluster/json-source.ts +1 -0
- package/src/cluster/payload-value.ts +1 -0
- package/src/cluster/socket.ts +13 -0
- package/src/cluster/subscriptions.ts +7 -2
- package/src/cluster/validators.ts +1 -0
- package/src/cluster/ws.d.ts +1 -1
- package/src/hosted-session/authority.ts +77 -0
- package/src/hosted-session/coordinator.ts +113 -56
- package/src/hosted-session/errors.ts +21 -0
- package/src/hosted-session/index.ts +14 -2
- package/src/hosted-session/reconnecting-watch.ts +148 -0
- package/src/hosted-session/types.ts +22 -8
- package/src/hosted-target/access-url.ts +46 -0
- package/src/hosted-target/adapter-request.ts +28 -0
- package/src/hosted-target/adapter-types.ts +39 -0
- package/src/hosted-target/bounds.ts +1 -0
- package/src/hosted-target/capsule-error-response.ts +107 -0
- package/src/hosted-target/errors.ts +36 -35
- package/src/hosted-target/index.ts +10 -23
- package/src/hosted-target/response-validation.ts +170 -62
- package/src/hosted-target/retry-executor.ts +62 -0
- package/src/hosted-target/retry.ts +47 -11
- package/src/hosted-target/target-adapter.ts +12 -8
- package/src/hosted-target/types.ts +19 -18
- package/src/hosted-target/zero-cloud-v1-adapter.ts +229 -316
- package/src/target/bounded-response.ts +68 -0
- package/src/target/credential-lock.ts +1 -3
- package/src/target/credential-store.ts +14 -10
- package/src/target/device-flow.ts +206 -71
- package/src/target/discovery-errors.ts +6 -0
- package/src/target/discovery-sections.ts +251 -0
- package/src/target/discovery-validation.ts +144 -0
- package/src/target/discovery.ts +163 -115
- package/src/target/index.ts +15 -11
- package/src/target/oauth-http.ts +27 -0
- package/src/target/refresh-exchange.ts +36 -0
- package/src/target/refresh-revocation.ts +29 -0
- package/src/target/route-template.ts +105 -0
- package/src/target/session-errors.ts +9 -0
- package/src/target/session-verification.ts +51 -0
- package/src/target/target-registry.ts +60 -27
- package/src/target/target-session-manager.ts +285 -0
- package/src/target/target-session.ts +105 -222
- package/src/target/token-response.ts +62 -0
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
[](https://www.npmjs.com/package/@the-open-engine/zeroshot)
|
|
16
16
|
[](https://github.com/the-open-engine/zeroshot/actions/workflows/ci.yml)
|
|
17
17
|
[](LICENSE)
|
|
18
|
-
[](#install)
|
|
19
19
|
[](#install)
|
|
20
20
|
[](https://github.com/the-open-engine/zeroshot)
|
|
21
21
|
[](#the-open-engine)
|
|
@@ -43,7 +43,7 @@ Zeroshot is an open-source, multi-agent orchestration engine for autonomous soft
|
|
|
43
43
|
npm install -g @the-open-engine/zeroshot
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
Requires **Node ≥
|
|
46
|
+
Requires **Node ≥ 22** and at least one provider CLI (Claude Code, Codex, Gemini, or OpenCode). The package includes the pinned Opcore constraints CLI; repository hook activation remains explicit. Linux and macOS today; Windows is deferred.
|
|
47
47
|
|
|
48
48
|
<div align="center">
|
|
49
49
|
<img src="docs/assets/zeroshot-demo.gif" alt="Zeroshot resolving an issue through the executor-verifier loop" width="760">
|
|
@@ -207,7 +207,7 @@ Zeroshot is **Layer 01 · Verification** of [The Open Engine](https://theopeneng
|
|
|
207
207
|
| 02 | Constraints: **Opcore** | Sibling · alpha |
|
|
208
208
|
| 03-05 | Intent · Context · Runtime | In development |
|
|
209
209
|
|
|
210
|
-
Zeroshot runs the loop: an agent writes the change, and an **independent** verifier decides whether it holds: approve, or a reproducible failure. **Opcore** is the sibling layer, a deterministic, local, read-only **constraints** gate for coding agents
|
|
210
|
+
Zeroshot runs the loop: an agent writes the change, and an **independent** verifier decides whether it holds: approve, or a reproducible failure. **Opcore** is the sibling layer, a deterministic, local, read-only **constraints** gate for coding agents. Zeroshot packages Opcore `0.2.1` and uses introduced-change validation so existing repository debt never blocks an otherwise clean change. Verification asks _"does this meet the goal?"_; constraints ask _"is this within tolerance?"_
|
|
211
211
|
|
|
212
212
|
Each layer ships the same way: extracted from the platform we run, then opened. **Trust nothing. Verify everything.**
|
|
213
213
|
|
package/cli/index.js
CHANGED
|
@@ -2647,6 +2647,7 @@ Shell completion:
|
|
|
2647
2647
|
);
|
|
2648
2648
|
|
|
2649
2649
|
// Run command - CLUSTER with auto-detection
|
|
2650
|
+
|
|
2650
2651
|
program
|
|
2651
2652
|
.command('run <input>')
|
|
2652
2653
|
.description(
|
|
@@ -3959,6 +3960,10 @@ for (const providerName of VALID_PROVIDERS) {
|
|
|
3959
3960
|
// Settings management
|
|
3960
3961
|
const settingsCmd = program.command('settings').description('Manage zeroshot settings');
|
|
3961
3962
|
const INTERNAL_SETTINGS_KEYS = new Set(['lastUpdateCheckClaim', '_targets']);
|
|
3963
|
+
// Fail closed while hosted commands are unpublished. Keeping these names out of the
|
|
3964
|
+
// default `run` rewrite makes them unknown commands rather than local task input.
|
|
3965
|
+
// Issue #920 deliberately has no CLI lifecycle or runtime execution surface.
|
|
3966
|
+
const UNREGISTERED_HOSTED_COMMAND_NAMES = new Set(['target', 'capsule']);
|
|
3962
3967
|
|
|
3963
3968
|
function visibleSettingKeys() {
|
|
3964
3969
|
return Object.keys(DEFAULT_SETTINGS).filter((key) => !INTERNAL_SETTINGS_KEYS.has(key));
|
|
@@ -4490,211 +4495,7 @@ settingsCmd.action(() => {
|
|
|
4490
4495
|
formatSettingsList(settings, true);
|
|
4491
4496
|
});
|
|
4492
4497
|
|
|
4493
|
-
//
|
|
4494
|
-
// Target modules are compiled during install/package preparation for the Node 18+ CLI.
|
|
4495
|
-
const importTarget = (mod) => import(`../lib/target/${mod}.js`);
|
|
4496
|
-
const targetCmd = program.command('target').description('Manage named remote targets');
|
|
4497
|
-
|
|
4498
|
-
targetCmd
|
|
4499
|
-
.command('add <name>')
|
|
4500
|
-
.description('Register a named remote target')
|
|
4501
|
-
.requiredOption('--url <url>', 'Service URL for the target')
|
|
4502
|
-
.action(async (name, options) => {
|
|
4503
|
-
try {
|
|
4504
|
-
const { addTarget } = await importTarget('target-registry');
|
|
4505
|
-
const settingsPort = {
|
|
4506
|
-
load: () => loadSettings(),
|
|
4507
|
-
mutate: (fn) => mutateSettings(fn),
|
|
4508
|
-
};
|
|
4509
|
-
const record = addTarget(name, options.url, settingsPort);
|
|
4510
|
-
console.log(chalk.green(`✓ Target "${name}" added (${record.url})`));
|
|
4511
|
-
} catch (error) {
|
|
4512
|
-
console.error(chalk.red(error.message));
|
|
4513
|
-
process.exit(1);
|
|
4514
|
-
}
|
|
4515
|
-
});
|
|
4516
|
-
|
|
4517
|
-
targetCmd
|
|
4518
|
-
.command('login <name>')
|
|
4519
|
-
.description('Authenticate with a remote target via device login')
|
|
4520
|
-
.action(async (name) => {
|
|
4521
|
-
try {
|
|
4522
|
-
const { getTarget } = await importTarget('target-registry');
|
|
4523
|
-
const { targetLogin } = await importTarget('target-session');
|
|
4524
|
-
const { KeyringCredentialStore } = await importTarget('credential-store');
|
|
4525
|
-
const { acquireTargetLock } = await importTarget('credential-lock');
|
|
4526
|
-
const { discoverTargetSessionEndpoints } = await importTarget('discovery');
|
|
4527
|
-
|
|
4528
|
-
const settingsPort = {
|
|
4529
|
-
load: () => loadSettings(),
|
|
4530
|
-
mutate: (fn) => mutateSettings(fn),
|
|
4531
|
-
};
|
|
4532
|
-
|
|
4533
|
-
const target = getTarget(name, settingsPort);
|
|
4534
|
-
if (!target) {
|
|
4535
|
-
console.error(chalk.red(`Target "${name}" not found.`));
|
|
4536
|
-
process.exit(1);
|
|
4537
|
-
}
|
|
4538
|
-
|
|
4539
|
-
const http = { fetch: (url, init) => fetch(url, init) };
|
|
4540
|
-
const discoveryEndpoints = await discoverTargetSessionEndpoints(target.url, http);
|
|
4541
|
-
|
|
4542
|
-
const credentialStore = await KeyringCredentialStore.create();
|
|
4543
|
-
const openPkg = await import('open');
|
|
4544
|
-
const browserOpen = openPkg.default || openPkg;
|
|
4545
|
-
|
|
4546
|
-
const result = await targetLogin(
|
|
4547
|
-
name,
|
|
4548
|
-
target,
|
|
4549
|
-
credentialStore,
|
|
4550
|
-
() => acquireTargetLock(target.id),
|
|
4551
|
-
settingsPort,
|
|
4552
|
-
{
|
|
4553
|
-
http,
|
|
4554
|
-
clock: { now: () => Date.now() },
|
|
4555
|
-
browserOpener: {
|
|
4556
|
-
open: async (url) => {
|
|
4557
|
-
await browserOpen(url);
|
|
4558
|
-
},
|
|
4559
|
-
},
|
|
4560
|
-
stderr: process.stderr,
|
|
4561
|
-
discoveryEndpoints,
|
|
4562
|
-
}
|
|
4563
|
-
);
|
|
4564
|
-
|
|
4565
|
-
console.log(
|
|
4566
|
-
chalk.green(`✓ Logged in to "${name}" (organization: ${result.organization.name})`)
|
|
4567
|
-
);
|
|
4568
|
-
} catch (error) {
|
|
4569
|
-
console.error(chalk.red(error.message));
|
|
4570
|
-
process.exit(1);
|
|
4571
|
-
}
|
|
4572
|
-
});
|
|
4573
|
-
|
|
4574
|
-
targetCmd
|
|
4575
|
-
.command('list')
|
|
4576
|
-
.description('List registered remote targets')
|
|
4577
|
-
.option('--json', 'Output as JSON')
|
|
4578
|
-
.action(async (options) => {
|
|
4579
|
-
try {
|
|
4580
|
-
const { listTargets } = await importTarget('target-registry');
|
|
4581
|
-
const settingsPort = {
|
|
4582
|
-
load: () => loadSettings(),
|
|
4583
|
-
mutate: (fn) => mutateSettings(fn),
|
|
4584
|
-
};
|
|
4585
|
-
|
|
4586
|
-
const targets = listTargets(settingsPort);
|
|
4587
|
-
|
|
4588
|
-
if (options.json) {
|
|
4589
|
-
const output = targets.map(({ name, record }) => ({
|
|
4590
|
-
name,
|
|
4591
|
-
id: record.id,
|
|
4592
|
-
url: record.url,
|
|
4593
|
-
organization: record.organization ?? null,
|
|
4594
|
-
loggedIn: false,
|
|
4595
|
-
createdAt: record.createdAt,
|
|
4596
|
-
}));
|
|
4597
|
-
|
|
4598
|
-
// Try to check keyring presence for each target
|
|
4599
|
-
try {
|
|
4600
|
-
const { KeyringCredentialStore } = await importTarget('credential-store');
|
|
4601
|
-
const { targetServiceKey, TARGET_ACCOUNT } = await importTarget('credential-store');
|
|
4602
|
-
const store = await KeyringCredentialStore.create();
|
|
4603
|
-
for (const item of output) {
|
|
4604
|
-
const matchingTarget = targets.find((t) => t.name === item.name);
|
|
4605
|
-
if (matchingTarget) {
|
|
4606
|
-
const cred = await store.get(
|
|
4607
|
-
targetServiceKey(matchingTarget.record.id),
|
|
4608
|
-
TARGET_ACCOUNT
|
|
4609
|
-
);
|
|
4610
|
-
item.loggedIn = cred !== null;
|
|
4611
|
-
}
|
|
4612
|
-
}
|
|
4613
|
-
} catch {
|
|
4614
|
-
// Keyring unavailable, all show as not logged in
|
|
4615
|
-
}
|
|
4616
|
-
|
|
4617
|
-
console.log(JSON.stringify(output, null, 2));
|
|
4618
|
-
return;
|
|
4619
|
-
}
|
|
4620
|
-
|
|
4621
|
-
if (targets.length === 0) {
|
|
4622
|
-
console.log(
|
|
4623
|
-
chalk.dim(
|
|
4624
|
-
'No targets registered. Use `zeroshot target add <name> --url <url>` to add one.'
|
|
4625
|
-
)
|
|
4626
|
-
);
|
|
4627
|
-
return;
|
|
4628
|
-
}
|
|
4629
|
-
|
|
4630
|
-
for (const { name, record } of targets) {
|
|
4631
|
-
const org = record.organization ? ` (org: ${record.organization.name})` : '';
|
|
4632
|
-
console.log(` ${chalk.bold(name)} ${record.url}${org}`);
|
|
4633
|
-
}
|
|
4634
|
-
} catch (error) {
|
|
4635
|
-
console.error(chalk.red(error.message));
|
|
4636
|
-
process.exit(1);
|
|
4637
|
-
}
|
|
4638
|
-
});
|
|
4639
|
-
|
|
4640
|
-
targetCmd
|
|
4641
|
-
.command('remove <name>')
|
|
4642
|
-
.description('Remove a named remote target')
|
|
4643
|
-
.option('--force', 'Remove even if remote revocation fails')
|
|
4644
|
-
.action(async (name, options) => {
|
|
4645
|
-
try {
|
|
4646
|
-
const { getTarget, removeTarget } = await importTarget('target-registry');
|
|
4647
|
-
const { revokeAndCleanup } = await importTarget('target-session');
|
|
4648
|
-
const { acquireTargetLock } = await importTarget('credential-lock');
|
|
4649
|
-
const { discoverTargetSessionEndpoints } = await importTarget('discovery');
|
|
4650
|
-
|
|
4651
|
-
const settingsPort = {
|
|
4652
|
-
load: () => loadSettings(),
|
|
4653
|
-
mutate: (fn) => mutateSettings(fn),
|
|
4654
|
-
};
|
|
4655
|
-
|
|
4656
|
-
const target = getTarget(name, settingsPort);
|
|
4657
|
-
if (!target) {
|
|
4658
|
-
console.error(chalk.red(`Target "${name}" not found.`));
|
|
4659
|
-
process.exit(1);
|
|
4660
|
-
}
|
|
4661
|
-
|
|
4662
|
-
// Try to revoke and cleanup keyring
|
|
4663
|
-
try {
|
|
4664
|
-
const { KeyringCredentialStore } = await importTarget('credential-store');
|
|
4665
|
-
const credentialStore = await KeyringCredentialStore.create();
|
|
4666
|
-
const http = { fetch: (url, init) => fetch(url, init) };
|
|
4667
|
-
const discoveryEndpoints = await discoverTargetSessionEndpoints(target.url, http);
|
|
4668
|
-
await revokeAndCleanup(
|
|
4669
|
-
target,
|
|
4670
|
-
credentialStore,
|
|
4671
|
-
() => acquireTargetLock(target.id),
|
|
4672
|
-
{
|
|
4673
|
-
http,
|
|
4674
|
-
discoveryEndpoints,
|
|
4675
|
-
},
|
|
4676
|
-
!!options.force
|
|
4677
|
-
);
|
|
4678
|
-
} catch (error) {
|
|
4679
|
-
if (!options.force) {
|
|
4680
|
-
console.error(chalk.red(error.message));
|
|
4681
|
-
process.exit(1);
|
|
4682
|
-
}
|
|
4683
|
-
// Force mode: continue with removal
|
|
4684
|
-
}
|
|
4685
|
-
|
|
4686
|
-
removeTarget(name, settingsPort);
|
|
4687
|
-
console.log(chalk.green(`✓ Target "${name}" removed`));
|
|
4688
|
-
} catch (error) {
|
|
4689
|
-
console.error(chalk.red(error.message));
|
|
4690
|
-
process.exit(1);
|
|
4691
|
-
}
|
|
4692
|
-
});
|
|
4693
|
-
|
|
4694
|
-
targetCmd.action(() => {
|
|
4695
|
-
targetCmd.help();
|
|
4696
|
-
});
|
|
4697
|
-
|
|
4498
|
+
// Hosted target commands intentionally are not registered on the stable CLI.
|
|
4698
4499
|
// Providers management
|
|
4699
4500
|
const providersCmd = program.command('providers').description('Manage AI providers');
|
|
4700
4501
|
providersCmd.action(async () => {
|
|
@@ -6255,6 +6056,16 @@ function isStartupUpdateEligible(argv, options = {}) {
|
|
|
6255
6056
|
});
|
|
6256
6057
|
}
|
|
6257
6058
|
|
|
6059
|
+
function applyDefaultCommand(args) {
|
|
6060
|
+
const firstArg = args[0];
|
|
6061
|
+
if (!firstArg || firstArg.startsWith('-')) return;
|
|
6062
|
+
|
|
6063
|
+
const commandNames = program.commands.map((command) => command.name());
|
|
6064
|
+
if (commandNames.includes(firstArg) || UNREGISTERED_HOSTED_COMMAND_NAMES.has(firstArg)) return;
|
|
6065
|
+
|
|
6066
|
+
process.argv.splice(2, 0, 'run');
|
|
6067
|
+
}
|
|
6068
|
+
|
|
6258
6069
|
// Main entry point
|
|
6259
6070
|
async function main() {
|
|
6260
6071
|
printLegacyDistroNotice();
|
|
@@ -6280,31 +6091,16 @@ async function main() {
|
|
|
6280
6091
|
checkForUpdates({ argv: startupArgs, eligibilityChecked: true });
|
|
6281
6092
|
}
|
|
6282
6093
|
|
|
6283
|
-
|
|
6094
|
+
const args = startupArgs;
|
|
6284
6095
|
|
|
6285
6096
|
if (args.length === 0) {
|
|
6286
6097
|
program.outputHelp();
|
|
6287
6098
|
return;
|
|
6288
6099
|
}
|
|
6289
6100
|
|
|
6290
|
-
//
|
|
6291
|
-
//
|
|
6292
|
-
args
|
|
6293
|
-
if (args.length > 0) {
|
|
6294
|
-
const firstArg = args[0];
|
|
6295
|
-
|
|
6296
|
-
// Skip if it's a flag/option (starts with -)
|
|
6297
|
-
// Skip if it's --help or --version (these are handled by commander)
|
|
6298
|
-
if (!firstArg.startsWith('-')) {
|
|
6299
|
-
// Get all registered command names
|
|
6300
|
-
const commandNames = program.commands.map((cmd) => cmd.name());
|
|
6301
|
-
|
|
6302
|
-
// If first arg is not a known command, prepend 'run'
|
|
6303
|
-
if (!commandNames.includes(firstArg)) {
|
|
6304
|
-
process.argv.splice(2, 0, 'run');
|
|
6305
|
-
}
|
|
6306
|
-
}
|
|
6307
|
-
}
|
|
6101
|
+
// Preserve the default local run shorthand without treating hosted-only command
|
|
6102
|
+
// names as task input in the stable parser.
|
|
6103
|
+
applyDefaultCommand(args);
|
|
6308
6104
|
|
|
6309
6105
|
program.parse();
|
|
6310
6106
|
}
|
|
@@ -4,12 +4,11 @@
|
|
|
4
4
|
# Build: docker build -t vibe-cluster-base vibe/cluster/docker/vibe-cluster/
|
|
5
5
|
# Usage: zeroshot run <task> --docker
|
|
6
6
|
|
|
7
|
-
FROM node:
|
|
7
|
+
FROM node:22-slim
|
|
8
8
|
|
|
9
9
|
# Upgrade npm to fix Arborist isDescendantOf bug (npm 10.x crash on complex peer deps)
|
|
10
10
|
# See: https://github.com/npm/cli/issues/7682
|
|
11
|
-
# Pinned to npm@11
|
|
12
|
-
# now requires node >=22 and breaks the build with EBADENGINE.
|
|
11
|
+
# Pinned to npm@11 to keep the container toolchain reproducible with the supported Node 22 line.
|
|
13
12
|
RUN npm install -g npm@11
|
|
14
13
|
|
|
15
14
|
# Version pinning for infrastructure tools
|
package/lib/cluster/client.cjs
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ClusterClient = void 0;
|
|
4
4
|
exports.connect = connect;
|
|
5
5
|
exports.connectInitialized = connectInitialized;
|
|
6
|
+
/// <reference path="./ws.d.ts" />
|
|
6
7
|
const protocol_js_1 = require("./generated/protocol.cjs");
|
|
7
8
|
const connection_js_1 = require("./connection.cjs");
|
|
8
9
|
const socket_js_1 = require("./socket.cjs");
|
|
@@ -82,10 +83,7 @@ class ClusterClient {
|
|
|
82
83
|
exports.ClusterClient = ClusterClient;
|
|
83
84
|
async function defaultWebSocketFactory(url, protocols, options) {
|
|
84
85
|
const globalWebSocket = globalThis.WebSocket;
|
|
85
|
-
if (globalWebSocket) {
|
|
86
|
-
if (options?.headers && Object.keys(options.headers).length > 0) {
|
|
87
|
-
throw new errors_js_1.ClusterConfigError('WebSocket upgrade headers require the ws library; the browser WebSocket API cannot carry request headers', 'HEADERS_UNSUPPORTED');
|
|
88
|
-
}
|
|
86
|
+
if (globalWebSocket && (!options?.headers || Object.keys(options.headers).length === 0)) {
|
|
89
87
|
return new globalWebSocket(url, protocols);
|
|
90
88
|
}
|
|
91
89
|
try {
|
|
@@ -114,6 +112,7 @@ async function waitForOpen(socket, signal) {
|
|
|
114
112
|
await new Promise((resolve, reject) => {
|
|
115
113
|
let settled = false;
|
|
116
114
|
const removers = [];
|
|
115
|
+
let upgradeFailure;
|
|
117
116
|
const settle = (fn) => {
|
|
118
117
|
if (settled)
|
|
119
118
|
return;
|
|
@@ -124,10 +123,34 @@ async function waitForOpen(socket, signal) {
|
|
|
124
123
|
fn();
|
|
125
124
|
};
|
|
126
125
|
const onAbort = () => settle(() => reject(new DOMException('connect aborted locally; the server may still have committed this request', 'AbortError')));
|
|
127
|
-
|
|
126
|
+
const onUnexpectedResponse = (...args) => {
|
|
127
|
+
const response = args.find((value) => value !== null && typeof value === 'object' && 'statusCode' in value);
|
|
128
|
+
const status = response?.statusCode;
|
|
129
|
+
upgradeFailure = typeof status === 'number'
|
|
130
|
+
? new errors_js_1.ClusterUpgradeError(status)
|
|
131
|
+
: new errors_js_1.ClusterTransportError('WebSocket upgrade rejected', 'UPGRADE_REJECTED');
|
|
132
|
+
response?.resume?.();
|
|
133
|
+
if (socket.terminate) {
|
|
134
|
+
socket.terminate();
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
settle(() => reject(upgradeFailure));
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
removers.push((0, socket_js_1.addSocketListener)(socket, 'open', () => settle(resolve)), (0, socket_js_1.addSocketListener)(socket, 'error', (error) => settle(() => reject(upgradeFailure ??
|
|
141
|
+
new errors_js_1.ClusterTransportError('WebSocket failed to open', 'OPEN_FAILED', { cause: error })))), (0, socket_js_1.addSocketListener)(socket, 'close', () => settle(() => reject(upgradeFailure ??
|
|
142
|
+
new errors_js_1.ClusterTransportError('WebSocket closed before opening', 'OPEN_FAILED')))), (0, socket_js_1.addSocketEmitterListener)(socket, 'unexpected-response', onUnexpectedResponse));
|
|
128
143
|
signal?.addEventListener('abort', onAbort, { once: true });
|
|
129
144
|
});
|
|
130
145
|
}
|
|
146
|
+
async function disposeFailedSocket(socket) {
|
|
147
|
+
if (socket.readyState === 0 && socket.terminate) {
|
|
148
|
+
socket.terminate();
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
await socket.close();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
131
154
|
async function connect(url, options = {}) {
|
|
132
155
|
const factory = options.webSocketFactory ?? defaultWebSocketFactory;
|
|
133
156
|
let socket;
|
|
@@ -141,7 +164,7 @@ async function connect(url, options = {}) {
|
|
|
141
164
|
catch (error) {
|
|
142
165
|
if (socket) {
|
|
143
166
|
try {
|
|
144
|
-
await socket
|
|
167
|
+
await disposeFailedSocket(socket);
|
|
145
168
|
}
|
|
146
169
|
catch { /* preserve the construction error */ }
|
|
147
170
|
}
|
|
@@ -162,7 +185,7 @@ async function connectInitialized(url, options = {}) {
|
|
|
162
185
|
catch (error) {
|
|
163
186
|
if (socket) {
|
|
164
187
|
try {
|
|
165
|
-
await socket
|
|
188
|
+
await disposeFailedSocket(socket);
|
|
166
189
|
}
|
|
167
190
|
catch { /* preserve the construction error */ }
|
|
168
191
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { AgentAttachParams, AgentAttachResult, ApplyParams, ApplyResult, DeleteParams, DeleteResult, GetParams, GetResult, InitializeParams, InitializeResult, LogsParams, LogsResult, PlanParams, PlanResult, ResubmitParams, ResubmitResult, RetryParams, RetryResult, StopParams, StopResult, UpdateParams, UpdateResult, WatchParams } from './generated/protocol.js';
|
|
2
|
+
import { Connection } from './connection.js';
|
|
3
|
+
import type { CallOptions } from './connection.js';
|
|
4
|
+
import type { WebSocketLike } from './socket.js';
|
|
5
|
+
import { AgentAttachSubscriptionStream, LogsSubscriptionStream } from './subscriptions.js';
|
|
6
|
+
import type { WatchSubscription } from './subscriptions.js';
|
|
7
|
+
export type { WatchSubscription } from './subscriptions.js';
|
|
8
|
+
export interface WebSocketFactoryOptions {
|
|
9
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
10
|
+
}
|
|
11
|
+
export interface ConnectOptions {
|
|
12
|
+
readonly protocols?: string | readonly string[];
|
|
13
|
+
readonly webSocketFactory?: (url: string, protocols?: string | readonly string[], options?: WebSocketFactoryOptions) => WebSocketLike | Promise<WebSocketLike>;
|
|
14
|
+
readonly signal?: AbortSignal;
|
|
15
|
+
readonly initialize?: InitializeParams;
|
|
16
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
17
|
+
}
|
|
18
|
+
export interface LogsSubscription {
|
|
19
|
+
readonly result: LogsResult;
|
|
20
|
+
readonly stream: LogsSubscriptionStream;
|
|
21
|
+
}
|
|
22
|
+
export interface AgentAttachSubscription {
|
|
23
|
+
readonly result: AgentAttachResult;
|
|
24
|
+
readonly stream: AgentAttachSubscriptionStream;
|
|
25
|
+
}
|
|
26
|
+
export interface CoherentWatchSubscription extends WatchSubscription {
|
|
27
|
+
readonly snapshot: GetResult;
|
|
28
|
+
}
|
|
29
|
+
export interface ConnectInitializedResult {
|
|
30
|
+
readonly connection: Connection;
|
|
31
|
+
readonly client: ClusterClient;
|
|
32
|
+
readonly initializeResult: InitializeResult;
|
|
33
|
+
}
|
|
34
|
+
export declare class ClusterClient {
|
|
35
|
+
readonly connection: Connection;
|
|
36
|
+
constructor(connection: Connection);
|
|
37
|
+
initialize(params?: InitializeParams, options?: CallOptions): Promise<InitializeResult>;
|
|
38
|
+
plan(params: PlanParams, options?: CallOptions): Promise<PlanResult>;
|
|
39
|
+
apply(params: ApplyParams, options?: CallOptions): Promise<ApplyResult>;
|
|
40
|
+
update(params: UpdateParams, options?: CallOptions): Promise<UpdateResult>;
|
|
41
|
+
stop(params: StopParams, options?: CallOptions): Promise<StopResult>;
|
|
42
|
+
retry(params: RetryParams, options?: CallOptions): Promise<RetryResult>;
|
|
43
|
+
resubmit(params: ResubmitParams, options?: CallOptions): Promise<ResubmitResult>;
|
|
44
|
+
delete(params: DeleteParams, options?: CallOptions): Promise<DeleteResult>;
|
|
45
|
+
get(params?: GetParams, options?: CallOptions): Promise<GetResult>;
|
|
46
|
+
watch(params?: WatchParams, options?: CallOptions): Promise<WatchSubscription>;
|
|
47
|
+
watchColdStart(params?: Omit<WatchParams, 'fromCursor'>, options?: CallOptions): Promise<CoherentWatchSubscription>;
|
|
48
|
+
logs(params?: LogsParams, options?: CallOptions): Promise<LogsSubscription>;
|
|
49
|
+
agentAttach(params: AgentAttachParams, options?: CallOptions): Promise<AgentAttachSubscription>;
|
|
50
|
+
}
|
|
51
|
+
export declare function connect(url: string, options?: ConnectOptions): Promise<Connection>;
|
|
52
|
+
export declare function connectInitialized(url: string, options?: ConnectOptions): Promise<ConnectInitializedResult>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { AgentAttachParams, AgentAttachResult, ApplyParams, ApplyResult, DeleteParams, DeleteResult, GetParams, GetResult, InitializeParams, InitializeResult, LogsParams, LogsResult, PlanParams, PlanResult, ResubmitParams, ResubmitResult, RetryParams, RetryResult, StopParams, StopResult, UpdateParams, UpdateResult, WatchParams } from './generated/protocol.js';
|
|
2
|
+
import { Connection } from './connection.js';
|
|
3
|
+
import type { CallOptions } from './connection.js';
|
|
4
|
+
import type { WebSocketLike } from './socket.js';
|
|
5
|
+
import { AgentAttachSubscriptionStream, LogsSubscriptionStream } from './subscriptions.js';
|
|
6
|
+
import type { WatchSubscription } from './subscriptions.js';
|
|
7
|
+
export type { WatchSubscription } from './subscriptions.js';
|
|
8
|
+
export interface WebSocketFactoryOptions {
|
|
9
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
10
|
+
}
|
|
11
|
+
export interface ConnectOptions {
|
|
12
|
+
readonly protocols?: string | readonly string[];
|
|
13
|
+
readonly webSocketFactory?: (url: string, protocols?: string | readonly string[], options?: WebSocketFactoryOptions) => WebSocketLike | Promise<WebSocketLike>;
|
|
14
|
+
readonly signal?: AbortSignal;
|
|
15
|
+
readonly initialize?: InitializeParams;
|
|
16
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
17
|
+
}
|
|
18
|
+
export interface LogsSubscription {
|
|
19
|
+
readonly result: LogsResult;
|
|
20
|
+
readonly stream: LogsSubscriptionStream;
|
|
21
|
+
}
|
|
22
|
+
export interface AgentAttachSubscription {
|
|
23
|
+
readonly result: AgentAttachResult;
|
|
24
|
+
readonly stream: AgentAttachSubscriptionStream;
|
|
25
|
+
}
|
|
26
|
+
export interface CoherentWatchSubscription extends WatchSubscription {
|
|
27
|
+
readonly snapshot: GetResult;
|
|
28
|
+
}
|
|
29
|
+
export interface ConnectInitializedResult {
|
|
30
|
+
readonly connection: Connection;
|
|
31
|
+
readonly client: ClusterClient;
|
|
32
|
+
readonly initializeResult: InitializeResult;
|
|
33
|
+
}
|
|
34
|
+
export declare class ClusterClient {
|
|
35
|
+
readonly connection: Connection;
|
|
36
|
+
constructor(connection: Connection);
|
|
37
|
+
initialize(params?: InitializeParams, options?: CallOptions): Promise<InitializeResult>;
|
|
38
|
+
plan(params: PlanParams, options?: CallOptions): Promise<PlanResult>;
|
|
39
|
+
apply(params: ApplyParams, options?: CallOptions): Promise<ApplyResult>;
|
|
40
|
+
update(params: UpdateParams, options?: CallOptions): Promise<UpdateResult>;
|
|
41
|
+
stop(params: StopParams, options?: CallOptions): Promise<StopResult>;
|
|
42
|
+
retry(params: RetryParams, options?: CallOptions): Promise<RetryResult>;
|
|
43
|
+
resubmit(params: ResubmitParams, options?: CallOptions): Promise<ResubmitResult>;
|
|
44
|
+
delete(params: DeleteParams, options?: CallOptions): Promise<DeleteResult>;
|
|
45
|
+
get(params?: GetParams, options?: CallOptions): Promise<GetResult>;
|
|
46
|
+
watch(params?: WatchParams, options?: CallOptions): Promise<WatchSubscription>;
|
|
47
|
+
watchColdStart(params?: Omit<WatchParams, 'fromCursor'>, options?: CallOptions): Promise<CoherentWatchSubscription>;
|
|
48
|
+
logs(params?: LogsParams, options?: CallOptions): Promise<LogsSubscription>;
|
|
49
|
+
agentAttach(params: AgentAttachParams, options?: CallOptions): Promise<AgentAttachSubscription>;
|
|
50
|
+
}
|
|
51
|
+
export declare function connect(url: string, options?: ConnectOptions): Promise<Connection>;
|
|
52
|
+
export declare function connectInitialized(url: string, options?: ConnectOptions): Promise<ConnectInitializedResult>;
|
package/lib/cluster/client.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import type { AgentAttachParams, AgentAttachResult, ApplyParams, ApplyResult, DeleteParams, DeleteResult, GetParams, GetResult, InitializeParams, InitializeResult, LogsParams, LogsResult, PlanParams, PlanResult, ResubmitParams, ResubmitResult, RetryParams, RetryResult, StopParams, StopResult, UpdateParams, UpdateResult, WatchParams
|
|
1
|
+
import type { AgentAttachParams, AgentAttachResult, ApplyParams, ApplyResult, DeleteParams, DeleteResult, GetParams, GetResult, InitializeParams, InitializeResult, LogsParams, LogsResult, PlanParams, PlanResult, ResubmitParams, ResubmitResult, RetryParams, RetryResult, StopParams, StopResult, UpdateParams, UpdateResult, WatchParams } from './generated/protocol.js';
|
|
2
2
|
import { Connection } from './connection.js';
|
|
3
3
|
import type { CallOptions } from './connection.js';
|
|
4
4
|
import type { WebSocketLike } from './socket.js';
|
|
5
|
-
import { AgentAttachSubscriptionStream, LogsSubscriptionStream
|
|
5
|
+
import { AgentAttachSubscriptionStream, LogsSubscriptionStream } from './subscriptions.js';
|
|
6
|
+
import type { WatchSubscription } from './subscriptions.js';
|
|
7
|
+
export type { WatchSubscription } from './subscriptions.js';
|
|
6
8
|
export interface WebSocketFactoryOptions {
|
|
7
9
|
readonly headers?: Readonly<Record<string, string>>;
|
|
8
10
|
}
|
|
@@ -13,10 +15,6 @@ export interface ConnectOptions {
|
|
|
13
15
|
readonly initialize?: InitializeParams;
|
|
14
16
|
readonly headers?: Readonly<Record<string, string>>;
|
|
15
17
|
}
|
|
16
|
-
export interface WatchSubscription {
|
|
17
|
-
readonly result: WatchResult;
|
|
18
|
-
readonly stream: WatchSubscriptionStream;
|
|
19
|
-
}
|
|
20
18
|
export interface LogsSubscription {
|
|
21
19
|
readonly result: LogsResult;
|
|
22
20
|
readonly stream: LogsSubscriptionStream;
|
package/lib/cluster/client.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
/// <reference path="./ws.d.ts" />
|
|
1
2
|
import { PROTOCOL_VERSION } from './generated/protocol.mjs';
|
|
2
3
|
import { Connection } from './connection.mjs';
|
|
3
|
-
import { addSocketListener } from './socket.mjs';
|
|
4
|
-
import { ClusterConfigError, ClusterProtocolError, ClusterTransportError } from './errors.mjs';
|
|
4
|
+
import { addSocketEmitterListener, addSocketListener } from './socket.mjs';
|
|
5
|
+
import { ClusterConfigError, ClusterProtocolError, ClusterTransportError, ClusterUpgradeError } from './errors.mjs';
|
|
5
6
|
import { AgentAttachSubscriptionStream, LogsSubscriptionStream, WatchSubscriptionStream, } from './subscriptions.mjs';
|
|
6
7
|
export class ClusterClient {
|
|
7
8
|
connection;
|
|
@@ -76,10 +77,7 @@ export class ClusterClient {
|
|
|
76
77
|
}
|
|
77
78
|
async function defaultWebSocketFactory(url, protocols, options) {
|
|
78
79
|
const globalWebSocket = globalThis.WebSocket;
|
|
79
|
-
if (globalWebSocket) {
|
|
80
|
-
if (options?.headers && Object.keys(options.headers).length > 0) {
|
|
81
|
-
throw new ClusterConfigError('WebSocket upgrade headers require the ws library; the browser WebSocket API cannot carry request headers', 'HEADERS_UNSUPPORTED');
|
|
82
|
-
}
|
|
80
|
+
if (globalWebSocket && (!options?.headers || Object.keys(options.headers).length === 0)) {
|
|
83
81
|
return new globalWebSocket(url, protocols);
|
|
84
82
|
}
|
|
85
83
|
try {
|
|
@@ -108,6 +106,7 @@ async function waitForOpen(socket, signal) {
|
|
|
108
106
|
await new Promise((resolve, reject) => {
|
|
109
107
|
let settled = false;
|
|
110
108
|
const removers = [];
|
|
109
|
+
let upgradeFailure;
|
|
111
110
|
const settle = (fn) => {
|
|
112
111
|
if (settled)
|
|
113
112
|
return;
|
|
@@ -118,10 +117,34 @@ async function waitForOpen(socket, signal) {
|
|
|
118
117
|
fn();
|
|
119
118
|
};
|
|
120
119
|
const onAbort = () => settle(() => reject(new DOMException('connect aborted locally; the server may still have committed this request', 'AbortError')));
|
|
121
|
-
|
|
120
|
+
const onUnexpectedResponse = (...args) => {
|
|
121
|
+
const response = args.find((value) => value !== null && typeof value === 'object' && 'statusCode' in value);
|
|
122
|
+
const status = response?.statusCode;
|
|
123
|
+
upgradeFailure = typeof status === 'number'
|
|
124
|
+
? new ClusterUpgradeError(status)
|
|
125
|
+
: new ClusterTransportError('WebSocket upgrade rejected', 'UPGRADE_REJECTED');
|
|
126
|
+
response?.resume?.();
|
|
127
|
+
if (socket.terminate) {
|
|
128
|
+
socket.terminate();
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
settle(() => reject(upgradeFailure));
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
removers.push(addSocketListener(socket, 'open', () => settle(resolve)), addSocketListener(socket, 'error', (error) => settle(() => reject(upgradeFailure ??
|
|
135
|
+
new ClusterTransportError('WebSocket failed to open', 'OPEN_FAILED', { cause: error })))), addSocketListener(socket, 'close', () => settle(() => reject(upgradeFailure ??
|
|
136
|
+
new ClusterTransportError('WebSocket closed before opening', 'OPEN_FAILED')))), addSocketEmitterListener(socket, 'unexpected-response', onUnexpectedResponse));
|
|
122
137
|
signal?.addEventListener('abort', onAbort, { once: true });
|
|
123
138
|
});
|
|
124
139
|
}
|
|
140
|
+
async function disposeFailedSocket(socket) {
|
|
141
|
+
if (socket.readyState === 0 && socket.terminate) {
|
|
142
|
+
socket.terminate();
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
await socket.close();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
125
148
|
export async function connect(url, options = {}) {
|
|
126
149
|
const factory = options.webSocketFactory ?? defaultWebSocketFactory;
|
|
127
150
|
let socket;
|
|
@@ -135,7 +158,7 @@ export async function connect(url, options = {}) {
|
|
|
135
158
|
catch (error) {
|
|
136
159
|
if (socket) {
|
|
137
160
|
try {
|
|
138
|
-
await socket
|
|
161
|
+
await disposeFailedSocket(socket);
|
|
139
162
|
}
|
|
140
163
|
catch { /* preserve the construction error */ }
|
|
141
164
|
}
|
|
@@ -156,7 +179,7 @@ export async function connectInitialized(url, options = {}) {
|
|
|
156
179
|
catch (error) {
|
|
157
180
|
if (socket) {
|
|
158
181
|
try {
|
|
159
|
-
await socket
|
|
182
|
+
await disposeFailedSocket(socket);
|
|
160
183
|
}
|
|
161
184
|
catch { /* preserve the construction error */ }
|
|
162
185
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PROTOCOL_DIAGNOSTIC_CAPACITY = exports.CONNECTION_TRANSITIONS = void 0;
|
|
4
|
+
exports.deferred = deferred;
|
|
5
|
+
if (!Object.prototype.hasOwnProperty.call(Symbol, 'asyncDispose')) {
|
|
6
|
+
Object.defineProperty(Symbol, 'asyncDispose', {
|
|
7
|
+
configurable: false, enumerable: false,
|
|
8
|
+
value: Symbol.for('Symbol.asyncDispose'), writable: false,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
exports.CONNECTION_TRANSITIONS = Object.freeze({
|
|
12
|
+
OPEN: Object.freeze(['CLOSING']),
|
|
13
|
+
CLOSING: Object.freeze(['CLOSED']),
|
|
14
|
+
CLOSED: Object.freeze([]),
|
|
15
|
+
});
|
|
16
|
+
exports.PROTOCOL_DIAGNOSTIC_CAPACITY = 128;
|
|
17
|
+
function deferred() {
|
|
18
|
+
let resolve;
|
|
19
|
+
let reject;
|
|
20
|
+
const promise = new Promise((onResolve, onReject) => {
|
|
21
|
+
resolve = onResolve;
|
|
22
|
+
reject = onReject;
|
|
23
|
+
});
|
|
24
|
+
return { promise, resolve, reject };
|
|
25
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type ConnectionState = 'OPEN' | 'CLOSING' | 'CLOSED';
|
|
2
|
+
export declare const CONNECTION_TRANSITIONS: Readonly<Record<ConnectionState, readonly ConnectionState[]>>;
|
|
3
|
+
export declare const PROTOCOL_DIAGNOSTIC_CAPACITY = 128;
|
|
4
|
+
export interface ConnectionCloseSnapshot {
|
|
5
|
+
readonly code: number | null;
|
|
6
|
+
readonly reason: null;
|
|
7
|
+
}
|
|
8
|
+
export type Deferred<T> = {
|
|
9
|
+
readonly promise: Promise<T>;
|
|
10
|
+
readonly resolve: (value: T) => void;
|
|
11
|
+
readonly reject: (reason: unknown) => void;
|
|
12
|
+
};
|
|
13
|
+
export declare function deferred<T>(): Deferred<T>;
|