@swmansion/argent 0.10.0 → 0.12.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 +4 -1
- package/assets/argent.tracecfg.pbtxt +133 -0
- package/assets/queries/README.md +93 -0
- package/assets/queries/cpu-hotspots.sql +106 -0
- package/assets/queries/function-callers.sql +62 -0
- package/assets/queries/hang-folds-batched.sql +88 -0
- package/assets/queries/hang-main-thread-samples.sql +32 -0
- package/assets/queries/hang-state-breakdown.sql +44 -0
- package/assets/queries/memory-rss.sql +25 -0
- package/assets/queries/thread-breakdown.sql +34 -0
- package/assets/queries/trace-bounds.sql +6 -0
- package/assets/queries/ui-hangs.sql +59 -0
- package/assets/trace-processor/LICENSE +235 -0
- package/assets/trace-processor/SHA256SUMS +4 -0
- package/assets/trace-processor/engine.mjs +42423 -0
- package/assets/trace-processor/engine_bundle.node.js +11130 -0
- package/assets/trace-processor/trace_processor.wasm +0 -0
- package/{dist → bin}/argent-android-devtools-0.1.0.apk +0 -0
- package/bin/argent-simulator-server.cjs +11 -3
- package/bin/darwin/ax-service +0 -0
- package/bin/darwin/resources/android/LICENSE.txt +186 -0
- package/bin/darwin/resources/android/README.md +11 -0
- package/bin/darwin/resources/android/arm64-v8a/libscreen-sharing-agent.so +0 -0
- package/bin/darwin/resources/android/armeabi-v7a/libscreen-sharing-agent.so +0 -0
- package/bin/darwin/resources/android/screen-sharing-agent.jar +0 -0
- package/bin/darwin/resources/android/x86_64/libscreen-sharing-agent.so +0 -0
- package/bin/darwin/simulator-server +0 -0
- package/bin/linux/resources/android/LICENSE.txt +186 -0
- package/bin/linux/resources/android/README.md +11 -0
- package/bin/linux/resources/android/arm64-v8a/libscreen-sharing-agent.so +0 -0
- package/bin/linux/resources/android/armeabi-v7a/libscreen-sharing-agent.so +0 -0
- package/bin/linux/resources/android/screen-sharing-agent.jar +0 -0
- package/bin/linux/resources/android/x86_64/libscreen-sharing-agent.so +0 -0
- package/bin/linux/simulator-server +0 -0
- package/bin/linux-arm64/resources/android/LICENSE.txt +186 -0
- package/bin/linux-arm64/resources/android/README.md +11 -0
- package/bin/linux-arm64/resources/android/arm64-v8a/libscreen-sharing-agent.so +0 -0
- package/bin/linux-arm64/resources/android/armeabi-v7a/libscreen-sharing-agent.so +0 -0
- package/bin/linux-arm64/resources/android/screen-sharing-agent.jar +0 -0
- package/bin/linux-arm64/resources/android/x86_64/libscreen-sharing-agent.so +0 -0
- package/bin/linux-arm64/simulator-server +0 -0
- package/dist/cli-cmds.mjs +1858 -1578
- package/dist/cli.js +0 -3
- package/dist/cli.js.map +1 -1
- package/dist/installer.mjs +119 -96
- package/dist/mcp-server.mjs +452 -92
- package/dist/preview-ui/index.html +4500 -645
- package/dist/preview-ui/theme.css +231 -0
- package/dist/preview-window/main.cjs +182 -0
- package/dist/tool-server.cjs +11265 -5220
- package/dylibs/libArgentInjectionBootstrap.dylib +0 -0
- package/dylibs/libKeyboardPatch.dylib +0 -0
- package/dylibs/libNativeDevtoolsIos.dylib +0 -0
- package/package.json +5 -2
- package/rules/argent.md +8 -2
- package/scripts/postinstall.cjs +6 -2
- package/skills/argent-device-interact/SKILL.md +36 -28
- package/skills/argent-lens/SKILL.md +101 -0
- package/skills/argent-metro-debugger/SKILL.md +18 -16
- package/skills/argent-native-profiler/SKILL.md +5 -5
- package/skills/argent-react-native-app-workflow/SKILL.md +8 -8
- /package/{dist → assets}/Argent.tracetemplate +0 -0
- /package/{manifest.json → assets/manifest.json} +0 -0
package/dist/mcp-server.mjs
CHANGED
|
@@ -6,7 +6,11 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
8
|
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
-
|
|
9
|
+
try {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
} catch (e) {
|
|
12
|
+
throw mod = 0, e;
|
|
13
|
+
}
|
|
10
14
|
};
|
|
11
15
|
var __export = (target, all) => {
|
|
12
16
|
for (var name in all)
|
|
@@ -2980,7 +2984,7 @@ var require_compile = __commonJS({
|
|
|
2980
2984
|
const schOrFunc = root.refs[ref];
|
|
2981
2985
|
if (schOrFunc)
|
|
2982
2986
|
return schOrFunc;
|
|
2983
|
-
let _sch =
|
|
2987
|
+
let _sch = resolve3.call(this, root, ref);
|
|
2984
2988
|
if (_sch === void 0) {
|
|
2985
2989
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
2986
2990
|
const { schemaId } = this.opts;
|
|
@@ -3007,7 +3011,7 @@ var require_compile = __commonJS({
|
|
|
3007
3011
|
function sameSchemaEnv(s1, s2) {
|
|
3008
3012
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3009
3013
|
}
|
|
3010
|
-
function
|
|
3014
|
+
function resolve3(root, ref) {
|
|
3011
3015
|
let sch;
|
|
3012
3016
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3013
3017
|
ref = sch;
|
|
@@ -3225,8 +3229,8 @@ var require_utils = __commonJS({
|
|
|
3225
3229
|
}
|
|
3226
3230
|
return ind;
|
|
3227
3231
|
}
|
|
3228
|
-
function removeDotSegments(
|
|
3229
|
-
let input =
|
|
3232
|
+
function removeDotSegments(path6) {
|
|
3233
|
+
let input = path6;
|
|
3230
3234
|
const output = [];
|
|
3231
3235
|
let nextSlash = -1;
|
|
3232
3236
|
let len = 0;
|
|
@@ -3478,8 +3482,8 @@ var require_schemes = __commonJS({
|
|
|
3478
3482
|
wsComponent.secure = void 0;
|
|
3479
3483
|
}
|
|
3480
3484
|
if (wsComponent.resourceName) {
|
|
3481
|
-
const [
|
|
3482
|
-
wsComponent.path =
|
|
3485
|
+
const [path6, query] = wsComponent.resourceName.split("?");
|
|
3486
|
+
wsComponent.path = path6 && path6 !== "/" ? path6 : void 0;
|
|
3483
3487
|
wsComponent.query = query;
|
|
3484
3488
|
wsComponent.resourceName = void 0;
|
|
3485
3489
|
}
|
|
@@ -3638,7 +3642,7 @@ var require_fast_uri = __commonJS({
|
|
|
3638
3642
|
}
|
|
3639
3643
|
return uri;
|
|
3640
3644
|
}
|
|
3641
|
-
function
|
|
3645
|
+
function resolve3(baseURI, relativeURI, options) {
|
|
3642
3646
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3643
3647
|
const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
3644
3648
|
schemelessOptions.skipEscape = true;
|
|
@@ -3896,7 +3900,7 @@ var require_fast_uri = __commonJS({
|
|
|
3896
3900
|
var fastUri = {
|
|
3897
3901
|
SCHEMES,
|
|
3898
3902
|
normalize,
|
|
3899
|
-
resolve,
|
|
3903
|
+
resolve: resolve3,
|
|
3900
3904
|
resolveComponent,
|
|
3901
3905
|
equal,
|
|
3902
3906
|
serialize,
|
|
@@ -6872,12 +6876,12 @@ var require_dist = __commonJS({
|
|
|
6872
6876
|
throw new Error(`Unknown format "${name}"`);
|
|
6873
6877
|
return f;
|
|
6874
6878
|
};
|
|
6875
|
-
function addFormats(ajv, list,
|
|
6879
|
+
function addFormats(ajv, list, fs4, exportName) {
|
|
6876
6880
|
var _a3;
|
|
6877
6881
|
var _b;
|
|
6878
6882
|
(_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
6879
6883
|
for (const f of list)
|
|
6880
|
-
ajv.addFormat(f,
|
|
6884
|
+
ajv.addFormat(f, fs4[f]);
|
|
6881
6885
|
}
|
|
6882
6886
|
module.exports = exports = formatsPlugin;
|
|
6883
6887
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -6886,9 +6890,9 @@ var require_dist = __commonJS({
|
|
|
6886
6890
|
});
|
|
6887
6891
|
|
|
6888
6892
|
// ../argent-mcp/src/mcp-server.ts
|
|
6889
|
-
import { appendFile, mkdir as
|
|
6890
|
-
import { dirname } from "node:path";
|
|
6891
|
-
import { homedir as
|
|
6893
|
+
import { appendFile, mkdir as mkdir5 } from "node:fs/promises";
|
|
6894
|
+
import { dirname as dirname3 } from "node:path";
|
|
6895
|
+
import { homedir as homedir4 } from "node:os";
|
|
6892
6896
|
|
|
6893
6897
|
// ../../node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
6894
6898
|
import process3 from "node:process";
|
|
@@ -7133,10 +7137,10 @@ function mergeDefs(...defs) {
|
|
|
7133
7137
|
function cloneDef(schema) {
|
|
7134
7138
|
return mergeDefs(schema._zod.def);
|
|
7135
7139
|
}
|
|
7136
|
-
function getElementAtPath(obj,
|
|
7137
|
-
if (!
|
|
7140
|
+
function getElementAtPath(obj, path6) {
|
|
7141
|
+
if (!path6)
|
|
7138
7142
|
return obj;
|
|
7139
|
-
return
|
|
7143
|
+
return path6.reduce((acc, key) => acc?.[key], obj);
|
|
7140
7144
|
}
|
|
7141
7145
|
function promiseAllObject(promisesObj) {
|
|
7142
7146
|
const keys = Object.keys(promisesObj);
|
|
@@ -7545,11 +7549,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
7545
7549
|
}
|
|
7546
7550
|
return false;
|
|
7547
7551
|
}
|
|
7548
|
-
function prefixIssues(
|
|
7552
|
+
function prefixIssues(path6, issues) {
|
|
7549
7553
|
return issues.map((iss) => {
|
|
7550
7554
|
var _a3;
|
|
7551
7555
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
7552
|
-
iss.path.unshift(
|
|
7556
|
+
iss.path.unshift(path6);
|
|
7553
7557
|
return iss;
|
|
7554
7558
|
});
|
|
7555
7559
|
}
|
|
@@ -7696,16 +7700,16 @@ function flattenError(error2, mapper = (issue2) => issue2.message) {
|
|
|
7696
7700
|
}
|
|
7697
7701
|
function formatError(error2, mapper = (issue2) => issue2.message) {
|
|
7698
7702
|
const fieldErrors = { _errors: [] };
|
|
7699
|
-
const processError = (error3,
|
|
7703
|
+
const processError = (error3, path6 = []) => {
|
|
7700
7704
|
for (const issue2 of error3.issues) {
|
|
7701
7705
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
7702
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
7706
|
+
issue2.errors.map((issues) => processError({ issues }, [...path6, ...issue2.path]));
|
|
7703
7707
|
} else if (issue2.code === "invalid_key") {
|
|
7704
|
-
processError({ issues: issue2.issues }, [...
|
|
7708
|
+
processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
|
|
7705
7709
|
} else if (issue2.code === "invalid_element") {
|
|
7706
|
-
processError({ issues: issue2.issues }, [...
|
|
7710
|
+
processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
|
|
7707
7711
|
} else {
|
|
7708
|
-
const fullpath = [...
|
|
7712
|
+
const fullpath = [...path6, ...issue2.path];
|
|
7709
7713
|
if (fullpath.length === 0) {
|
|
7710
7714
|
fieldErrors._errors.push(mapper(issue2));
|
|
7711
7715
|
} else {
|
|
@@ -13697,12 +13701,12 @@ var StdioServerTransport = class {
|
|
|
13697
13701
|
this.onclose?.();
|
|
13698
13702
|
}
|
|
13699
13703
|
send(message) {
|
|
13700
|
-
return new Promise((
|
|
13704
|
+
return new Promise((resolve3) => {
|
|
13701
13705
|
const json = serializeMessage(message);
|
|
13702
13706
|
if (this._stdout.write(json)) {
|
|
13703
|
-
|
|
13707
|
+
resolve3();
|
|
13704
13708
|
} else {
|
|
13705
|
-
this._stdout.once("drain",
|
|
13709
|
+
this._stdout.once("drain", resolve3);
|
|
13706
13710
|
}
|
|
13707
13711
|
});
|
|
13708
13712
|
}
|
|
@@ -14300,7 +14304,7 @@ var Protocol = class {
|
|
|
14300
14304
|
return;
|
|
14301
14305
|
}
|
|
14302
14306
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
14303
|
-
await new Promise((
|
|
14307
|
+
await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
|
|
14304
14308
|
options?.signal?.throwIfAborted();
|
|
14305
14309
|
}
|
|
14306
14310
|
} catch (error2) {
|
|
@@ -14317,7 +14321,7 @@ var Protocol = class {
|
|
|
14317
14321
|
*/
|
|
14318
14322
|
request(request, resultSchema, options) {
|
|
14319
14323
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
14320
|
-
return new Promise((
|
|
14324
|
+
return new Promise((resolve3, reject) => {
|
|
14321
14325
|
const earlyReject = (error2) => {
|
|
14322
14326
|
reject(error2);
|
|
14323
14327
|
};
|
|
@@ -14395,7 +14399,7 @@ var Protocol = class {
|
|
|
14395
14399
|
if (!parseResult.success) {
|
|
14396
14400
|
reject(parseResult.error);
|
|
14397
14401
|
} else {
|
|
14398
|
-
|
|
14402
|
+
resolve3(parseResult.data);
|
|
14399
14403
|
}
|
|
14400
14404
|
} catch (error2) {
|
|
14401
14405
|
reject(error2);
|
|
@@ -14611,21 +14615,21 @@ var Protocol = class {
|
|
|
14611
14615
|
* the error appropriately (e.g., by failing the task, logging, etc.). The Protocol layer
|
|
14612
14616
|
* simply propagates the error.
|
|
14613
14617
|
*/
|
|
14614
|
-
async _enqueueTaskMessage(taskId, message,
|
|
14618
|
+
async _enqueueTaskMessage(taskId, message, sessionId2) {
|
|
14615
14619
|
if (!this._taskStore || !this._taskMessageQueue) {
|
|
14616
14620
|
throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
|
|
14617
14621
|
}
|
|
14618
14622
|
const maxQueueSize = this._options?.maxTaskQueueSize;
|
|
14619
|
-
await this._taskMessageQueue.enqueue(taskId, message,
|
|
14623
|
+
await this._taskMessageQueue.enqueue(taskId, message, sessionId2, maxQueueSize);
|
|
14620
14624
|
}
|
|
14621
14625
|
/**
|
|
14622
14626
|
* Clears the message queue for a task and rejects any pending request resolvers.
|
|
14623
14627
|
* @param taskId The task ID whose queue should be cleared
|
|
14624
14628
|
* @param sessionId Optional session ID for binding the operation to a specific session
|
|
14625
14629
|
*/
|
|
14626
|
-
async _clearTaskQueue(taskId,
|
|
14630
|
+
async _clearTaskQueue(taskId, sessionId2) {
|
|
14627
14631
|
if (this._taskMessageQueue) {
|
|
14628
|
-
const messages = await this._taskMessageQueue.dequeueAll(taskId,
|
|
14632
|
+
const messages = await this._taskMessageQueue.dequeueAll(taskId, sessionId2);
|
|
14629
14633
|
for (const message of messages) {
|
|
14630
14634
|
if (message.type === "request" && isJSONRPCRequest(message.message)) {
|
|
14631
14635
|
const requestId = message.message.id;
|
|
@@ -14656,19 +14660,19 @@ var Protocol = class {
|
|
|
14656
14660
|
}
|
|
14657
14661
|
} catch {
|
|
14658
14662
|
}
|
|
14659
|
-
return new Promise((
|
|
14663
|
+
return new Promise((resolve3, reject) => {
|
|
14660
14664
|
if (signal.aborted) {
|
|
14661
14665
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
14662
14666
|
return;
|
|
14663
14667
|
}
|
|
14664
|
-
const timeoutId = setTimeout(
|
|
14668
|
+
const timeoutId = setTimeout(resolve3, interval);
|
|
14665
14669
|
signal.addEventListener("abort", () => {
|
|
14666
14670
|
clearTimeout(timeoutId);
|
|
14667
14671
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
14668
14672
|
}, { once: true });
|
|
14669
14673
|
});
|
|
14670
14674
|
}
|
|
14671
|
-
requestTaskStore(request,
|
|
14675
|
+
requestTaskStore(request, sessionId2) {
|
|
14672
14676
|
const taskStore = this._taskStore;
|
|
14673
14677
|
if (!taskStore) {
|
|
14674
14678
|
throw new Error("No task store configured");
|
|
@@ -14681,18 +14685,18 @@ var Protocol = class {
|
|
|
14681
14685
|
return await taskStore.createTask(taskParams, request.id, {
|
|
14682
14686
|
method: request.method,
|
|
14683
14687
|
params: request.params
|
|
14684
|
-
},
|
|
14688
|
+
}, sessionId2);
|
|
14685
14689
|
},
|
|
14686
14690
|
getTask: async (taskId) => {
|
|
14687
|
-
const task = await taskStore.getTask(taskId,
|
|
14691
|
+
const task = await taskStore.getTask(taskId, sessionId2);
|
|
14688
14692
|
if (!task) {
|
|
14689
14693
|
throw new McpError(ErrorCode.InvalidParams, "Failed to retrieve task: Task not found");
|
|
14690
14694
|
}
|
|
14691
14695
|
return task;
|
|
14692
14696
|
},
|
|
14693
14697
|
storeTaskResult: async (taskId, status, result) => {
|
|
14694
|
-
await taskStore.storeTaskResult(taskId, status, result,
|
|
14695
|
-
const task = await taskStore.getTask(taskId,
|
|
14698
|
+
await taskStore.storeTaskResult(taskId, status, result, sessionId2);
|
|
14699
|
+
const task = await taskStore.getTask(taskId, sessionId2);
|
|
14696
14700
|
if (task) {
|
|
14697
14701
|
const notification = TaskStatusNotificationSchema.parse({
|
|
14698
14702
|
method: "notifications/tasks/status",
|
|
@@ -14705,18 +14709,18 @@ var Protocol = class {
|
|
|
14705
14709
|
}
|
|
14706
14710
|
},
|
|
14707
14711
|
getTaskResult: (taskId) => {
|
|
14708
|
-
return taskStore.getTaskResult(taskId,
|
|
14712
|
+
return taskStore.getTaskResult(taskId, sessionId2);
|
|
14709
14713
|
},
|
|
14710
14714
|
updateTaskStatus: async (taskId, status, statusMessage) => {
|
|
14711
|
-
const task = await taskStore.getTask(taskId,
|
|
14715
|
+
const task = await taskStore.getTask(taskId, sessionId2);
|
|
14712
14716
|
if (!task) {
|
|
14713
14717
|
throw new McpError(ErrorCode.InvalidParams, `Task "${taskId}" not found - it may have been cleaned up`);
|
|
14714
14718
|
}
|
|
14715
14719
|
if (isTerminal(task.status)) {
|
|
14716
14720
|
throw new McpError(ErrorCode.InvalidParams, `Cannot update task "${taskId}" from terminal status "${task.status}" to "${status}". Terminal states (completed, failed, cancelled) cannot transition to other states.`);
|
|
14717
14721
|
}
|
|
14718
|
-
await taskStore.updateTaskStatus(taskId, status, statusMessage,
|
|
14719
|
-
const updatedTask = await taskStore.getTask(taskId,
|
|
14722
|
+
await taskStore.updateTaskStatus(taskId, status, statusMessage, sessionId2);
|
|
14723
|
+
const updatedTask = await taskStore.getTask(taskId, sessionId2);
|
|
14720
14724
|
if (updatedTask) {
|
|
14721
14725
|
const notification = TaskStatusNotificationSchema.parse({
|
|
14722
14726
|
method: "notifications/tasks/status",
|
|
@@ -14729,7 +14733,7 @@ var Protocol = class {
|
|
|
14729
14733
|
}
|
|
14730
14734
|
},
|
|
14731
14735
|
listTasks: (cursor) => {
|
|
14732
|
-
return taskStore.listTasks(cursor,
|
|
14736
|
+
return taskStore.listTasks(cursor, sessionId2);
|
|
14733
14737
|
}
|
|
14734
14738
|
};
|
|
14735
14739
|
}
|
|
@@ -15080,8 +15084,8 @@ var Server = class extends Protocol {
|
|
|
15080
15084
|
this._serverInfo = _serverInfo;
|
|
15081
15085
|
this._loggingLevels = /* @__PURE__ */ new Map();
|
|
15082
15086
|
this.LOG_LEVEL_SEVERITY = new Map(LoggingLevelSchema.options.map((level, index) => [level, index]));
|
|
15083
|
-
this.isMessageIgnored = (level,
|
|
15084
|
-
const currentLevel = this._loggingLevels.get(
|
|
15087
|
+
this.isMessageIgnored = (level, sessionId2) => {
|
|
15088
|
+
const currentLevel = this._loggingLevels.get(sessionId2);
|
|
15085
15089
|
return currentLevel ? this.LOG_LEVEL_SEVERITY.get(level) < this.LOG_LEVEL_SEVERITY.get(currentLevel) : false;
|
|
15086
15090
|
};
|
|
15087
15091
|
this._capabilities = options?.capabilities ?? {};
|
|
@@ -15424,9 +15428,9 @@ var Server = class extends Protocol {
|
|
|
15424
15428
|
* @param params
|
|
15425
15429
|
* @param sessionId optional for stateless and backward compatibility
|
|
15426
15430
|
*/
|
|
15427
|
-
async sendLoggingMessage(params,
|
|
15431
|
+
async sendLoggingMessage(params, sessionId2) {
|
|
15428
15432
|
if (this._capabilities.logging) {
|
|
15429
|
-
if (!this.isMessageIgnored(params.level,
|
|
15433
|
+
if (!this.isMessageIgnored(params.level, sessionId2)) {
|
|
15430
15434
|
return this.notification({ method: "notifications/message", params });
|
|
15431
15435
|
}
|
|
15432
15436
|
}
|
|
@@ -15483,7 +15487,7 @@ function generateToken() {
|
|
|
15483
15487
|
return randomBytes(AUTH_TOKEN_BYTES).toString("hex");
|
|
15484
15488
|
}
|
|
15485
15489
|
function findFreePort() {
|
|
15486
|
-
return new Promise((
|
|
15490
|
+
return new Promise((resolve3, reject) => {
|
|
15487
15491
|
const srv = net.createServer();
|
|
15488
15492
|
srv.listen(0, "127.0.0.1", () => {
|
|
15489
15493
|
const addr = srv.address();
|
|
@@ -15494,7 +15498,7 @@ function findFreePort() {
|
|
|
15494
15498
|
const port = addr.port;
|
|
15495
15499
|
srv.close((err) => {
|
|
15496
15500
|
if (err) reject(err);
|
|
15497
|
-
else
|
|
15501
|
+
else resolve3(port);
|
|
15498
15502
|
});
|
|
15499
15503
|
});
|
|
15500
15504
|
srv.on("error", reject);
|
|
@@ -15536,7 +15540,7 @@ async function isToolsServerHealthy(port, host = "127.0.0.1", timeoutMs = 2e3, t
|
|
|
15536
15540
|
}
|
|
15537
15541
|
}
|
|
15538
15542
|
function spawnToolsServer(paths, port, options = {}) {
|
|
15539
|
-
return new Promise((
|
|
15543
|
+
return new Promise((resolve3, reject) => {
|
|
15540
15544
|
let logFd;
|
|
15541
15545
|
try {
|
|
15542
15546
|
fs.mkdirSync(STATE_DIR, { recursive: true });
|
|
@@ -15568,7 +15572,7 @@ function spawnToolsServer(paths, port, options = {}) {
|
|
|
15568
15572
|
const actualPort = parseInt(match[1], 10);
|
|
15569
15573
|
rl.close();
|
|
15570
15574
|
child.stdout?.resume();
|
|
15571
|
-
settle(() =>
|
|
15575
|
+
settle(() => resolve3({ port: actualPort, pid }));
|
|
15572
15576
|
}
|
|
15573
15577
|
});
|
|
15574
15578
|
child.on("error", (err) => {
|
|
@@ -15699,9 +15703,236 @@ async function isRemoteRouted() {
|
|
|
15699
15703
|
return url !== null;
|
|
15700
15704
|
}
|
|
15701
15705
|
|
|
15702
|
-
// ../argent-
|
|
15706
|
+
// ../argent-tools-client/src/file-inputs.ts
|
|
15707
|
+
import { mkdir as mkdir3, stat, writeFile as writeFile3 } from "node:fs/promises";
|
|
15703
15708
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
15709
|
+
import * as path3 from "node:path";
|
|
15710
|
+
var FILE_INPUT_MARKER = "__argentFileInput";
|
|
15711
|
+
var CLIENT_FILE_MARKER = "__argentClientFile";
|
|
15712
|
+
var MAX_CONTENT_BYTES = 32 * 1024 * 1024;
|
|
15713
|
+
function interpolatePath(template, args) {
|
|
15714
|
+
let missing = false;
|
|
15715
|
+
const out = template.replace(/\$\{([A-Za-z0-9_]+)\}/g, (_m, name) => {
|
|
15716
|
+
const v = args[name];
|
|
15717
|
+
if (typeof v !== "string" || v.length === 0) {
|
|
15718
|
+
missing = true;
|
|
15719
|
+
return "";
|
|
15720
|
+
}
|
|
15721
|
+
return v;
|
|
15722
|
+
});
|
|
15723
|
+
return missing ? null : out;
|
|
15724
|
+
}
|
|
15725
|
+
async function prepareFileInputs(specs, args, opts) {
|
|
15726
|
+
if (!specs || specs.length === 0 || typeof args !== "object" || args === null) {
|
|
15727
|
+
return args;
|
|
15728
|
+
}
|
|
15729
|
+
const record2 = args;
|
|
15730
|
+
let out = null;
|
|
15731
|
+
for (const spec of specs) {
|
|
15732
|
+
if (spec.target in record2 && typeof record2[spec.target] !== "string") continue;
|
|
15733
|
+
const filePath = interpolatePath(spec.path, record2);
|
|
15734
|
+
if (filePath === null) continue;
|
|
15735
|
+
if (spec.target in record2 && record2[spec.target] !== filePath) continue;
|
|
15736
|
+
const wire = { [FILE_INPUT_MARKER]: true, path: filePath };
|
|
15737
|
+
if (spec.kind === "file") {
|
|
15738
|
+
try {
|
|
15739
|
+
const st = await stat(filePath);
|
|
15740
|
+
if (st.isFile()) {
|
|
15741
|
+
wire.size = st.size;
|
|
15742
|
+
wire.mtimeMs = st.mtimeMs;
|
|
15743
|
+
if (opts.includeContent && st.size <= MAX_CONTENT_BYTES) {
|
|
15744
|
+
wire.content = (await readFile3(filePath)).toString("base64");
|
|
15745
|
+
} else if (opts.includeContent) {
|
|
15746
|
+
wire.contentOmitted = "size-limit";
|
|
15747
|
+
}
|
|
15748
|
+
}
|
|
15749
|
+
} catch {
|
|
15750
|
+
}
|
|
15751
|
+
}
|
|
15752
|
+
out = out ?? { ...record2 };
|
|
15753
|
+
out[spec.target] = wire;
|
|
15754
|
+
}
|
|
15755
|
+
return out ?? args;
|
|
15756
|
+
}
|
|
15757
|
+
function isAllowedClientFilePath(p) {
|
|
15758
|
+
if (!path3.isAbsolute(p)) return false;
|
|
15759
|
+
const segments = p.split(/[\\/]+/);
|
|
15760
|
+
if (segments.includes("..")) return false;
|
|
15761
|
+
const file = segments[segments.length - 1] ?? "";
|
|
15762
|
+
if (!/^[A-Za-z0-9_-]+\.yaml$/.test(file)) return false;
|
|
15763
|
+
return segments[segments.length - 3] === ".argent" && segments[segments.length - 2] === "flows";
|
|
15764
|
+
}
|
|
15765
|
+
function isClientFileDirective(value) {
|
|
15766
|
+
return !!value && typeof value === "object" && value[CLIENT_FILE_MARKER] === true && typeof value.path === "string" && typeof value.content === "string";
|
|
15767
|
+
}
|
|
15768
|
+
async function applyClientFileDirectives(result) {
|
|
15769
|
+
const written = [];
|
|
15770
|
+
async function walk(value) {
|
|
15771
|
+
if (isClientFileDirective(value)) {
|
|
15772
|
+
if (!isAllowedClientFilePath(value.path)) return null;
|
|
15773
|
+
try {
|
|
15774
|
+
await mkdir3(path3.dirname(value.path), { recursive: true });
|
|
15775
|
+
await writeFile3(value.path, value.content, "utf8");
|
|
15776
|
+
written.push(value.path);
|
|
15777
|
+
return value.path;
|
|
15778
|
+
} catch {
|
|
15779
|
+
return null;
|
|
15780
|
+
}
|
|
15781
|
+
}
|
|
15782
|
+
if (Array.isArray(value)) {
|
|
15783
|
+
return Promise.all(value.map(walk));
|
|
15784
|
+
}
|
|
15785
|
+
if (value && typeof value === "object") {
|
|
15786
|
+
const out = {};
|
|
15787
|
+
for (const [k, v] of Object.entries(value)) {
|
|
15788
|
+
out[k] = await walk(v);
|
|
15789
|
+
}
|
|
15790
|
+
return out;
|
|
15791
|
+
}
|
|
15792
|
+
return value;
|
|
15793
|
+
}
|
|
15794
|
+
const rewritten = await walk(result);
|
|
15795
|
+
return { result: rewritten, written };
|
|
15796
|
+
}
|
|
15797
|
+
|
|
15798
|
+
// ../argent-tools-client/src/artifacts.ts
|
|
15799
|
+
import { mkdir as mkdir4, readFile as readFile4, rm, stat as stat2, writeFile as writeFile4 } from "node:fs/promises";
|
|
15800
|
+
import { tmpdir } from "node:os";
|
|
15801
|
+
import { basename, join as join3 } from "node:path";
|
|
15802
|
+
import { createHash } from "node:crypto";
|
|
15803
|
+
import { execFile } from "node:child_process";
|
|
15804
|
+
import { promisify } from "node:util";
|
|
15805
|
+
var execFileAsync = promisify(execFile);
|
|
15806
|
+
var ARTIFACT_MARKER = "__argentArtifact";
|
|
15807
|
+
function isArtifactHandle(value) {
|
|
15808
|
+
return !!value && typeof value === "object" && value[ARTIFACT_MARKER] === true && typeof value.id === "string" && typeof value.filename === "string";
|
|
15809
|
+
}
|
|
15810
|
+
var SESSION_ID = null;
|
|
15811
|
+
function sessionId() {
|
|
15812
|
+
if (!SESSION_ID) {
|
|
15813
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:T]/g, (m) => m === "T" ? "-" : "").slice(0, 15);
|
|
15814
|
+
SESSION_ID = `${stamp}-${process.pid}`;
|
|
15815
|
+
}
|
|
15816
|
+
return SESSION_ID;
|
|
15817
|
+
}
|
|
15818
|
+
function sanitizeSegment(segment) {
|
|
15819
|
+
return segment.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
15820
|
+
}
|
|
15821
|
+
function projectSlug() {
|
|
15822
|
+
const cwd = process.cwd();
|
|
15823
|
+
const hash = createHash("sha1").update(cwd).digest("hex").slice(0, 6);
|
|
15824
|
+
const name = sanitizeSegment(basename(cwd)) || "root";
|
|
15825
|
+
return `${name}-${hash}`;
|
|
15826
|
+
}
|
|
15827
|
+
function artifactsRoot() {
|
|
15828
|
+
return process.env.ARGENT_ARTIFACTS_DIR ?? join3(tmpdir(), "argent-artifacts");
|
|
15829
|
+
}
|
|
15830
|
+
function artifactDir(deviceId) {
|
|
15831
|
+
const parts = [artifactsRoot(), projectSlug(), sessionId()];
|
|
15832
|
+
if (deviceId) parts.push(sanitizeSegment(deviceId));
|
|
15833
|
+
return join3(...parts);
|
|
15834
|
+
}
|
|
15835
|
+
async function resolveLocalFile(handle) {
|
|
15836
|
+
if (!handle.hostPath) return null;
|
|
15837
|
+
try {
|
|
15838
|
+
const st = await stat2(handle.hostPath);
|
|
15839
|
+
if (handle.archive) {
|
|
15840
|
+
return st.isDirectory() ? handle.hostPath : null;
|
|
15841
|
+
}
|
|
15842
|
+
if (!st.isFile()) return null;
|
|
15843
|
+
if (st.size !== handle.size) return null;
|
|
15844
|
+
if (handle.mtimeMs != null && Math.round(st.mtimeMs) !== Math.round(handle.mtimeMs)) {
|
|
15845
|
+
return null;
|
|
15846
|
+
}
|
|
15847
|
+
return handle.hostPath;
|
|
15848
|
+
} catch {
|
|
15849
|
+
return null;
|
|
15850
|
+
}
|
|
15851
|
+
}
|
|
15852
|
+
async function downloadAndExtractArchive(handle, data, dir) {
|
|
15853
|
+
const tarball = join3(dir, `${sanitizeSegment(handle.filename)}.tar.gz`);
|
|
15854
|
+
try {
|
|
15855
|
+
await writeFile4(tarball, data);
|
|
15856
|
+
await execFileAsync("tar", ["-xzf", tarball, "-C", dir]);
|
|
15857
|
+
return join3(dir, handle.filename);
|
|
15858
|
+
} catch {
|
|
15859
|
+
return null;
|
|
15860
|
+
} finally {
|
|
15861
|
+
await rm(tarball, { force: true }).catch(() => {
|
|
15862
|
+
});
|
|
15863
|
+
}
|
|
15864
|
+
}
|
|
15865
|
+
async function materializeArtifacts(result, ctx) {
|
|
15866
|
+
const images = [];
|
|
15867
|
+
const fetchFn = ctx.fetchImpl ?? fetch;
|
|
15868
|
+
const authHeaders2 = ctx.authToken ? { Authorization: `Bearer ${ctx.authToken}` } : {};
|
|
15869
|
+
const dir = artifactDir(ctx.deviceId);
|
|
15870
|
+
let dirReady = false;
|
|
15871
|
+
async function ensureDir() {
|
|
15872
|
+
if (!dirReady) {
|
|
15873
|
+
await mkdir4(dir, { recursive: true });
|
|
15874
|
+
dirReady = true;
|
|
15875
|
+
}
|
|
15876
|
+
}
|
|
15877
|
+
async function walk(value) {
|
|
15878
|
+
if (isArtifactHandle(value)) {
|
|
15879
|
+
const localPath = await resolveLocalFile(value);
|
|
15880
|
+
if (localPath) {
|
|
15881
|
+
if (value.mimeType.startsWith("image/")) {
|
|
15882
|
+
images.push({ localPath, data: await readFile4(localPath), mimeType: value.mimeType });
|
|
15883
|
+
}
|
|
15884
|
+
return localPath;
|
|
15885
|
+
}
|
|
15886
|
+
try {
|
|
15887
|
+
const res = await fetchFn(`${ctx.toolsUrl}/artifacts/${value.id}`, {
|
|
15888
|
+
headers: authHeaders2
|
|
15889
|
+
});
|
|
15890
|
+
if (!res.ok) return null;
|
|
15891
|
+
const data = Buffer.from(await res.arrayBuffer());
|
|
15892
|
+
await ensureDir();
|
|
15893
|
+
if (value.archive === "tar.gz") {
|
|
15894
|
+
return await downloadAndExtractArchive(value, data, dir);
|
|
15895
|
+
}
|
|
15896
|
+
if (value.size > 0 && data.length !== value.size) return null;
|
|
15897
|
+
const downloadedPath = join3(dir, sanitizeSegment(value.filename));
|
|
15898
|
+
await writeFile4(downloadedPath, data);
|
|
15899
|
+
if (value.mimeType.startsWith("image/")) {
|
|
15900
|
+
images.push({ localPath: downloadedPath, data, mimeType: value.mimeType });
|
|
15901
|
+
}
|
|
15902
|
+
return downloadedPath;
|
|
15903
|
+
} catch {
|
|
15904
|
+
return null;
|
|
15905
|
+
}
|
|
15906
|
+
}
|
|
15907
|
+
if (Array.isArray(value)) {
|
|
15908
|
+
return Promise.all(value.map(walk));
|
|
15909
|
+
}
|
|
15910
|
+
if (value && typeof value === "object") {
|
|
15911
|
+
const out = {};
|
|
15912
|
+
for (const [k, v] of Object.entries(value)) {
|
|
15913
|
+
out[k] = await walk(v);
|
|
15914
|
+
}
|
|
15915
|
+
return out;
|
|
15916
|
+
}
|
|
15917
|
+
return value;
|
|
15918
|
+
}
|
|
15919
|
+
const rewritten = await walk(result);
|
|
15920
|
+
return { result: rewritten, images };
|
|
15921
|
+
}
|
|
15922
|
+
function getDeviceIdFromArgs(args) {
|
|
15923
|
+
if (!args || typeof args !== "object") return void 0;
|
|
15924
|
+
const rec = args;
|
|
15925
|
+
if (typeof rec.udid === "string") return rec.udid;
|
|
15926
|
+
if (typeof rec.device_id === "string") return rec.device_id;
|
|
15927
|
+
return void 0;
|
|
15928
|
+
}
|
|
15929
|
+
|
|
15930
|
+
// ../argent-mcp/src/content.ts
|
|
15931
|
+
import { readFile as readFile5 } from "node:fs/promises";
|
|
15704
15932
|
var PNG_SIGNATURE = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
|
|
15933
|
+
function imageBlock(data, mimeType) {
|
|
15934
|
+
return { type: "image", data: data.toString("base64"), mimeType };
|
|
15935
|
+
}
|
|
15705
15936
|
async function fetchPngBytes(url) {
|
|
15706
15937
|
try {
|
|
15707
15938
|
const res = await fetch(url);
|
|
@@ -15714,22 +15945,38 @@ async function fetchPngBytes(url) {
|
|
|
15714
15945
|
return null;
|
|
15715
15946
|
}
|
|
15716
15947
|
}
|
|
15717
|
-
async function toMcpContent(result, outputHint, args) {
|
|
15718
|
-
|
|
15948
|
+
async function toMcpContent(result, outputHint, ctx, args) {
|
|
15949
|
+
const suppressImage = isRecord(args) && args.includeImageInContext === false;
|
|
15950
|
+
if (ctx) {
|
|
15951
|
+
const { result: rewritten, images } = await materializeArtifacts(result, ctx);
|
|
15952
|
+
if (outputHint === "image") {
|
|
15953
|
+
if (images.length > 0) {
|
|
15954
|
+
const saved = { type: "text", text: `Saved: ${images[0].localPath}` };
|
|
15955
|
+
if (suppressImage) return [saved];
|
|
15956
|
+
const blocks2 = images.map((img) => imageBlock(img.data, img.mimeType));
|
|
15957
|
+
blocks2.push(saved);
|
|
15958
|
+
return blocks2;
|
|
15959
|
+
}
|
|
15960
|
+
return legacyImageContent(rewritten, suppressImage);
|
|
15961
|
+
}
|
|
15962
|
+
const blocks = [{ type: "text", text: JSON.stringify(rewritten, null, 2) }];
|
|
15963
|
+
if (!suppressImage) for (const img of images) blocks.push(imageBlock(img.data, img.mimeType));
|
|
15964
|
+
return blocks;
|
|
15965
|
+
}
|
|
15966
|
+
if (outputHint === "image") {
|
|
15967
|
+
return legacyImageContent(result, suppressImage);
|
|
15968
|
+
}
|
|
15969
|
+
return [{ type: "text", text: JSON.stringify(result, null, 2) }];
|
|
15970
|
+
}
|
|
15971
|
+
async function legacyImageContent(result, suppressImage) {
|
|
15972
|
+
if (result && typeof result === "object" && "url" in result) {
|
|
15719
15973
|
const r = result;
|
|
15720
|
-
if (
|
|
15721
|
-
return [{ type: "text", text: `Saved: ${r.path}` }];
|
|
15974
|
+
if (suppressImage) {
|
|
15975
|
+
return [{ type: "text", text: `Saved: ${r.path ?? ""}` }];
|
|
15722
15976
|
}
|
|
15723
15977
|
const buf = await fetchPngBytes(r.url);
|
|
15724
15978
|
if (buf) {
|
|
15725
|
-
return [
|
|
15726
|
-
{
|
|
15727
|
-
type: "image",
|
|
15728
|
-
data: buf.toString("base64"),
|
|
15729
|
-
mimeType: "image/png"
|
|
15730
|
-
},
|
|
15731
|
-
{ type: "text", text: `Saved: ${r.path ?? ""}` }
|
|
15732
|
-
];
|
|
15979
|
+
return [imageBlock(buf, "image/png"), { type: "text", text: `Saved: ${r.path ?? ""}` }];
|
|
15733
15980
|
}
|
|
15734
15981
|
return [
|
|
15735
15982
|
{
|
|
@@ -15747,20 +15994,39 @@ function isScreenshotDiffResult(value) {
|
|
|
15747
15994
|
if (!isRecord(value)) return false;
|
|
15748
15995
|
return typeof value.summary === "string";
|
|
15749
15996
|
}
|
|
15750
|
-
async function screenshotDiffToMcpContent(result) {
|
|
15997
|
+
async function screenshotDiffToMcpContent(result, ctx) {
|
|
15751
15998
|
const blocks = [];
|
|
15752
|
-
|
|
15753
|
-
|
|
15754
|
-
|
|
15755
|
-
|
|
15756
|
-
|
|
15757
|
-
|
|
15758
|
-
|
|
15999
|
+
let contextDiffPath = result.contextDiffPath;
|
|
16000
|
+
let materializedImages = [];
|
|
16001
|
+
if (ctx) {
|
|
16002
|
+
const { result: rewritten, images } = await materializeArtifacts(result, ctx);
|
|
16003
|
+
contextDiffPath = rewritten.contextDiffPath;
|
|
16004
|
+
materializedImages = images;
|
|
16005
|
+
}
|
|
16006
|
+
if (typeof contextDiffPath === "string") {
|
|
16007
|
+
const fromMaterializer = materializedImages.find((img) => img.localPath === contextDiffPath);
|
|
16008
|
+
if (fromMaterializer) {
|
|
16009
|
+
blocks.push({
|
|
16010
|
+
type: "image",
|
|
16011
|
+
data: fromMaterializer.data.toString("base64"),
|
|
16012
|
+
mimeType: fromMaterializer.mimeType
|
|
16013
|
+
});
|
|
16014
|
+
} else {
|
|
16015
|
+
try {
|
|
16016
|
+
const buf = await readFile5(contextDiffPath);
|
|
16017
|
+
blocks.push({
|
|
16018
|
+
type: "image",
|
|
16019
|
+
data: buf.toString("base64"),
|
|
16020
|
+
mimeType: "image/png"
|
|
16021
|
+
});
|
|
16022
|
+
} catch {
|
|
16023
|
+
}
|
|
16024
|
+
}
|
|
15759
16025
|
}
|
|
15760
16026
|
blocks.push({ type: "text", text: result.summary });
|
|
15761
16027
|
return blocks;
|
|
15762
16028
|
}
|
|
15763
|
-
async function flowRunToMcpContent(result) {
|
|
16029
|
+
async function flowRunToMcpContent(result, ctx) {
|
|
15764
16030
|
const blocks = [];
|
|
15765
16031
|
if (result.executionPrerequisite) {
|
|
15766
16032
|
blocks.push({
|
|
@@ -15784,7 +16050,7 @@ async function flowRunToMcpContent(result) {
|
|
|
15784
16050
|
});
|
|
15785
16051
|
} else {
|
|
15786
16052
|
blocks.push({ type: "text", text: `[${num}] ${step.tool}` });
|
|
15787
|
-
const stepContent = await toMcpContent(step.result, step.outputHint, step.args);
|
|
16053
|
+
const stepContent = await toMcpContent(step.result, step.outputHint, ctx, step.args);
|
|
15788
16054
|
blocks.push(...stepContent);
|
|
15789
16055
|
}
|
|
15790
16056
|
}
|
|
@@ -15792,10 +16058,70 @@ async function flowRunToMcpContent(result) {
|
|
|
15792
16058
|
return blocks;
|
|
15793
16059
|
}
|
|
15794
16060
|
|
|
16061
|
+
// ../configuration-core/src/flags.ts
|
|
16062
|
+
import * as fs2 from "node:fs";
|
|
16063
|
+
import * as path4 from "node:path";
|
|
16064
|
+
import { homedir as homedir3 } from "node:os";
|
|
16065
|
+
var PROJECT_MARKERS = [".argent", ".git", "package.json"];
|
|
16066
|
+
function resolveProjectRoot(startDir) {
|
|
16067
|
+
const initial = path4.resolve(startDir);
|
|
16068
|
+
let current = initial;
|
|
16069
|
+
while (true) {
|
|
16070
|
+
for (const marker of PROJECT_MARKERS) {
|
|
16071
|
+
if (fs2.existsSync(path4.join(current, marker))) return current;
|
|
16072
|
+
}
|
|
16073
|
+
const parent = path4.dirname(current);
|
|
16074
|
+
if (parent === current) return initial;
|
|
16075
|
+
current = parent;
|
|
16076
|
+
}
|
|
16077
|
+
}
|
|
16078
|
+
function getFlagsPath(scope, options = {}) {
|
|
16079
|
+
const home = options.homeDir ?? homedir3();
|
|
16080
|
+
if (scope === "global") {
|
|
16081
|
+
return path4.join(home, ".argent", "flags.json");
|
|
16082
|
+
}
|
|
16083
|
+
const cwd = options.cwd ?? process.cwd();
|
|
16084
|
+
return path4.join(resolveProjectRoot(cwd), ".argent", "flags.json");
|
|
16085
|
+
}
|
|
16086
|
+
function readFlagsFile(filePath) {
|
|
16087
|
+
let raw;
|
|
16088
|
+
try {
|
|
16089
|
+
raw = fs2.readFileSync(filePath, "utf8");
|
|
16090
|
+
} catch {
|
|
16091
|
+
return {};
|
|
16092
|
+
}
|
|
16093
|
+
let parsed;
|
|
16094
|
+
try {
|
|
16095
|
+
parsed = JSON.parse(raw);
|
|
16096
|
+
} catch {
|
|
16097
|
+
return {};
|
|
16098
|
+
}
|
|
16099
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
16100
|
+
const flags = parsed.flags;
|
|
16101
|
+
if (!flags || typeof flags !== "object" || Array.isArray(flags)) return {};
|
|
16102
|
+
const out = {};
|
|
16103
|
+
for (const [k, v] of Object.entries(flags)) {
|
|
16104
|
+
if (typeof v === "boolean") out[k] = v;
|
|
16105
|
+
}
|
|
16106
|
+
return out;
|
|
16107
|
+
}
|
|
16108
|
+
function readFlags(scope, options = {}) {
|
|
16109
|
+
return readFlagsFile(getFlagsPath(scope, options));
|
|
16110
|
+
}
|
|
16111
|
+
function isFlagEnabled(name, options = {}) {
|
|
16112
|
+
const projectFlags = readFlags("project", options);
|
|
16113
|
+
if (Object.hasOwn(projectFlags, name)) return projectFlags[name];
|
|
16114
|
+
const globalFlags = readFlags("global", options);
|
|
16115
|
+
if (Object.hasOwn(globalFlags, name)) return globalFlags[name];
|
|
16116
|
+
return false;
|
|
16117
|
+
}
|
|
16118
|
+
|
|
15795
16119
|
// ../argent-mcp/src/auto-screenshot.ts
|
|
15796
16120
|
var AUTO_SCREENSHOT_TOOLS = /* @__PURE__ */ new Set([
|
|
15797
16121
|
"gesture-tap",
|
|
15798
16122
|
"gesture-swipe",
|
|
16123
|
+
"gesture-scroll",
|
|
16124
|
+
"gesture-drag",
|
|
15799
16125
|
"gesture-custom",
|
|
15800
16126
|
"gesture-pinch",
|
|
15801
16127
|
"gesture-rotate",
|
|
@@ -15813,6 +16139,8 @@ var AUTO_SCREENSHOT_DELAY_MS_BY_TOOL = {
|
|
|
15813
16139
|
"restart-app": 3e3,
|
|
15814
16140
|
"open-url": 2e3,
|
|
15815
16141
|
"gesture-swipe": 1500,
|
|
16142
|
+
"gesture-scroll": 1500,
|
|
16143
|
+
"gesture-drag": 1500,
|
|
15816
16144
|
"gesture-custom": 1500,
|
|
15817
16145
|
"gesture-tap": 1500,
|
|
15818
16146
|
"gesture-pinch": 1500,
|
|
@@ -15824,9 +16152,8 @@ var AUTO_SCREENSHOT_DELAY_MS_BY_TOOL = {
|
|
|
15824
16152
|
"describe": 100
|
|
15825
16153
|
};
|
|
15826
16154
|
var DEFAULT_DELAY_MS = 1400;
|
|
15827
|
-
function autoScreenshotEnabled() {
|
|
15828
|
-
|
|
15829
|
-
return v === void 0 || v === "" || v === "1" || v.toLowerCase() === "true";
|
|
16155
|
+
function autoScreenshotEnabled(options) {
|
|
16156
|
+
return !isFlagEnabled("disable-auto-screenshot", options);
|
|
15830
16157
|
}
|
|
15831
16158
|
function getUdidFromArgs(args) {
|
|
15832
16159
|
if (args && typeof args === "object" && "udid" in args && typeof args.udid === "string") {
|
|
@@ -15866,6 +16193,19 @@ function toMcpTool(t) {
|
|
|
15866
16193
|
};
|
|
15867
16194
|
}
|
|
15868
16195
|
|
|
16196
|
+
// ../argent-mcp/src/installed-version.ts
|
|
16197
|
+
import * as fs3 from "node:fs";
|
|
16198
|
+
import * as path5 from "node:path";
|
|
16199
|
+
function getInstalledVersion() {
|
|
16200
|
+
try {
|
|
16201
|
+
const pkgPath = path5.resolve(import.meta.dirname, "..", "package.json");
|
|
16202
|
+
const pkg = JSON.parse(fs3.readFileSync(pkgPath, "utf8"));
|
|
16203
|
+
return pkg.version ?? "unknown";
|
|
16204
|
+
} catch {
|
|
16205
|
+
return "unknown";
|
|
16206
|
+
}
|
|
16207
|
+
}
|
|
16208
|
+
|
|
15869
16209
|
// ../argent-mcp/src/mcp-server.ts
|
|
15870
16210
|
var MAX_RETRIES = 4;
|
|
15871
16211
|
var EXP_BACKOFF_BASE = 250;
|
|
@@ -15897,6 +16237,7 @@ async function fetchWithReconnect(getUrl, reconnect, config2) {
|
|
|
15897
16237
|
throw lastError;
|
|
15898
16238
|
}
|
|
15899
16239
|
async function startMcpServer(options) {
|
|
16240
|
+
const autoScreenshotOn = autoScreenshotEnabled();
|
|
15900
16241
|
let TOOLS_URL;
|
|
15901
16242
|
let AUTH_TOKEN;
|
|
15902
16243
|
const resolved = await getResolvedToolsUrl();
|
|
@@ -15930,12 +16271,12 @@ async function startMcpServer(options) {
|
|
|
15930
16271
|
}
|
|
15931
16272
|
return reconnectPromise;
|
|
15932
16273
|
}
|
|
15933
|
-
const LOG_FILE2 = process.env.ARGENT_MCP_LOG ?? `${
|
|
16274
|
+
const LOG_FILE2 = process.env.ARGENT_MCP_LOG ?? `${homedir4()}/.argent/mcp-calls.log`;
|
|
15934
16275
|
let logDirReady = false;
|
|
15935
16276
|
async function spyLog(entry) {
|
|
15936
16277
|
try {
|
|
15937
16278
|
if (!logDirReady) {
|
|
15938
|
-
await
|
|
16279
|
+
await mkdir5(dirname3(LOG_FILE2), { recursive: true });
|
|
15939
16280
|
logDirReady = true;
|
|
15940
16281
|
}
|
|
15941
16282
|
await appendFile(LOG_FILE2, JSON.stringify(entry) + "\n");
|
|
@@ -15952,23 +16293,33 @@ async function startMcpServer(options) {
|
|
|
15952
16293
|
async function callTool(name, args) {
|
|
15953
16294
|
const tools = await fetchTools();
|
|
15954
16295
|
const meta2 = tools.find((t) => t.name === name);
|
|
16296
|
+
let finalArgs = args;
|
|
16297
|
+
if (meta2?.fileInputs?.length) {
|
|
16298
|
+
finalArgs = await prepareFileInputs(meta2.fileInputs, args ?? {}, {
|
|
16299
|
+
// `resolved` is the startup routing decision that picked TOOLS_URL —
|
|
16300
|
+
// an external target means this process may not share the server's
|
|
16301
|
+
// filesystem, so file bytes must ride along.
|
|
16302
|
+
includeContent: resolved.url !== null
|
|
16303
|
+
});
|
|
16304
|
+
}
|
|
15955
16305
|
const res = await fetchWithReconnect(() => `${TOOLS_URL}/tools/${name}`, reconnect, {
|
|
15956
16306
|
init: {
|
|
15957
16307
|
method: "POST",
|
|
15958
16308
|
headers: { "Content-Type": "application/json", ...authHeader() },
|
|
15959
|
-
body: JSON.stringify(
|
|
16309
|
+
body: JSON.stringify(finalArgs ?? {})
|
|
15960
16310
|
},
|
|
15961
16311
|
fetchTimeoutMs: meta2?.longRunning ? null : FETCH_TIMEOUT_MS
|
|
15962
16312
|
});
|
|
15963
16313
|
const json = await res.json();
|
|
15964
16314
|
if (!res.ok) throw new Error(json.error ?? json.message ?? res.statusText);
|
|
15965
|
-
|
|
16315
|
+
const { result: data } = await applyClientFileDirectives(json.data);
|
|
16316
|
+
return { result: data, outputHint: meta2?.outputHint, note: json.note };
|
|
15966
16317
|
}
|
|
15967
16318
|
const server = new Server(
|
|
15968
|
-
{ name: "argent", version:
|
|
16319
|
+
{ name: "argent", version: getInstalledVersion() },
|
|
15969
16320
|
{
|
|
15970
16321
|
capabilities: { tools: {} },
|
|
15971
|
-
instructions: "Argent \u2014 iOS Simulator
|
|
16322
|
+
instructions: "Argent \u2014 iOS Simulator, Android Emulator, and Chromium app control for interacting, testing, profiling and debugging mobile and Chromium applications. Always use discovery tools (describe / debugger-component-tree / screenshot) before tapping \u2014 never guess coordinates. On session end: call stop-all-simulator-servers and perform any necessary cleanup. Full guidance is in the argent rule loaded from .claude/rules/argent.md."
|
|
15972
16323
|
}
|
|
15973
16324
|
);
|
|
15974
16325
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
@@ -16006,21 +16357,30 @@ async function startMcpServer(options) {
|
|
|
16006
16357
|
isError: false,
|
|
16007
16358
|
result
|
|
16008
16359
|
});
|
|
16360
|
+
const ctx = {
|
|
16361
|
+
toolsUrl: TOOLS_URL,
|
|
16362
|
+
authToken: AUTH_TOKEN,
|
|
16363
|
+
deviceId: getDeviceIdFromArgs(params.arguments)
|
|
16364
|
+
};
|
|
16009
16365
|
let content;
|
|
16010
16366
|
if (params.name === "flow-execute" && result && typeof result === "object" && "flow" in result && "steps" in result) {
|
|
16011
|
-
content = await flowRunToMcpContent(result);
|
|
16367
|
+
content = await flowRunToMcpContent(result, ctx);
|
|
16012
16368
|
} else if (params.name === "screenshot-diff" && isScreenshotDiffResult(result)) {
|
|
16013
|
-
content = await screenshotDiffToMcpContent(result);
|
|
16369
|
+
content = await screenshotDiffToMcpContent(result, ctx);
|
|
16014
16370
|
} else {
|
|
16015
|
-
content = await toMcpContent(result, outputHint, params.arguments);
|
|
16371
|
+
content = await toMcpContent(result, outputHint, ctx, params.arguments);
|
|
16016
16372
|
}
|
|
16017
16373
|
const udid = getUdidFromArgs(params.arguments);
|
|
16018
|
-
if (
|
|
16374
|
+
if (autoScreenshotOn && udid && shouldAutoScreenshot(params.name)) {
|
|
16019
16375
|
const delayMs = getAutoScreenshotDelayMs(params.name);
|
|
16020
16376
|
if (delayMs > 0) await new Promise((r) => setTimeout(r, delayMs));
|
|
16021
16377
|
try {
|
|
16022
16378
|
const screenshotResult = await callTool("screenshot", { udid });
|
|
16023
|
-
const screenshotContent = await toMcpContent(screenshotResult.result, "image", {
|
|
16379
|
+
const screenshotContent = await toMcpContent(screenshotResult.result, "image", {
|
|
16380
|
+
toolsUrl: TOOLS_URL,
|
|
16381
|
+
authToken: AUTH_TOKEN,
|
|
16382
|
+
deviceId: udid
|
|
16383
|
+
});
|
|
16024
16384
|
const hasImage = screenshotContent.some((b) => b.type === "image");
|
|
16025
16385
|
if (hasImage) {
|
|
16026
16386
|
content = [
|
|
@@ -16083,7 +16443,7 @@ async function startMcpServer(options) {
|
|
|
16083
16443
|
}, HEALTH_INTERVAL_MS);
|
|
16084
16444
|
healthInterval.unref();
|
|
16085
16445
|
}
|
|
16086
|
-
if (process.env.
|
|
16446
|
+
if (process.env.ARGENT_TOOL_SERVER_SHUTDOWN_ON_MCP_EXIT === "1") {
|
|
16087
16447
|
process.stdin.on("close", () => {
|
|
16088
16448
|
fetch(`${TOOLS_URL}/shutdown`, { method: "POST", headers: authHeader() }).catch(() => {
|
|
16089
16449
|
});
|