@swmansion/argent 0.8.1 → 0.10.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/README.md +49 -9
- package/bin/argent-simulator-server.cjs +56 -0
- package/bin/{ax-service → darwin/ax-service} +0 -0
- package/bin/{simulator-server → darwin/simulator-server} +0 -0
- package/bin/linux/simulator-server +0 -0
- package/dist/argent-android-devtools-0.1.0.apk +0 -0
- package/dist/cli-cmds.mjs +2364 -76
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +23 -2
- package/dist/cli.js.map +1 -1
- package/dist/installer.mjs +598 -122
- package/dist/mcp-server.mjs +196 -53
- package/dist/tool-server.cjs +6059 -859
- package/dylibs/libArgentInjectionBootstrap.dylib +0 -0
- package/dylibs/libKeyboardPatch.dylib +0 -0
- package/dylibs/libNativeDevtoolsIos.dylib +0 -0
- package/package.json +2 -2
- package/rules/argent.md +8 -2
- package/skills/argent-android-emulator-setup/SKILL.md +1 -1
- package/skills/argent-device-interact/SKILL.md +11 -2
- package/skills/argent-react-native-app-workflow/SKILL.md +2 -0
- package/skills/argent-screenshot-diff/SKILL.md +67 -0
- package/skills/argent-test-ui-flow/SKILL.md +38 -16
package/dist/mcp-server.mjs
CHANGED
|
@@ -3225,8 +3225,8 @@ var require_utils = __commonJS({
|
|
|
3225
3225
|
}
|
|
3226
3226
|
return ind;
|
|
3227
3227
|
}
|
|
3228
|
-
function removeDotSegments(
|
|
3229
|
-
let input =
|
|
3228
|
+
function removeDotSegments(path3) {
|
|
3229
|
+
let input = path3;
|
|
3230
3230
|
const output = [];
|
|
3231
3231
|
let nextSlash = -1;
|
|
3232
3232
|
let len = 0;
|
|
@@ -3478,8 +3478,8 @@ var require_schemes = __commonJS({
|
|
|
3478
3478
|
wsComponent.secure = void 0;
|
|
3479
3479
|
}
|
|
3480
3480
|
if (wsComponent.resourceName) {
|
|
3481
|
-
const [
|
|
3482
|
-
wsComponent.path =
|
|
3481
|
+
const [path3, query] = wsComponent.resourceName.split("?");
|
|
3482
|
+
wsComponent.path = path3 && path3 !== "/" ? path3 : void 0;
|
|
3483
3483
|
wsComponent.query = query;
|
|
3484
3484
|
wsComponent.resourceName = void 0;
|
|
3485
3485
|
}
|
|
@@ -6886,9 +6886,9 @@ var require_dist = __commonJS({
|
|
|
6886
6886
|
});
|
|
6887
6887
|
|
|
6888
6888
|
// ../argent-mcp/src/mcp-server.ts
|
|
6889
|
-
import { appendFile, mkdir as
|
|
6889
|
+
import { appendFile, mkdir as mkdir3 } from "node:fs/promises";
|
|
6890
6890
|
import { dirname } from "node:path";
|
|
6891
|
-
import { homedir as
|
|
6891
|
+
import { homedir as homedir3 } from "node:os";
|
|
6892
6892
|
|
|
6893
6893
|
// ../../node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
6894
6894
|
import process3 from "node:process";
|
|
@@ -7133,10 +7133,10 @@ function mergeDefs(...defs) {
|
|
|
7133
7133
|
function cloneDef(schema) {
|
|
7134
7134
|
return mergeDefs(schema._zod.def);
|
|
7135
7135
|
}
|
|
7136
|
-
function getElementAtPath(obj,
|
|
7137
|
-
if (!
|
|
7136
|
+
function getElementAtPath(obj, path3) {
|
|
7137
|
+
if (!path3)
|
|
7138
7138
|
return obj;
|
|
7139
|
-
return
|
|
7139
|
+
return path3.reduce((acc, key) => acc?.[key], obj);
|
|
7140
7140
|
}
|
|
7141
7141
|
function promiseAllObject(promisesObj) {
|
|
7142
7142
|
const keys = Object.keys(promisesObj);
|
|
@@ -7545,11 +7545,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
7545
7545
|
}
|
|
7546
7546
|
return false;
|
|
7547
7547
|
}
|
|
7548
|
-
function prefixIssues(
|
|
7548
|
+
function prefixIssues(path3, issues) {
|
|
7549
7549
|
return issues.map((iss) => {
|
|
7550
7550
|
var _a3;
|
|
7551
7551
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
7552
|
-
iss.path.unshift(
|
|
7552
|
+
iss.path.unshift(path3);
|
|
7553
7553
|
return iss;
|
|
7554
7554
|
});
|
|
7555
7555
|
}
|
|
@@ -7696,16 +7696,16 @@ function flattenError(error2, mapper = (issue2) => issue2.message) {
|
|
|
7696
7696
|
}
|
|
7697
7697
|
function formatError(error2, mapper = (issue2) => issue2.message) {
|
|
7698
7698
|
const fieldErrors = { _errors: [] };
|
|
7699
|
-
const processError = (error3,
|
|
7699
|
+
const processError = (error3, path3 = []) => {
|
|
7700
7700
|
for (const issue2 of error3.issues) {
|
|
7701
7701
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
7702
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
7702
|
+
issue2.errors.map((issues) => processError({ issues }, [...path3, ...issue2.path]));
|
|
7703
7703
|
} else if (issue2.code === "invalid_key") {
|
|
7704
|
-
processError({ issues: issue2.issues }, [...
|
|
7704
|
+
processError({ issues: issue2.issues }, [...path3, ...issue2.path]);
|
|
7705
7705
|
} else if (issue2.code === "invalid_element") {
|
|
7706
|
-
processError({ issues: issue2.issues }, [...
|
|
7706
|
+
processError({ issues: issue2.issues }, [...path3, ...issue2.path]);
|
|
7707
7707
|
} else {
|
|
7708
|
-
const fullpath = [...
|
|
7708
|
+
const fullpath = [...path3, ...issue2.path];
|
|
7709
7709
|
if (fullpath.length === 0) {
|
|
7710
7710
|
fieldErrors._errors.push(mapper(issue2));
|
|
7711
7711
|
} else {
|
|
@@ -15457,17 +15457,30 @@ import * as path from "node:path";
|
|
|
15457
15457
|
import * as readline from "node:readline";
|
|
15458
15458
|
import { homedir } from "node:os";
|
|
15459
15459
|
import { spawn } from "node:child_process";
|
|
15460
|
-
import {
|
|
15460
|
+
import { randomBytes } from "node:crypto";
|
|
15461
|
+
import { mkdir, writeFile, readFile, unlink, rename, chmod } from "node:fs/promises";
|
|
15461
15462
|
var STATE_DIR = path.join(homedir(), ".argent");
|
|
15462
15463
|
var STATE_FILE = path.join(STATE_DIR, "tool-server.json");
|
|
15463
15464
|
var LOG_FILE = path.join(STATE_DIR, "tool-server.log");
|
|
15464
|
-
|
|
15465
|
-
|
|
15465
|
+
var AUTH_TOKEN_BYTES = 32;
|
|
15466
|
+
var AUTH_TOKEN_ENV = "ARGENT_AUTH_TOKEN";
|
|
15467
|
+
var AUTOSPAWN_IDLE_TIMEOUT_MINUTES = 30;
|
|
15468
|
+
function buildToolsServerEnv(paths, port, baseEnv = process.env, options = {}) {
|
|
15469
|
+
const env = {
|
|
15466
15470
|
...baseEnv,
|
|
15467
|
-
|
|
15471
|
+
ARGENT_PORT: String(port),
|
|
15468
15472
|
ARGENT_SIMULATOR_SERVER_DIR: paths.simulatorServerDir,
|
|
15469
15473
|
ARGENT_NATIVE_DEVTOOLS_DIR: paths.nativeDevtoolsDir
|
|
15470
15474
|
};
|
|
15475
|
+
if (options.host !== void 0) env.ARGENT_HOST = options.host;
|
|
15476
|
+
if (options.idleTimeoutMinutes !== void 0) {
|
|
15477
|
+
env.ARGENT_IDLE_TIMEOUT_MINUTES = String(options.idleTimeoutMinutes);
|
|
15478
|
+
}
|
|
15479
|
+
if (options.token) env[AUTH_TOKEN_ENV] = options.token;
|
|
15480
|
+
return env;
|
|
15481
|
+
}
|
|
15482
|
+
function generateToken() {
|
|
15483
|
+
return randomBytes(AUTH_TOKEN_BYTES).toString("hex");
|
|
15471
15484
|
}
|
|
15472
15485
|
function findFreePort() {
|
|
15473
15486
|
return new Promise((resolve, reject) => {
|
|
@@ -15495,12 +15508,25 @@ function isProcessAlive(pid) {
|
|
|
15495
15508
|
return false;
|
|
15496
15509
|
}
|
|
15497
15510
|
}
|
|
15498
|
-
|
|
15511
|
+
function healthCheckHost(host) {
|
|
15512
|
+
if (host === "0.0.0.0" || host === "") return "127.0.0.1";
|
|
15513
|
+
if (host === "::" || host === "::0") return "::1";
|
|
15514
|
+
return host;
|
|
15515
|
+
}
|
|
15516
|
+
function formatUrl(host, port) {
|
|
15517
|
+
const h = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
|
|
15518
|
+
return `http://${h}:${port}`;
|
|
15519
|
+
}
|
|
15520
|
+
function authHeaders(token) {
|
|
15521
|
+
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
15522
|
+
}
|
|
15523
|
+
async function isToolsServerHealthy(port, host = "127.0.0.1", timeoutMs = 2e3, token) {
|
|
15499
15524
|
const controller = new AbortController();
|
|
15500
|
-
const timer = setTimeout(() => controller.abort(),
|
|
15525
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
15501
15526
|
try {
|
|
15502
|
-
const res = await fetch(
|
|
15503
|
-
signal: controller.signal
|
|
15527
|
+
const res = await fetch(`${formatUrl(healthCheckHost(host), port)}/tools`, {
|
|
15528
|
+
signal: controller.signal,
|
|
15529
|
+
headers: authHeaders(token)
|
|
15504
15530
|
});
|
|
15505
15531
|
return res.ok;
|
|
15506
15532
|
} catch {
|
|
@@ -15509,7 +15535,7 @@ async function isHealthy(port) {
|
|
|
15509
15535
|
clearTimeout(timer);
|
|
15510
15536
|
}
|
|
15511
15537
|
}
|
|
15512
|
-
function spawnToolsServer(paths, port) {
|
|
15538
|
+
function spawnToolsServer(paths, port, options = {}) {
|
|
15513
15539
|
return new Promise((resolve, reject) => {
|
|
15514
15540
|
let logFd;
|
|
15515
15541
|
try {
|
|
@@ -15521,7 +15547,7 @@ function spawnToolsServer(paths, port) {
|
|
|
15521
15547
|
const child = spawn("node", [paths.bundlePath, "start"], {
|
|
15522
15548
|
detached: true,
|
|
15523
15549
|
stdio: ["ignore", "pipe", logFd],
|
|
15524
|
-
env: buildToolsServerEnv(paths, port)
|
|
15550
|
+
env: buildToolsServerEnv(paths, port, process.env, options)
|
|
15525
15551
|
});
|
|
15526
15552
|
child.unref();
|
|
15527
15553
|
const pid = child.pid;
|
|
@@ -15537,7 +15563,7 @@ function spawnToolsServer(paths, port) {
|
|
|
15537
15563
|
};
|
|
15538
15564
|
const rl = readline.createInterface({ input: child.stdout });
|
|
15539
15565
|
rl.on("line", (line) => {
|
|
15540
|
-
const match = line.match(/Tools server listening on http
|
|
15566
|
+
const match = line.match(/Tools server listening on http:\/\/.+:(\d+)/);
|
|
15541
15567
|
if (match) {
|
|
15542
15568
|
const actualPort = parseInt(match[1], 10);
|
|
15543
15569
|
rl.close();
|
|
@@ -15560,7 +15586,7 @@ function spawnToolsServer(paths, port) {
|
|
|
15560
15586
|
rl.on("close", () => clearTimeout(timer));
|
|
15561
15587
|
});
|
|
15562
15588
|
}
|
|
15563
|
-
async function
|
|
15589
|
+
async function readToolsServerState() {
|
|
15564
15590
|
try {
|
|
15565
15591
|
const raw = await readFile(STATE_FILE, "utf8");
|
|
15566
15592
|
return JSON.parse(raw);
|
|
@@ -15568,40 +15594,113 @@ async function readState() {
|
|
|
15568
15594
|
return null;
|
|
15569
15595
|
}
|
|
15570
15596
|
}
|
|
15571
|
-
async function
|
|
15597
|
+
async function writeToolsServerState(state) {
|
|
15572
15598
|
await mkdir(STATE_DIR, { recursive: true });
|
|
15573
|
-
|
|
15599
|
+
const tmp = `${STATE_FILE}.${process.pid}.tmp`;
|
|
15600
|
+
try {
|
|
15601
|
+
await writeFile(tmp, JSON.stringify(state, null, 2) + "\n", {
|
|
15602
|
+
encoding: "utf8",
|
|
15603
|
+
mode: 384
|
|
15604
|
+
});
|
|
15605
|
+
await chmod(tmp, 384);
|
|
15606
|
+
await rename(tmp, STATE_FILE);
|
|
15607
|
+
} catch (err) {
|
|
15608
|
+
await unlink(tmp).catch(() => {
|
|
15609
|
+
});
|
|
15610
|
+
throw err;
|
|
15611
|
+
}
|
|
15574
15612
|
}
|
|
15575
|
-
async function
|
|
15613
|
+
async function clearToolsServerState() {
|
|
15576
15614
|
try {
|
|
15577
15615
|
await unlink(STATE_FILE);
|
|
15578
15616
|
} catch {
|
|
15579
15617
|
}
|
|
15580
15618
|
}
|
|
15619
|
+
var readState = readToolsServerState;
|
|
15620
|
+
var writeState = writeToolsServerState;
|
|
15621
|
+
var clearState = clearToolsServerState;
|
|
15581
15622
|
async function ensureToolsServer(paths) {
|
|
15582
15623
|
const state = await readState();
|
|
15583
15624
|
if (state) {
|
|
15584
15625
|
const alive = isProcessAlive(state.pid);
|
|
15585
15626
|
if (alive) {
|
|
15586
|
-
const
|
|
15627
|
+
const host = state.host ?? "127.0.0.1";
|
|
15628
|
+
const healthy = await isToolsServerHealthy(state.port, host, 2e3, state.token);
|
|
15587
15629
|
if (healthy) {
|
|
15588
|
-
return
|
|
15630
|
+
return {
|
|
15631
|
+
url: formatUrl(healthCheckHost(host), state.port),
|
|
15632
|
+
token: state.token ?? ""
|
|
15633
|
+
};
|
|
15589
15634
|
}
|
|
15590
15635
|
}
|
|
15591
15636
|
await clearState();
|
|
15592
15637
|
}
|
|
15638
|
+
const token = generateToken();
|
|
15593
15639
|
const port = await findFreePort();
|
|
15594
|
-
const { port: actualPort, pid } = await spawnToolsServer(paths, port
|
|
15640
|
+
const { port: actualPort, pid } = await spawnToolsServer(paths, port, {
|
|
15641
|
+
token,
|
|
15642
|
+
idleTimeoutMinutes: AUTOSPAWN_IDLE_TIMEOUT_MINUTES
|
|
15643
|
+
});
|
|
15595
15644
|
await writeState({
|
|
15596
15645
|
port: actualPort,
|
|
15597
15646
|
pid,
|
|
15598
15647
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15599
|
-
bundlePath: paths.bundlePath
|
|
15648
|
+
bundlePath: paths.bundlePath,
|
|
15649
|
+
host: "127.0.0.1",
|
|
15650
|
+
token
|
|
15600
15651
|
});
|
|
15601
|
-
return
|
|
15652
|
+
return { url: formatUrl("127.0.0.1", actualPort), token };
|
|
15653
|
+
}
|
|
15654
|
+
|
|
15655
|
+
// ../argent-tools-client/src/link-config.ts
|
|
15656
|
+
import * as path2 from "node:path";
|
|
15657
|
+
import { homedir as homedir2 } from "node:os";
|
|
15658
|
+
import { mkdir as mkdir2, writeFile as writeFile2, readFile as readFile2, unlink as unlink2, chmod as chmod2 } from "node:fs/promises";
|
|
15659
|
+
var LINK_DIR = path2.join(homedir2(), ".argent");
|
|
15660
|
+
var LINK_FILE = path2.join(LINK_DIR, "link.json");
|
|
15661
|
+
async function readLinkConfig() {
|
|
15662
|
+
try {
|
|
15663
|
+
const raw = await readFile2(LINK_FILE, "utf8");
|
|
15664
|
+
const parsed = JSON.parse(raw);
|
|
15665
|
+
if (!parsed || typeof parsed.url !== "string" || typeof parsed.host !== "string" || typeof parsed.port !== "number" || typeof parsed.createdAt !== "string") {
|
|
15666
|
+
return null;
|
|
15667
|
+
}
|
|
15668
|
+
return {
|
|
15669
|
+
url: parsed.url,
|
|
15670
|
+
host: parsed.host,
|
|
15671
|
+
port: parsed.port,
|
|
15672
|
+
createdAt: parsed.createdAt,
|
|
15673
|
+
...typeof parsed.token === "string" ? { token: parsed.token } : {}
|
|
15674
|
+
};
|
|
15675
|
+
} catch {
|
|
15676
|
+
return null;
|
|
15677
|
+
}
|
|
15678
|
+
}
|
|
15679
|
+
async function getResolvedToolsUrl() {
|
|
15680
|
+
const envUrl = process.env.ARGENT_TOOLS_URL;
|
|
15681
|
+
if (envUrl) {
|
|
15682
|
+
const link2 = await readLinkConfig();
|
|
15683
|
+
const envToken = process.env[AUTH_TOKEN_ENV];
|
|
15684
|
+
return {
|
|
15685
|
+
url: envUrl,
|
|
15686
|
+
source: "env",
|
|
15687
|
+
...envToken ? { token: envToken } : {},
|
|
15688
|
+
...link2 ? { shadowedLink: link2 } : {}
|
|
15689
|
+
};
|
|
15690
|
+
}
|
|
15691
|
+
const link = await readLinkConfig();
|
|
15692
|
+
if (link) {
|
|
15693
|
+
return { url: link.url, source: "link", ...link.token ? { token: link.token } : {} };
|
|
15694
|
+
}
|
|
15695
|
+
return { url: null, source: "none" };
|
|
15696
|
+
}
|
|
15697
|
+
async function isRemoteRouted() {
|
|
15698
|
+
const { url } = await getResolvedToolsUrl();
|
|
15699
|
+
return url !== null;
|
|
15602
15700
|
}
|
|
15603
15701
|
|
|
15604
15702
|
// ../argent-mcp/src/content.ts
|
|
15703
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
15605
15704
|
var PNG_SIGNATURE = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
|
|
15606
15705
|
async function fetchPngBytes(url) {
|
|
15607
15706
|
try {
|
|
@@ -15615,9 +15714,12 @@ async function fetchPngBytes(url) {
|
|
|
15615
15714
|
return null;
|
|
15616
15715
|
}
|
|
15617
15716
|
}
|
|
15618
|
-
async function toMcpContent(result, outputHint) {
|
|
15717
|
+
async function toMcpContent(result, outputHint, args) {
|
|
15619
15718
|
if (outputHint === "image" && result && typeof result === "object" && "url" in result) {
|
|
15620
15719
|
const r = result;
|
|
15720
|
+
if (isRecord(args) && args.includeImageInContext === false) {
|
|
15721
|
+
return [{ type: "text", text: `Saved: ${r.path}` }];
|
|
15722
|
+
}
|
|
15621
15723
|
const buf = await fetchPngBytes(r.url);
|
|
15622
15724
|
if (buf) {
|
|
15623
15725
|
return [
|
|
@@ -15638,6 +15740,26 @@ async function toMcpContent(result, outputHint) {
|
|
|
15638
15740
|
}
|
|
15639
15741
|
return [{ type: "text", text: JSON.stringify(result, null, 2) }];
|
|
15640
15742
|
}
|
|
15743
|
+
function isRecord(value) {
|
|
15744
|
+
return value !== null && typeof value === "object";
|
|
15745
|
+
}
|
|
15746
|
+
function isScreenshotDiffResult(value) {
|
|
15747
|
+
if (!isRecord(value)) return false;
|
|
15748
|
+
return typeof value.summary === "string";
|
|
15749
|
+
}
|
|
15750
|
+
async function screenshotDiffToMcpContent(result) {
|
|
15751
|
+
const blocks = [];
|
|
15752
|
+
if (typeof result.contextDiffPath === "string") {
|
|
15753
|
+
const buf = await readFile3(result.contextDiffPath);
|
|
15754
|
+
blocks.push({
|
|
15755
|
+
type: "image",
|
|
15756
|
+
data: buf.toString("base64"),
|
|
15757
|
+
mimeType: "image/png"
|
|
15758
|
+
});
|
|
15759
|
+
}
|
|
15760
|
+
blocks.push({ type: "text", text: result.summary });
|
|
15761
|
+
return blocks;
|
|
15762
|
+
}
|
|
15641
15763
|
async function flowRunToMcpContent(result) {
|
|
15642
15764
|
const blocks = [];
|
|
15643
15765
|
if (result.executionPrerequisite) {
|
|
@@ -15662,7 +15784,7 @@ async function flowRunToMcpContent(result) {
|
|
|
15662
15784
|
});
|
|
15663
15785
|
} else {
|
|
15664
15786
|
blocks.push({ type: "text", text: `[${num}] ${step.tool}` });
|
|
15665
|
-
const stepContent = await toMcpContent(step.result, step.outputHint);
|
|
15787
|
+
const stepContent = await toMcpContent(step.result, step.outputHint, step.args);
|
|
15666
15788
|
blocks.push(...stepContent);
|
|
15667
15789
|
}
|
|
15668
15790
|
}
|
|
@@ -15776,35 +15898,44 @@ async function fetchWithReconnect(getUrl, reconnect, config2) {
|
|
|
15776
15898
|
}
|
|
15777
15899
|
async function startMcpServer(options) {
|
|
15778
15900
|
let TOOLS_URL;
|
|
15779
|
-
|
|
15780
|
-
|
|
15901
|
+
let AUTH_TOKEN;
|
|
15902
|
+
const resolved = await getResolvedToolsUrl();
|
|
15903
|
+
if (resolved.url) {
|
|
15904
|
+
TOOLS_URL = resolved.url;
|
|
15905
|
+
AUTH_TOKEN = resolved.token ?? "";
|
|
15781
15906
|
} else {
|
|
15782
15907
|
try {
|
|
15783
|
-
|
|
15908
|
+
const handle = await ensureToolsServer(options.paths);
|
|
15909
|
+
TOOLS_URL = handle.url;
|
|
15910
|
+
AUTH_TOKEN = handle.token;
|
|
15784
15911
|
} catch (err) {
|
|
15785
15912
|
process.stderr.write(`[argent] Failed to start tools server: ${err}
|
|
15786
15913
|
`);
|
|
15787
15914
|
process.exit(1);
|
|
15788
15915
|
}
|
|
15789
15916
|
}
|
|
15917
|
+
function authHeader() {
|
|
15918
|
+
return AUTH_TOKEN ? { Authorization: `Bearer ${AUTH_TOKEN}` } : {};
|
|
15919
|
+
}
|
|
15790
15920
|
let reconnectPromise = null;
|
|
15791
15921
|
async function reconnect() {
|
|
15792
|
-
if (
|
|
15922
|
+
if (await isRemoteRouted()) return;
|
|
15793
15923
|
if (!reconnectPromise) {
|
|
15794
|
-
reconnectPromise = ensureToolsServer(options.paths).then((
|
|
15795
|
-
TOOLS_URL = url;
|
|
15924
|
+
reconnectPromise = ensureToolsServer(options.paths).then((handle) => {
|
|
15925
|
+
TOOLS_URL = handle.url;
|
|
15926
|
+
AUTH_TOKEN = handle.token;
|
|
15796
15927
|
}).finally(() => {
|
|
15797
15928
|
reconnectPromise = null;
|
|
15798
15929
|
});
|
|
15799
15930
|
}
|
|
15800
15931
|
return reconnectPromise;
|
|
15801
15932
|
}
|
|
15802
|
-
const LOG_FILE2 = process.env.ARGENT_MCP_LOG ?? `${
|
|
15933
|
+
const LOG_FILE2 = process.env.ARGENT_MCP_LOG ?? `${homedir3()}/.argent/mcp-calls.log`;
|
|
15803
15934
|
let logDirReady = false;
|
|
15804
15935
|
async function spyLog(entry) {
|
|
15805
15936
|
try {
|
|
15806
15937
|
if (!logDirReady) {
|
|
15807
|
-
await
|
|
15938
|
+
await mkdir3(dirname(LOG_FILE2), { recursive: true });
|
|
15808
15939
|
logDirReady = true;
|
|
15809
15940
|
}
|
|
15810
15941
|
await appendFile(LOG_FILE2, JSON.stringify(entry) + "\n");
|
|
@@ -15812,7 +15943,9 @@ async function startMcpServer(options) {
|
|
|
15812
15943
|
}
|
|
15813
15944
|
}
|
|
15814
15945
|
async function fetchTools() {
|
|
15815
|
-
const res = await fetchWithReconnect(() => `${TOOLS_URL}/tools`, reconnect
|
|
15946
|
+
const res = await fetchWithReconnect(() => `${TOOLS_URL}/tools`, reconnect, {
|
|
15947
|
+
init: { headers: authHeader() }
|
|
15948
|
+
});
|
|
15816
15949
|
const json = await res.json();
|
|
15817
15950
|
return json.tools;
|
|
15818
15951
|
}
|
|
@@ -15822,7 +15955,7 @@ async function startMcpServer(options) {
|
|
|
15822
15955
|
const res = await fetchWithReconnect(() => `${TOOLS_URL}/tools/${name}`, reconnect, {
|
|
15823
15956
|
init: {
|
|
15824
15957
|
method: "POST",
|
|
15825
|
-
headers: { "Content-Type": "application/json" },
|
|
15958
|
+
headers: { "Content-Type": "application/json", ...authHeader() },
|
|
15826
15959
|
body: JSON.stringify(args ?? {})
|
|
15827
15960
|
},
|
|
15828
15961
|
fetchTimeoutMs: meta2?.longRunning ? null : FETCH_TIMEOUT_MS
|
|
@@ -15873,14 +16006,21 @@ async function startMcpServer(options) {
|
|
|
15873
16006
|
isError: false,
|
|
15874
16007
|
result
|
|
15875
16008
|
});
|
|
15876
|
-
let content
|
|
16009
|
+
let content;
|
|
16010
|
+
if (params.name === "flow-execute" && result && typeof result === "object" && "flow" in result && "steps" in result) {
|
|
16011
|
+
content = await flowRunToMcpContent(result);
|
|
16012
|
+
} else if (params.name === "screenshot-diff" && isScreenshotDiffResult(result)) {
|
|
16013
|
+
content = await screenshotDiffToMcpContent(result);
|
|
16014
|
+
} else {
|
|
16015
|
+
content = await toMcpContent(result, outputHint, params.arguments);
|
|
16016
|
+
}
|
|
15877
16017
|
const udid = getUdidFromArgs(params.arguments);
|
|
15878
16018
|
if (autoScreenshotEnabled() && udid && shouldAutoScreenshot(params.name)) {
|
|
15879
16019
|
const delayMs = getAutoScreenshotDelayMs(params.name);
|
|
15880
16020
|
if (delayMs > 0) await new Promise((r) => setTimeout(r, delayMs));
|
|
15881
16021
|
try {
|
|
15882
16022
|
const screenshotResult = await callTool("screenshot", { udid });
|
|
15883
|
-
const screenshotContent = await toMcpContent(screenshotResult.result, "image");
|
|
16023
|
+
const screenshotContent = await toMcpContent(screenshotResult.result, "image", { udid });
|
|
15884
16024
|
const hasImage = screenshotContent.some((b) => b.type === "image");
|
|
15885
16025
|
if (hasImage) {
|
|
15886
16026
|
content = [
|
|
@@ -15920,14 +16060,17 @@ async function startMcpServer(options) {
|
|
|
15920
16060
|
}
|
|
15921
16061
|
});
|
|
15922
16062
|
await server.connect(new StdioServerTransport());
|
|
15923
|
-
if (!
|
|
16063
|
+
if (!await isRemoteRouted()) {
|
|
15924
16064
|
const HEALTH_INTERVAL_MS = 3e4;
|
|
15925
16065
|
const healthInterval = setInterval(async () => {
|
|
15926
16066
|
try {
|
|
15927
16067
|
const controller = new AbortController();
|
|
15928
16068
|
const timer = setTimeout(() => controller.abort(), 3e3);
|
|
15929
16069
|
try {
|
|
15930
|
-
const res = await fetch(`${TOOLS_URL}/tools`, {
|
|
16070
|
+
const res = await fetch(`${TOOLS_URL}/tools`, {
|
|
16071
|
+
signal: controller.signal,
|
|
16072
|
+
headers: authHeader()
|
|
16073
|
+
});
|
|
15931
16074
|
if (!res.ok) throw new Error(`health check returned ${res.status}`);
|
|
15932
16075
|
} finally {
|
|
15933
16076
|
clearTimeout(timer);
|
|
@@ -15942,7 +16085,7 @@ async function startMcpServer(options) {
|
|
|
15942
16085
|
}
|
|
15943
16086
|
if (process.env.ARGENT_AUTO_SHUTDOWN === "1") {
|
|
15944
16087
|
process.stdin.on("close", () => {
|
|
15945
|
-
fetch(`${TOOLS_URL}/shutdown`, { method: "POST" }).catch(() => {
|
|
16088
|
+
fetch(`${TOOLS_URL}/shutdown`, { method: "POST", headers: authHeader() }).catch(() => {
|
|
15946
16089
|
});
|
|
15947
16090
|
setTimeout(() => process.exit(0), 5e3);
|
|
15948
16091
|
});
|