@dinoxx/dinox-cli 2.8.0 → 2.8.1
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.
|
@@ -7,6 +7,7 @@ import { ClientSideConnection, ndJsonStream, PROTOCOL_VERSION, } from '@agentcli
|
|
|
7
7
|
import { generateId } from '../../utils/id.js';
|
|
8
8
|
import { getPackageVersion } from '../../utils/version.js';
|
|
9
9
|
import { codexGeneratedImagesDir, codexImagesSince } from './codexImages.js';
|
|
10
|
+
import { agentLaunch } from '../spawnAgent.js';
|
|
10
11
|
const TOOL_STATUS = {
|
|
11
12
|
pending: 'pending',
|
|
12
13
|
in_progress: 'running',
|
|
@@ -278,13 +279,14 @@ export class AcpGatewayAdapter {
|
|
|
278
279
|
const command = this.gateway.command;
|
|
279
280
|
if (!command)
|
|
280
281
|
throw new Error(`Gateway ${this.gateway.name} has no ACP command`);
|
|
281
|
-
const
|
|
282
|
+
const launch = agentLaunch(command, this.gateway.args ?? [], {
|
|
282
283
|
cwd: this.gateway.cwd ?? os.homedir(),
|
|
283
284
|
env: { ...process.env, ...(this.gateway.env ?? {}) },
|
|
284
285
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
285
286
|
// The daemon runs without a visible console on Windows; keep agents that way.
|
|
286
287
|
windowsHide: true,
|
|
287
288
|
});
|
|
289
|
+
const child = spawn(launch.command, launch.args, launch.options);
|
|
288
290
|
child.stderr.on('data', (chunk) => this.log('agent stderr', { text: chunk.toString('utf8').slice(0, 2000) }));
|
|
289
291
|
const exited = new Promise((_, reject) => {
|
|
290
292
|
child.once('error', reject);
|
package/dist/gateway/detect.js
CHANGED
|
@@ -3,6 +3,7 @@ import fs from 'node:fs/promises';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { Readable, Writable } from 'node:stream';
|
|
5
5
|
import { ClientSideConnection, ndJsonStream, PROTOCOL_VERSION } from '@agentclientprotocol/sdk';
|
|
6
|
+
import { agentLaunch } from './spawnAgent.js';
|
|
6
7
|
import { getPackageVersion } from '../utils/version.js';
|
|
7
8
|
/**
|
|
8
9
|
* Known agents that speak ACP over stdio. Each lists launch variants in order;
|
|
@@ -70,7 +71,10 @@ export async function findExecutable(name, envPath = process.env.PATH ?? '') {
|
|
|
70
71
|
}
|
|
71
72
|
/** Starts the agent, runs `initialize`, and stops it. Never leaves the process running. */
|
|
72
73
|
export async function probeAcpAgent(command, args, timeoutMs = PROBE_TIMEOUT_MS) {
|
|
73
|
-
const
|
|
74
|
+
const launch = agentLaunch(command, args, { stdio: ['pipe', 'pipe', 'ignore'], env: process.env, windowsHide: true });
|
|
75
|
+
const child = spawn(launch.command, launch.args, launch.options);
|
|
76
|
+
if (!child.stdin || !child.stdout)
|
|
77
|
+
throw new Error('ACP probe stdio was not piped');
|
|
74
78
|
let timer;
|
|
75
79
|
try {
|
|
76
80
|
const exited = new Promise((_, reject) => {
|
|
@@ -97,7 +101,7 @@ export async function probeAcpAgent(command, args, timeoutMs = PROBE_TIMEOUT_MS)
|
|
|
97
101
|
}
|
|
98
102
|
finally {
|
|
99
103
|
clearTimeout(timer);
|
|
100
|
-
child.stdin
|
|
104
|
+
child.stdin?.destroy();
|
|
101
105
|
child.kill('SIGTERM');
|
|
102
106
|
}
|
|
103
107
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SpawnOptions } from 'node:child_process';
|
|
2
|
+
export type AgentLaunch = {
|
|
3
|
+
command: string;
|
|
4
|
+
args: readonly string[];
|
|
5
|
+
options: SpawnOptions;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Node's `spawn` cannot execute a Windows `.cmd` / `.bat` directly: CreateProcess
|
|
9
|
+
* returns EINVAL. npm global shims are those files (`claude-agent-acp.CMD`).
|
|
10
|
+
* Launch them through `cmd.exe /d /s /c`, with the same argument array everywhere else.
|
|
11
|
+
*/
|
|
12
|
+
export declare function agentLaunch(command: string, args: readonly string[], options: SpawnOptions, platform?: NodeJS.Platform): AgentLaunch;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const WINDOWS_BATCH = /\.(?:cmd|bat)$/i;
|
|
2
|
+
/** Characters cmd.exe would interpret if a batch path or argument reached the shell unquoted. */
|
|
3
|
+
const CMD_METACHARACTERS = /[\0\r\n"&|<>^%]/;
|
|
4
|
+
/**
|
|
5
|
+
* Node's `spawn` cannot execute a Windows `.cmd` / `.bat` directly: CreateProcess
|
|
6
|
+
* returns EINVAL. npm global shims are those files (`claude-agent-acp.CMD`).
|
|
7
|
+
* Launch them through `cmd.exe /d /s /c`, with the same argument array everywhere else.
|
|
8
|
+
*/
|
|
9
|
+
export function agentLaunch(command, args, options, platform = process.platform) {
|
|
10
|
+
if (platform !== 'win32' || !WINDOWS_BATCH.test(command)) {
|
|
11
|
+
return { command, args, options };
|
|
12
|
+
}
|
|
13
|
+
for (const part of [command, ...args]) {
|
|
14
|
+
if (CMD_METACHARACTERS.test(part)) {
|
|
15
|
+
throw new Error(`Cannot launch a Windows batch file containing shell metacharacters (${part})`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const inner = [quoteCmdArg(command), ...args.map(quoteCmdArg)].join(' ');
|
|
19
|
+
return {
|
|
20
|
+
command: process.env.ComSpec || 'cmd.exe',
|
|
21
|
+
args: ['/d', '/s', '/c', `"${inner}"`],
|
|
22
|
+
options: { ...options, windowsVerbatimArguments: true },
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** Quote one argv token for CommandLineToArgvW. Tokens without spaces stay bare. */
|
|
26
|
+
function quoteCmdArg(value) {
|
|
27
|
+
if (value.length === 0)
|
|
28
|
+
return '""';
|
|
29
|
+
if (!/[\s"]/.test(value))
|
|
30
|
+
return value;
|
|
31
|
+
return `"${value.replace(/(\\*)"/g, '$1$1\\"').replace(/(\\*)$/, '$1$1')}"`;
|
|
32
|
+
}
|