@phnx-labs/agents-cli 1.22.103 → 1.22.105
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/CHANGELOG.md +39 -0
- package/README.md +1 -1
- package/dist/commands/accounts.js +2 -2
- package/dist/commands/computer.d.ts +100 -79
- package/dist/commands/computer.js +290 -830
- package/dist/commands/run-device-picker.d.ts +58 -0
- package/dist/commands/run-device-picker.js +222 -0
- package/dist/commands/setup-computer.js +20 -1
- package/dist/commands/setup-secrets.d.ts +2 -2
- package/dist/commands/setup-secrets.js +1 -1
- package/dist/commands/view.js +4 -6
- package/dist/lib/account-catalog.d.ts +22 -1
- package/dist/lib/account-catalog.js +72 -38
- package/dist/lib/accounting/usage.js +18 -14
- package/dist/lib/agent-spec/agents.d.ts +1 -0
- package/dist/lib/agent-spec/agents.js +1 -1
- package/dist/lib/browser/drivers/ssh.js +1 -1
- package/dist/lib/computer/context.d.ts +83 -0
- package/dist/lib/computer/context.js +91 -0
- package/dist/lib/computer/policy.d.ts +46 -0
- package/dist/lib/computer/policy.js +160 -0
- package/dist/lib/computer/record.d.ts +38 -0
- package/dist/lib/computer/record.js +86 -0
- package/dist/lib/computer/sessions-list.js +6 -6
- package/dist/lib/computer-client.d.ts +150 -0
- package/dist/lib/computer-client.js +222 -0
- package/dist/lib/exec.js +35 -1
- package/dist/lib/harness/adapters/claude.d.ts +37 -0
- package/dist/lib/harness/adapters/claude.js +69 -0
- package/dist/lib/helper-download.d.ts +1 -1
- package/dist/lib/helper-download.js +1 -1
- package/dist/lib/helper-versions.d.ts +9 -4
- package/dist/lib/helper-versions.js +8 -8
- package/dist/lib/installations/shims.js +8 -4
- package/dist/lib/menubar/download-menubar.d.ts +2 -1
- package/dist/lib/menubar/download-menubar.js +2 -1
- package/dist/lib/secrets-client.d.ts +3 -3
- package/dist/lib/secrets-client.js +15 -38
- package/dist/lib/session/db.js +1 -1
- package/dist/lib/sha256-asset.d.ts +2 -1
- package/dist/lib/sha256-asset.js +2 -1
- package/dist/lib/ssh-tunnel.d.ts +61 -0
- package/dist/lib/ssh-tunnel.js +105 -0
- package/dist/lib/summarizer/summarize.d.ts +2 -2
- package/dist/lib/summarizer/summarize.js +10 -3
- package/package.json +2 -3
- package/dist/commands/computer-actions.d.ts +0 -55
- package/dist/commands/computer-actions.js +0 -594
- package/dist/computer.d.ts +0 -2
- package/dist/computer.js +0 -7
- package/dist/lib/computer/actions.d.ts +0 -36
- package/dist/lib/computer/actions.js +0 -162
- package/dist/lib/computer/computer-rpc.d.ts +0 -39
- package/dist/lib/computer/computer-rpc.js +0 -447
- package/dist/lib/computer/des.d.ts +0 -1
- package/dist/lib/computer/des.js +0 -114
- package/dist/lib/computer/dispatch.d.ts +0 -10
- package/dist/lib/computer/dispatch.js +0 -133
- package/dist/lib/computer/download.d.ts +0 -54
- package/dist/lib/computer/download.js +0 -83
- package/dist/lib/computer/loop.d.ts +0 -62
- package/dist/lib/computer/loop.js +0 -98
- package/dist/lib/computer/model.d.ts +0 -44
- package/dist/lib/computer/model.js +0 -157
- package/dist/lib/computer/rfb-client.d.ts +0 -53
- package/dist/lib/computer/rfb-client.js +0 -562
- package/dist/lib/computer/ssh-tunnel.d.ts +0 -189
- package/dist/lib/computer/ssh-tunnel.js +0 -584
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* On-demand download + verification of the macOS menu-bar helper
|
|
3
3
|
* ("MenubarHelper.app").
|
|
4
4
|
*
|
|
5
|
-
* Mirrors the ComputerHelper download model
|
|
5
|
+
* Mirrors the ComputerHelper download model the computer subsystem used before
|
|
6
|
+
* it was extracted (PHNX-4075): the
|
|
6
7
|
* helper ships as a signed + notarized `.app` zipped as a GitHub release asset
|
|
7
8
|
* on the helper's own `menubar/v<x.y.z>` tag, NOT the CLI's tag (see
|
|
8
9
|
* `helper-versions.ts`). A fresh `npm i -g` machine whose tarball lacks a
|
|
@@ -116,8 +116,8 @@ export declare function invocation(bin: string): {
|
|
|
116
116
|
export declare function buildServeEnv(base?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
117
117
|
/**
|
|
118
118
|
* Send one operation to the standalone secrets CLI and await its typed result.
|
|
119
|
-
*
|
|
120
|
-
*
|
|
119
|
+
* Spawns `secrets __serve` once for the operation; `parseResponse` checks the
|
|
120
|
+
* protocol on the reply it already carries. Throws a {@link SecretsClientError}
|
|
121
121
|
* carrying the server's `{code, message}` on failure.
|
|
122
122
|
*/
|
|
123
123
|
export declare function secretsRequest<T = unknown>(op: string, args?: unknown[], context?: SecretsContext): Promise<T>;
|
|
@@ -127,7 +127,7 @@ export declare function secretsRequest<T = unknown>(op: string, args?: unknown[]
|
|
|
127
127
|
* Bounded by a spawn timeout. POSIX only.
|
|
128
128
|
*/
|
|
129
129
|
export declare function secretsRequestSync<T = unknown>(op: string, args?: unknown[], context?: SecretsContext): T;
|
|
130
|
-
/** Test hook: forget the cached binary
|
|
130
|
+
/** Test hook: forget the cached binary so a new env is re-resolved. */
|
|
131
131
|
export declare function _resetSecretsClientForTest(): void;
|
|
132
132
|
/** Shorten the sync bound for a test that plants a hanging standalone; reset restores it. */
|
|
133
133
|
export declare function _setSyncServeTimeoutForTest(ms: number): void;
|
|
@@ -297,7 +297,18 @@ function parseResponse(raw) {
|
|
|
297
297
|
catch {
|
|
298
298
|
throw new SecretsClientError('INVALID_RESPONSE', `secrets returned a non-JSON response${describeNonJson(text)}`);
|
|
299
299
|
}
|
|
300
|
-
if (!parsed ||
|
|
300
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
301
|
+
throw new SecretsClientError('INVALID_RESPONSE', 'secrets returned a malformed response envelope');
|
|
302
|
+
}
|
|
303
|
+
// Every reply carries the protocol it was written against, so version
|
|
304
|
+
// negotiation rides the answer itself — there is no separate handshake spawn
|
|
305
|
+
// to pay a cold Node boot for (PHNX-4082). A mismatch is the standalone being
|
|
306
|
+
// too old or too new, which is actionable; anything else is a broken envelope.
|
|
307
|
+
if (typeof parsed.v === 'number' && parsed.v !== PROTOCOL_VERSION) {
|
|
308
|
+
throw new SecretsClientError('PROTOCOL_UNSUPPORTED', `secrets speaks protocol ${String(parsed.v)}; this agents-cli needs ${PROTOCOL_VERSION}. ` +
|
|
309
|
+
'Update the standalone CLI (npm i -g @phnx-labs/secrets-cli).');
|
|
310
|
+
}
|
|
311
|
+
if (parsed.v !== PROTOCOL_VERSION || typeof parsed.id !== 'string') {
|
|
301
312
|
throw new SecretsClientError('INVALID_RESPONSE', 'secrets returned a malformed response envelope');
|
|
302
313
|
}
|
|
303
314
|
if (parsed.ok)
|
|
@@ -445,45 +456,14 @@ function serveOnceSync(op, args, context) {
|
|
|
445
456
|
}
|
|
446
457
|
return parseResponse(raw);
|
|
447
458
|
}
|
|
448
|
-
// --- handshake (once per process) ------------------------------------------
|
|
449
|
-
let handshakeReady = false;
|
|
450
|
-
let handshakePromise = null;
|
|
451
|
-
function checkHandshake(result) {
|
|
452
|
-
const protocol = result?.protocol;
|
|
453
|
-
if (protocol !== PROTOCOL_VERSION) {
|
|
454
|
-
throw new SecretsClientError('PROTOCOL_UNSUPPORTED', `secrets speaks protocol ${String(protocol)}; this agents-cli needs ${PROTOCOL_VERSION}. ` +
|
|
455
|
-
'Update the standalone CLI (npm i -g @phnx-labs/secrets-cli).');
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
async function ensureHandshake() {
|
|
459
|
-
if (handshakeReady)
|
|
460
|
-
return;
|
|
461
|
-
if (!handshakePromise) {
|
|
462
|
-
handshakePromise = (async () => {
|
|
463
|
-
checkHandshake(await serveOnce('handshake', []));
|
|
464
|
-
handshakeReady = true;
|
|
465
|
-
})().catch((error) => {
|
|
466
|
-
handshakePromise = null;
|
|
467
|
-
throw error;
|
|
468
|
-
});
|
|
469
|
-
}
|
|
470
|
-
await handshakePromise;
|
|
471
|
-
}
|
|
472
|
-
function ensureHandshakeSync() {
|
|
473
|
-
if (handshakeReady)
|
|
474
|
-
return;
|
|
475
|
-
checkHandshake(serveOnceSync('handshake', []));
|
|
476
|
-
handshakeReady = true;
|
|
477
|
-
}
|
|
478
459
|
// --- primitives ------------------------------------------------------------
|
|
479
460
|
/**
|
|
480
461
|
* Send one operation to the standalone secrets CLI and await its typed result.
|
|
481
|
-
*
|
|
482
|
-
*
|
|
462
|
+
* Spawns `secrets __serve` once for the operation; `parseResponse` checks the
|
|
463
|
+
* protocol on the reply it already carries. Throws a {@link SecretsClientError}
|
|
483
464
|
* carrying the server's `{code, message}` on failure.
|
|
484
465
|
*/
|
|
485
466
|
export async function secretsRequest(op, args = [], context) {
|
|
486
|
-
await ensureHandshake();
|
|
487
467
|
return (await serveOnce(op, args, context));
|
|
488
468
|
}
|
|
489
469
|
/**
|
|
@@ -492,14 +472,11 @@ export async function secretsRequest(op, args = [], context) {
|
|
|
492
472
|
* Bounded by a spawn timeout. POSIX only.
|
|
493
473
|
*/
|
|
494
474
|
export function secretsRequestSync(op, args = [], context) {
|
|
495
|
-
ensureHandshakeSync();
|
|
496
475
|
return serveOnceSync(op, args, context);
|
|
497
476
|
}
|
|
498
|
-
/** Test hook: forget the cached binary
|
|
477
|
+
/** Test hook: forget the cached binary so a new env is re-resolved. */
|
|
499
478
|
export function _resetSecretsClientForTest() {
|
|
500
479
|
cachedBin = undefined;
|
|
501
|
-
handshakeReady = false;
|
|
502
|
-
handshakePromise = null;
|
|
503
480
|
requestCounter = 0;
|
|
504
481
|
syncServeTimeoutMs = SYNC_SERVE_TIMEOUT_MS;
|
|
505
482
|
}
|
package/dist/lib/session/db.js
CHANGED
|
@@ -488,7 +488,7 @@ CREATE INDEX IF NOT EXISTS idx_browser_sessions_started ON browser_sessions(star
|
|
|
488
488
|
-- silently vanished on day 8. This row carries the same identity into the durable
|
|
489
489
|
-- store; the ledger is untouched and remains the audit log, with no second pruner.
|
|
490
490
|
--
|
|
491
|
-
-- Keyed on invocation_id, the id
|
|
491
|
+
-- Keyed on invocation_id, the id recordComputerAction stamps once per emitting CLI
|
|
492
492
|
-- process: one explicit verb is one row, and a whole "computer run" observe/act
|
|
493
493
|
-- loop is also one row. task_preview is already bounded by events.ts truncate()
|
|
494
494
|
-- before it is ever written, and typed-text content is never captured at all.
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* sha256 helpers for verifying downloaded release assets.
|
|
3
3
|
*
|
|
4
4
|
* These live in their own LEAF module — importing only `node:crypto` and
|
|
5
|
-
* `node:fs` — on purpose. They used to sit in
|
|
5
|
+
* `node:fs` — on purpose. They used to sit in the computer subsystem's ssh-tunnel
|
|
6
|
+
* module (since extracted, PHNX-4075), whose
|
|
6
7
|
* own import graph reached `browser/drivers/ssh.ts` -> `browser/chrome.ts` ->
|
|
7
8
|
* the in-repo secrets engine's own keychain-helper downloader, which imported
|
|
8
9
|
* back into `helper-download.ts` while it was still evaluating — before
|
package/dist/lib/sha256-asset.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* sha256 helpers for verifying downloaded release assets.
|
|
3
3
|
*
|
|
4
4
|
* These live in their own LEAF module — importing only `node:crypto` and
|
|
5
|
-
* `node:fs` — on purpose. They used to sit in
|
|
5
|
+
* `node:fs` — on purpose. They used to sit in the computer subsystem's ssh-tunnel
|
|
6
|
+
* module (since extracted, PHNX-4075), whose
|
|
6
7
|
* own import graph reached `browser/drivers/ssh.ts` -> `browser/chrome.ts` ->
|
|
7
8
|
* the in-repo secrets engine's own keychain-helper downloader, which imported
|
|
8
9
|
* back into `helper-download.ts` while it was still evaluating — before
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ssh-tunnel.ts — the generic `ssh -L localPort:127.0.0.1:remotePort -N`
|
|
3
|
+
* port-forward, plus the fleet-device resolution that names its far end.
|
|
4
|
+
*
|
|
5
|
+
* WHY IT LIVES HERE. These primitives used to sit in `lib/computer/ssh-tunnel.ts`
|
|
6
|
+
* alongside the Windows computer-helper provisioning, because `agents computer
|
|
7
|
+
* --device` was their second caller after the browser CDP driver. The computer
|
|
8
|
+
* engine has since moved to the standalone `computer` CLI (PHNX-4075), so a
|
|
9
|
+
* generic tunnel parked in a deleted subsystem's directory would have gone with
|
|
10
|
+
* it and taken `agents browser`'s remote path down. It is fleet plumbing — the
|
|
11
|
+
* devices registry, the hardened ssh baseline, a local loopback port — and
|
|
12
|
+
* belongs in the fleet layer, not under a feature.
|
|
13
|
+
*
|
|
14
|
+
* Its callers are thin: `browser/drivers/ssh.ts` holds a tunnel for one CDP
|
|
15
|
+
* session, and `lib/computer/context.ts` uses `resolveRemoteDevice` alone —
|
|
16
|
+
* `agents computer --device` resolves the fleet name here and forwards the
|
|
17
|
+
* answer to the standalone engine, which opens and owns its own tunnel (it
|
|
18
|
+
* holds the helper token that tunnel's transport needs).
|
|
19
|
+
*/
|
|
20
|
+
import { type ChildProcess } from 'child_process';
|
|
21
|
+
import { type DeviceProfile } from './devices/registry.js';
|
|
22
|
+
export interface StartTunnelOptions {
|
|
23
|
+
extraSshArgs?: string[];
|
|
24
|
+
}
|
|
25
|
+
/** Build the ssh argv (after the `ssh` program name) for an `-L` tunnel. Pure.
|
|
26
|
+
*
|
|
27
|
+
* Composes the shared hardened baseline (`SSH_OPTS`) rather than re-listing it,
|
|
28
|
+
* so the tunnel inherits the same options — crucially the keepalive, which lets
|
|
29
|
+
* a dropped `-N` tunnel exit instead of lingering as a zombie on the laptop. */
|
|
30
|
+
export declare function buildTunnelArgs(user: string, host: string, localPort: number, remotePort: number, extraSshArgs?: string[]): string[];
|
|
31
|
+
/**
|
|
32
|
+
* Spawn `ssh -L localPort:127.0.0.1:remotePort -N user@host`.
|
|
33
|
+
*
|
|
34
|
+
* stderr is captured so a tunnel that dies inside 500ms rejects with the ssh
|
|
35
|
+
* error — the browser driver's original contract. The tunnel is held by this
|
|
36
|
+
* process for the lifetime of the session that opened it.
|
|
37
|
+
*/
|
|
38
|
+
export declare function startSSHTunnel(user: string, host: string, localPort: number, remotePort: number, opts?: StartTunnelOptions): Promise<ChildProcess>;
|
|
39
|
+
/** One registered device, resolved to everything an ssh invocation needs. */
|
|
40
|
+
export interface ResolvedRemoteDevice {
|
|
41
|
+
device: DeviceProfile;
|
|
42
|
+
target: string;
|
|
43
|
+
user: string;
|
|
44
|
+
host: string;
|
|
45
|
+
/** Per-device identity flags (`-i <key> -o IdentitiesOnly=yes`), possibly empty. */
|
|
46
|
+
identityArgs: string[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolve a registered device to its ssh pieces, or throw a clear error.
|
|
50
|
+
*
|
|
51
|
+
* `expectPlatform` is how a caller keeps a platform requirement it used to
|
|
52
|
+
* hard-code: `agents computer --device` drives the Windows helper daemon, so it
|
|
53
|
+
* passes `'windows'` and gets the same refusal as before. Callers with no
|
|
54
|
+
* platform requirement (the browser driver) omit it. The gate is a parameter
|
|
55
|
+
* rather than a baked-in check so this module stays fleet-generic — a
|
|
56
|
+
* hard-coded `windows` here would be a feature rule in shared plumbing.
|
|
57
|
+
*/
|
|
58
|
+
export declare function resolveRemoteDevice(name: string, opts?: {
|
|
59
|
+
expectPlatform?: DeviceProfile['platform'];
|
|
60
|
+
forWhat?: string;
|
|
61
|
+
}): Promise<ResolvedRemoteDevice>;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ssh-tunnel.ts — the generic `ssh -L localPort:127.0.0.1:remotePort -N`
|
|
3
|
+
* port-forward, plus the fleet-device resolution that names its far end.
|
|
4
|
+
*
|
|
5
|
+
* WHY IT LIVES HERE. These primitives used to sit in `lib/computer/ssh-tunnel.ts`
|
|
6
|
+
* alongside the Windows computer-helper provisioning, because `agents computer
|
|
7
|
+
* --device` was their second caller after the browser CDP driver. The computer
|
|
8
|
+
* engine has since moved to the standalone `computer` CLI (PHNX-4075), so a
|
|
9
|
+
* generic tunnel parked in a deleted subsystem's directory would have gone with
|
|
10
|
+
* it and taken `agents browser`'s remote path down. It is fleet plumbing — the
|
|
11
|
+
* devices registry, the hardened ssh baseline, a local loopback port — and
|
|
12
|
+
* belongs in the fleet layer, not under a feature.
|
|
13
|
+
*
|
|
14
|
+
* Its callers are thin: `browser/drivers/ssh.ts` holds a tunnel for one CDP
|
|
15
|
+
* session, and `lib/computer/context.ts` uses `resolveRemoteDevice` alone —
|
|
16
|
+
* `agents computer --device` resolves the fleet name here and forwards the
|
|
17
|
+
* answer to the standalone engine, which opens and owns its own tunnel (it
|
|
18
|
+
* holds the helper token that tunnel's transport needs).
|
|
19
|
+
*/
|
|
20
|
+
import { spawn } from 'child_process';
|
|
21
|
+
import { SSH_OPTS, assertValidSshTarget } from './ssh-exec.js';
|
|
22
|
+
import { getDevice } from './devices/registry.js';
|
|
23
|
+
import { deviceIdentityArgs, sshTargetFor } from './devices/connect.js';
|
|
24
|
+
import { hostNameFor } from './devices/ssh-config.js';
|
|
25
|
+
/** Build the ssh argv (after the `ssh` program name) for an `-L` tunnel. Pure.
|
|
26
|
+
*
|
|
27
|
+
* Composes the shared hardened baseline (`SSH_OPTS`) rather than re-listing it,
|
|
28
|
+
* so the tunnel inherits the same options — crucially the keepalive, which lets
|
|
29
|
+
* a dropped `-N` tunnel exit instead of lingering as a zombie on the laptop. */
|
|
30
|
+
export function buildTunnelArgs(user, host, localPort, remotePort, extraSshArgs = []) {
|
|
31
|
+
return [
|
|
32
|
+
'-L',
|
|
33
|
+
`${localPort}:127.0.0.1:${remotePort}`,
|
|
34
|
+
`${user}@${host}`,
|
|
35
|
+
'-N',
|
|
36
|
+
...extraSshArgs,
|
|
37
|
+
...SSH_OPTS,
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Spawn `ssh -L localPort:127.0.0.1:remotePort -N user@host`.
|
|
42
|
+
*
|
|
43
|
+
* stderr is captured so a tunnel that dies inside 500ms rejects with the ssh
|
|
44
|
+
* error — the browser driver's original contract. The tunnel is held by this
|
|
45
|
+
* process for the lifetime of the session that opened it.
|
|
46
|
+
*/
|
|
47
|
+
export function startSSHTunnel(user, host, localPort, remotePort, opts = {}) {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
// `user`/`host` can originate from a browser ssh:// profile or a device
|
|
50
|
+
// record. buildTunnelArgs places `${user}@${host}` before `-N`/SSH_OPTS, so
|
|
51
|
+
// a `-`-leading user would be parsed as an ssh option flag (option
|
|
52
|
+
// injection). Validate at the spawn sink so every caller is covered; reject
|
|
53
|
+
// (rather than throw synchronously) to keep the Promise contract.
|
|
54
|
+
try {
|
|
55
|
+
assertValidSshTarget(`${user}@${host}`);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
reject(err);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const args = buildTunnelArgs(user, host, localPort, remotePort, opts.extraSshArgs);
|
|
62
|
+
const tunnel = spawn('ssh', args, {
|
|
63
|
+
stdio: ['ignore', 'ignore', 'pipe'],
|
|
64
|
+
detached: false,
|
|
65
|
+
windowsHide: true,
|
|
66
|
+
});
|
|
67
|
+
let stderr = '';
|
|
68
|
+
tunnel.stderr?.on('data', (data) => {
|
|
69
|
+
stderr += data.toString();
|
|
70
|
+
});
|
|
71
|
+
tunnel.on('error', (err) => {
|
|
72
|
+
reject(new Error(`SSH tunnel failed: ${err.message}`));
|
|
73
|
+
});
|
|
74
|
+
setTimeout(() => {
|
|
75
|
+
if (tunnel.killed)
|
|
76
|
+
reject(new Error(`SSH tunnel died: ${stderr}`));
|
|
77
|
+
else
|
|
78
|
+
resolve(tunnel);
|
|
79
|
+
}, 500);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Resolve a registered device to its ssh pieces, or throw a clear error.
|
|
84
|
+
*
|
|
85
|
+
* `expectPlatform` is how a caller keeps a platform requirement it used to
|
|
86
|
+
* hard-code: `agents computer --device` drives the Windows helper daemon, so it
|
|
87
|
+
* passes `'windows'` and gets the same refusal as before. Callers with no
|
|
88
|
+
* platform requirement (the browser driver) omit it. The gate is a parameter
|
|
89
|
+
* rather than a baked-in check so this module stays fleet-generic — a
|
|
90
|
+
* hard-coded `windows` here would be a feature rule in shared plumbing.
|
|
91
|
+
*/
|
|
92
|
+
export async function resolveRemoteDevice(name, opts = {}) {
|
|
93
|
+
const device = await getDevice(name);
|
|
94
|
+
if (!device) {
|
|
95
|
+
throw new Error(`Unknown device '${name}'. Register it with \`agents devices add\` / \`agents devices sync\`, then retry.`);
|
|
96
|
+
}
|
|
97
|
+
if (opts.expectPlatform && device.platform !== opts.expectPlatform) {
|
|
98
|
+
const what = opts.forWhat ?? `this command`;
|
|
99
|
+
throw new Error(`Device '${name}' is ${device.platform}, not ${opts.expectPlatform}. ${what} needs a ${opts.expectPlatform} device.`);
|
|
100
|
+
}
|
|
101
|
+
const target = sshTargetFor(device); // validates address + injection guard
|
|
102
|
+
const host = hostNameFor(device); // sshTargetFor already threw if absent
|
|
103
|
+
const user = device.user || process.env.USER || 'Administrator';
|
|
104
|
+
return { device, target, user, host, identityArgs: deviceIdentityArgs(device) };
|
|
105
|
+
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* A pure boundary: given the session's first user turn (the goal source) and its
|
|
5
5
|
* live progress (todos / plan / phase off the state engine), it asks a local
|
|
6
|
-
* Anthropic-wire endpoint (Ollama / vLLM / LiteLLM
|
|
7
|
-
*
|
|
6
|
+
* Anthropic-wire endpoint (Ollama / vLLM / LiteLLM) for a strict JSON
|
|
7
|
+
* `{goal, checkpoints, checklist}`
|
|
8
8
|
* and validates the shape. On ANY failure — network, non-2xx, non-JSON, wrong
|
|
9
9
|
* shape — it returns `undefined`, and the caller records `summaryState: 'skipped'`.
|
|
10
10
|
*
|
|
@@ -3,15 +3,22 @@
|
|
|
3
3
|
*
|
|
4
4
|
* A pure boundary: given the session's first user turn (the goal source) and its
|
|
5
5
|
* live progress (todos / plan / phase off the state engine), it asks a local
|
|
6
|
-
* Anthropic-wire endpoint (Ollama / vLLM / LiteLLM
|
|
7
|
-
*
|
|
6
|
+
* Anthropic-wire endpoint (Ollama / vLLM / LiteLLM) for a strict JSON
|
|
7
|
+
* `{goal, checkpoints, checklist}`
|
|
8
8
|
* and validates the shape. On ANY failure — network, non-2xx, non-JSON, wrong
|
|
9
9
|
* shape — it returns `undefined`, and the caller records `summaryState: 'skipped'`.
|
|
10
10
|
*
|
|
11
11
|
* NEVER called on the request path: only the background SessionSummarizerService
|
|
12
12
|
* invokes it, debounced and reader-gated.
|
|
13
13
|
*/
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The `anthropic-version` header this request sends. Declared here because this
|
|
16
|
+
* is now its only caller: it used to be imported from the computer subsystem's
|
|
17
|
+
* model client, which left with the standalone `computer` engine (PHNX-4075).
|
|
18
|
+
* A shared constants module for one string used in one request would be more
|
|
19
|
+
* indirection than the string.
|
|
20
|
+
*/
|
|
21
|
+
const ANTHROPIC_VERSION = '2023-06-01';
|
|
15
22
|
const SYSTEM_PROMPT = [
|
|
16
23
|
'You summarize a coding-agent session for an operator dashboard.',
|
|
17
24
|
'Reply with ONLY a single JSON object, no prose and no code fences, of exactly this shape:',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phnx-labs/agents-cli",
|
|
3
|
-
"version": "1.22.
|
|
3
|
+
"version": "1.22.105",
|
|
4
4
|
"description": "One CLI for all your AI coding agents - versions, config, cloud dispatch, sessions, and teams (now with first-class Grok Build CLI support)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -17,8 +17,7 @@
|
|
|
17
17
|
"bin": {
|
|
18
18
|
"agents": "dist/index.js",
|
|
19
19
|
"ag": "dist/index.js",
|
|
20
|
-
"browser": "dist/browser.js"
|
|
21
|
-
"computer": "dist/computer.js"
|
|
20
|
+
"browser": "dist/browser.js"
|
|
22
21
|
},
|
|
23
22
|
"files": [
|
|
24
23
|
"dist/**/*.js",
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { type ComputerClient, type RPCResponse } from '../lib/computer/computer-rpc.js';
|
|
3
|
-
export { emitComputerAction, pickTarget, resolveTargetPidDecision, type AppInfo } from '../lib/computer/actions.js';
|
|
4
|
-
export declare function parseXY(s: string, flag: string): {
|
|
5
|
-
x: number;
|
|
6
|
-
y: number;
|
|
7
|
-
};
|
|
8
|
-
export declare function buildElementOrCoords(opts: {
|
|
9
|
-
id?: string;
|
|
10
|
-
x?: number;
|
|
11
|
-
y?: number;
|
|
12
|
-
}): {
|
|
13
|
-
ok: true;
|
|
14
|
-
params: Record<string, unknown>;
|
|
15
|
-
} | {
|
|
16
|
-
ok: false;
|
|
17
|
-
error: string;
|
|
18
|
-
};
|
|
19
|
-
export declare function buildRaiseParams(opts: {
|
|
20
|
-
windowId?: number;
|
|
21
|
-
title?: string;
|
|
22
|
-
}): Record<string, unknown>;
|
|
23
|
-
export declare const CHAR_DELAY_MIN_MS = 1;
|
|
24
|
-
export declare const CHAR_DELAY_MAX_MS = 250;
|
|
25
|
-
export declare function clampCharDelay(ms: number | undefined): number | undefined;
|
|
26
|
-
export declare function buildWaitParams(opts: {
|
|
27
|
-
duration?: number;
|
|
28
|
-
id?: string;
|
|
29
|
-
until?: string;
|
|
30
|
-
role?: string;
|
|
31
|
-
label?: string;
|
|
32
|
-
identifier?: string;
|
|
33
|
-
timeout?: number;
|
|
34
|
-
}): {
|
|
35
|
-
ok: true;
|
|
36
|
-
params: Record<string, unknown>;
|
|
37
|
-
} | {
|
|
38
|
-
ok: false;
|
|
39
|
-
error: string;
|
|
40
|
-
};
|
|
41
|
-
export declare function withClient<T>(fn: (client: ComputerClient) => Promise<T>): Promise<T>;
|
|
42
|
-
export declare function unwrap(r: RPCResponse): Record<string, unknown>;
|
|
43
|
-
export declare function focusStealNotes(opts: {
|
|
44
|
-
id?: string;
|
|
45
|
-
x?: number;
|
|
46
|
-
y?: number;
|
|
47
|
-
raise?: boolean;
|
|
48
|
-
}): string[];
|
|
49
|
-
export declare function shouldRaise(opts: {
|
|
50
|
-
id?: string;
|
|
51
|
-
raise?: boolean;
|
|
52
|
-
}): boolean;
|
|
53
|
-
export declare function appPathIsElectron(appPath: string | null, exists?: (p: string) => boolean): boolean;
|
|
54
|
-
export declare function electronWebviewTip(appLabel: string): string;
|
|
55
|
-
export declare function registerActionCommands(program: Command): void;
|