@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.
Files changed (271) hide show
  1. package/CHANGELOG.md +301 -0
  2. package/dist/bootstrap.js +4 -11
  3. package/dist/commands/accounts.js +7 -4
  4. package/dist/commands/browser.d.ts +52 -70
  5. package/dist/commands/browser.js +192 -3562
  6. package/dist/commands/daemon.d.ts +39 -2
  7. package/dist/commands/daemon.js +72 -73
  8. package/dist/commands/events.js +1 -1
  9. package/dist/commands/exec.js +53 -1
  10. package/dist/commands/projects.js +92 -7
  11. package/dist/commands/repo.js +13 -49
  12. package/dist/commands/route.js +5 -5
  13. package/dist/commands/routines.js +39 -12
  14. package/dist/commands/sessions-render.d.ts +1 -1
  15. package/dist/commands/sessions-render.js +0 -1
  16. package/dist/commands/sessions.test-fixture.d.ts +0 -1
  17. package/dist/commands/sessions.test-fixture.js +0 -37
  18. package/dist/commands/setup-browser.d.ts +17 -12
  19. package/dist/commands/setup-browser.js +52 -87
  20. package/dist/commands/setup-preferences.d.ts +0 -17
  21. package/dist/commands/setup-preferences.js +18 -49
  22. package/dist/commands/setup.js +9 -9
  23. package/dist/commands/ssh.js +10 -1
  24. package/dist/commands/sync.js +6 -44
  25. package/dist/commands/teams.js +0 -1
  26. package/dist/commands/update.d.ts +19 -0
  27. package/dist/commands/update.js +34 -6
  28. package/dist/commands/view.d.ts +12 -1
  29. package/dist/commands/view.js +47 -2
  30. package/dist/index.js +107 -26
  31. package/dist/lib/account-capabilities.js +0 -2
  32. package/dist/lib/account-catalog.d.ts +38 -0
  33. package/dist/lib/account-catalog.js +110 -26
  34. package/dist/lib/account-provider-registry.js +1 -1
  35. package/dist/lib/account-registry.d.ts +1 -1
  36. package/dist/lib/account-registry.js +36 -2
  37. package/dist/lib/accounting/rotate.js +22 -8
  38. package/dist/lib/accounting/usage-ingest.d.ts +6 -1
  39. package/dist/lib/accounting/usage-ingest.js +115 -45
  40. package/dist/lib/accounting/usage-sync.d.ts +134 -31
  41. package/dist/lib/accounting/usage-sync.js +227 -66
  42. package/dist/lib/accounting/usage.d.ts +16 -3
  43. package/dist/lib/accounting/usage.js +26 -8
  44. package/dist/lib/accounts/add.d.ts +3 -1
  45. package/dist/lib/accounts/add.js +24 -13
  46. package/dist/lib/accounts/slots.d.ts +8 -0
  47. package/dist/lib/accounts/slots.js +17 -0
  48. package/dist/lib/add-dir.js +0 -1
  49. package/dist/lib/agent-cli-commands.js +0 -1
  50. package/dist/lib/agent-spec/agents.d.ts +6 -7
  51. package/dist/lib/agent-spec/agents.js +7 -60
  52. package/dist/lib/auth-health.d.ts +69 -1
  53. package/dist/lib/auth-health.js +133 -4
  54. package/dist/lib/browser/context.d.ts +82 -0
  55. package/dist/lib/browser/context.js +88 -0
  56. package/dist/lib/browser/paths.d.ts +25 -0
  57. package/dist/lib/browser/paths.js +51 -0
  58. package/dist/lib/browser/record.d.ts +38 -0
  59. package/dist/lib/browser/record.js +57 -0
  60. package/dist/lib/browser/sessions-list.js +1 -2
  61. package/dist/lib/browser-client.d.ts +158 -0
  62. package/dist/lib/browser-client.js +234 -0
  63. package/dist/lib/channels/owner-sink.d.ts +1 -18
  64. package/dist/lib/channels/owner-sink.js +29 -82
  65. package/dist/lib/channels/providers/rush.d.ts +7 -7
  66. package/dist/lib/channels/providers/rush.js +127 -57
  67. package/dist/lib/claude-account-token.d.ts +7 -1
  68. package/dist/lib/claude-account-token.js +26 -4
  69. package/dist/lib/claude-statusline.d.ts +1 -1
  70. package/dist/lib/claude-statusline.js +15 -3
  71. package/dist/lib/commands.js +1 -1
  72. package/dist/lib/crabbox/lease.js +1 -1
  73. package/dist/lib/crabbox/runtimes.js +1 -3
  74. package/dist/lib/daemon/account-state-daemon-service.js +1 -0
  75. package/dist/lib/daemon/auth-sync-service.d.ts +21 -18
  76. package/dist/lib/daemon/auth-sync-service.js +37 -43
  77. package/dist/lib/daemon/daemon.d.ts +25 -14
  78. package/dist/lib/daemon/daemon.js +92 -154
  79. package/dist/lib/daemon/runner.d.ts +2 -2
  80. package/dist/lib/daemon/runner.js +32 -9
  81. package/dist/lib/daemon/self-update-service.d.ts +35 -34
  82. package/dist/lib/daemon/self-update-service.js +40 -36
  83. package/dist/lib/daemon/service.d.ts +12 -8
  84. package/dist/lib/daemon/supervisor.d.ts +65 -54
  85. package/dist/lib/daemon/supervisor.js +136 -171
  86. package/dist/lib/daemon/testdata/process-view-start.js +5 -2
  87. package/dist/lib/daemon/usage-sync-service.d.ts +21 -30
  88. package/dist/lib/daemon/usage-sync-service.js +46 -78
  89. package/dist/lib/daemon-health.d.ts +22 -5
  90. package/dist/lib/daemon-health.js +47 -3
  91. package/dist/lib/daemon-services.d.ts +1 -1
  92. package/dist/lib/daemon-services.js +0 -10
  93. package/dist/lib/daemon-ticks.js +4 -2
  94. package/dist/lib/devices/doctor-findings.js +8 -11
  95. package/dist/lib/devices/harness-inventory.js +14 -5
  96. package/dist/lib/exec-account-home.js +5 -0
  97. package/dist/lib/exec.js +10 -13
  98. package/dist/lib/feed/events.js +0 -1
  99. package/dist/lib/feed/tool-activity.js +5 -2
  100. package/dist/lib/fleet-shared-state.d.ts +45 -0
  101. package/dist/lib/fleet-shared-state.js +78 -9
  102. package/dist/lib/fs-atomic.js +25 -0
  103. package/dist/lib/github/pr-mergeable.d.ts +4 -2
  104. package/dist/lib/github/pr-mergeable.js +5 -3
  105. package/dist/lib/github/project-prs.d.ts +58 -3
  106. package/dist/lib/github/project-prs.js +205 -7
  107. package/dist/lib/harness/adapters/cursor.js +14 -4
  108. package/dist/lib/harness-auth-capabilities.d.ts +4 -3
  109. package/dist/lib/harness-auth-capabilities.js +1 -2
  110. package/dist/lib/helper-versions.js +1 -1
  111. package/dist/lib/hooks/cache.d.ts +7 -0
  112. package/dist/lib/hooks/cache.js +27 -2
  113. package/dist/lib/hooks/install.js +7 -1
  114. package/dist/lib/hosts/ready.d.ts +38 -8
  115. package/dist/lib/hosts/ready.js +62 -14
  116. package/dist/lib/installations/active-check.d.ts +27 -0
  117. package/dist/lib/installations/active-check.js +61 -0
  118. package/dist/lib/installations/migrate.js +6 -3
  119. package/dist/lib/installations/shims.d.ts +1 -1
  120. package/dist/lib/installations/shims.js +32 -12
  121. package/dist/lib/installations/store.d.ts +9 -0
  122. package/dist/lib/installations/store.js +24 -0
  123. package/dist/lib/installations/update.js +21 -15
  124. package/dist/lib/installations/versions.js +15 -3
  125. package/dist/lib/manifest.js +1 -1
  126. package/dist/lib/models.js +0 -2
  127. package/dist/lib/open-url.js +28 -54
  128. package/dist/lib/profiles.js +0 -2
  129. package/dist/lib/projects.d.ts +16 -0
  130. package/dist/lib/projects.js +31 -0
  131. package/dist/lib/refresh.js +1 -1
  132. package/dist/lib/routine-readiness.d.ts +35 -0
  133. package/dist/lib/routine-readiness.js +74 -16
  134. package/dist/lib/rules/compile.js +6 -0
  135. package/dist/lib/sandbox.js +0 -2
  136. package/dist/lib/secrets-policy.d.ts +89 -11
  137. package/dist/lib/secrets-policy.js +175 -28
  138. package/dist/lib/session/active.d.ts +17 -6
  139. package/dist/lib/session/active.js +105 -49
  140. package/dist/lib/session/db.d.ts +1 -1
  141. package/dist/lib/session/db.js +65 -18
  142. package/dist/lib/session/discover.js +1 -283
  143. package/dist/lib/session/mirror.d.ts +4 -3
  144. package/dist/lib/session/mirror.js +4 -3
  145. package/dist/lib/session/parse.d.ts +0 -2
  146. package/dist/lib/session/parse.js +1 -138
  147. package/dist/lib/session/pid-registry.d.ts +6 -3
  148. package/dist/lib/session/pid-registry.js +18 -8
  149. package/dist/lib/session/remote/watch.d.ts +1 -1
  150. package/dist/lib/session/remote/watch.js +7 -3
  151. package/dist/lib/session/throughput.d.ts +1 -3
  152. package/dist/lib/session/throughput.js +0 -20
  153. package/dist/lib/session/types.d.ts +2 -2
  154. package/dist/lib/session/types.js +2 -2
  155. package/dist/lib/sessions-client.d.ts +60 -1
  156. package/dist/lib/sessions-client.js +227 -4
  157. package/dist/lib/setup-tool-status.js +5 -10
  158. package/dist/lib/signin-badge.d.ts +3 -2
  159. package/dist/lib/signin-badge.js +6 -3
  160. package/dist/lib/smart-launch.js +4 -1
  161. package/dist/lib/staleness/detectors/commands.d.ts +1 -1
  162. package/dist/lib/staleness/detectors/hooks.d.ts +1 -1
  163. package/dist/lib/staleness/detectors/mcp.d.ts +1 -1
  164. package/dist/lib/staleness/detectors/permissions.d.ts +1 -1
  165. package/dist/lib/staleness/detectors/plugins.d.ts +1 -1
  166. package/dist/lib/staleness/detectors/rules.d.ts +1 -1
  167. package/dist/lib/staleness/detectors/skills.d.ts +1 -1
  168. package/dist/lib/staleness/detectors/subagents.d.ts +1 -1
  169. package/dist/lib/staleness/detectors/workflows.d.ts +1 -1
  170. package/dist/lib/staleness/writers/commands.d.ts +1 -1
  171. package/dist/lib/staleness/writers/hooks.d.ts +1 -1
  172. package/dist/lib/staleness/writers/mcp.d.ts +1 -1
  173. package/dist/lib/staleness/writers/permissions.d.ts +1 -1
  174. package/dist/lib/staleness/writers/plugins.d.ts +1 -1
  175. package/dist/lib/staleness/writers/rules.d.ts +1 -1
  176. package/dist/lib/staleness/writers/skills.d.ts +1 -1
  177. package/dist/lib/staleness/writers/sources.js +5 -0
  178. package/dist/lib/staleness/writers/subagents.d.ts +1 -1
  179. package/dist/lib/staleness/writers/workflows.d.ts +1 -1
  180. package/dist/lib/state.d.ts +6 -4
  181. package/dist/lib/state.js +7 -17
  182. package/dist/lib/teams/parsers.d.ts +1 -1
  183. package/dist/lib/teams/parsers.js +1 -136
  184. package/dist/lib/teams/placement-probe.js +50 -15
  185. package/dist/lib/teams/scheduler.d.ts +7 -0
  186. package/dist/lib/types.d.ts +16 -1
  187. package/dist/lib/types.js +1 -1
  188. package/dist/lib/view-types.d.ts +32 -0
  189. package/dist/lib/watchdog/read.js +0 -1
  190. package/dist/lib/watchdog/rotate.js +1 -2
  191. package/dist/lib/watchdog/runner.js +2 -2
  192. package/dist/lib/watchdog/watchdog.d.ts +1 -1
  193. package/dist/lib/watchdog/watchdogTail.js +0 -31
  194. package/package.json +1 -1
  195. package/scripts/postinstall.js +8 -8
  196. package/dist/browser.d.ts +0 -2
  197. package/dist/browser.js +0 -17
  198. package/dist/commands/browser-picker.d.ts +0 -18
  199. package/dist/commands/browser-picker.js +0 -97
  200. package/dist/lib/browser/arc-discovery.d.ts +0 -52
  201. package/dist/lib/browser/arc-discovery.js +0 -197
  202. package/dist/lib/browser/arc-dom.d.ts +0 -14
  203. package/dist/lib/browser/arc-dom.js +0 -121
  204. package/dist/lib/browser/caller-identity.d.ts +0 -40
  205. package/dist/lib/browser/caller-identity.js +0 -175
  206. package/dist/lib/browser/cdp.d.ts +0 -51
  207. package/dist/lib/browser/cdp.js +0 -254
  208. package/dist/lib/browser/chrome.d.ts +0 -141
  209. package/dist/lib/browser/chrome.js +0 -704
  210. package/dist/lib/browser/chromium-discovery.d.ts +0 -28
  211. package/dist/lib/browser/chromium-discovery.js +0 -96
  212. package/dist/lib/browser/devices.d.ts +0 -34
  213. package/dist/lib/browser/devices.js +0 -61
  214. package/dist/lib/browser/domain-skills.d.ts +0 -71
  215. package/dist/lib/browser/domain-skills.js +0 -195
  216. package/dist/lib/browser/drivers/arc.d.ts +0 -40
  217. package/dist/lib/browser/drivers/arc.js +0 -276
  218. package/dist/lib/browser/drivers/firefox.d.ts +0 -99
  219. package/dist/lib/browser/drivers/firefox.js +0 -377
  220. package/dist/lib/browser/drivers/local.d.ts +0 -55
  221. package/dist/lib/browser/drivers/local.js +0 -266
  222. package/dist/lib/browser/drivers/ssh.d.ts +0 -120
  223. package/dist/lib/browser/drivers/ssh.js +0 -467
  224. package/dist/lib/browser/editor.d.ts +0 -3
  225. package/dist/lib/browser/editor.js +0 -50
  226. package/dist/lib/browser/ffmpeg.d.ts +0 -12
  227. package/dist/lib/browser/ffmpeg.js +0 -184
  228. package/dist/lib/browser/firefox-discovery.d.ts +0 -69
  229. package/dist/lib/browser/firefox-discovery.js +0 -162
  230. package/dist/lib/browser/har.d.ts +0 -85
  231. package/dist/lib/browser/har.js +0 -77
  232. package/dist/lib/browser/hygiene.d.ts +0 -97
  233. package/dist/lib/browser/hygiene.js +0 -153
  234. package/dist/lib/browser/index.d.ts +0 -5
  235. package/dist/lib/browser/index.js +0 -5
  236. package/dist/lib/browser/input.d.ts +0 -7
  237. package/dist/lib/browser/input.js +0 -92
  238. package/dist/lib/browser/ipc.d.ts +0 -204
  239. package/dist/lib/browser/ipc.js +0 -1453
  240. package/dist/lib/browser/login-detection.d.ts +0 -87
  241. package/dist/lib/browser/login-detection.js +0 -274
  242. package/dist/lib/browser/profiles.d.ts +0 -422
  243. package/dist/lib/browser/profiles.js +0 -1157
  244. package/dist/lib/browser/refs.d.ts +0 -89
  245. package/dist/lib/browser/refs.js +0 -191
  246. package/dist/lib/browser/registry.d.ts +0 -70
  247. package/dist/lib/browser/registry.js +0 -252
  248. package/dist/lib/browser/remote-control.d.ts +0 -59
  249. package/dist/lib/browser/remote-control.js +0 -85
  250. package/dist/lib/browser/resolve-target.d.ts +0 -66
  251. package/dist/lib/browser/resolve-target.js +0 -264
  252. package/dist/lib/browser/runtime-state.d.ts +0 -291
  253. package/dist/lib/browser/runtime-state.js +0 -584
  254. package/dist/lib/browser/secret-ref.d.ts +0 -10
  255. package/dist/lib/browser/secret-ref.js +0 -14
  256. package/dist/lib/browser/service.d.ts +0 -812
  257. package/dist/lib/browser/service.js +0 -4693
  258. package/dist/lib/browser/stream.d.ts +0 -17
  259. package/dist/lib/browser/stream.js +0 -72
  260. package/dist/lib/browser/task-index.d.ts +0 -78
  261. package/dist/lib/browser/task-index.js +0 -199
  262. package/dist/lib/browser/types.d.ts +0 -647
  263. package/dist/lib/browser/types.js +0 -61
  264. package/dist/lib/browser/upload.d.ts +0 -29
  265. package/dist/lib/browser/upload.js +0 -298
  266. package/dist/lib/daemon/browser-ipc-service.d.ts +0 -20
  267. package/dist/lib/daemon/browser-ipc-service.js +0 -46
  268. package/dist/lib/daemon/browser-task-reap-service.d.ts +0 -14
  269. package/dist/lib/daemon/browser-task-reap-service.js +0 -26
  270. package/dist/lib/fleet-shared-repo-sync.d.ts +0 -55
  271. 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, so
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
- export declare function readLivePidSessionEntry(pid: number): PidSessionEntry | undefined;
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 start && entry.processIdentity?.startTime ? start === entry.processIdentity.startTime : undefined;
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
- export function readLivePidSessionEntry(pid) {
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 = start ? Date.parse(start) : NaN;
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' | 'gemini';
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), Gemini (single JSON), and OpenCode.
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' | 'gemini' | 'antigravity' | 'opencode' | 'openclaw' | 'rush' | 'hermes' | 'grok' | 'kimi' | 'droid' | 'cursor' | 'muse';
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), Gemini (single JSON), and OpenCode.
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', 'gemini', 'antigravity', 'opencode', 'openclaw', 'rush', 'hermes', 'grok', 'kimi', 'droid', 'cursor', 'muse'];
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
- export declare function isReadQuery(args: string[]): boolean;
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";