@phnx-labs/agents-cli 1.22.92 → 1.22.94

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 (55) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +5 -0
  3. package/dist/commands/browser.d.ts +1 -0
  4. package/dist/commands/browser.js +145 -11
  5. package/dist/lib/browser/arc-discovery.d.ts +60 -0
  6. package/dist/lib/browser/arc-discovery.js +187 -0
  7. package/dist/lib/browser/arc-dom.d.ts +14 -0
  8. package/dist/lib/browser/arc-dom.js +121 -0
  9. package/dist/lib/browser/drivers/arc.d.ts +57 -0
  10. package/dist/lib/browser/drivers/arc.js +281 -0
  11. package/dist/lib/browser/profiles.d.ts +5 -1
  12. package/dist/lib/browser/profiles.js +94 -9
  13. package/dist/lib/browser/refs.d.ts +2 -0
  14. package/dist/lib/browser/refs.js +2 -1
  15. package/dist/lib/browser/resolve-target.d.ts +2 -0
  16. package/dist/lib/browser/resolve-target.js +8 -0
  17. package/dist/lib/browser/runtime-state.js +9 -1
  18. package/dist/lib/browser/service.d.ts +37 -3
  19. package/dist/lib/browser/service.js +571 -41
  20. package/dist/lib/browser/types.d.ts +55 -1
  21. package/dist/lib/claude-account-token.d.ts +13 -0
  22. package/dist/lib/claude-account-token.js +29 -0
  23. package/dist/lib/daemon/attention-notify-service.d.ts +5 -2
  24. package/dist/lib/daemon/attention-notify-service.js +9 -2
  25. package/dist/lib/exec.js +11 -0
  26. package/dist/lib/feed/answer.js +9 -0
  27. package/dist/lib/feed/attention.d.ts +18 -2
  28. package/dist/lib/feed/attention.js +0 -0
  29. package/dist/lib/feed/feed.d.ts +6 -2
  30. package/dist/lib/feed/feed.js +10 -4
  31. package/dist/lib/harness/adapter.d.ts +23 -0
  32. package/dist/lib/harness/adapter.js +29 -0
  33. package/dist/lib/harness/adapters/claude.js +5 -3
  34. package/dist/lib/harness/adapters/copilot.js +4 -2
  35. package/dist/lib/harness/adapters/grok.js +4 -2
  36. package/dist/lib/harness/adapters/kimi.js +4 -2
  37. package/dist/lib/harness/adapters/muse.js +4 -3
  38. package/dist/lib/harness/adapters/opencode.js +4 -2
  39. package/dist/lib/helper-download.js +1 -1
  40. package/dist/lib/helper-versions.js +1 -1
  41. package/dist/lib/installations/shims.d.ts +2 -2
  42. package/dist/lib/installations/shims.js +16 -8
  43. package/dist/lib/menubar/download-menubar.js +4 -1
  44. package/dist/lib/menubar/install-menubar.d.ts +10 -9
  45. package/dist/lib/menubar/install-menubar.js +17 -15
  46. package/dist/lib/secrets-policy.d.ts +5 -2
  47. package/dist/lib/secrets-policy.js +18 -4
  48. package/dist/lib/session/active.d.ts +18 -11
  49. package/dist/lib/session/active.js +52 -44
  50. package/dist/lib/session/session-cache.d.ts +1 -1
  51. package/dist/lib/session/session-cache.js +1 -0
  52. package/dist/lib/session/state.d.ts +26 -0
  53. package/dist/lib/session/state.js +43 -27
  54. package/dist/lib/types.d.ts +7 -0
  55. package/package.json +1 -1
@@ -399,10 +399,10 @@ export function structuredQuestionFromAsk(args) {
399
399
  return { text, reason: 'question', options: options.length ? options : undefined };
400
400
  }
401
401
  /**
402
- * Canonical approve/deny choices for an interactive prompt that carries no
403
- * agent-supplied option list: Claude's plan-review and permission dialogs. Approve
404
- * is reliably option 1; deny/keep-planning maps to ESC, which cancels the prompt in
405
- * every variant (2- or 3-option) — safer than guessing a digit that could differ.
402
+ * Canonical approve/send-back choices for Claude's plan-review dialog, which
403
+ * carries no agent-supplied option list. Approve is reliably option 1; keep-planning
404
+ * maps to ESC, which cancels the prompt in every variant (2- or 3-option) — safer
405
+ * than guessing a digit that could differ.
406
406
  */
407
407
  function planReviewQuestion() {
408
408
  return {
@@ -414,15 +414,22 @@ function planReviewQuestion() {
414
414
  ],
415
415
  };
416
416
  }
417
- function permissionQuestion(preview) {
418
- return {
419
- text: preview ? `Permission — ${preview}` : 'Waiting on a permission prompt',
420
- reason: 'permission',
421
- options: [
422
- { label: 'Approve', key: '1' },
423
- { label: 'Deny', key: 'esc' },
424
- ],
425
- };
417
+ /**
418
+ * The harness's own stamp on an event, as ms — or undefined when the event carries
419
+ * none. A stamp LATER than the file's last write cannot have come from the
420
+ * transcript (a parser that finds no stamp fills the field with its own parse
421
+ * time), so it is rejected rather than read as "just happened": the mtime is the
422
+ * physical upper bound on when any transcript line was written.
423
+ */
424
+ function eventStampMs(e, mtimeMs) {
425
+ if (!e?.timestamp)
426
+ return undefined;
427
+ const ms = Date.parse(e.timestamp);
428
+ if (!Number.isFinite(ms))
429
+ return undefined;
430
+ if (mtimeMs != null && ms > mtimeMs)
431
+ return undefined;
432
+ return ms;
426
433
  }
427
434
  /** Does an assistant message read as a question directed at the user? */
428
435
  function looksLikeQuestion(text) {
@@ -461,7 +468,8 @@ function lastOf(events, pred) {
461
468
  */
462
469
  export function inferActivity(events, ctx = {}) {
463
470
  const windowMs = ctx.activeWindowMs ?? ACTIVE_WINDOW_MS;
464
- const fresh = ctx.mtimeMs != null && Date.now() - ctx.mtimeMs < windowMs;
471
+ const nowMs = ctx.nowMs ?? Date.now();
472
+ const fresh = ctx.mtimeMs != null && nowMs - ctx.mtimeMs < windowMs;
465
473
  // A non-live process (pidAlive === false) can never be "working"; the strongest
466
474
  // it gets is "waiting on you" (a dangling question) or "idle".
467
475
  const canWork = ctx.pidAlive !== false && (ctx.pidAlive === true || fresh);
@@ -494,6 +502,7 @@ export function inferActivity(events, ctx = {}) {
494
502
  lastRole: lastMsg?.role,
495
503
  lastEventKind: last?.type,
496
504
  lastActivityMs: ctx.mtimeMs,
505
+ lastEventMs: eventStampMs(last, ctx.mtimeMs),
497
506
  preview: previewSource ? describeEvent(previewSource) : undefined,
498
507
  todos,
499
508
  tail: tail.length ? tail : undefined,
@@ -514,14 +523,17 @@ export function inferActivity(events, ctx = {}) {
514
523
  const question = structuredQuestionFromAsk(lastPlanOrAsk.args) ?? { text: 'Asked you a question', reason: 'question' };
515
524
  return { ...base, activity: 'waiting_input', awaitingReason: 'question', preview: question.text, question };
516
525
  }
517
- // Pending tool call (tool_use with no following tool_result): mid-turn.
526
+ // Pending tool call (tool_use with no following tool_result): the call is in
527
+ // flight for as long as the process is alive. A command that has run for ten
528
+ // minutes and a permission dialog that has sat for ten minutes leave the SAME
529
+ // transcript — a tool_use with no result and a quiet file — so elapsed time is
530
+ // not evidence of a request, and this engine never labels one `permission`
531
+ // (PHNX-3999: the "is the user idle?" reminder and the two-minute mark were both
532
+ // being rendered with Approve/Deny). The harness's own `permission_prompt` hook
533
+ // event, carried by the feed block, is the only evidence a dialog is up; the
534
+ // attention reconciler confirms it against `lastEventMs`.
518
535
  if (last.type === 'tool_use') {
519
- if (canWork && fresh)
520
- return { ...base, activity: 'working' };
521
- // Alive but the file hasn't moved — likely blocked on a permission prompt.
522
- if (ctx.pidAlive)
523
- return { ...base, activity: 'waiting_input', awaitingReason: 'permission', question: permissionQuestion(base.preview) };
524
- return { ...base, activity: 'idle' };
536
+ return { ...base, activity: canWork ? 'working' : 'idle' };
525
537
  }
526
538
  // Thinking or a tool result just landed → agent is mid-turn if recently active.
527
539
  if (last.type === 'thinking' || last.type === 'tool_result' || last.type === 'error') {
@@ -537,12 +549,16 @@ export function inferActivity(events, ctx = {}) {
537
549
  // A prose question takes a free-text reply (no select-list), so no options/keys.
538
550
  // Unlike the structural plan/ask signals above, the prose heuristic DECAYS: a
539
551
  // question nobody answered within PROSE_QUESTION_FRESH_MS is a session that
540
- // ended, not one that needs you (RUSH-1522). A prose "?" is only "waiting on
541
- // you" while the file is DEMONSTRABLY fresh — with no mtime signal at all we
542
- // cannot assert freshness, so the heuristic must not fire (an unknown-age
543
- // prose question is a session that ended, closing RUSH-1522's null-mtime hole
544
- // where a null mtime kept the question forever).
545
- const questionFresh = ctx.mtimeMs != null && Date.now() - ctx.mtimeMs < PROSE_QUESTION_FRESH_MS;
552
+ // ended, not one that needs you (RUSH-1522). The question's age is the
553
+ // assistant message's own stamp when the harness wrote one — the exact moment
554
+ // it was asked — and the file's last write when it did not; the age is measured
555
+ // against `ctx.nowMs`, never a clock frozen at parse time, so the verdict
556
+ // expires on schedule even while the bytes sit still (PHNX-3999). With no age
557
+ // evidence at all the heuristic must not fire (an unknown-age prose question is
558
+ // a session that ended, closing RUSH-1522's null-mtime hole where a null mtime
559
+ // kept the question forever).
560
+ const askedAtMs = eventStampMs(last, ctx.mtimeMs) ?? ctx.mtimeMs;
561
+ const questionFresh = askedAtMs != null && nowMs - askedAtMs < PROSE_QUESTION_FRESH_MS;
546
562
  if (questionFresh && looksLikeQuestion(last.content ?? '')) {
547
563
  const text = oneLine(last.content ?? '');
548
564
  return { ...base, activity: 'waiting_input', awaitingReason: 'question', question: { text, reason: 'question' } };
@@ -1303,6 +1303,13 @@ export interface BrowserProfileConfig {
1303
1303
  logDir?: string;
1304
1304
  /** Optional SSH host where logDir lives, e.g. "user@remote-host". */
1305
1305
  logHost?: string;
1306
+ /** Stable native identity for an Arc Space profile; display names are never addresses. */
1307
+ arc?: {
1308
+ profileId: string;
1309
+ profileName: string;
1310
+ spaceId: string;
1311
+ spaceTitle: string;
1312
+ };
1306
1313
  }
1307
1314
  /** Options controlling which agents and resources are synced during `agents sync` / `agents use`. */
1308
1315
  export interface SyncOptions {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phnx-labs/agents-cli",
3
- "version": "1.22.92",
3
+ "version": "1.22.94",
4
4
  "description": "One CLI for all your AI coding agents - versions, config, cloud dispatch, sessions, and teams (now with first-class Grok Build CLI support)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",