@vodmal/vdx-cli 0.31.1 → 0.31.2
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/package.json +1 -1
- package/src/ai.ts +26 -9
- package/src/index.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vodmal/vdx-cli",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.2",
|
|
4
4
|
"description": "vdx — unified lifecycle interface (up/down/build/test/check/fix) + versioned maturity audit with drift detection. Pairs with the vdx Claude Code plugin.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vdx",
|
package/src/ai.ts
CHANGED
|
@@ -292,6 +292,20 @@ export function renderSessionName(template: string, vars: Record<string, string>
|
|
|
292
292
|
return name.replace(/[.:]/g, '_');
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
+
/**
|
|
296
|
+
* The session for an agent started next to running ones: `name`, `name-2`, `name-3`… — the
|
|
297
|
+
* first no agent of the project runs in (absent, or a shell left behind). Each agent has a
|
|
298
|
+
* session of its own: tmux keeps one current window per session, and an agent started as a
|
|
299
|
+
* window next to another moved every terminal on the session to it (vdx-ai DL #36).
|
|
300
|
+
*/
|
|
301
|
+
export function freeSessionName(name: string, running: { pane: { session: string } }[]): string {
|
|
302
|
+
const busy = new Set(running.map((a) => a.pane.session));
|
|
303
|
+
for (let n = 1; ; n++) {
|
|
304
|
+
const candidate = n === 1 ? name : `${name}-${n}`;
|
|
305
|
+
if (!busy.has(candidate)) return candidate;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
295
309
|
export interface LaunchPlan {
|
|
296
310
|
projectRoot: string;
|
|
297
311
|
project: string;
|
|
@@ -804,7 +818,9 @@ function renderPlan(
|
|
|
804
818
|
plan: LaunchPlan,
|
|
805
819
|
multiplexer: Multiplexer,
|
|
806
820
|
running: AgentPane[],
|
|
807
|
-
focusedOf: (pid: number) => boolean
|
|
821
|
+
focusedOf: (pid: number) => boolean,
|
|
822
|
+
/** The session a start would make: next to running agents, one of its own. */
|
|
823
|
+
session: string,
|
|
808
824
|
): string {
|
|
809
825
|
const lines = [
|
|
810
826
|
`vdx ai — ${plan.projectRoot}`,
|
|
@@ -819,7 +835,7 @@ function renderPlan(
|
|
|
819
835
|
for (const c of plan.confirm) lines.push(` confirm: "${c.screen}" → ${c.keys.join(' ')}`);
|
|
820
836
|
lines.push(
|
|
821
837
|
multiplexer === 'tmux'
|
|
822
|
-
? ` session: tmux; a new session is named "${
|
|
838
|
+
? ` session: tmux; a new session is named "${session}"`
|
|
823
839
|
: ' session: this terminal (no tmux)',
|
|
824
840
|
);
|
|
825
841
|
if (multiplexer === 'tmux') {
|
|
@@ -1618,7 +1634,9 @@ export function runAi(opts: AiOptions, deps: AiDeps): number {
|
|
|
1618
1634
|
? foldersWarning(denied, multiplexer === 'tmux', environment.session?.folders_fix, deps.home)
|
|
1619
1635
|
: [];
|
|
1620
1636
|
if (opts.dryRun) {
|
|
1621
|
-
deps.out(
|
|
1637
|
+
deps.out(
|
|
1638
|
+
renderPlan(plan, multiplexer, running, focusedOf, freeSessionName(plan.sessionName, alongside ? running : [])),
|
|
1639
|
+
);
|
|
1622
1640
|
for (const l of choice?.lines ?? []) deps.out(` conversation: ${l}\n`);
|
|
1623
1641
|
for (const l of folders) deps.out(` ${l}\n`);
|
|
1624
1642
|
ensureAuthor(projectRoot, poolDirs, deps, true);
|
|
@@ -1758,10 +1776,9 @@ export function runAi(opts: AiOptions, deps: AiDeps): number {
|
|
|
1758
1776
|
if (opts.restart) log(`note: no running ${plan.command} in this project — starting one`);
|
|
1759
1777
|
const line = agentLine(plan, [...plan.args, ...plan.resumeArgs]);
|
|
1760
1778
|
const cmd = tmuxShellCommand(line, deps.shell);
|
|
1761
|
-
const
|
|
1762
|
-
const
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
return finish(settleResumed(plan, paneId, deps), plan.sessionName, paneId, opts, deps);
|
|
1779
|
+
const session = freeSessionName(plan.sessionName, running);
|
|
1780
|
+
const reuse = tmux.hasSession(session);
|
|
1781
|
+
const paneId = reuse ? tmux.newWindow(session, projectRoot, cmd) : tmux.newSession(session, projectRoot, cmd);
|
|
1782
|
+
log(`▶ ${session}${reuse ? ' (new window)' : ''}: ${line}`);
|
|
1783
|
+
return finish(settleResumed(plan, paneId, deps), session, paneId, opts, deps);
|
|
1767
1784
|
}
|
package/src/index.ts
CHANGED
|
@@ -83,7 +83,7 @@ the project's files). Hand a person \`vdx ai\`, not \`<agent> --<flag>\`.
|
|
|
83
83
|
@host the same command on <host> over ssh: its vdx, profile and tmux
|
|
84
84
|
--new a new conversation instead of continuing the last one; an agent
|
|
85
85
|
already running here keeps running, the new one starts next to
|
|
86
|
-
it
|
|
86
|
+
it, in a tmux session of its own (<name>-2, -3, …)
|
|
87
87
|
--focused a new conversation, as --new, in a session nothing wakes: the
|
|
88
88
|
agent, its hooks and MCP servers get VDX_FOCUSED=1 — for the
|
|
89
89
|
plugins that wake sessions to leave it alone — and the profile's
|