@swmansion/argent 0.26.1-next.9 → 0.27.1-next.0
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/bin/darwin/simulator-server +0 -0
- package/bin/linux/simulator-server +0 -0
- package/bin/linux-arm64/simulator-server +0 -0
- package/bin/win32/simulator-server.exe +0 -0
- package/dist/cli-cmds.mjs +76 -32
- package/dist/client.d.ts +52 -0
- package/dist/client.js +2417 -0
- package/dist/installer.mjs +27 -13
- package/dist/mcp-server.mjs +39 -17
- package/dist/tool-server.cjs +30 -10
- package/package.json +27 -1
- package/skills/argent-device-interact/SKILL.md +1 -1
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/cli-cmds.mjs
CHANGED
|
@@ -1675,7 +1675,9 @@ function spawnToolsServer(paths, port, options = {}) {
|
|
|
1675
1675
|
} catch {
|
|
1676
1676
|
logFd = fs.openSync("/dev/null", "w");
|
|
1677
1677
|
}
|
|
1678
|
-
const
|
|
1678
|
+
const { bun, deno, electron } = process.versions;
|
|
1679
|
+
const nodeBin = !(bun || deno || electron) && fs.existsSync(process.execPath) ? process.execPath : "node";
|
|
1680
|
+
const child = spawn(nodeBin, [paths.bundlePath, "start"], {
|
|
1679
1681
|
detached: true,
|
|
1680
1682
|
stdio: ["ignore", "pipe", logFd],
|
|
1681
1683
|
env: buildToolsServerEnv(paths, port, process.env, options)
|
|
@@ -1683,7 +1685,14 @@ function spawnToolsServer(paths, port, options = {}) {
|
|
|
1683
1685
|
child.unref();
|
|
1684
1686
|
const pid = child.pid;
|
|
1685
1687
|
if (!pid) {
|
|
1686
|
-
|
|
1688
|
+
child.once(
|
|
1689
|
+
"error",
|
|
1690
|
+
(err) => reject(
|
|
1691
|
+
new Error(
|
|
1692
|
+
err.code === "ENOENT" && nodeBin === "node" ? "Could not start the argent tool-server: `node` was not found on PATH. Install Node.js 20+ or add it to PATH." : `Could not start the argent tool-server: ${err.message}`
|
|
1693
|
+
)
|
|
1694
|
+
)
|
|
1695
|
+
);
|
|
1687
1696
|
return;
|
|
1688
1697
|
}
|
|
1689
1698
|
let settled = false;
|
|
@@ -1847,14 +1856,20 @@ async function terminatePid(pid, stillOurs) {
|
|
|
1847
1856
|
}
|
|
1848
1857
|
async function killToolServer(bundlePath) {
|
|
1849
1858
|
const state2 = await readState(bundlePath);
|
|
1850
|
-
if (!state2) return;
|
|
1851
|
-
|
|
1859
|
+
if (!state2) return false;
|
|
1860
|
+
const stillOurs = () => couldBeOurToolServer(state2.pid, state2.bundlePath);
|
|
1861
|
+
const alive = isProcessAlive(state2.pid);
|
|
1862
|
+
if (alive && !stillOurs()) return false;
|
|
1863
|
+
if (alive) await terminatePid(state2.pid, stillOurs);
|
|
1852
1864
|
await clearToolsServerState(bundlePath ?? state2.bundlePath);
|
|
1865
|
+
return alive;
|
|
1853
1866
|
}
|
|
1854
1867
|
var PS_BIN = ["/bin/ps", "/usr/bin/ps"].find((p) => fs.existsSync(p)) ?? "ps";
|
|
1855
1868
|
var PS_WIDTH_FLAGS = ["-ww"];
|
|
1856
|
-
|
|
1869
|
+
var PS_LOCALE = process.platform === "darwin" ? "en_US.UTF-8" : "C.UTF-8";
|
|
1870
|
+
function readProcessCommandLine(pid, flags2 = PS_WIDTH_FLAGS, env = { ...process.env, LC_ALL: PS_LOCALE }) {
|
|
1857
1871
|
return execFileSync(PS_BIN, [...flags2, "-p", String(pid), "-o", "command="], {
|
|
1872
|
+
env,
|
|
1858
1873
|
encoding: "utf8",
|
|
1859
1874
|
timeout: 2e3,
|
|
1860
1875
|
// A recycled pid can sit on a process with an argv past Node's 1 MiB exec
|
|
@@ -1869,19 +1884,27 @@ function readProcessCommandLine(pid, flags2 = PS_WIDTH_FLAGS) {
|
|
|
1869
1884
|
function couldBeOurToolServer(pid, marker) {
|
|
1870
1885
|
if (!marker) return false;
|
|
1871
1886
|
if (process.platform === "win32") return true;
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1887
|
+
const escaped = marker.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1888
|
+
const ours = new RegExp(`(?:^|[\\t\\n\\v\\f\\r ])${escaped} start(?:[\\t\\n\\v\\f\\r ]|$)`);
|
|
1889
|
+
const nonAscii = [...marker].some((c2) => c2.charCodeAt(0) > 127);
|
|
1890
|
+
let failure;
|
|
1891
|
+
for (const env of [void 0, process.env]) {
|
|
1892
|
+
try {
|
|
1893
|
+
if (ours.test(readProcessCommandLine(pid, PS_WIDTH_FLAGS, env))) return true;
|
|
1894
|
+
failure = void 0;
|
|
1895
|
+
if (!nonAscii) break;
|
|
1896
|
+
} catch (err) {
|
|
1897
|
+
failure = String(err);
|
|
1898
|
+
if (err.code === "ETIMEDOUT") break;
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
if (failure !== void 0) {
|
|
1876
1902
|
process.stderr.write(
|
|
1877
|
-
`[launcher] ps could not read pid ${pid}'s command line; leaving it alone: ${
|
|
1903
|
+
`[launcher] ps could not read pid ${pid}'s command line; leaving it alone: ${failure}
|
|
1878
1904
|
`
|
|
1879
1905
|
);
|
|
1880
|
-
return false;
|
|
1881
1906
|
}
|
|
1882
|
-
|
|
1883
|
-
const escaped = marker.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1884
|
-
return new RegExp(`(?:^|\\s)${escaped} start(?:\\s|$)`).test(cmd);
|
|
1907
|
+
return false;
|
|
1885
1908
|
}
|
|
1886
1909
|
var LOCK_WAIT_TIMEOUT_MS = 3e4;
|
|
1887
1910
|
var LOCK_STALE_MS = 45e3;
|
|
@@ -17130,7 +17153,7 @@ function sha256File(filePath) {
|
|
|
17130
17153
|
createReadStream(filePath).on("data", (chunk) => hash2.update(chunk)).on("end", () => resolve11(hash2.digest("hex"))).on("error", reject);
|
|
17131
17154
|
});
|
|
17132
17155
|
}
|
|
17133
|
-
async function uploadTar(tarPath, endpoint) {
|
|
17156
|
+
async function uploadTar(tarPath, endpoint, signal) {
|
|
17134
17157
|
const init2 = {
|
|
17135
17158
|
method: "POST",
|
|
17136
17159
|
headers: {
|
|
@@ -17138,7 +17161,8 @@ async function uploadTar(tarPath, endpoint) {
|
|
|
17138
17161
|
...endpoint.token ? { Authorization: `Bearer ${endpoint.token}` } : {}
|
|
17139
17162
|
},
|
|
17140
17163
|
body: createReadStream(tarPath),
|
|
17141
|
-
duplex: "half"
|
|
17164
|
+
duplex: "half",
|
|
17165
|
+
signal
|
|
17142
17166
|
};
|
|
17143
17167
|
const res = await fetch(`${endpoint.url}/upload`, init2);
|
|
17144
17168
|
if (!res.ok) {
|
|
@@ -17190,7 +17214,7 @@ async function prepareFileInputs(specs, args, opts) {
|
|
|
17190
17214
|
);
|
|
17191
17215
|
tarPath = await tarball(filePath);
|
|
17192
17216
|
wire.contentHash = await sha256File(tarPath);
|
|
17193
|
-
wire.uploadId = await uploadTar(tarPath, opts.uploadEndpoint);
|
|
17217
|
+
wire.uploadId = await uploadTar(tarPath, opts.uploadEndpoint, opts.signal);
|
|
17194
17218
|
} finally {
|
|
17195
17219
|
if (tarPath) await rm2(tarPath, { force: true }).catch(() => {
|
|
17196
17220
|
});
|
|
@@ -17259,7 +17283,7 @@ var ToolInvocationError = class extends Error {
|
|
|
17259
17283
|
function authHeaders2(token) {
|
|
17260
17284
|
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
17261
17285
|
}
|
|
17262
|
-
async function consumeToolStream(body, onProgress) {
|
|
17286
|
+
async function consumeToolStream(body, onProgress, signal) {
|
|
17263
17287
|
let final;
|
|
17264
17288
|
const handleLine = (line) => {
|
|
17265
17289
|
if (!line.trim()) return;
|
|
@@ -17283,6 +17307,7 @@ async function consumeToolStream(body, onProgress) {
|
|
|
17283
17307
|
buffered += decoder.decode(value, { stream: true });
|
|
17284
17308
|
let newline;
|
|
17285
17309
|
while ((newline = buffered.indexOf("\n")) !== -1) {
|
|
17310
|
+
signal?.throwIfAborted();
|
|
17286
17311
|
const line = buffered.slice(0, newline);
|
|
17287
17312
|
buffered = buffered.slice(newline + 1);
|
|
17288
17313
|
handleLine(line);
|
|
@@ -17295,6 +17320,7 @@ async function consumeToolStream(body, onProgress) {
|
|
|
17295
17320
|
});
|
|
17296
17321
|
throw err;
|
|
17297
17322
|
}
|
|
17323
|
+
signal?.throwIfAborted();
|
|
17298
17324
|
if (!final) {
|
|
17299
17325
|
throw new Error("tool stream ended without a result \u2014 connection lost mid-run?");
|
|
17300
17326
|
}
|
|
@@ -17321,27 +17347,33 @@ function createToolsClient(options = {}) {
|
|
|
17321
17347
|
cached3 = await ensureToolsServer(options.paths);
|
|
17322
17348
|
return cached3;
|
|
17323
17349
|
}
|
|
17324
|
-
async function fetchTools() {
|
|
17350
|
+
async function fetchTools(opts) {
|
|
17351
|
+
opts?.signal?.throwIfAborted();
|
|
17325
17352
|
const { url: url2, token } = await baseUrl();
|
|
17326
|
-
const res = await fetch(`${url2}/tools`, {
|
|
17353
|
+
const res = await fetch(`${url2}/tools`, {
|
|
17354
|
+
headers: authHeaders2(token),
|
|
17355
|
+
signal: opts?.signal
|
|
17356
|
+
});
|
|
17327
17357
|
if (!res.ok) throw new Error(`GET /tools failed: ${res.status} ${res.statusText}`);
|
|
17328
17358
|
const json2 = await res.json();
|
|
17329
17359
|
return json2.tools;
|
|
17330
17360
|
}
|
|
17331
|
-
async function fetchTool(name) {
|
|
17332
|
-
const tools2 = await fetchTools();
|
|
17361
|
+
async function fetchTool(name, opts) {
|
|
17362
|
+
const tools2 = await fetchTools(opts);
|
|
17333
17363
|
return tools2.find((t2) => t2.name === name) ?? null;
|
|
17334
17364
|
}
|
|
17335
17365
|
async function callTool(name, args, opts) {
|
|
17366
|
+
opts?.signal?.throwIfAborted();
|
|
17336
17367
|
const { url: url2, token } = await baseUrl();
|
|
17337
17368
|
let finalArgs = args;
|
|
17338
|
-
const meta3 = await fetchTool(name);
|
|
17369
|
+
const meta3 = await fetchTool(name, { signal: opts?.signal });
|
|
17339
17370
|
if (meta3?.fileInputs?.length) {
|
|
17340
17371
|
const { url: routedUrl } = await getResolvedToolsUrl();
|
|
17341
17372
|
const isRemote = routedUrl !== null;
|
|
17342
17373
|
finalArgs = await prepareFileInputs(meta3.fileInputs, args ?? {}, {
|
|
17343
17374
|
includeContent: isRemote,
|
|
17344
|
-
uploadEndpoint: isRemote ? { url: url2, token } : void 0
|
|
17375
|
+
uploadEndpoint: isRemote ? { url: url2, token } : void 0,
|
|
17376
|
+
signal: opts?.signal
|
|
17345
17377
|
});
|
|
17346
17378
|
}
|
|
17347
17379
|
const res = await fetch(`${url2}/tools/${encodeURIComponent(name)}`, {
|
|
@@ -17351,13 +17383,17 @@ function createToolsClient(options = {}) {
|
|
|
17351
17383
|
...opts?.onProgress ? { Accept: "application/x-ndjson" } : {},
|
|
17352
17384
|
...authHeaders2(token)
|
|
17353
17385
|
},
|
|
17354
|
-
body: JSON.stringify(finalArgs ?? {})
|
|
17386
|
+
body: JSON.stringify(finalArgs ?? {}),
|
|
17387
|
+
signal: opts?.signal
|
|
17355
17388
|
});
|
|
17356
17389
|
const contentType = res.headers.get("content-type") ?? "";
|
|
17357
17390
|
if (opts?.onProgress && res.ok && res.body && contentType.includes("application/x-ndjson")) {
|
|
17358
|
-
return consumeToolStream(res.body, opts.onProgress);
|
|
17391
|
+
return consumeToolStream(res.body, opts.onProgress, opts.signal);
|
|
17359
17392
|
}
|
|
17360
|
-
const json2 = await res.json().catch(() =>
|
|
17393
|
+
const json2 = await res.json().catch(() => {
|
|
17394
|
+
opts?.signal?.throwIfAborted();
|
|
17395
|
+
return {};
|
|
17396
|
+
});
|
|
17361
17397
|
if (!res.ok) {
|
|
17362
17398
|
throw new ToolInvocationError(errorBodyMessage(json2) ?? `${res.status} ${res.statusText}`, {
|
|
17363
17399
|
errorCode: json2.error_code,
|
|
@@ -17365,6 +17401,7 @@ function createToolsClient(options = {}) {
|
|
|
17365
17401
|
issues: Array.isArray(json2.issues) ? json2.issues : void 0
|
|
17366
17402
|
});
|
|
17367
17403
|
}
|
|
17404
|
+
opts?.signal?.throwIfAborted();
|
|
17368
17405
|
const { result: data } = await applyClientFileDirectives(json2.data);
|
|
17369
17406
|
return { data, note: json2.note };
|
|
17370
17407
|
}
|
|
@@ -18275,7 +18312,8 @@ async function materializeArtifacts(result, ctx) {
|
|
|
18275
18312
|
return null;
|
|
18276
18313
|
}
|
|
18277
18314
|
const res = await fetchFn(`${ctx.toolsUrl}/artifacts/${value.id}`, {
|
|
18278
|
-
headers: authHeaders3
|
|
18315
|
+
headers: authHeaders3,
|
|
18316
|
+
signal: ctx.signal
|
|
18279
18317
|
});
|
|
18280
18318
|
if (!res.ok) return null;
|
|
18281
18319
|
const data = await readCapped(res, value.size);
|
|
@@ -18302,7 +18340,8 @@ async function materializeArtifacts(result, ctx) {
|
|
|
18302
18340
|
}
|
|
18303
18341
|
try {
|
|
18304
18342
|
const res = await fetchFn(`${ctx.toolsUrl}/artifacts/${value.id}`, {
|
|
18305
|
-
headers: authHeaders3
|
|
18343
|
+
headers: authHeaders3,
|
|
18344
|
+
signal: ctx.signal
|
|
18306
18345
|
});
|
|
18307
18346
|
if (!res.ok) return null;
|
|
18308
18347
|
const data = Buffer.from(await res.arrayBuffer());
|
|
@@ -21877,7 +21916,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
21877
21916
|
var SESSION_ID2 = randomUUID5();
|
|
21878
21917
|
function readCliVersion() {
|
|
21879
21918
|
if (true) {
|
|
21880
|
-
return "0.
|
|
21919
|
+
return "0.27.1-next.0";
|
|
21881
21920
|
}
|
|
21882
21921
|
return "0.0.0";
|
|
21883
21922
|
}
|
|
@@ -24188,8 +24227,13 @@ async function stopCmd(paths) {
|
|
|
24188
24227
|
Stop one with: kill <pid>`);
|
|
24189
24228
|
return;
|
|
24190
24229
|
}
|
|
24191
|
-
await killToolServer(paths?.bundlePath)
|
|
24192
|
-
|
|
24230
|
+
if (await killToolServer(paths?.bundlePath)) {
|
|
24231
|
+
console.log(`tool-server stopped (pid ${state2.pid}).`);
|
|
24232
|
+
} else {
|
|
24233
|
+
console.log(
|
|
24234
|
+
`tool-server: not running (pid ${state2.pid} is gone or not an argent tool-server).`
|
|
24235
|
+
);
|
|
24236
|
+
}
|
|
24193
24237
|
}
|
|
24194
24238
|
function logsCmd(follow) {
|
|
24195
24239
|
if (!fs11.existsSync(LOG_FILE2)) {
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export interface ArgentTool {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
/** JSON Schema of the tool's arguments. */
|
|
5
|
+
inputSchema: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
export interface ArgentToolResult<T = unknown> {
|
|
8
|
+
/** The tool's result. Artifacts (screenshots, recordings) are local file paths. */
|
|
9
|
+
data: T;
|
|
10
|
+
/** Optional advisory note the tool attached to the result. */
|
|
11
|
+
note?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface CallToolOptions {
|
|
14
|
+
/** Receive progress events while a long-running tool works. */
|
|
15
|
+
onProgress?: (event: unknown) => void;
|
|
16
|
+
/** Stop waiting for the call. It rejects with the signal's reason, not ArgentToolError. */
|
|
17
|
+
signal?: AbortSignal;
|
|
18
|
+
}
|
|
19
|
+
/** The tool-server rejected or failed a call. */
|
|
20
|
+
export declare class ArgentToolError extends Error {
|
|
21
|
+
/** Stable failure code, when the server sent one. */
|
|
22
|
+
readonly code?: string;
|
|
23
|
+
/** Failure category, e.g. "subprocess", when the server sent one. */
|
|
24
|
+
readonly kind?: string;
|
|
25
|
+
/** Schema issues of a rejected argument object; set only on a validation failure. */
|
|
26
|
+
readonly issues?: readonly unknown[];
|
|
27
|
+
constructor(message: string, details?: {
|
|
28
|
+
code?: string;
|
|
29
|
+
kind?: string;
|
|
30
|
+
issues?: readonly unknown[];
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
export interface ArgentFlag {
|
|
34
|
+
name: string;
|
|
35
|
+
description: string;
|
|
36
|
+
/** Effective state, as `argent flags` reports it. */
|
|
37
|
+
enabled: boolean;
|
|
38
|
+
}
|
|
39
|
+
/** Feature flags and their effective state: project overrides global, then the default. */
|
|
40
|
+
export declare function listFlags(): ArgentFlag[];
|
|
41
|
+
export interface ArgentClient {
|
|
42
|
+
listTools(options?: {
|
|
43
|
+
signal?: AbortSignal;
|
|
44
|
+
}): Promise<ArgentTool[]>;
|
|
45
|
+
callTool<T = unknown>(name: string, args?: Record<string, unknown>, options?: CallToolOptions): Promise<ArgentToolResult<T>>;
|
|
46
|
+
/**
|
|
47
|
+
* Stop this install's local tool-server, like `argent server stop`. The next
|
|
48
|
+
* call starts a fresh one. Resolves false when none was running.
|
|
49
|
+
*/
|
|
50
|
+
stopServer(): Promise<boolean>;
|
|
51
|
+
}
|
|
52
|
+
export declare function createArgentClient(): ArgentClient;
|