@phnx-labs/agents-cli 1.22.52 → 1.22.54
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 +336 -0
- package/README.md +42 -9
- package/dist/bootstrap.js +55 -154
- package/dist/cli/command-registry.d.ts +5 -0
- package/dist/cli/command-registry.js +8 -1
- package/dist/commands/accounts.js +220 -174
- package/dist/commands/apply.js +6 -3
- package/dist/commands/auth-mint.d.ts +8 -0
- package/dist/commands/auth-mint.js +96 -0
- package/dist/commands/auth.js +5 -1
- package/dist/commands/browser.js +1 -1
- package/dist/commands/cost.js +8 -2
- package/dist/commands/daemon.js +2 -2
- package/dist/commands/doctor.js +6 -1
- package/dist/commands/exec.js +26 -17
- package/dist/commands/fleet-capture.js +7 -0
- package/dist/commands/focus.d.ts +1 -0
- package/dist/commands/focus.js +4 -2
- package/dist/commands/go.d.ts +5 -4
- package/dist/commands/go.js +8 -7
- package/dist/commands/insights.js +9 -0
- package/dist/commands/monitors.js +85 -30
- package/dist/commands/output.js +8 -2
- package/dist/commands/repo.js +18 -0
- package/dist/commands/secrets.js +33 -14
- package/dist/commands/sessions-inject.js +8 -3
- package/dist/commands/sessions-picker.js +2 -1
- package/dist/commands/sessions.d.ts +20 -12
- package/dist/commands/sessions.js +94 -40
- package/dist/commands/setup-accounts.d.ts +8 -0
- package/dist/commands/setup-accounts.js +47 -0
- package/dist/commands/setup.d.ts +1 -1
- package/dist/commands/setup.js +11 -2
- package/dist/commands/share.d.ts +52 -3
- package/dist/commands/share.js +262 -18
- package/dist/commands/ssh.d.ts +7 -0
- package/dist/commands/ssh.js +53 -14
- package/dist/commands/status.js +14 -0
- package/dist/commands/sync.js +44 -0
- package/dist/commands/view.d.ts +3 -1
- package/dist/commands/view.js +5 -4
- package/dist/lib/account-registry.d.ts +15 -5
- package/dist/lib/account-registry.js +165 -53
- package/dist/lib/accounting/rotate.d.ts +20 -6
- package/dist/lib/accounting/rotate.js +38 -7
- package/dist/lib/accounting/usage.d.ts +37 -1
- package/dist/lib/accounting/usage.js +71 -6
- package/dist/lib/agent-spec/agents.d.ts +5 -2
- package/dist/lib/agent-spec/agents.js +25 -7
- package/dist/lib/analytics/mix-commands.js +12 -6
- package/dist/lib/answer-router.js +2 -1
- package/dist/lib/auth-mint.d.ts +150 -0
- package/dist/lib/auth-mint.js +434 -0
- package/dist/lib/browser/profiles.d.ts +18 -0
- package/dist/lib/browser/profiles.js +26 -1
- package/dist/lib/browser/registry.d.ts +44 -14
- package/dist/lib/browser/registry.js +141 -45
- package/dist/lib/browser/remote-control.d.ts +9 -7
- package/dist/lib/browser/remote-control.js +9 -7
- package/dist/lib/claude-account-token.d.ts +10 -0
- package/dist/lib/claude-account-token.js +14 -4
- package/dist/lib/config-drift.d.ts +37 -0
- package/dist/lib/config-drift.js +72 -0
- package/dist/lib/daemon/auth-sync-service.d.ts +19 -0
- package/dist/lib/daemon/auth-sync-service.js +34 -0
- package/dist/lib/daemon/daemon.js +30 -4
- package/dist/lib/daemon/runner.js +10 -2
- package/dist/lib/daemon-services.d.ts +1 -1
- package/dist/lib/daemon-services.js +5 -0
- package/dist/lib/device-config.d.ts +3 -3
- package/dist/lib/device-config.js +8 -7
- package/dist/lib/devices/config-migration.js +147 -1
- package/dist/lib/devices/connect.d.ts +26 -0
- package/dist/lib/devices/connect.js +48 -1
- package/dist/lib/devices/device-docs.d.ts +35 -0
- package/dist/lib/devices/device-docs.js +163 -0
- package/dist/lib/devices/discovery-policy.d.ts +14 -2
- package/dist/lib/devices/discovery-policy.js +31 -21
- package/dist/lib/devices/doctor-findings.d.ts +5 -1
- package/dist/lib/devices/doctor-findings.js +19 -1
- package/dist/lib/devices/registry.d.ts +11 -5
- package/dist/lib/devices/registry.js +46 -18
- package/dist/lib/exec.d.ts +88 -30
- package/dist/lib/exec.js +138 -34
- package/dist/lib/feed/feed.d.ts +10 -2
- package/dist/lib/feed/feed.js +35 -2
- package/dist/lib/feed-broadcast.js +1 -1
- package/dist/lib/fleet/apply.d.ts +11 -0
- package/dist/lib/fleet/apply.js +23 -3
- package/dist/lib/fleet/auth-sync.js +5 -3
- package/dist/lib/help.d.ts +9 -0
- package/dist/lib/help.js +29 -1
- package/dist/lib/hosts/dispatch.d.ts +4 -3
- package/dist/lib/hosts/dispatch.js +12 -8
- package/dist/lib/hosts/passthrough.d.ts +1 -10
- package/dist/lib/hosts/passthrough.js +1 -13
- package/dist/lib/hosts/providers/local.d.ts +9 -3
- package/dist/lib/hosts/providers/local.js +23 -12
- package/dist/lib/hosts/reconnect.d.ts +7 -4
- package/dist/lib/hosts/reconnect.js +29 -25
- package/dist/lib/hosts/registry.js +4 -1
- package/dist/lib/hosts/remote-os.js +3 -1
- package/dist/lib/installations/versions.js +9 -1
- package/dist/lib/linux-userns.d.ts +58 -0
- package/dist/lib/linux-userns.js +116 -0
- package/dist/lib/memory.d.ts +26 -0
- package/dist/lib/memory.js +80 -1
- package/dist/lib/monitors/config.d.ts +11 -0
- package/dist/lib/monitors/config.js +8 -0
- package/dist/lib/monitors/engine.js +8 -1
- package/dist/lib/monitors/state.d.ts +37 -1
- package/dist/lib/monitors/state.js +79 -4
- package/dist/lib/permissions-registry.d.ts +2 -0
- package/dist/lib/permissions-registry.js +116 -14
- package/dist/lib/permissions.d.ts +5 -3
- package/dist/lib/permissions.js +25 -27
- package/dist/lib/profiles.d.ts +8 -7
- package/dist/lib/profiles.js +12 -0
- package/dist/lib/project-key.d.ts +9 -0
- package/dist/lib/project-key.js +11 -0
- package/dist/lib/secrets/bundles.d.ts +35 -0
- package/dist/lib/secrets/bundles.js +78 -1
- package/dist/lib/secrets/push.d.ts +3 -8
- package/dist/lib/secrets/push.js +18 -14
- package/dist/lib/secrets/remote.d.ts +9 -18
- package/dist/lib/secrets/remote.js +11 -26
- package/dist/lib/secrets/reserved-sync.d.ts +65 -0
- package/dist/lib/secrets/reserved-sync.js +129 -0
- package/dist/lib/self-heal/checks/hook-manifest.d.ts +2 -0
- package/dist/lib/self-heal/checks/hook-manifest.js +56 -0
- package/dist/lib/self-heal/registry.js +4 -0
- package/dist/lib/self-heal/types.d.ts +1 -1
- package/dist/lib/session/active.d.ts +10 -1
- package/dist/lib/session/active.js +8 -5
- package/dist/lib/session/actor-sidecar.d.ts +7 -0
- package/dist/lib/session/actor-sidecar.js +2 -0
- package/dist/lib/session/db.d.ts +39 -4
- package/dist/lib/session/db.js +168 -31
- package/dist/lib/session/discover.d.ts +32 -4
- package/dist/lib/session/discover.js +126 -37
- package/dist/lib/session/insights.d.ts +14 -0
- package/dist/lib/session/insights.js +25 -2
- package/dist/lib/session/linear.js +1 -1
- package/dist/lib/session/live-metadata.js +1 -0
- package/dist/lib/session/pid-registry.d.ts +7 -0
- package/dist/lib/session/prompt.d.ts +15 -0
- package/dist/lib/session/prompt.js +21 -0
- package/dist/lib/session/shell-programs.d.ts +17 -0
- package/dist/lib/session/shell-programs.js +21 -0
- package/dist/lib/session/state.js +2 -1
- package/dist/lib/session/stream-render.js +2 -1
- package/dist/lib/session/tool-calls.js +2 -5
- package/dist/lib/session/trajectory-html.js +2 -1
- package/dist/lib/session/trajectory.js +3 -12
- package/dist/lib/session/types.d.ts +25 -0
- package/dist/lib/session/types.js +10 -0
- package/dist/lib/share/publish.d.ts +53 -5
- package/dist/lib/share/publish.js +99 -17
- package/dist/lib/share/worker-template.js +594 -64
- package/dist/lib/startup/root-command.js +2 -1
- package/dist/lib/state.d.ts +24 -0
- package/dist/lib/state.js +318 -54
- package/dist/lib/sync-status.d.ts +4 -0
- package/dist/lib/sync-status.js +3 -0
- package/dist/lib/terminal/resolve.d.ts +7 -0
- package/dist/lib/terminal/resolve.js +41 -2
- package/dist/lib/traces/classify.js +24 -19
- package/dist/lib/traces/insights.d.ts +67 -0
- package/dist/lib/traces/insights.js +178 -0
- package/dist/lib/traces/phenotype.d.ts +67 -0
- package/dist/lib/traces/phenotype.js +437 -0
- package/dist/lib/traces/segments.d.ts +133 -0
- package/dist/lib/traces/segments.js +301 -0
- package/dist/lib/traces/sync.d.ts +33 -0
- package/dist/lib/traces/sync.js +11 -2
- package/dist/lib/types.d.ts +47 -1
- package/dist/lib/usage-refresh.js +2 -1
- package/dist/lib/view-types.d.ts +2 -0
- package/dist/lib/watchdog/runner.js +18 -4
- package/package.json +2 -1
|
@@ -9,6 +9,8 @@ import { readFileSync } from 'node:fs';
|
|
|
9
9
|
import { basename } from 'node:path';
|
|
10
10
|
import { execFileSync } from 'node:child_process';
|
|
11
11
|
import { hostname as osHostname } from 'node:os';
|
|
12
|
+
import { createHash } from 'node:crypto';
|
|
13
|
+
import { readSession } from '../identity/client.js';
|
|
12
14
|
import { readShareConfig } from './config.js';
|
|
13
15
|
import { resolveGitHubUsername } from '../git.js';
|
|
14
16
|
import { resolveShareBackend, sanitizeShareNamespace } from './backend.js';
|
|
@@ -16,6 +18,9 @@ import { captureCover, OG_WIDTH, OG_HEIGHT, OG_SCALE } from './capture.js';
|
|
|
16
18
|
import { deriveMeta, injectOgMeta } from './og.js';
|
|
17
19
|
import { injectAnalyticsBeacon } from './analytics.js';
|
|
18
20
|
import { prepareShareHtml } from './html.js';
|
|
21
|
+
/** The visibility levels a share may carry — the Worker's own set, used to
|
|
22
|
+
* validate `--visibility` and `share visibility <target> <level>`. */
|
|
23
|
+
export const SHARE_VISIBILITY_LEVELS = ['public', 'unlisted', 'me', 'org'];
|
|
19
24
|
/**
|
|
20
25
|
* `--unlisted` / `{ unlisted: true }` map to `unlisted`; `--visibility me|org`
|
|
21
26
|
* passes through; otherwise `visibility` (default public).
|
|
@@ -35,13 +40,16 @@ export function resolveShareVisibility(opts = {}) {
|
|
|
35
40
|
*/
|
|
36
41
|
export const RESERVED_META_KEYS = [
|
|
37
42
|
'expires-at',
|
|
43
|
+
'published-at',
|
|
38
44
|
'visibility',
|
|
39
45
|
'owner',
|
|
46
|
+
'org_domain',
|
|
40
47
|
'agent',
|
|
41
48
|
'session',
|
|
42
49
|
'host',
|
|
43
50
|
'repo',
|
|
44
51
|
'date',
|
|
52
|
+
'avatar',
|
|
45
53
|
'label',
|
|
46
54
|
'label-source',
|
|
47
55
|
];
|
|
@@ -64,6 +72,26 @@ export function resolveShareProvenance(opts = {}) {
|
|
|
64
72
|
date: (opts.now ?? new Date()).toISOString().slice(0, 10),
|
|
65
73
|
};
|
|
66
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* The sharer's avatar URL, stamped so the share bar can show a real profile
|
|
77
|
+
* picture instead of only the initials circle. We key a Gravatar on the SHA-256
|
|
78
|
+
* of the signed-in user's lowercased email (Gravatar resolves either MD5 or
|
|
79
|
+
* SHA-256), with `d=404` so Gravatar returns 404 for a user who has none — the
|
|
80
|
+
* bar's `<img>` onerror then falls back to the initials circle. Only the hash
|
|
81
|
+
* lands in public metadata, never the raw email. Returns '' when signed out
|
|
82
|
+
* (BYO without a Phoenix session), leaving the bar on the initials circle.
|
|
83
|
+
*
|
|
84
|
+
* `opts.session === null` means "explicitly signed out" (a test seam / BYO) and
|
|
85
|
+
* yields ''; `undefined` reads the real persisted session.
|
|
86
|
+
*/
|
|
87
|
+
export function resolveShareAvatar(opts = {}) {
|
|
88
|
+
const session = opts.session !== undefined ? opts.session : readSession();
|
|
89
|
+
const email = session?.email?.trim().toLowerCase();
|
|
90
|
+
if (!email)
|
|
91
|
+
return '';
|
|
92
|
+
const hash = createHash('sha256').update(email).digest('hex');
|
|
93
|
+
return `https://www.gravatar.com/avatar/${hash}?d=404&s=52`;
|
|
94
|
+
}
|
|
67
95
|
/**
|
|
68
96
|
* Parse repeated `--meta key=value` CLI args into a validated metadata record.
|
|
69
97
|
* Keys are lowercase `[a-z0-9-]`, up to 64 characters, and may not collide with
|
|
@@ -80,12 +108,12 @@ export function parseMetaEntries(pairs) {
|
|
|
80
108
|
}
|
|
81
109
|
const key = pair.slice(0, eq).trim();
|
|
82
110
|
const value = pair.slice(eq + 1);
|
|
83
|
-
if (!META_KEY_RE.test(key)) {
|
|
84
|
-
throw new Error(`Bad --meta key '${key}'. Keys are lowercase letters, digits, and hyphens, up to 64 characters.`);
|
|
85
|
-
}
|
|
86
111
|
if (RESERVED_META_KEYS.includes(key)) {
|
|
87
112
|
throw new Error(`--meta ${key}=… is reserved (Worker-stamped, or set automatically from your session/git) — pass a different key.`);
|
|
88
113
|
}
|
|
114
|
+
if (!META_KEY_RE.test(key)) {
|
|
115
|
+
throw new Error(`Bad --meta key '${key}'. Keys are lowercase letters, digits, and hyphens, up to 64 characters.`);
|
|
116
|
+
}
|
|
89
117
|
meta[key] = value;
|
|
90
118
|
}
|
|
91
119
|
return meta;
|
|
@@ -142,10 +170,13 @@ const HEADER_TRANSLITERATIONS = [
|
|
|
142
170
|
* The transliterations above cover what actually shows up; anything else outside
|
|
143
171
|
* latin1 is dropped, and a value that transliterates to nothing at all (a title
|
|
144
172
|
* written entirely in a non-latin script) degrades to a marker rather than an
|
|
145
|
-
* empty header.
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
173
|
+
* empty header. This value is the **latin1-safe floor** every Worker can read: a
|
|
174
|
+
* pre-Unicode Worker only ever sees `x-share-<field>`, so it MUST stay folded.
|
|
175
|
+
* Full Unicode rides ALONGSIDE it in a percent-encoded companion header
|
|
176
|
+
* (`toPercentHeaderValue` / {@link needsUnicodeCompanion}), which a new Worker
|
|
177
|
+
* opts into via `x-share-encoding: percent` and an old one ignores — so a
|
|
178
|
+
* Japanese/emoji title renders in full on an updated Worker and still folds
|
|
179
|
+
* gracefully everywhere else (PHNX-2786).
|
|
149
180
|
*/
|
|
150
181
|
export function toHeaderValue(text) {
|
|
151
182
|
let safe = text;
|
|
@@ -159,6 +190,31 @@ export function toHeaderValue(text) {
|
|
|
159
190
|
return safe;
|
|
160
191
|
return text.trim() ? '(unnamed)' : '';
|
|
161
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Whether text carries a code point above latin1 (U+00FF) — the meaningful
|
|
195
|
+
* display content `fetch`'s ByteString cannot hold, which {@link toHeaderValue}
|
|
196
|
+
* therefore transliterates or drops. This is the range worth carrying in the
|
|
197
|
+
* percent-encoded companion: an em dash, a curly quote, an emoji, or any
|
|
198
|
+
* CJK/Arabic/Hindi text. A plain accented latin1 name (`José`, é = U+00E9) is
|
|
199
|
+
* NOT lossy and needs no companion.
|
|
200
|
+
*
|
|
201
|
+
* `toHeaderValue` ALSO strips C0/C1 control characters (below U+0020, and
|
|
202
|
+
* U+007F–U+009F), which this deliberately does not flag: a raw ANSI/control
|
|
203
|
+
* sequence is not display text and must not be reconstructed into a page's
|
|
204
|
+
* rendered metadata, so it stays dropped on both the old and new Worker paths.
|
|
205
|
+
*/
|
|
206
|
+
export function needsUnicodeCompanion(text) {
|
|
207
|
+
return /[^\u0000-\u00ff]/.test(text);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Percent-encode a single-line free-text value for the `x-share-<field>-u`
|
|
211
|
+
* companion header. Whitespace is collapsed first (matching the folded value's
|
|
212
|
+
* single-line shape), then `encodeURIComponent` makes it pure-ASCII and
|
|
213
|
+
* header-safe. The Worker recovers the original with `decodeURIComponent`.
|
|
214
|
+
*/
|
|
215
|
+
export function toPercentHeaderValue(text) {
|
|
216
|
+
return encodeURIComponent(text.replace(/\s+/g, ' ').trim());
|
|
217
|
+
}
|
|
162
218
|
/**
|
|
163
219
|
* Best-effort human title when `--label` is omitted: the HTML `<title>`, else a
|
|
164
220
|
* Markdown frontmatter `title:`, else the filename. Always returns something —
|
|
@@ -462,6 +518,7 @@ export async function publishToEndpoint(filePath, endpoint, opts = {}) {
|
|
|
462
518
|
const unlisted = visibility === 'unlisted';
|
|
463
519
|
const pageUrl = `${endpoint.baseUrl.replace(/\/+$/, '')}/${key}`;
|
|
464
520
|
const provenance = opts.provenance ?? resolveShareProvenance();
|
|
521
|
+
const avatarUrl = opts.avatar ?? resolveShareAvatar({ session: opts.session });
|
|
465
522
|
const meta = opts.meta ?? {};
|
|
466
523
|
const put = opts.uploader ??
|
|
467
524
|
(async (u, b, h) => {
|
|
@@ -511,35 +568,60 @@ export async function publishToEndpoint(filePath, endpoint, opts = {}) {
|
|
|
511
568
|
metadataPreview.repo = provenance.repo;
|
|
512
569
|
if (provenance.date)
|
|
513
570
|
metadataPreview.date = provenance.date;
|
|
571
|
+
if (avatarUrl)
|
|
572
|
+
metadataPreview.avatar = avatarUrl;
|
|
514
573
|
assertMetadataSize(metadataPreview);
|
|
515
574
|
const authHeaders = (contentType) => {
|
|
516
575
|
const h = { authorization: `Bearer ${endpoint.token}`, 'content-type': contentType };
|
|
517
576
|
if (expiresAt)
|
|
518
577
|
h['x-share-expires-at'] = expiresAt;
|
|
519
578
|
h['x-share-visibility'] = visibility;
|
|
520
|
-
//
|
|
521
|
-
//
|
|
522
|
-
//
|
|
579
|
+
// Two headers per free-text field, backward-compatible by construction
|
|
580
|
+
// (PHNX-2786): `x-share-<field>` always carries the latin1-safe folded value
|
|
581
|
+
// an already-deployed Worker reads verbatim, and — only when the fold is lossy
|
|
582
|
+
// (a curly quote, em dash, emoji, CJK/Arabic/Hindi) — a percent-encoded
|
|
583
|
+
// `x-share-<field>-u` companion carries the full Unicode. A new Worker opts
|
|
584
|
+
// into the companions via `x-share-encoding: percent`; an old one ignores the
|
|
585
|
+
// unknown headers and keeps folding gracefully. The floor also keeps the
|
|
586
|
+
// ByteString crash fixed: a non-latin1 code point never reaches a raw header.
|
|
587
|
+
let unicodeCompanion = false;
|
|
588
|
+
const setText = (name, value) => {
|
|
589
|
+
h[name] = toHeaderValue(value);
|
|
590
|
+
if (needsUnicodeCompanion(value)) {
|
|
591
|
+
h[`${name}-u`] = toPercentHeaderValue(value);
|
|
592
|
+
unicodeCompanion = true;
|
|
593
|
+
}
|
|
594
|
+
};
|
|
523
595
|
if (provenance.agent)
|
|
524
|
-
|
|
596
|
+
setText('x-share-agent', provenance.agent);
|
|
525
597
|
if (provenance.session)
|
|
526
|
-
|
|
598
|
+
setText('x-share-session', provenance.session);
|
|
527
599
|
if (provenance.host)
|
|
528
|
-
|
|
600
|
+
setText('x-share-host', provenance.host);
|
|
529
601
|
if (provenance.repo)
|
|
530
|
-
|
|
602
|
+
setText('x-share-repo', provenance.repo);
|
|
531
603
|
if (provenance.date)
|
|
532
|
-
|
|
533
|
-
|
|
604
|
+
setText('x-share-date', provenance.date);
|
|
605
|
+
if (avatarUrl)
|
|
606
|
+
setText('x-share-avatar', avatarUrl);
|
|
607
|
+
setText('x-share-label', label);
|
|
534
608
|
h['x-share-label-source'] = labelSource;
|
|
535
609
|
// Per VALUE, before JSON.stringify — folding the serialized form would rewrite
|
|
536
610
|
// a curly quote inside a value into a bare `"`, which is structural in JSON and
|
|
537
611
|
// makes the Worker's JSON.parse throw. It swallows that error, so every --meta
|
|
538
|
-
// key would silently vanish on a 200.
|
|
612
|
+
// key would silently vanish on a 200. The companion carries the whole raw meta
|
|
613
|
+
// object percent-encoded once, so a new Worker recovers full-Unicode keys AND
|
|
614
|
+
// values in one JSON.parse rather than per-field.
|
|
539
615
|
if (Object.keys(meta).length > 0) {
|
|
540
616
|
const headerMeta = Object.fromEntries(Object.entries(meta).map(([k, v]) => [toHeaderValue(k), toHeaderValue(v)]));
|
|
541
617
|
h['x-share-meta'] = JSON.stringify(headerMeta);
|
|
618
|
+
if (Object.entries(meta).some(([k, v]) => needsUnicodeCompanion(k) || needsUnicodeCompanion(v))) {
|
|
619
|
+
h['x-share-meta-u'] = encodeURIComponent(JSON.stringify(meta));
|
|
620
|
+
unicodeCompanion = true;
|
|
621
|
+
}
|
|
542
622
|
}
|
|
623
|
+
if (unicodeCompanion)
|
|
624
|
+
h['x-share-encoding'] = 'percent';
|
|
543
625
|
if (opts.noRevision)
|
|
544
626
|
h['x-share-no-revision'] = '1';
|
|
545
627
|
return h;
|