@phnx-labs/agents-cli 1.22.117 → 1.22.119
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 +301 -0
- package/dist/bootstrap.js +4 -11
- package/dist/commands/accounts.js +7 -4
- package/dist/commands/browser.d.ts +52 -70
- package/dist/commands/browser.js +192 -3562
- package/dist/commands/daemon.d.ts +39 -2
- package/dist/commands/daemon.js +72 -73
- package/dist/commands/events.js +1 -1
- package/dist/commands/exec.js +53 -1
- package/dist/commands/projects.js +92 -7
- package/dist/commands/repo.js +13 -49
- package/dist/commands/route.js +5 -5
- package/dist/commands/routines.js +39 -12
- package/dist/commands/sessions-render.d.ts +1 -1
- package/dist/commands/sessions-render.js +0 -1
- package/dist/commands/sessions.test-fixture.d.ts +0 -1
- package/dist/commands/sessions.test-fixture.js +0 -37
- package/dist/commands/setup-browser.d.ts +17 -12
- package/dist/commands/setup-browser.js +52 -87
- package/dist/commands/setup-preferences.d.ts +0 -17
- package/dist/commands/setup-preferences.js +18 -49
- package/dist/commands/setup.js +9 -9
- package/dist/commands/ssh.js +10 -1
- package/dist/commands/sync.js +6 -44
- package/dist/commands/teams.js +0 -1
- package/dist/commands/update.d.ts +19 -0
- package/dist/commands/update.js +34 -6
- package/dist/commands/view.d.ts +12 -1
- package/dist/commands/view.js +47 -2
- package/dist/index.js +107 -26
- package/dist/lib/account-capabilities.js +0 -2
- package/dist/lib/account-catalog.d.ts +38 -0
- package/dist/lib/account-catalog.js +110 -26
- package/dist/lib/account-provider-registry.js +1 -1
- package/dist/lib/account-registry.d.ts +1 -1
- package/dist/lib/account-registry.js +36 -2
- package/dist/lib/accounting/rotate.js +22 -8
- package/dist/lib/accounting/usage-ingest.d.ts +6 -1
- package/dist/lib/accounting/usage-ingest.js +115 -45
- package/dist/lib/accounting/usage-sync.d.ts +134 -31
- package/dist/lib/accounting/usage-sync.js +227 -66
- package/dist/lib/accounting/usage.d.ts +16 -3
- package/dist/lib/accounting/usage.js +26 -8
- package/dist/lib/accounts/add.d.ts +3 -1
- package/dist/lib/accounts/add.js +24 -13
- package/dist/lib/accounts/slots.d.ts +8 -0
- package/dist/lib/accounts/slots.js +17 -0
- package/dist/lib/add-dir.js +0 -1
- package/dist/lib/agent-cli-commands.js +0 -1
- package/dist/lib/agent-spec/agents.d.ts +6 -7
- package/dist/lib/agent-spec/agents.js +7 -60
- package/dist/lib/auth-health.d.ts +69 -1
- package/dist/lib/auth-health.js +133 -4
- package/dist/lib/browser/context.d.ts +82 -0
- package/dist/lib/browser/context.js +88 -0
- package/dist/lib/browser/paths.d.ts +25 -0
- package/dist/lib/browser/paths.js +51 -0
- package/dist/lib/browser/record.d.ts +38 -0
- package/dist/lib/browser/record.js +57 -0
- package/dist/lib/browser/sessions-list.js +1 -2
- package/dist/lib/browser-client.d.ts +158 -0
- package/dist/lib/browser-client.js +234 -0
- package/dist/lib/channels/owner-sink.d.ts +1 -18
- package/dist/lib/channels/owner-sink.js +29 -82
- package/dist/lib/channels/providers/rush.d.ts +7 -7
- package/dist/lib/channels/providers/rush.js +127 -57
- package/dist/lib/claude-account-token.d.ts +7 -1
- package/dist/lib/claude-account-token.js +26 -4
- package/dist/lib/claude-statusline.d.ts +1 -1
- package/dist/lib/claude-statusline.js +15 -3
- package/dist/lib/commands.js +1 -1
- package/dist/lib/crabbox/lease.js +1 -1
- package/dist/lib/crabbox/runtimes.js +1 -3
- package/dist/lib/daemon/account-state-daemon-service.js +1 -0
- package/dist/lib/daemon/auth-sync-service.d.ts +21 -18
- package/dist/lib/daemon/auth-sync-service.js +37 -43
- package/dist/lib/daemon/daemon.d.ts +25 -14
- package/dist/lib/daemon/daemon.js +92 -154
- package/dist/lib/daemon/runner.d.ts +2 -2
- package/dist/lib/daemon/runner.js +32 -9
- package/dist/lib/daemon/self-update-service.d.ts +35 -34
- package/dist/lib/daemon/self-update-service.js +40 -36
- package/dist/lib/daemon/service.d.ts +12 -8
- package/dist/lib/daemon/supervisor.d.ts +65 -54
- package/dist/lib/daemon/supervisor.js +136 -171
- package/dist/lib/daemon/testdata/process-view-start.js +5 -2
- package/dist/lib/daemon/usage-sync-service.d.ts +21 -30
- package/dist/lib/daemon/usage-sync-service.js +46 -78
- package/dist/lib/daemon-health.d.ts +22 -5
- package/dist/lib/daemon-health.js +47 -3
- package/dist/lib/daemon-services.d.ts +1 -1
- package/dist/lib/daemon-services.js +0 -10
- package/dist/lib/daemon-ticks.js +4 -2
- package/dist/lib/devices/doctor-findings.js +8 -11
- package/dist/lib/devices/harness-inventory.js +14 -5
- package/dist/lib/exec-account-home.js +5 -0
- package/dist/lib/exec.js +10 -13
- package/dist/lib/feed/events.js +0 -1
- package/dist/lib/feed/tool-activity.js +5 -2
- package/dist/lib/fleet-shared-state.d.ts +45 -0
- package/dist/lib/fleet-shared-state.js +78 -9
- package/dist/lib/fs-atomic.js +25 -0
- package/dist/lib/github/pr-mergeable.d.ts +4 -2
- package/dist/lib/github/pr-mergeable.js +5 -3
- package/dist/lib/github/project-prs.d.ts +58 -3
- package/dist/lib/github/project-prs.js +205 -7
- package/dist/lib/harness/adapters/cursor.js +14 -4
- package/dist/lib/harness-auth-capabilities.d.ts +4 -3
- package/dist/lib/harness-auth-capabilities.js +1 -2
- package/dist/lib/helper-versions.js +1 -1
- package/dist/lib/hooks/cache.d.ts +7 -0
- package/dist/lib/hooks/cache.js +27 -2
- package/dist/lib/hooks/install.js +7 -1
- package/dist/lib/hosts/ready.d.ts +38 -8
- package/dist/lib/hosts/ready.js +62 -14
- package/dist/lib/installations/active-check.d.ts +27 -0
- package/dist/lib/installations/active-check.js +61 -0
- package/dist/lib/installations/migrate.js +6 -3
- package/dist/lib/installations/shims.d.ts +1 -1
- package/dist/lib/installations/shims.js +32 -12
- package/dist/lib/installations/store.d.ts +9 -0
- package/dist/lib/installations/store.js +24 -0
- package/dist/lib/installations/update.js +21 -15
- package/dist/lib/installations/versions.js +15 -3
- package/dist/lib/manifest.js +1 -1
- package/dist/lib/models.js +0 -2
- package/dist/lib/open-url.js +28 -54
- package/dist/lib/profiles.js +0 -2
- package/dist/lib/projects.d.ts +16 -0
- package/dist/lib/projects.js +31 -0
- package/dist/lib/refresh.js +1 -1
- package/dist/lib/routine-readiness.d.ts +35 -0
- package/dist/lib/routine-readiness.js +74 -16
- package/dist/lib/rules/compile.js +6 -0
- package/dist/lib/sandbox.js +0 -2
- package/dist/lib/secrets-policy.d.ts +89 -11
- package/dist/lib/secrets-policy.js +175 -28
- package/dist/lib/session/active.d.ts +17 -6
- package/dist/lib/session/active.js +105 -49
- package/dist/lib/session/db.d.ts +1 -1
- package/dist/lib/session/db.js +65 -18
- package/dist/lib/session/discover.js +1 -283
- package/dist/lib/session/mirror.d.ts +4 -3
- package/dist/lib/session/mirror.js +4 -3
- package/dist/lib/session/parse.d.ts +0 -2
- package/dist/lib/session/parse.js +1 -138
- package/dist/lib/session/pid-registry.d.ts +6 -3
- package/dist/lib/session/pid-registry.js +18 -8
- package/dist/lib/session/remote/watch.d.ts +1 -1
- package/dist/lib/session/remote/watch.js +7 -3
- package/dist/lib/session/throughput.d.ts +1 -3
- package/dist/lib/session/throughput.js +0 -20
- package/dist/lib/session/types.d.ts +2 -2
- package/dist/lib/session/types.js +2 -2
- package/dist/lib/sessions-client.d.ts +60 -1
- package/dist/lib/sessions-client.js +227 -4
- package/dist/lib/setup-tool-status.js +5 -10
- package/dist/lib/signin-badge.d.ts +3 -2
- package/dist/lib/signin-badge.js +6 -3
- package/dist/lib/smart-launch.js +4 -1
- package/dist/lib/staleness/detectors/commands.d.ts +1 -1
- package/dist/lib/staleness/detectors/hooks.d.ts +1 -1
- package/dist/lib/staleness/detectors/mcp.d.ts +1 -1
- package/dist/lib/staleness/detectors/permissions.d.ts +1 -1
- package/dist/lib/staleness/detectors/plugins.d.ts +1 -1
- package/dist/lib/staleness/detectors/rules.d.ts +1 -1
- package/dist/lib/staleness/detectors/skills.d.ts +1 -1
- package/dist/lib/staleness/detectors/subagents.d.ts +1 -1
- package/dist/lib/staleness/detectors/workflows.d.ts +1 -1
- package/dist/lib/staleness/writers/commands.d.ts +1 -1
- package/dist/lib/staleness/writers/hooks.d.ts +1 -1
- package/dist/lib/staleness/writers/mcp.d.ts +1 -1
- package/dist/lib/staleness/writers/permissions.d.ts +1 -1
- package/dist/lib/staleness/writers/plugins.d.ts +1 -1
- package/dist/lib/staleness/writers/rules.d.ts +1 -1
- package/dist/lib/staleness/writers/skills.d.ts +1 -1
- package/dist/lib/staleness/writers/sources.js +5 -0
- package/dist/lib/staleness/writers/subagents.d.ts +1 -1
- package/dist/lib/staleness/writers/workflows.d.ts +1 -1
- package/dist/lib/state.d.ts +6 -4
- package/dist/lib/state.js +7 -17
- package/dist/lib/teams/parsers.d.ts +1 -1
- package/dist/lib/teams/parsers.js +1 -136
- package/dist/lib/teams/placement-probe.js +50 -15
- package/dist/lib/teams/scheduler.d.ts +7 -0
- package/dist/lib/types.d.ts +16 -1
- package/dist/lib/types.js +1 -1
- package/dist/lib/view-types.d.ts +32 -0
- package/dist/lib/watchdog/read.js +0 -1
- package/dist/lib/watchdog/rotate.js +1 -2
- package/dist/lib/watchdog/runner.js +2 -2
- package/dist/lib/watchdog/watchdog.d.ts +1 -1
- package/dist/lib/watchdog/watchdogTail.js +0 -31
- package/package.json +1 -1
- package/scripts/postinstall.js +8 -8
- package/dist/browser.d.ts +0 -2
- package/dist/browser.js +0 -17
- package/dist/commands/browser-picker.d.ts +0 -18
- package/dist/commands/browser-picker.js +0 -97
- package/dist/lib/browser/arc-discovery.d.ts +0 -52
- package/dist/lib/browser/arc-discovery.js +0 -197
- package/dist/lib/browser/arc-dom.d.ts +0 -14
- package/dist/lib/browser/arc-dom.js +0 -121
- package/dist/lib/browser/caller-identity.d.ts +0 -40
- package/dist/lib/browser/caller-identity.js +0 -175
- package/dist/lib/browser/cdp.d.ts +0 -51
- package/dist/lib/browser/cdp.js +0 -254
- package/dist/lib/browser/chrome.d.ts +0 -141
- package/dist/lib/browser/chrome.js +0 -704
- package/dist/lib/browser/chromium-discovery.d.ts +0 -28
- package/dist/lib/browser/chromium-discovery.js +0 -96
- package/dist/lib/browser/devices.d.ts +0 -34
- package/dist/lib/browser/devices.js +0 -61
- package/dist/lib/browser/domain-skills.d.ts +0 -71
- package/dist/lib/browser/domain-skills.js +0 -195
- package/dist/lib/browser/drivers/arc.d.ts +0 -40
- package/dist/lib/browser/drivers/arc.js +0 -276
- package/dist/lib/browser/drivers/firefox.d.ts +0 -99
- package/dist/lib/browser/drivers/firefox.js +0 -377
- package/dist/lib/browser/drivers/local.d.ts +0 -55
- package/dist/lib/browser/drivers/local.js +0 -266
- package/dist/lib/browser/drivers/ssh.d.ts +0 -120
- package/dist/lib/browser/drivers/ssh.js +0 -467
- package/dist/lib/browser/editor.d.ts +0 -3
- package/dist/lib/browser/editor.js +0 -50
- package/dist/lib/browser/ffmpeg.d.ts +0 -12
- package/dist/lib/browser/ffmpeg.js +0 -184
- package/dist/lib/browser/firefox-discovery.d.ts +0 -69
- package/dist/lib/browser/firefox-discovery.js +0 -162
- package/dist/lib/browser/har.d.ts +0 -85
- package/dist/lib/browser/har.js +0 -77
- package/dist/lib/browser/hygiene.d.ts +0 -97
- package/dist/lib/browser/hygiene.js +0 -153
- package/dist/lib/browser/index.d.ts +0 -5
- package/dist/lib/browser/index.js +0 -5
- package/dist/lib/browser/input.d.ts +0 -7
- package/dist/lib/browser/input.js +0 -92
- package/dist/lib/browser/ipc.d.ts +0 -204
- package/dist/lib/browser/ipc.js +0 -1453
- package/dist/lib/browser/login-detection.d.ts +0 -87
- package/dist/lib/browser/login-detection.js +0 -274
- package/dist/lib/browser/profiles.d.ts +0 -422
- package/dist/lib/browser/profiles.js +0 -1157
- package/dist/lib/browser/refs.d.ts +0 -89
- package/dist/lib/browser/refs.js +0 -191
- package/dist/lib/browser/registry.d.ts +0 -70
- package/dist/lib/browser/registry.js +0 -252
- package/dist/lib/browser/remote-control.d.ts +0 -59
- package/dist/lib/browser/remote-control.js +0 -85
- package/dist/lib/browser/resolve-target.d.ts +0 -66
- package/dist/lib/browser/resolve-target.js +0 -264
- package/dist/lib/browser/runtime-state.d.ts +0 -291
- package/dist/lib/browser/runtime-state.js +0 -584
- package/dist/lib/browser/secret-ref.d.ts +0 -10
- package/dist/lib/browser/secret-ref.js +0 -14
- package/dist/lib/browser/service.d.ts +0 -812
- package/dist/lib/browser/service.js +0 -4693
- package/dist/lib/browser/stream.d.ts +0 -17
- package/dist/lib/browser/stream.js +0 -72
- package/dist/lib/browser/task-index.d.ts +0 -78
- package/dist/lib/browser/task-index.js +0 -199
- package/dist/lib/browser/types.d.ts +0 -647
- package/dist/lib/browser/types.js +0 -61
- package/dist/lib/browser/upload.d.ts +0 -29
- package/dist/lib/browser/upload.js +0 -298
- package/dist/lib/daemon/browser-ipc-service.d.ts +0 -20
- package/dist/lib/daemon/browser-ipc-service.js +0 -46
- package/dist/lib/daemon/browser-task-reap-service.d.ts +0 -14
- package/dist/lib/daemon/browser-task-reap-service.js +0 -26
- package/dist/lib/fleet-shared-repo-sync.d.ts +0 -55
- package/dist/lib/fleet-shared-repo-sync.js +0 -490
|
@@ -142,7 +142,6 @@ function truncateNormalizedToolOutput(output, maxChars) {
|
|
|
142
142
|
const TRANSCRIPT_PARSERS = {
|
|
143
143
|
claude: (filePath, opts) => parseClaude(filePath, opts),
|
|
144
144
|
codex: (filePath) => parseCodex(filePath),
|
|
145
|
-
gemini: (filePath) => parseGemini(filePath),
|
|
146
145
|
antigravity: (filePath) => parseAntigravity(filePath),
|
|
147
146
|
// Cloud-captured opencode sessions are normalized JSONL (produced by the
|
|
148
147
|
// factory at capture time), NOT the local `opencode.db#<session>` SQLite
|
|
@@ -183,14 +182,10 @@ export function detectAgent(filePath) {
|
|
|
183
182
|
return 'claude';
|
|
184
183
|
if (filePath.includes('/.codex/') || filePath.includes('\\.codex\\'))
|
|
185
184
|
return 'codex';
|
|
186
|
-
// Antigravity lives under ~/.gemini/antigravity-cli/conversations/<uuid>.db
|
|
187
|
-
// it must be matched BEFORE the generic /.gemini/ check below or it would be
|
|
188
|
-
// misdetected as Gemini.
|
|
185
|
+
// Antigravity lives under ~/.gemini/antigravity-cli/conversations/<uuid>.db.
|
|
189
186
|
if ((filePath.includes('/antigravity-cli/conversations/') || filePath.includes('\\antigravity-cli\\conversations\\'))
|
|
190
187
|
&& filePath.endsWith('.db'))
|
|
191
188
|
return 'antigravity';
|
|
192
|
-
if (filePath.includes('/.gemini/') || filePath.includes('\\.gemini\\'))
|
|
193
|
-
return 'gemini';
|
|
194
189
|
if (filePath.includes('/.grok/') || filePath.includes('\\.grok\\'))
|
|
195
190
|
return 'grok';
|
|
196
191
|
if (filePath.includes('/.rush/') || filePath.includes('\\.rush\\'))
|
|
@@ -216,9 +211,6 @@ export function detectAgent(filePath) {
|
|
|
216
211
|
return cloudMatch[1];
|
|
217
212
|
if (filePath.includes('opencode.db'))
|
|
218
213
|
return 'opencode';
|
|
219
|
-
// Try file extension + content heuristic
|
|
220
|
-
if (filePath.endsWith('.json'))
|
|
221
|
-
return 'gemini';
|
|
222
214
|
return null;
|
|
223
215
|
}
|
|
224
216
|
/**
|
|
@@ -1051,135 +1043,6 @@ export function parseCodexContent(content) {
|
|
|
1051
1043
|
}
|
|
1052
1044
|
return events;
|
|
1053
1045
|
}
|
|
1054
|
-
// ---------------------------------------------------------------------------
|
|
1055
|
-
// Gemini parser
|
|
1056
|
-
// ---------------------------------------------------------------------------
|
|
1057
|
-
/** Parse a Gemini JSON session file into normalized events. */
|
|
1058
|
-
export function parseGemini(filePath) {
|
|
1059
|
-
const content = safeReadSessionFile(filePath);
|
|
1060
|
-
let session;
|
|
1061
|
-
try {
|
|
1062
|
-
session = JSON.parse(content);
|
|
1063
|
-
}
|
|
1064
|
-
catch {
|
|
1065
|
-
/* Gemini session file is not valid JSON */
|
|
1066
|
-
throw new Error(`Failed to parse Gemini session: ${filePath}`);
|
|
1067
|
-
}
|
|
1068
|
-
const messages = session.messages || [];
|
|
1069
|
-
const events = [];
|
|
1070
|
-
events.push({
|
|
1071
|
-
type: 'init',
|
|
1072
|
-
agent: 'gemini',
|
|
1073
|
-
timestamp: session.startTime || new Date().toISOString(),
|
|
1074
|
-
content: `Gemini session ${session.sessionId || ''}`.trim(),
|
|
1075
|
-
});
|
|
1076
|
-
for (const msg of messages) {
|
|
1077
|
-
const timestamp = msg.timestamp || session.startTime || new Date().toISOString();
|
|
1078
|
-
if (msg.type === 'user') {
|
|
1079
|
-
const text = extractGeminiContent(msg.content);
|
|
1080
|
-
if (text) {
|
|
1081
|
-
events.push({
|
|
1082
|
-
type: 'message',
|
|
1083
|
-
agent: 'gemini',
|
|
1084
|
-
timestamp,
|
|
1085
|
-
role: 'user',
|
|
1086
|
-
content: text,
|
|
1087
|
-
});
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
else if (msg.type === 'gemini') {
|
|
1091
|
-
// Reasoning thoughts
|
|
1092
|
-
if (Array.isArray(msg.thoughts)) {
|
|
1093
|
-
for (const thought of msg.thoughts) {
|
|
1094
|
-
const text = thought.description || thought.subject || '';
|
|
1095
|
-
if (text.trim()) {
|
|
1096
|
-
const subject = thought.subject ? `**${thought.subject}**: ` : '';
|
|
1097
|
-
events.push({
|
|
1098
|
-
type: 'thinking',
|
|
1099
|
-
agent: 'gemini',
|
|
1100
|
-
timestamp: thought.timestamp || timestamp,
|
|
1101
|
-
content: `${subject}${thought.description || ''}`.trim(),
|
|
1102
|
-
});
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
// Assistant text
|
|
1107
|
-
const text = extractGeminiContent(msg.content);
|
|
1108
|
-
if (text) {
|
|
1109
|
-
events.push({
|
|
1110
|
-
type: 'message',
|
|
1111
|
-
agent: 'gemini',
|
|
1112
|
-
timestamp,
|
|
1113
|
-
role: 'assistant',
|
|
1114
|
-
content: text,
|
|
1115
|
-
});
|
|
1116
|
-
}
|
|
1117
|
-
// Tool calls (Gemini inlines call + result on the same message)
|
|
1118
|
-
if (Array.isArray(msg.toolCalls)) {
|
|
1119
|
-
for (const tc of msg.toolCalls) {
|
|
1120
|
-
const toolName = tc.name || 'unknown';
|
|
1121
|
-
const args = tc.args || {};
|
|
1122
|
-
events.push({
|
|
1123
|
-
type: 'tool_use',
|
|
1124
|
-
agent: 'gemini',
|
|
1125
|
-
timestamp: tc.timestamp || timestamp,
|
|
1126
|
-
tool: toolName,
|
|
1127
|
-
callId: typeof tc.id === 'string' ? tc.id : undefined,
|
|
1128
|
-
args,
|
|
1129
|
-
command: ['run_shell_command', 'shell', 'bash'].includes(toolName) ? args.command : undefined,
|
|
1130
|
-
path: args.file_path || args.path || undefined,
|
|
1131
|
-
});
|
|
1132
|
-
// Inline result
|
|
1133
|
-
if (tc.result || tc.status) {
|
|
1134
|
-
let output = '';
|
|
1135
|
-
if (Array.isArray(tc.result)) {
|
|
1136
|
-
for (const r of tc.result) {
|
|
1137
|
-
const resp = r?.functionResponse?.response;
|
|
1138
|
-
if (resp?.output) {
|
|
1139
|
-
output += String(resp.output);
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
else if (typeof tc.result === 'string') {
|
|
1144
|
-
output = tc.result;
|
|
1145
|
-
}
|
|
1146
|
-
events.push({
|
|
1147
|
-
type: 'tool_result',
|
|
1148
|
-
agent: 'gemini',
|
|
1149
|
-
timestamp: tc.timestamp || timestamp,
|
|
1150
|
-
tool: toolName,
|
|
1151
|
-
callId: typeof tc.id === 'string' ? tc.id : undefined,
|
|
1152
|
-
success: tc.status === 'success',
|
|
1153
|
-
output,
|
|
1154
|
-
});
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
}
|
|
1160
|
-
return events;
|
|
1161
|
-
}
|
|
1162
|
-
/**
|
|
1163
|
-
* Extract text content from Gemini's content field,
|
|
1164
|
-
* which can be a string or an array of {text: string} parts.
|
|
1165
|
-
*/
|
|
1166
|
-
function extractGeminiContent(content) {
|
|
1167
|
-
if (typeof content === 'string')
|
|
1168
|
-
return content.trim();
|
|
1169
|
-
if (Array.isArray(content)) {
|
|
1170
|
-
return content
|
|
1171
|
-
.map((part) => {
|
|
1172
|
-
if (typeof part === 'string')
|
|
1173
|
-
return part;
|
|
1174
|
-
if (typeof part?.text === 'string')
|
|
1175
|
-
return part.text;
|
|
1176
|
-
return '';
|
|
1177
|
-
})
|
|
1178
|
-
.join('\n')
|
|
1179
|
-
.trim();
|
|
1180
|
-
}
|
|
1181
|
-
return '';
|
|
1182
|
-
}
|
|
1183
1046
|
/** Read a base-128 varint from `b` at offset `i`; returns [value, nextOffset]. */
|
|
1184
1047
|
function readVarint(b, i) {
|
|
1185
1048
|
let shift = 0;
|
|
@@ -58,8 +58,10 @@ export interface PidSessionEntry {
|
|
|
58
58
|
startTime?: string;
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
|
+
/** ps lstart fields can differ in padding or date formatting between invocations. */
|
|
62
|
+
export declare function processStartTimesMatch(recorded: string | undefined, observed: string | undefined): boolean | undefined;
|
|
61
63
|
/** Read-only identity proof for exact joins. Unknown is never a positive match. */
|
|
62
|
-
export declare function pidSessionEntryMatchesLiveProcess(entry: PidSessionEntry): boolean | undefined;
|
|
64
|
+
export declare function pidSessionEntryMatchesLiveProcess(entry: PidSessionEntry, startTime?: string): boolean | undefined;
|
|
63
65
|
export declare function isSessionIdShape(value: string): boolean;
|
|
64
66
|
export declare function extractSessionIdArg(args: string[]): string | undefined;
|
|
65
67
|
/**
|
|
@@ -86,8 +88,9 @@ export declare function sessionIdFromLivePid(pid: number): string | undefined;
|
|
|
86
88
|
export declare function writePidSessionEntry(entry: PidSessionEntry): void;
|
|
87
89
|
/** Look up a live pid's recorded session. Returns undefined if absent/corrupt. */
|
|
88
90
|
export declare function readPidSessionEntry(pid: number): PidSessionEntry | undefined;
|
|
89
|
-
/** Live consumers require identity proof; raw history is not a PID binding.
|
|
90
|
-
|
|
91
|
+
/** Live consumers require identity proof; raw history is not a PID binding.
|
|
92
|
+
* A shared process snapshot may supply lstart to avoid a per-pid ps probe. */
|
|
93
|
+
export declare function readLivePidSessionEntry(pid: number, startTime?: string): PidSessionEntry | undefined;
|
|
91
94
|
/**
|
|
92
95
|
* Every recorded launch, one entry per live-or-dead pid. Used to index launches
|
|
93
96
|
* by their `tmuxPane` so the authoritative tmux source can attribute a pane it did
|
|
@@ -55,16 +55,25 @@ function darwinStartTime(pid) {
|
|
|
55
55
|
return undefined;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
function processStartTimeMs(value) {
|
|
59
|
+
return typeof value === 'string' ? Date.parse(value.trim().replace(/\s+/g, ' ')) : NaN;
|
|
60
|
+
}
|
|
61
|
+
/** ps lstart fields can differ in padding or date formatting between invocations. */
|
|
62
|
+
export function processStartTimesMatch(recorded, observed) {
|
|
63
|
+
const recordedMs = processStartTimeMs(recorded);
|
|
64
|
+
const observedMs = processStartTimeMs(observed);
|
|
65
|
+
return Number.isFinite(recordedMs) && Number.isFinite(observedMs) ? recordedMs === observedMs : undefined;
|
|
66
|
+
}
|
|
58
67
|
/** Read-only identity proof for exact joins. Unknown is never a positive match. */
|
|
59
|
-
export function pidSessionEntryMatchesLiveProcess(entry) {
|
|
68
|
+
export function pidSessionEntryMatchesLiveProcess(entry, startTime) {
|
|
60
69
|
if (!Number.isInteger(entry.pid) || entry.pid < 1)
|
|
61
70
|
return undefined;
|
|
62
71
|
if (process.platform === 'darwin') {
|
|
63
72
|
const exists = pidExists(entry.pid);
|
|
64
73
|
if (exists !== true)
|
|
65
74
|
return exists;
|
|
66
|
-
const start = darwinStartTime(entry.pid);
|
|
67
|
-
return
|
|
75
|
+
const start = startTime ?? darwinStartTime(entry.pid);
|
|
76
|
+
return processStartTimesMatch(entry.processIdentity?.startTime, start);
|
|
68
77
|
}
|
|
69
78
|
if (process.platform !== 'linux')
|
|
70
79
|
return undefined;
|
|
@@ -233,8 +242,9 @@ export function readPidSessionEntry(pid) {
|
|
|
233
242
|
}
|
|
234
243
|
return undefined;
|
|
235
244
|
}
|
|
236
|
-
/** Live consumers require identity proof; raw history is not a PID binding.
|
|
237
|
-
|
|
245
|
+
/** Live consumers require identity proof; raw history is not a PID binding.
|
|
246
|
+
* A shared process snapshot may supply lstart to avoid a per-pid ps probe. */
|
|
247
|
+
export function readLivePidSessionEntry(pid, startTime) {
|
|
238
248
|
const entry = readPidSessionEntry(pid);
|
|
239
249
|
if (!entry || !hostProcessView())
|
|
240
250
|
return undefined;
|
|
@@ -244,8 +254,8 @@ export function readLivePidSessionEntry(pid) {
|
|
|
244
254
|
// Upgrade a native legacy launch only after the home namespace is proven,
|
|
245
255
|
// and the actual process start excludes a recycled PID. Hook timestamps may
|
|
246
256
|
// be later than process start, but cannot predate this process incarnation.
|
|
247
|
-
const start = darwinStartTime(pid);
|
|
248
|
-
const startMs =
|
|
257
|
+
const start = startTime ?? darwinStartTime(pid);
|
|
258
|
+
const startMs = processStartTimeMs(start);
|
|
249
259
|
if (Number.isFinite(startMs) && entry.startedAtMs >= startMs - 1000 && entry.startedAtMs <= Date.now()) {
|
|
250
260
|
const scope = hostProcessView();
|
|
251
261
|
entry.processIdentity = process.platform === 'linux'
|
|
@@ -257,7 +267,7 @@ export function readLivePidSessionEntry(pid) {
|
|
|
257
267
|
catch { /* read remains useful */ }
|
|
258
268
|
}
|
|
259
269
|
}
|
|
260
|
-
return pidSessionEntryMatchesLiveProcess(entry) === true ? entry : undefined;
|
|
270
|
+
return pidSessionEntryMatchesLiveProcess(entry, startTime) === true ? entry : undefined;
|
|
261
271
|
}
|
|
262
272
|
/**
|
|
263
273
|
* Every recorded launch, one entry per live-or-dead pid. Used to index launches
|
|
@@ -88,7 +88,7 @@ export declare function sessionWatchRowKey(scope: string, row: ActiveSession): s
|
|
|
88
88
|
export declare function toSessionWatchRow(scope: string, row: ActiveSession): SessionWatchRow;
|
|
89
89
|
/** Project one durable indexed session into the same canonical watch contract
|
|
90
90
|
* as live sessions. This is the only history backfill consumed by AGI EXT. */
|
|
91
|
-
export declare function toPreviousSessionWatchRow(scope: string, session: SessionMeta): SessionWatchRow;
|
|
91
|
+
export declare function toPreviousSessionWatchRow(scope: string, session: SessionMeta, accounts?: import("../../account-registry.js").NativeAccount[]): SessionWatchRow;
|
|
92
92
|
/** Stream-local sequencer and convergent row diff. */
|
|
93
93
|
export declare class SessionWatchState {
|
|
94
94
|
readonly streamId: string;
|
|
@@ -8,7 +8,9 @@ import { machineId, normalizeHost } from '../../machine-id.js';
|
|
|
8
8
|
import { shellQuote } from '../../ssh-exec.js';
|
|
9
9
|
import { streamFromPeer } from './peer-stream.js';
|
|
10
10
|
import { buildWindowsAgentsCommand, remoteShellFor } from '../../hosts/remote-cmd.js';
|
|
11
|
-
import { isReapableOrphan } from '../active.js';
|
|
11
|
+
import { isReapableOrphan, sessionAccountLabel } from '../active.js';
|
|
12
|
+
import { listNativeAccounts } from '../../account-registry.js';
|
|
13
|
+
import { readMeta } from '../../state.js';
|
|
12
14
|
import { querySessions, readSessionSummaryAny, readSessionTimelineAny } from '../db.js';
|
|
13
15
|
import { linearIssueUrl } from '../linear.js';
|
|
14
16
|
import { sessionAgentSupportsResume } from '../recovery.js';
|
|
@@ -79,7 +81,7 @@ function previousRowTitle(session, foldedHeadline) {
|
|
|
79
81
|
}
|
|
80
82
|
/** Project one durable indexed session into the same canonical watch contract
|
|
81
83
|
* as live sessions. This is the only history backfill consumed by AGI EXT. */
|
|
82
|
-
export function toPreviousSessionWatchRow(scope, session) {
|
|
84
|
+
export function toPreviousSessionWatchRow(scope, session, accounts = listNativeAccounts(readMeta())) {
|
|
83
85
|
const resumable = sessionAgentSupportsResume(session.agent);
|
|
84
86
|
const sourceDevice = normalizeHost(session.machine ?? scope);
|
|
85
87
|
const startedAtMs = epochMs(session.timestamp);
|
|
@@ -125,6 +127,7 @@ export function toPreviousSessionWatchRow(scope, session) {
|
|
|
125
127
|
...(session.firstUserMessage ? { firstUserMessage: session.firstUserMessage } : {}),
|
|
126
128
|
...(session.version ? { version: session.version } : {}),
|
|
127
129
|
...(session.account ? { account: session.account } : {}),
|
|
130
|
+
accountLabel: sessionAccountLabel(session.agent, session, accounts),
|
|
128
131
|
...(session.prUrl ? { pr: { url: session.prUrl, number: session.prNumber } } : {}),
|
|
129
132
|
...(worktree ? { worktree } : {}),
|
|
130
133
|
...(session.gitBranch ? { branch: session.gitBranch } : {}),
|
|
@@ -226,10 +229,11 @@ export class SessionWatchState {
|
|
|
226
229
|
const liveRows = sourceRows.map((row) => toSessionWatchRow(scope, row));
|
|
227
230
|
const sourceIds = new Set(liveRows.map((row) => row.sessionId).filter((id) => Boolean(id)));
|
|
228
231
|
const rows = new Map(liveRows.map((row) => [row.rowKey, row]));
|
|
232
|
+
const accounts = indexedRows.length ? listNativeAccounts(readMeta()) : [];
|
|
229
233
|
for (const indexed of indexedRows) {
|
|
230
234
|
if (sourceIds.has(indexed.id))
|
|
231
235
|
continue;
|
|
232
|
-
const row = toPreviousSessionWatchRow(scope, indexed);
|
|
236
|
+
const row = toPreviousSessionWatchRow(scope, indexed, accounts);
|
|
233
237
|
rows.set(row.rowKey, row);
|
|
234
238
|
}
|
|
235
239
|
this.prunePrevious(scope, rows);
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* straight off `agents sessions --active --json` instead (issue #741).
|
|
9
9
|
*/
|
|
10
10
|
/** Agents whose transcript formats report per-turn output-token usage. */
|
|
11
|
-
type ThroughputAgent = 'claude' | 'codex'
|
|
11
|
+
type ThroughputAgent = 'claude' | 'codex';
|
|
12
12
|
/**
|
|
13
13
|
* Output-token throughput (tokens/sec) over the last `windowSec` seconds.
|
|
14
14
|
*
|
|
@@ -22,8 +22,6 @@ type ThroughputAgent = 'claude' | 'codex' | 'gemini';
|
|
|
22
22
|
* - Codex: JSONL. Each token_count event is `{type: 'event_msg', timestamp,
|
|
23
23
|
* payload: {type: 'token_count', info: {last_token_usage: {output_tokens,
|
|
24
24
|
* reasoning_output_tokens}}}}`. `last_token_usage` is per-turn (not cumulative).
|
|
25
|
-
* - Gemini: single JSON object. `{messages: [{type: 'gemini', timestamp,
|
|
26
|
-
* tokens: {output, thoughts}}]}`. Caller must pass the whole file.
|
|
27
25
|
*/
|
|
28
26
|
export declare function computeTokPerSec(sessionContent: string, agent: ThroughputAgent, windowSec?: number, now?: number): number;
|
|
29
27
|
export {};
|
|
@@ -22,30 +22,10 @@ const DEFAULT_THROUGHPUT_WINDOW_SEC = 60;
|
|
|
22
22
|
* - Codex: JSONL. Each token_count event is `{type: 'event_msg', timestamp,
|
|
23
23
|
* payload: {type: 'token_count', info: {last_token_usage: {output_tokens,
|
|
24
24
|
* reasoning_output_tokens}}}}`. `last_token_usage` is per-turn (not cumulative).
|
|
25
|
-
* - Gemini: single JSON object. `{messages: [{type: 'gemini', timestamp,
|
|
26
|
-
* tokens: {output, thoughts}}]}`. Caller must pass the whole file.
|
|
27
25
|
*/
|
|
28
26
|
export function computeTokPerSec(sessionContent, agent, windowSec = DEFAULT_THROUGHPUT_WINDOW_SEC, now = Date.now()) {
|
|
29
27
|
const cutoff = now - windowSec * 1000;
|
|
30
28
|
let total = 0;
|
|
31
|
-
if (agent === 'gemini') {
|
|
32
|
-
try {
|
|
33
|
-
const d = JSON.parse(sessionContent);
|
|
34
|
-
const messages = Array.isArray(d?.messages) ? d.messages : [];
|
|
35
|
-
for (const m of messages) {
|
|
36
|
-
if (m?.type !== 'gemini')
|
|
37
|
-
continue;
|
|
38
|
-
const ts = typeof m.timestamp === 'string' ? Date.parse(m.timestamp) : 0;
|
|
39
|
-
if (!ts || ts < cutoff)
|
|
40
|
-
continue;
|
|
41
|
-
const out = typeof m?.tokens?.output === 'number' ? m.tokens.output : 0;
|
|
42
|
-
const thoughts = typeof m?.tokens?.thoughts === 'number' ? m.tokens.thoughts : 0;
|
|
43
|
-
total += out + thoughts;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
catch { /* malformed gemini file → 0 */ }
|
|
47
|
-
return total / windowSec;
|
|
48
|
-
}
|
|
49
29
|
const lines = sessionContent.split(/\r?\n/);
|
|
50
30
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
51
31
|
const line = lines[i];
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
* Session data model.
|
|
3
3
|
*
|
|
4
4
|
* Normalized types that unify the different session storage formats used by
|
|
5
|
-
* Claude (JSONL), Codex (JSONL events),
|
|
5
|
+
* Claude (JSONL), Codex (JSONL events), and OpenCode.
|
|
6
6
|
* Everything in the session pipeline -- discovery, parsing, rendering --
|
|
7
7
|
* speaks these types.
|
|
8
8
|
*/
|
|
9
9
|
/** Agents that store session data on disk and can be discovered by `agents sessions`. */
|
|
10
|
-
export type SessionAgentId = 'claude' | 'codex' | '
|
|
10
|
+
export type SessionAgentId = 'claude' | 'codex' | 'antigravity' | 'opencode' | 'openclaw' | 'rush' | 'hermes' | 'grok' | 'kimi' | 'droid' | 'cursor' | 'muse';
|
|
11
11
|
/** Effective permissions mode used to launch a managed agent session. */
|
|
12
12
|
export type SessionRunMode = 'plan' | 'edit' | 'auto' | 'skip';
|
|
13
13
|
/** All agents with session discovery support, in display order. */
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
* Session data model.
|
|
3
3
|
*
|
|
4
4
|
* Normalized types that unify the different session storage formats used by
|
|
5
|
-
* Claude (JSONL), Codex (JSONL events),
|
|
5
|
+
* Claude (JSONL), Codex (JSONL events), and OpenCode.
|
|
6
6
|
* Everything in the session pipeline -- discovery, parsing, rendering --
|
|
7
7
|
* speaks these types.
|
|
8
8
|
*/
|
|
9
9
|
/** All agents with session discovery support, in display order. */
|
|
10
|
-
export const SESSION_AGENTS = ['claude', 'codex', '
|
|
10
|
+
export const SESSION_AGENTS = ['claude', 'codex', 'antigravity', 'opencode', 'openclaw', 'rush', 'hermes', 'grok', 'kimi', 'droid', 'cursor', 'muse'];
|
|
11
11
|
/**
|
|
12
12
|
* True when `agent` stores session data `agents sessions` can discover (a member
|
|
13
13
|
* of {@link SESSION_AGENTS}). The single predicate every session-index writer
|
|
@@ -7,7 +7,66 @@ export declare function invocation(bin: string): {
|
|
|
7
7
|
command: string;
|
|
8
8
|
prefix: string[];
|
|
9
9
|
};
|
|
10
|
-
|
|
10
|
+
/** True if any 0.2.0-only filter flag is present — one case that needs the version probe. */
|
|
11
|
+
export declare function usesFilterFlags(args: string[]): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* True if the 0.2.1 point-to-one remote read flag `--host <value>` (or `--host=value`)
|
|
14
|
+
* is present — the other case that needs the version probe, gated on its own floor.
|
|
15
|
+
*/
|
|
16
|
+
export declare function usesHostFlag(args: string[]): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Whether the resolved `sessions` binary is at or above `minVersion`. A probe
|
|
19
|
+
* failure or an unparseable version reads as unsupported — the safe direction
|
|
20
|
+
* (in-repo engine handles it), never a mis-route to an old binary.
|
|
21
|
+
*/
|
|
22
|
+
export declare function sessionsBinSupports(bin: string, minVersion: string): boolean;
|
|
23
|
+
/** Whether the resolved `sessions` binary is new enough for the 0.2.0 filters. */
|
|
24
|
+
export declare function sessionsBinSupportsFilters(bin: string): boolean;
|
|
25
|
+
/** Whether the resolved `sessions` binary is new enough for the 0.2.1 `--host` flag. */
|
|
26
|
+
export declare function sessionsBinSupportsHost(bin: string): boolean;
|
|
27
|
+
export declare function isReadQuery(args: string[], opts?: {
|
|
28
|
+
filters?: boolean;
|
|
29
|
+
host?: boolean;
|
|
30
|
+
}): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Plan the rewrite of a `sessions` READ query that names EXACTLY ONE device via
|
|
33
|
+
* `--device <name>` (and no explicit `--host`) into the standalone's
|
|
34
|
+
* point-to-one remote read: the caller resolves the device to an ssh target and
|
|
35
|
+
* appends `--host ssh://<target>` to `readArgs`, forwarding it to the LOCAL
|
|
36
|
+
* standalone (which owns the ssh hop). This is the local-orchestration collapse
|
|
37
|
+
* (secrets-cli model): `sessions` owns the remote read, replacing the in-repo
|
|
38
|
+
* `--device` peer fan-out — WHEN it is safe (the caller gates on the LOCAL
|
|
39
|
+
* standalone supporting `--host`, >=0.2.1, and falls through to the in-repo
|
|
40
|
+
* fan-out if the PEER lacks the standalone).
|
|
41
|
+
*
|
|
42
|
+
* `sessions --host` is point-to-one, so ONLY a single unambiguous device may
|
|
43
|
+
* collapse; a multi-device query MUST stay on the in-repo fan-out, which parses
|
|
44
|
+
* commander's variadic `--device` correctly. Returns null (→ in-repo path,
|
|
45
|
+
* unchanged) when the query is not a single-device read:
|
|
46
|
+
* - no `--device`/`-D`, or a missing/flag-shaped value;
|
|
47
|
+
* - `--device`/`-D` appears more than once (`--device box --device mac-mini`);
|
|
48
|
+
* - the value is a fan-out sentinel `all`/`fleet` (case-insensitive);
|
|
49
|
+
* - a bare token immediately follows the value (`--device box mac-mini`) —
|
|
50
|
+
* commander's variadic would take it as a second device, so this is
|
|
51
|
+
* multi-device too;
|
|
52
|
+
* - an explicit `--host` is already on the argv — it wins, matching `secrets`'
|
|
53
|
+
* `rewriteDeviceToHost`, so we never add a second `--host`;
|
|
54
|
+
* - the remaining query (with `--device` stripped) is not a read — a lifecycle
|
|
55
|
+
* `--device` (resume/watch/inject/focus/…) keeps its in-repo/`runOnPeer`
|
|
56
|
+
* behavior exactly.
|
|
57
|
+
*
|
|
58
|
+
* Pure and argv-only: fleet resolution (device → ssh target, via
|
|
59
|
+
* `resolveRemoteDevice`) and the version gate live in the caller so this is unit
|
|
60
|
+
* testable with real inputs. `filters` mirrors the caller's version gate for the
|
|
61
|
+
* 0.2.0 filter flags (the `--device` token is not a filter flag, so it is
|
|
62
|
+
* computed identically on the original argv and on `readArgs`).
|
|
63
|
+
*/
|
|
64
|
+
export declare function planDeviceHostRead(args: string[], opts?: {
|
|
65
|
+
filters?: boolean;
|
|
66
|
+
}): {
|
|
67
|
+
device: string;
|
|
68
|
+
readArgs: string[];
|
|
69
|
+
} | null;
|
|
11
70
|
/** Test seam: drop the memoized bin so PATH fixtures can re-resolve. */
|
|
12
71
|
export declare function _resetSessionsClientForTest(): void;
|
|
13
72
|
export declare const SESSIONS_INSTALL_HINT = "npm i -g @phnx-labs/sessions-cli";
|