@phnx-labs/agents-cli 1.22.83 → 1.22.85
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 +96 -0
- package/README.md +80 -53
- package/dist/bootstrap.d.ts +7 -6
- package/dist/bootstrap.js +20 -27
- package/dist/cli/command-registry.js +5 -1
- package/dist/commands/accounts.d.ts +6 -13
- package/dist/commands/accounts.js +330 -143
- package/dist/commands/apply.js +1 -1
- package/dist/commands/auth-mint.d.ts +7 -3
- package/dist/commands/auth-mint.js +21 -9
- package/dist/commands/auth.js +2 -3
- package/dist/commands/browser.js +10 -10
- package/dist/commands/daemon.d.ts +7 -3
- package/dist/commands/daemon.js +40 -25
- package/dist/commands/doctor.js +28 -2
- package/dist/commands/exec.js +87 -39
- package/dist/commands/fleet-capture.js +21 -2
- package/dist/commands/harness-wizard.js +2 -2
- package/dist/commands/lease.js +7 -12
- package/dist/commands/profiles.d.ts +2 -2
- package/dist/commands/profiles.js +20 -13
- package/dist/commands/repo.js +3 -3
- package/dist/commands/run-account-picker.d.ts +3 -3
- package/dist/commands/run-account-picker.js +29 -30
- package/dist/commands/secrets-passthrough.d.ts +20 -0
- package/dist/commands/secrets-passthrough.js +43 -0
- package/dist/commands/sessions-trace.d.ts +11 -0
- package/dist/commands/sessions-trace.js +71 -0
- package/dist/commands/setup-accounts.d.ts +3 -2
- package/dist/commands/setup-accounts.js +4 -4
- package/dist/commands/setup-secrets.d.ts +16 -21
- package/dist/commands/setup-secrets.js +43 -224
- package/dist/commands/ssh.js +2 -2
- package/dist/commands/sync.js +1 -1
- package/dist/commands/update.d.ts +10 -0
- package/dist/commands/update.js +43 -40
- package/dist/commands/versions.d.ts +11 -11
- package/dist/commands/versions.js +131 -83
- package/dist/commands/view.d.ts +1 -9
- package/dist/commands/view.js +41 -55
- package/dist/commands/webhook.js +5 -5
- package/dist/commands/workflows.js +2 -1
- package/dist/index.d.ts +12 -12
- package/dist/index.js +13 -42
- package/dist/lib/account-capabilities.d.ts +1 -1
- package/dist/lib/account-capabilities.js +1 -1
- package/dist/lib/account-catalog.d.ts +121 -6
- package/dist/lib/account-catalog.js +421 -7
- package/dist/lib/account-registry.d.ts +8 -30
- package/dist/lib/account-registry.js +36 -79
- package/dist/lib/account-schema.d.ts +1 -1
- package/dist/lib/account-schema.js +1 -1
- package/dist/lib/accounting/account-pool-collect.js +16 -4
- package/dist/lib/accounting/rotate.d.ts +20 -7
- package/dist/lib/accounting/rotate.js +89 -13
- package/dist/lib/accounting/usage.js +11 -16
- package/dist/lib/accounts/add.d.ts +138 -0
- package/dist/lib/accounts/add.js +651 -0
- package/dist/lib/accounts/migrate.d.ts +117 -0
- package/dist/lib/accounts/migrate.js +536 -0
- package/dist/lib/accounts/slots.d.ts +13 -0
- package/dist/lib/accounts/slots.js +100 -0
- package/dist/lib/agent-spec/agents.d.ts +16 -0
- package/dist/lib/agent-spec/agents.js +32 -4
- package/dist/lib/app-bundle-install.js +5 -4
- package/dist/lib/auth-health.d.ts +3 -0
- package/dist/lib/auth-health.js +11 -0
- package/dist/lib/auth-mint.d.ts +52 -16
- package/dist/lib/auth-mint.js +117 -39
- package/dist/lib/browser/chrome.d.ts +1 -1
- package/dist/lib/browser/chrome.js +5 -5
- package/dist/lib/byok-usage.js +3 -3
- package/dist/lib/claude-account-token.d.ts +47 -3
- package/dist/lib/claude-account-token.js +172 -50
- package/dist/lib/cloud/antigravity.js +4 -4
- package/dist/lib/cloud/cursor.js +4 -4
- package/dist/lib/crabbox/cli.d.ts +1 -1
- package/dist/lib/crabbox/cli.js +6 -6
- package/dist/lib/crabbox/runtimes.d.ts +3 -3
- package/dist/lib/crabbox/runtimes.js +5 -5
- package/dist/lib/daemon/account-state-daemon-service.d.ts +37 -1
- package/dist/lib/daemon/account-state-daemon-service.js +199 -3
- package/dist/lib/daemon/auth-sync-service.js +28 -1
- package/dist/lib/daemon/daemon.d.ts +6 -16
- package/dist/lib/daemon/daemon.js +52 -97
- package/dist/lib/daemon/daemon.test-fixture.d.ts +7 -9
- package/dist/lib/daemon/daemon.test-fixture.js +22 -40
- package/dist/lib/daemon/harness-update-service.d.ts +1 -1
- package/dist/lib/daemon/harness-update-service.js +1 -1
- package/dist/lib/daemon/runner.d.ts +15 -3
- package/dist/lib/daemon/runner.js +49 -24
- package/dist/lib/daemon-health.d.ts +1 -2
- package/dist/lib/daemon-health.js +7 -6
- package/dist/lib/daemon-services.d.ts +1 -1
- package/dist/lib/daemon-services.js +1 -11
- package/dist/lib/daemon-ticks.js +23 -2
- package/dist/lib/daemon-webhooks.d.ts +8 -7
- package/dist/lib/daemon-webhooks.js +10 -9
- package/dist/lib/device-config.js +1 -1
- package/dist/lib/devices/doctor-findings.d.ts +1 -1
- package/dist/lib/devices/harness-inventory.d.ts +39 -0
- package/dist/lib/devices/harness-inventory.js +126 -4
- package/dist/lib/doctor-diff.js +2 -1
- package/dist/lib/exec-account-home.d.ts +38 -0
- package/dist/lib/exec-account-home.js +164 -0
- package/dist/lib/exec.d.ts +30 -0
- package/dist/lib/exec.js +101 -31
- package/dist/lib/feed/activity-stream.d.ts +60 -0
- package/dist/lib/feed/activity-stream.js +271 -0
- package/dist/lib/feed/activity.d.ts +7 -0
- package/dist/lib/feed/activity.js +10 -4
- package/dist/lib/feed/watch.d.ts +9 -3
- package/dist/lib/feed/watch.js +72 -36
- package/dist/lib/fleet/apply.d.ts +2 -2
- package/dist/lib/fleet/apply.js +4 -4
- package/dist/lib/fleet/auth-sync.js +4 -3
- package/dist/lib/fleet-shared-repo-sync.js +6 -9
- package/dist/lib/fleet-shared-state.d.ts +6 -0
- package/dist/lib/harness/adapter.d.ts +7 -7
- package/dist/lib/harness/adapter.js +10 -6
- package/dist/lib/harness/adapters/grok.js +8 -3
- package/dist/lib/harness/adapters/muse.js +1 -1
- package/dist/lib/harness/adapters/opencode.js +12 -3
- package/dist/lib/harness-auth-capabilities.d.ts +61 -0
- package/dist/lib/harness-auth-capabilities.js +52 -0
- package/dist/lib/helper-versions.d.ts +6 -4
- package/dist/lib/helper-versions.js +5 -4
- package/dist/lib/hosts/credential-transport.d.ts +10 -0
- package/dist/lib/hosts/credential-transport.js +37 -0
- package/dist/lib/hosts/dispatch.d.ts +7 -0
- package/dist/lib/hosts/dispatch.js +13 -6
- package/dist/lib/identity/client.d.ts +3 -3
- package/dist/lib/identity/client.js +3 -3
- package/dist/lib/installations/index.d.ts +1 -1
- package/dist/lib/installations/index.js +1 -1
- package/dist/lib/installations/migrate.js +9 -0
- package/dist/lib/installations/resolve.js +1 -1
- package/dist/lib/installations/shims.d.ts +15 -0
- package/dist/lib/installations/shims.js +69 -0
- package/dist/lib/installations/store.d.ts +43 -0
- package/dist/lib/installations/store.js +75 -7
- package/dist/lib/installations/versions.js +1 -1
- package/dist/lib/menubar/install-menubar.d.ts +3 -3
- package/dist/lib/menubar/install-menubar.js +3 -3
- package/dist/lib/native-accounts.d.ts +35 -0
- package/dist/lib/native-accounts.js +41 -0
- package/dist/lib/net-close.d.ts +11 -0
- package/dist/lib/net-close.js +25 -0
- package/dist/lib/openclaw-keychain.js +27 -1
- package/dist/lib/profiles.js +22 -9
- package/dist/lib/project-resources.js +1 -1
- package/dist/lib/reserved-stores.d.ts +53 -0
- package/dist/lib/reserved-stores.js +120 -0
- package/dist/lib/secrets-client.d.ts +191 -0
- package/dist/lib/secrets-client.js +710 -0
- package/dist/lib/secrets-policy.d.ts +222 -0
- package/dist/lib/secrets-policy.js +483 -0
- package/dist/lib/secrets-types.d.ts +188 -0
- package/dist/lib/secrets-types.js +24 -0
- package/dist/lib/service-manifest.js +3 -4
- package/dist/lib/session/active.d.ts +38 -4
- package/dist/lib/session/active.js +36 -4
- package/dist/lib/session/bash-command.js +10 -0
- package/dist/lib/session/db.d.ts +65 -2
- package/dist/lib/session/db.js +178 -18
- package/dist/lib/session/mirror.d.ts +5 -0
- package/dist/lib/session/mirror.js +166 -0
- package/dist/lib/session/parse.d.ts +49 -0
- package/dist/lib/session/parse.js +324 -30
- package/dist/lib/session/prompt.d.ts +93 -2
- package/dist/lib/session/prompt.js +266 -15
- package/dist/lib/session/remote/peer-stream.d.ts +47 -0
- package/dist/lib/session/remote/peer-stream.js +142 -0
- package/dist/lib/session/remote/watch.d.ts +1 -1
- package/dist/lib/session/remote/watch.js +41 -42
- package/dist/lib/session/session-cache.d.ts +9 -0
- package/dist/lib/session/session-cache.js +40 -2
- package/dist/lib/session/sync/config.js +2 -2
- package/dist/lib/session/timeline-pass.d.ts +129 -0
- package/dist/lib/session/timeline-pass.js +323 -0
- package/dist/lib/session/timeline.d.ts +182 -0
- package/dist/lib/session/timeline.js +636 -0
- package/dist/lib/session/types.d.ts +155 -1
- package/dist/lib/sha256-asset.d.ts +11 -16
- package/dist/lib/sha256-asset.js +11 -16
- package/dist/lib/share/config.js +14 -5
- package/dist/lib/signin-badge.d.ts +26 -0
- package/dist/lib/signin-badge.js +42 -0
- package/dist/lib/staleness/detectors/workflows.js +3 -105
- package/dist/lib/staleness/writers/workflows.js +2 -1
- package/dist/lib/state.d.ts +7 -4
- package/dist/lib/state.js +18 -7
- package/dist/lib/summarizer/pass.d.ts +2 -0
- package/dist/lib/summarizer/pass.js +14 -1
- package/dist/lib/summarizer/summarize.d.ts +7 -0
- package/dist/lib/summarizer/summarize.js +3 -0
- package/dist/lib/sync-umbrella.js +2 -2
- package/dist/lib/teams/agents.js +1 -1
- package/dist/lib/types.d.ts +74 -33
- package/dist/lib/view-types.d.ts +6 -3
- package/dist/lib/workflows-registry.d.ts +71 -0
- package/dist/lib/workflows-registry.js +280 -0
- package/dist/lib/workflows.d.ts +21 -21
- package/dist/lib/workflows.js +12 -327
- package/package.json +2 -3
- package/scripts/postinstall.js +4 -29
- package/dist/commands/secrets-import.d.ts +0 -18
- package/dist/commands/secrets-import.js +0 -74
- package/dist/commands/secrets-migrate.d.ts +0 -25
- package/dist/commands/secrets-migrate.js +0 -334
- package/dist/commands/secrets-rotate-passphrase.d.ts +0 -17
- package/dist/commands/secrets-rotate-passphrase.js +0 -96
- package/dist/commands/secrets-sync.d.ts +0 -11
- package/dist/commands/secrets-sync.js +0 -153
- package/dist/commands/secrets-vault.d.ts +0 -10
- package/dist/commands/secrets-vault.js +0 -130
- package/dist/commands/secrets.d.ts +0 -212
- package/dist/commands/secrets.js +0 -3030
- package/dist/lib/accounts/connect.d.ts +0 -170
- package/dist/lib/accounts/connect.js +0 -383
- package/dist/lib/daemon/keychain-reap-service.d.ts +0 -17
- package/dist/lib/daemon/keychain-reap-service.js +0 -32
- package/dist/lib/daemon/secrets-broker-service.d.ts +0 -21
- package/dist/lib/daemon/secrets-broker-service.js +0 -51
- package/dist/lib/secrets/agent.d.ts +0 -358
- package/dist/lib/secrets/agent.js +0 -1291
- package/dist/lib/secrets/audit.d.ts +0 -46
- package/dist/lib/secrets/audit.js +0 -101
- package/dist/lib/secrets/bundles.d.ts +0 -290
- package/dist/lib/secrets/bundles.js +0 -1547
- package/dist/lib/secrets/download-keychain.d.ts +0 -47
- package/dist/lib/secrets/download-keychain.js +0 -70
- package/dist/lib/secrets/drivers/rush.d.ts +0 -14
- package/dist/lib/secrets/drivers/rush.js +0 -90
- package/dist/lib/secrets/fallback.d.ts +0 -48
- package/dist/lib/secrets/fallback.js +0 -48
- package/dist/lib/secrets/filestore.d.ts +0 -222
- package/dist/lib/secrets/filestore.js +0 -1099
- package/dist/lib/secrets/headless.d.ts +0 -43
- package/dist/lib/secrets/headless.js +0 -56
- package/dist/lib/secrets/icloud-import.d.ts +0 -79
- package/dist/lib/secrets/icloud-import.js +0 -206
- package/dist/lib/secrets/index.d.ts +0 -451
- package/dist/lib/secrets/index.js +0 -1568
- package/dist/lib/secrets/install-helper.d.ts +0 -72
- package/dist/lib/secrets/install-helper.js +0 -245
- package/dist/lib/secrets/lease.d.ts +0 -25
- package/dist/lib/secrets/lease.js +0 -44
- package/dist/lib/secrets/linux.d.ts +0 -77
- package/dist/lib/secrets/linux.js +0 -393
- package/dist/lib/secrets/list-filter.d.ts +0 -109
- package/dist/lib/secrets/list-filter.js +0 -261
- package/dist/lib/secrets/mcp.d.ts +0 -93
- package/dist/lib/secrets/mcp.js +0 -211
- package/dist/lib/secrets/profiles.d.ts +0 -10
- package/dist/lib/secrets/profiles.js +0 -13
- package/dist/lib/secrets/push.d.ts +0 -133
- package/dist/lib/secrets/push.js +0 -273
- package/dist/lib/secrets/rc-hygiene.d.ts +0 -63
- package/dist/lib/secrets/rc-hygiene.js +0 -143
- package/dist/lib/secrets/read-backoff.d.ts +0 -27
- package/dist/lib/secrets/read-backoff.js +0 -64
- package/dist/lib/secrets/reaper.d.ts +0 -90
- package/dist/lib/secrets/reaper.js +0 -243
- package/dist/lib/secrets/remote.d.ts +0 -152
- package/dist/lib/secrets/remote.js +0 -344
- package/dist/lib/secrets/reserved-sync.d.ts +0 -66
- package/dist/lib/secrets/reserved-sync.js +0 -147
- package/dist/lib/secrets/scope.d.ts +0 -26
- package/dist/lib/secrets/scope.js +0 -29
- package/dist/lib/secrets/session-store.d.ts +0 -107
- package/dist/lib/secrets/session-store.js +0 -342
- package/dist/lib/secrets/sync-backend.d.ts +0 -48
- package/dist/lib/secrets/sync-backend.js +0 -13
- package/dist/lib/secrets/sync-commands.d.ts +0 -21
- package/dist/lib/secrets/sync-commands.js +0 -21
- package/dist/lib/secrets/sync.d.ts +0 -48
- package/dist/lib/secrets/sync.js +0 -237
- package/dist/lib/secrets/unlock-hints.d.ts +0 -27
- package/dist/lib/secrets/unlock-hints.js +0 -36
- package/dist/lib/secrets/usage-db.d.ts +0 -46
- package/dist/lib/secrets/usage-db.js +0 -96
- package/dist/lib/secrets/vault-age-helper.d.ts +0 -1
- package/dist/lib/secrets/vault-age-helper.js +0 -34
- package/dist/lib/secrets/vault.d.ts +0 -49
- package/dist/lib/secrets/vault.js +0 -399
- package/dist/lib/secrets/windows.d.ts +0 -81
- package/dist/lib/secrets/windows.js +0 -556
- package/scripts/install-helper.js +0 -97
- /package/dist/lib/{secrets/sync-passphrase.d.ts → sync-passphrase.d.ts} +0 -0
- /package/dist/lib/{secrets/sync-passphrase.js → sync-passphrase.js} +0 -0
|
@@ -30,6 +30,43 @@ export const SESSION_MIRROR_MAX_ROWS = 200;
|
|
|
30
30
|
export const SESSION_MIRROR_SNIPPET_MAX = 280;
|
|
31
31
|
/** Mirror rows older than this since their last sync are pruned (staleness/size ceiling). */
|
|
32
32
|
export const SESSION_MIRROR_MAX_AGE_MS = 14 * 24 * 60 * 60_000;
|
|
33
|
+
/** Caps for the timeline block on a published mirror row. */
|
|
34
|
+
export const SESSION_MIRROR_MAX_STEPS = 8;
|
|
35
|
+
export const SESSION_MIRROR_STEP_TEXT_MAX = 160;
|
|
36
|
+
export const SESSION_MIRROR_REQUEST_MAX = 2_000;
|
|
37
|
+
export const SESSION_MIRROR_MAX_FILES = 8;
|
|
38
|
+
function cap(value, max) {
|
|
39
|
+
return value.length > max ? value.slice(0, max) : value;
|
|
40
|
+
}
|
|
41
|
+
/** Bound the tidied request: prose capped, chips capped, never re-derived. */
|
|
42
|
+
function boundedRequest(request) {
|
|
43
|
+
return {
|
|
44
|
+
...request,
|
|
45
|
+
text: cap(request.text, SESSION_MIRROR_REQUEST_MAX),
|
|
46
|
+
headline: cap(request.headline, SESSION_MIRROR_STEP_TEXT_MAX),
|
|
47
|
+
...(request.command ? { command: cap(request.command, 120) } : {}),
|
|
48
|
+
attachments: request.attachments.slice(0, SESSION_MIRROR_MAX_FILES)
|
|
49
|
+
.map((a) => ({ kind: a.kind, name: cap(a.name, 120) })),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** Bound the step list. Counters are kept exact — only text is truncated. */
|
|
53
|
+
function boundedTimeline(timeline) {
|
|
54
|
+
const steps = timeline.steps.slice(-SESSION_MIRROR_MAX_STEPS).map((step) => ({
|
|
55
|
+
...step,
|
|
56
|
+
text: cap(step.text, SESSION_MIRROR_STEP_TEXT_MAX),
|
|
57
|
+
...(step.now ? { now: cap(step.now, SESSION_MIRROR_STEP_TEXT_MAX) } : {}),
|
|
58
|
+
...(step.marks ? { marks: step.marks.slice(0, 4).map((mark) => cap(mark, 40)) } : {}),
|
|
59
|
+
}));
|
|
60
|
+
return { ...timeline, steps, ...(timeline.reason ? { reason: cap(timeline.reason, 200) } : {}) };
|
|
61
|
+
}
|
|
62
|
+
/** Bound the file rows; `total` still reports the real count. */
|
|
63
|
+
function boundedFiles(files) {
|
|
64
|
+
return {
|
|
65
|
+
...files,
|
|
66
|
+
changes: files.changes.slice(0, SESSION_MIRROR_MAX_FILES)
|
|
67
|
+
.map((change) => ({ ...change, path: cap(change.path, 400) })),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
33
70
|
function snippet(value, max = SESSION_MIRROR_SNIPPET_MAX) {
|
|
34
71
|
if (!value)
|
|
35
72
|
return undefined;
|
|
@@ -83,6 +120,12 @@ export async function publishSessionMirrorToSharedStore(options = {}) {
|
|
|
83
120
|
}
|
|
84
121
|
: {}),
|
|
85
122
|
...(s.summary?.summaryState ? { summaryState: s.summary.summaryState } : {}),
|
|
123
|
+
// Same bound-on-publish discipline as the summary above: the fleet state file
|
|
124
|
+
// is git-synced, so the request text, the step list, and the file rows are
|
|
125
|
+
// capped here rather than shipped raw (PHNX-3939).
|
|
126
|
+
...(s.timeline?.request ? { request: boundedRequest(s.timeline.request) } : {}),
|
|
127
|
+
...(s.timeline?.timeline ? { timeline: boundedTimeline(s.timeline.timeline) } : {}),
|
|
128
|
+
...(s.timeline?.files ? { files: boundedFiles(s.timeline.files) } : {}),
|
|
86
129
|
capturedAt,
|
|
87
130
|
}));
|
|
88
131
|
try {
|
|
@@ -133,8 +176,131 @@ function toUpsert(raw) {
|
|
|
133
176
|
ticketId: cap(r.ticketId, 64),
|
|
134
177
|
prUrl: cap(r.prUrl, 512),
|
|
135
178
|
summary: toMirrorSummary(r),
|
|
179
|
+
timeline: toMirrorTimeline(r),
|
|
136
180
|
};
|
|
137
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Validate an untrusted peer's published request/timeline/files into the bounded
|
|
184
|
+
* projection the local cache stores (PHNX-3939). Bounds mirror the publish side,
|
|
185
|
+
* so a hostile or oversized peer cannot bloat this box's cache. Only a row that
|
|
186
|
+
* carries a well-formed timeline is kept; a malformed one is dropped whole
|
|
187
|
+
* rather than partially trusted.
|
|
188
|
+
*/
|
|
189
|
+
function toMirrorTimeline(r) {
|
|
190
|
+
const timeline = toMirrorTimelineBlock(r.timeline);
|
|
191
|
+
if (!timeline)
|
|
192
|
+
return undefined;
|
|
193
|
+
return {
|
|
194
|
+
timeline,
|
|
195
|
+
...(toMirrorRequest(r.request) ? { request: toMirrorRequest(r.request) } : {}),
|
|
196
|
+
...(toMirrorFiles(r.files) ? { files: toMirrorFiles(r.files) } : {}),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function isRecord(v) {
|
|
200
|
+
return Boolean(v) && typeof v === 'object' && !Array.isArray(v);
|
|
201
|
+
}
|
|
202
|
+
function count(v) {
|
|
203
|
+
return typeof v === 'number' && Number.isFinite(v) && v >= 0 ? Math.floor(v) : 0;
|
|
204
|
+
}
|
|
205
|
+
/** The verb keys a peer's `mix` may carry — anything else is dropped, not trusted. */
|
|
206
|
+
const MIRROR_VERB_CLASSES = [
|
|
207
|
+
'read', 'edit', 'run', 'git', 'test', 'browser', 'agent', 'other',
|
|
208
|
+
];
|
|
209
|
+
/** A peer's per-verb breakdown, whitelisted by key and clamped by value. */
|
|
210
|
+
function toMirrorMix(raw) {
|
|
211
|
+
if (!isRecord(raw))
|
|
212
|
+
return undefined;
|
|
213
|
+
const mix = {};
|
|
214
|
+
for (const verb of MIRROR_VERB_CLASSES) {
|
|
215
|
+
const n = count(raw[verb]);
|
|
216
|
+
if (n > 0)
|
|
217
|
+
mix[verb] = n;
|
|
218
|
+
}
|
|
219
|
+
return Object.keys(mix).length ? mix : undefined;
|
|
220
|
+
}
|
|
221
|
+
function toMirrorTimelineBlock(raw) {
|
|
222
|
+
if (!isRecord(raw))
|
|
223
|
+
return undefined;
|
|
224
|
+
const state = raw.state;
|
|
225
|
+
if (state !== 'ready' && state !== 'partial' && state !== 'unavailable')
|
|
226
|
+
return undefined;
|
|
227
|
+
const steps = (Array.isArray(raw.steps) ? raw.steps : [])
|
|
228
|
+
.filter(isRecord)
|
|
229
|
+
.filter((step) => isString(step.text) && isString(step.at))
|
|
230
|
+
.slice(0, SESSION_MIRROR_MAX_STEPS)
|
|
231
|
+
.map((step) => ({
|
|
232
|
+
text: String(step.text).slice(0, SESSION_MIRROR_STEP_TEXT_MAX),
|
|
233
|
+
at: String(step.at).slice(0, 40),
|
|
234
|
+
...(isString(step.endedAt) ? { endedAt: step.endedAt.slice(0, 40) } : {}),
|
|
235
|
+
source: (step.source === 'thinking' || step.source === 'derived' || step.source === 'user'
|
|
236
|
+
? step.source : 'narration'),
|
|
237
|
+
tools: count(step.tools),
|
|
238
|
+
failed: count(step.failed),
|
|
239
|
+
blocked: count(step.blocked),
|
|
240
|
+
...(isString(step.now) ? { now: step.now.slice(0, SESSION_MIRROR_STEP_TEXT_MAX) } : {}),
|
|
241
|
+
// `mix` and `live` are what the sidebar renders a step WITH ("6 run ·
|
|
242
|
+
// 2 blocked", the amber now-line). Dropping them here made a remote row
|
|
243
|
+
// disagree with the local one about what a live step even is, while `now`
|
|
244
|
+
// survived — so they ride through, whitelisted like every other field.
|
|
245
|
+
...(step.live === true ? { live: true } : {}),
|
|
246
|
+
...(() => {
|
|
247
|
+
const mix = toMirrorMix(step.mix);
|
|
248
|
+
return mix ? { mix } : {};
|
|
249
|
+
})(),
|
|
250
|
+
...(Array.isArray(step.marks)
|
|
251
|
+
? { marks: step.marks.filter(isString).slice(0, 4).map((mark) => mark.slice(0, 40)) }
|
|
252
|
+
: {}),
|
|
253
|
+
}));
|
|
254
|
+
const earlier = isRecord(raw.earlier) ? raw.earlier : {};
|
|
255
|
+
return {
|
|
256
|
+
steps,
|
|
257
|
+
earlier: { steps: count(earlier.steps), tools: count(earlier.tools), failed: count(earlier.failed) },
|
|
258
|
+
tools: count(raw.tools),
|
|
259
|
+
failed: count(raw.failed),
|
|
260
|
+
blocked: count(raw.blocked),
|
|
261
|
+
spanMs: count(raw.spanMs),
|
|
262
|
+
state,
|
|
263
|
+
...(isString(raw.reason) ? { reason: raw.reason.slice(0, 200) } : {}),
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
function toMirrorRequest(raw) {
|
|
267
|
+
if (!isRecord(raw) || !isString(raw.headline))
|
|
268
|
+
return undefined;
|
|
269
|
+
const kind = raw.kind;
|
|
270
|
+
return {
|
|
271
|
+
text: isString(raw.text) ? raw.text.slice(0, SESSION_MIRROR_REQUEST_MAX) : '',
|
|
272
|
+
headline: raw.headline.slice(0, SESSION_MIRROR_STEP_TEXT_MAX),
|
|
273
|
+
kind: kind === 'image' || kind === 'command' || kind === 'skill' ? kind : 'text',
|
|
274
|
+
...(isString(raw.command) ? { command: raw.command.slice(0, 120) } : {}),
|
|
275
|
+
attachments: (Array.isArray(raw.attachments) ? raw.attachments : [])
|
|
276
|
+
.filter(isRecord)
|
|
277
|
+
.filter((a) => isString(a.name))
|
|
278
|
+
.slice(0, SESSION_MIRROR_MAX_FILES)
|
|
279
|
+
.map((a) => ({
|
|
280
|
+
kind: a.kind === 'image' || a.kind === 'dir' ? a.kind : 'file',
|
|
281
|
+
name: String(a.name).slice(0, 120),
|
|
282
|
+
})),
|
|
283
|
+
pastedLines: count(raw.pastedLines),
|
|
284
|
+
...(typeof raw.turns === 'number' ? { turns: count(raw.turns) } : {}),
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
function toMirrorFiles(raw) {
|
|
288
|
+
if (!isRecord(raw))
|
|
289
|
+
return undefined;
|
|
290
|
+
const changes = (Array.isArray(raw.changes) ? raw.changes : [])
|
|
291
|
+
.filter(isRecord)
|
|
292
|
+
.filter((change) => isString(change.path))
|
|
293
|
+
.slice(0, SESSION_MIRROR_MAX_FILES)
|
|
294
|
+
.map((change) => ({
|
|
295
|
+
path: String(change.path).slice(0, 400),
|
|
296
|
+
op: (change.op === 'created' || change.op === 'deleted' ? change.op : 'modified'),
|
|
297
|
+
edits: count(change.edits),
|
|
298
|
+
at: isString(change.at) ? change.at.slice(0, 40) : '',
|
|
299
|
+
}));
|
|
300
|
+
if (!changes.length)
|
|
301
|
+
return undefined;
|
|
302
|
+
return { changes, total: count(raw.total) || changes.length, source: raw.source === 'harness' ? 'harness' : 'tools' };
|
|
303
|
+
}
|
|
138
304
|
/** One published summary state, validated back into the union or undefined. */
|
|
139
305
|
function toSummaryState(v) {
|
|
140
306
|
return v === 'pending' || v === 'ready' || v === 'skipped' ? v : undefined;
|
|
@@ -33,6 +33,14 @@ export interface ParseSessionOptions {
|
|
|
33
33
|
maxToolOutputChars?: number;
|
|
34
34
|
/** Opt-in because interrupts are not user messages and would change the published event stream. */
|
|
35
35
|
includeInterrupts?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Opt-in `file_change` events from the harness's own file ledger (Claude
|
|
38
|
+
* `file-history-delta`). Opt-in for the same reason as
|
|
39
|
+
* {@link includeInterrupts}: they are not tool calls, and emitting them by
|
|
40
|
+
* default would change every published event stream (message counts, digests,
|
|
41
|
+
* trajectories) for a signal only the timeline fold consumes.
|
|
42
|
+
*/
|
|
43
|
+
includeFileHistory?: boolean;
|
|
36
44
|
}
|
|
37
45
|
export declare function parseSession(filePath: string, agent?: SessionAgentId, opts?: ParseSessionOptions): SessionEvent[];
|
|
38
46
|
/** Infer the agent type from a session file path using known directory conventions. */
|
|
@@ -75,6 +83,28 @@ export declare function applyPatchTargets(input: string): Array<{
|
|
|
75
83
|
op: 'Add' | 'Update' | 'Delete';
|
|
76
84
|
}>;
|
|
77
85
|
export declare function applyPatchTargetPaths(input: string): string[];
|
|
86
|
+
/**
|
|
87
|
+
* Codex writes its turn TWICE in one rollout: the raw `response_item` records
|
|
88
|
+
* the model exchanged, and a parallel `event_msg` / `item_completed` stream of
|
|
89
|
+
* typed, already-classified items. The two overlap — on a 6,244-line rollout on
|
|
90
|
+
* zion (2026-09-06) the same turn appears as 648 `custom_tool_call` +
|
|
91
|
+
* 60 `function_call` records AND as 1,038 `CommandExecution` items — so the two
|
|
92
|
+
* MUST NOT be merged into one event list: every consumer that counts tool calls
|
|
93
|
+
* (digest, trajectory, insights, the tool index) would double-count.
|
|
94
|
+
*
|
|
95
|
+
* {@link parseCodexContent} therefore keeps reading `response_item` and this is
|
|
96
|
+
* a SEPARATE reader over the item stream, for consumers that want the harness's
|
|
97
|
+
* own classification instead of re-deriving it: the command as Codex parsed it
|
|
98
|
+
* (`parsed_cmd.type`), its `exit_code`/`status`, the per-path `FileChange`
|
|
99
|
+
* ledger, `AgentMessage.phase` (`commentary` is the narration between calls),
|
|
100
|
+
* web searches, sub-agent activity and compactions. The timeline fold is the
|
|
101
|
+
* consumer; `parseSession` is untouched.
|
|
102
|
+
*
|
|
103
|
+
* Version-tolerant by construction: an item type this does not know folds to a
|
|
104
|
+
* generic `other` tool_use rather than throwing, so a Codex release that adds an
|
|
105
|
+
* item type degrades to a counted step instead of an empty timeline.
|
|
106
|
+
*/
|
|
107
|
+
export declare function parseCodexItemsContent(content: string): SessionEvent[];
|
|
78
108
|
/**
|
|
79
109
|
* Parse Codex JSONL *content* (already read into a string) into normalized
|
|
80
110
|
* events. Split from `parseCodex` so the tail reader can parse just the last
|
|
@@ -142,6 +172,25 @@ export declare function sessionFilePathContainer(filePath: string): string;
|
|
|
142
172
|
* timestamps aren't stored, so every event carries the session's `created_at`
|
|
143
173
|
* (from summary.json), falling back to the transcript's mtime.
|
|
144
174
|
*/
|
|
175
|
+
/**
|
|
176
|
+
* Counters Grok writes beside its transcript in `signals.json` — the only place
|
|
177
|
+
* a Grok session records milestones and failures, since `chat_history.jsonl`
|
|
178
|
+
* carries no timestamps and no exit codes. Read by the timeline fold to mark a
|
|
179
|
+
* session that committed / opened / merged a PR and to report a tool-failure
|
|
180
|
+
* count the event stream cannot supply.
|
|
181
|
+
*/
|
|
182
|
+
export interface GrokSessionSignals {
|
|
183
|
+
gitCommitCount: number;
|
|
184
|
+
prCreatedCount: number;
|
|
185
|
+
prMergedCount: number;
|
|
186
|
+
toolFailureCount: number;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Read `signals.json` next to a Grok transcript. Returns `undefined` when the
|
|
190
|
+
* file is absent or unreadable — a Grok session simply has no signals then, and
|
|
191
|
+
* the fold reports what it does have rather than inventing zeros.
|
|
192
|
+
*/
|
|
193
|
+
export declare function readGrokSignals(filePath: string): GrokSessionSignals | undefined;
|
|
145
194
|
export declare function parseGrok(filePath: string): SessionEvent[];
|
|
146
195
|
/**
|
|
147
196
|
* The transcript query {@link parseOpenCode} runs, exported so a test can assert
|