@phnx-labs/agents-cli 1.22.110 → 1.22.112

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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.22.112
4
+
5
+ - **Runs expand portable home paths on the executing device (PHNX-3940).** A remote resume terminal could open successfully while its child failed to start because `--cwd '$HOME'` was treated as a literal directory. The shared run path now expands `$HOME` and `~` locally, while preserving those anchors until remote dispatch reaches its target. This fixes direct runs and resumed conversations alike.
6
+
7
+ ## 1.22.111
8
+
9
+ - **Remote session resume accepts the resolver’s launch metadata (PHNX-3940).** A reachable peer’s valid session row could be rejected because it included a mode or custom harness, leaving the session undiscoverable. The reader now accepts both fields while keeping private transcript paths out of the resolver contract. Malformed responses are reported as invalid data instead of an unreachable device.
10
+
3
11
  ## 1.22.110
4
12
 
5
13
  - **Session rows are named by what YOU asked for, not by the agent's latest
@@ -6,8 +6,97 @@
6
6
  * injection, and multi-agent fallback chains for rate-limit resilience.
7
7
  */
8
8
  import { type Command } from 'commander';
9
- import type { ExecEffort } from '../lib/exec.js';
9
+ import type { ExecMode, ExecEffort } from '../lib/exec.js';
10
10
  import { RUN_AUTO_KEYWORD } from '../lib/types.js';
11
+ interface ExecCommandActionOptions {
12
+ mode: ExecMode;
13
+ effort: ExecEffort;
14
+ model?: string;
15
+ cwd?: string;
16
+ /** --project <slug>[@worktree]: resolve cwd from the projects root shorthand. */
17
+ project?: string;
18
+ addDir: string[];
19
+ env: string[];
20
+ secrets: string[];
21
+ /** Commander maps `--no-auto-secrets` to `autoSecrets` (default true, false when passed). */
22
+ autoSecrets?: boolean;
23
+ json?: boolean;
24
+ quiet?: boolean;
25
+ headless?: boolean;
26
+ interactive?: boolean;
27
+ /** --no-auth-check: Commander maps it to `authCheck` (default true, false when passed). Silences the logged-out preflight warning on an interactive launch. */
28
+ authCheck?: boolean;
29
+ /** --resume [id]: string id/prefix, or `true` for the bare flag (interactive picker). */
30
+ resume?: string | boolean;
31
+ sessionId?: string;
32
+ /** --name <slug>: durable launch handle, resolvable via `agents sessions <name>`. */
33
+ name?: string;
34
+ /** --notify: post a desktop notification when a headless run finishes. */
35
+ notify?: boolean;
36
+ /** `--no-trace-sync` → commander maps it to `traceSync` (default true, false when passed). Skips the run-exit trace auto-sync for this run (PHNX-3628). */
37
+ traceSync?: boolean;
38
+ /** --terminal [backend]: open this run in a terminal tab; `true` = auto-detect. */
39
+ terminal?: string | boolean;
40
+ verbose?: boolean;
41
+ raw?: boolean;
42
+ /** `--no-tmux` → commander sets this false (default true) to bypass the tmux wrapper. */
43
+ tmux?: boolean;
44
+ /** `--disable-tmux` → explicit alias of --no-tmux. */
45
+ disableTmux?: boolean;
46
+ timeout?: string;
47
+ fallback?: string;
48
+ balanced?: boolean;
49
+ strategy?: string;
50
+ /** Restrict selection to a named provider account discovered from live version homes. */
51
+ account?: string;
52
+ /**
53
+ * @deprecated Hidden alias for `--device auto`. Resolved before host dispatch.
54
+ * Remove after one release.
55
+ */
56
+ smart?: boolean;
57
+ acp?: boolean;
58
+ yes?: boolean;
59
+ loop?: boolean;
60
+ resumeCheckpoint?: string;
61
+ maxIterations?: string;
62
+ budget?: string;
63
+ until?: string;
64
+ interval?: string;
65
+ where?: string;
66
+ host?: string;
67
+ device?: string;
68
+ on?: string;
69
+ computer?: string;
70
+ remoteCwd?: string;
71
+ follow?: boolean;
72
+ any?: boolean;
73
+ copyCreds?: boolean;
74
+ lease?: string | boolean;
75
+ box?: string;
76
+ keepBox?: boolean;
77
+ fresh?: boolean;
78
+ reuse?: boolean;
79
+ bare?: boolean;
80
+ tailscale?: boolean;
81
+ cloud?: boolean;
82
+ provider?: string;
83
+ repo?: string[];
84
+ branch?: string;
85
+ cloudEnv?: string;
86
+ secretsKeys?: string;
87
+ allowExpired?: boolean;
88
+ emitSessionId?: boolean;
89
+ /** --broadcast: matrix-run the same prompt/task across agents × models. */
90
+ broadcast?: boolean;
91
+ /** --task <id>: house broadcast task (with --broadcast). */
92
+ task?: string;
93
+ /** --list-tasks: list broadcast tasks. */
94
+ listTasks?: boolean;
95
+ /** --results [run-id]: show saved broadcast runs. */
96
+ results?: string | true;
97
+ /** --concurrency <n>: broadcast cell parallelism. */
98
+ concurrency?: string;
99
+ }
11
100
  /** Validate a caller-supplied session id before it reaches tmux, paths, indexes, or remote dispatch. */
12
101
  export declare function parseExplicitSessionId(value: string): string;
13
102
  export interface RunPickerMarkers {
@@ -210,5 +299,21 @@ export declare function runWorkflowForEach(spec: import('../lib/workflows.js').F
210
299
  cwd: string;
211
300
  effort?: ExecEffort;
212
301
  }): Promise<number>;
302
+ /**
303
+ * The run's working directory from `--cwd` / `--project`. `--project <slug>` owns
304
+ * the directory and is mutually exclusive with `--cwd`/`--remote-cwd`; both the
305
+ * main dispatch and the `--terminal` handoff need the same answer, so the rule
306
+ * and its error live here once instead of in two places that can drift.
307
+ *
308
+ * A project that binds several directories also contributes the ones it is not
309
+ * landing in as `--add-dir` grants, so an agent on a multi-repo project can
310
+ * actually reach the sibling checkouts. Claude / Cursor / Kimi take the native
311
+ * flag; Codex folds them into workspace_roots; Grok widens its sandbox profile
312
+ * (and always injects a rules note). Other harnesses have no multi-root surface
313
+ * and ignore the grants (cwd only).
314
+ */
315
+ export declare function resolveRunCwd(options: Pick<ExecCommandActionOptions, 'cwd' | 'project' | 'remoteCwd' | 'addDir'>, opts: {
316
+ forRemote: boolean;
317
+ }): Promise<string | undefined>;
213
318
  /** Register the `agents run <agent> [prompt]` command. */
214
319
  export declare function registerRunCommand(program: Command): void;
@@ -467,9 +467,13 @@ export async function runWorkflowForEach(spec, opts) {
467
467
  * (and always injects a rules note). Other harnesses have no multi-root surface
468
468
  * and ignore the grants (cwd only).
469
469
  */
470
- async function resolveRunCwd(options, opts) {
471
- if (!options.project)
472
- return options.cwd;
470
+ export async function resolveRunCwd(options, opts) {
471
+ if (!options.project) {
472
+ if (!options.cwd || opts.forRemote)
473
+ return options.cwd;
474
+ const { expandLocalHome } = await import('../lib/project-root.js');
475
+ return expandLocalHome(options.cwd);
476
+ }
473
477
  if (options.cwd || options.remoteCwd) {
474
478
  console.error(chalk.red('Pass --project alone — not with --cwd or --remote-cwd.'));
475
479
  process.exit(1);
@@ -1614,13 +1618,9 @@ agents run auto --device yosemite-s0 "fix the flaky test" # pin the device
1614
1618
  const { armRunFinishTraceSync } = await import('../lib/run-trace-sync.js');
1615
1619
  armRunFinishTraceSync({ disabled: options.traceSync === false });
1616
1620
  }
1617
- // --project <slug>[@worktree]: resolve the projects-root shorthand into a
1618
- // cwd. On a host run it resolves home-relative (`~/…`, so the host expands
1619
- // it); locally it becomes an absolute path. It owns the working directory,
1620
- // so it is mutually exclusive with both --cwd and --remote-cwd.
1621
- if (options.project) {
1622
- options.cwd = await resolveRunCwd(options, { forRemote: hostGiven.length > 0 });
1623
- }
1621
+ // Home anchors belong to the executing host; preserve them until a remote
1622
+ // invocation reaches its local execution path.
1623
+ options.cwd = await resolveRunCwd(options, { forRemote: hostGiven.length > 0 });
1624
1624
  if (hostGiven.length > 0) {
1625
1625
  if (new Set(hostGiven).size > 1) {
1626
1626
  console.error(chalk.red('Conflicting --device values values — pass just one.'));
@@ -170,7 +170,7 @@ export async function gatherRemoteAgentsJson(options, deps = {}) {
170
170
  if (!cancelled) {
171
171
  parseFailed.push(target.name);
172
172
  if (!options.quiet) {
173
- process.stderr.write(chalk.gray(` ${target.name}: unreachable or no agents CLI — skipped\n`));
173
+ process.stderr.write(chalk.gray(` ${target.name}: invalid response data — skipped\n`));
174
174
  }
175
175
  }
176
176
  return [];
@@ -95,7 +95,7 @@ export function parseRemoteList(stdout, machine) {
95
95
  * malformed/non-array JSON is an incomplete source, not an empty machine. */
96
96
  const SAFE_RESOLVER_KEYS = new Set([
97
97
  'id', 'shortId', 'agent', 'origin', 'timestamp', 'lastActivity', 'project',
98
- 'version', 'label', 'topic', 'machine',
98
+ 'version', 'harness', 'mode', 'label', 'topic', 'machine',
99
99
  ]);
100
100
  function isSafeResolverRow(value) {
101
101
  if (typeof value.id !== 'string' || typeof value.shortId !== 'string'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phnx-labs/agents-cli",
3
- "version": "1.22.110",
3
+ "version": "1.22.112",
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",