@swmansion/argent 0.10.0 → 0.11.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/darwin/ax-service +0 -0
- package/dist/cli-cmds.mjs +868 -701
- package/dist/installer.mjs +9 -0
- package/dist/mcp-server.mjs +297 -79
- package/dist/tool-server.cjs +3270 -1413
- package/dylibs/libArgentInjectionBootstrap.dylib +0 -0
- package/dylibs/libKeyboardPatch.dylib +0 -0
- package/dylibs/libNativeDevtoolsIos.dylib +0 -0
- package/package.json +2 -2
- package/skills/argent-native-profiler/SKILL.md +5 -5
- /package/{dist → assets}/Argent.tracetemplate +0 -0
- /package/{manifest.json → assets/manifest.json} +0 -0
package/dist/mcp-server.mjs
CHANGED
|
@@ -2980,7 +2980,7 @@ var require_compile = __commonJS({
|
|
|
2980
2980
|
const schOrFunc = root.refs[ref];
|
|
2981
2981
|
if (schOrFunc)
|
|
2982
2982
|
return schOrFunc;
|
|
2983
|
-
let _sch =
|
|
2983
|
+
let _sch = resolve2.call(this, root, ref);
|
|
2984
2984
|
if (_sch === void 0) {
|
|
2985
2985
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
2986
2986
|
const { schemaId } = this.opts;
|
|
@@ -3007,7 +3007,7 @@ var require_compile = __commonJS({
|
|
|
3007
3007
|
function sameSchemaEnv(s1, s2) {
|
|
3008
3008
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3009
3009
|
}
|
|
3010
|
-
function
|
|
3010
|
+
function resolve2(root, ref) {
|
|
3011
3011
|
let sch;
|
|
3012
3012
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3013
3013
|
ref = sch;
|
|
@@ -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(path4) {
|
|
3229
|
+
let input = path4;
|
|
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 [path4, query] = wsComponent.resourceName.split("?");
|
|
3482
|
+
wsComponent.path = path4 && path4 !== "/" ? path4 : void 0;
|
|
3483
3483
|
wsComponent.query = query;
|
|
3484
3484
|
wsComponent.resourceName = void 0;
|
|
3485
3485
|
}
|
|
@@ -3638,7 +3638,7 @@ var require_fast_uri = __commonJS({
|
|
|
3638
3638
|
}
|
|
3639
3639
|
return uri;
|
|
3640
3640
|
}
|
|
3641
|
-
function
|
|
3641
|
+
function resolve2(baseURI, relativeURI, options) {
|
|
3642
3642
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3643
3643
|
const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
3644
3644
|
schemelessOptions.skipEscape = true;
|
|
@@ -3896,7 +3896,7 @@ var require_fast_uri = __commonJS({
|
|
|
3896
3896
|
var fastUri = {
|
|
3897
3897
|
SCHEMES,
|
|
3898
3898
|
normalize,
|
|
3899
|
-
resolve,
|
|
3899
|
+
resolve: resolve2,
|
|
3900
3900
|
resolveComponent,
|
|
3901
3901
|
equal,
|
|
3902
3902
|
serialize,
|
|
@@ -6872,12 +6872,12 @@ var require_dist = __commonJS({
|
|
|
6872
6872
|
throw new Error(`Unknown format "${name}"`);
|
|
6873
6873
|
return f;
|
|
6874
6874
|
};
|
|
6875
|
-
function addFormats(ajv, list,
|
|
6875
|
+
function addFormats(ajv, list, fs3, exportName) {
|
|
6876
6876
|
var _a3;
|
|
6877
6877
|
var _b;
|
|
6878
6878
|
(_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
6879
6879
|
for (const f of list)
|
|
6880
|
-
ajv.addFormat(f,
|
|
6880
|
+
ajv.addFormat(f, fs3[f]);
|
|
6881
6881
|
}
|
|
6882
6882
|
module.exports = exports = formatsPlugin;
|
|
6883
6883
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -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
|
|
6890
|
-
import { dirname } from "node:path";
|
|
6891
|
-
import { homedir as
|
|
6889
|
+
import { appendFile, mkdir as mkdir4 } from "node:fs/promises";
|
|
6890
|
+
import { dirname as dirname2 } from "node:path";
|
|
6891
|
+
import { homedir as homedir4 } 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, path4) {
|
|
7137
|
+
if (!path4)
|
|
7138
7138
|
return obj;
|
|
7139
|
-
return
|
|
7139
|
+
return path4.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(path4, 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(path4);
|
|
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, path4 = []) => {
|
|
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 }, [...path4, ...issue2.path]));
|
|
7703
7703
|
} else if (issue2.code === "invalid_key") {
|
|
7704
|
-
processError({ issues: issue2.issues }, [...
|
|
7704
|
+
processError({ issues: issue2.issues }, [...path4, ...issue2.path]);
|
|
7705
7705
|
} else if (issue2.code === "invalid_element") {
|
|
7706
|
-
processError({ issues: issue2.issues }, [...
|
|
7706
|
+
processError({ issues: issue2.issues }, [...path4, ...issue2.path]);
|
|
7707
7707
|
} else {
|
|
7708
|
-
const fullpath = [...
|
|
7708
|
+
const fullpath = [...path4, ...issue2.path];
|
|
7709
7709
|
if (fullpath.length === 0) {
|
|
7710
7710
|
fieldErrors._errors.push(mapper(issue2));
|
|
7711
7711
|
} else {
|
|
@@ -13697,12 +13697,12 @@ var StdioServerTransport = class {
|
|
|
13697
13697
|
this.onclose?.();
|
|
13698
13698
|
}
|
|
13699
13699
|
send(message) {
|
|
13700
|
-
return new Promise((
|
|
13700
|
+
return new Promise((resolve2) => {
|
|
13701
13701
|
const json = serializeMessage(message);
|
|
13702
13702
|
if (this._stdout.write(json)) {
|
|
13703
|
-
|
|
13703
|
+
resolve2();
|
|
13704
13704
|
} else {
|
|
13705
|
-
this._stdout.once("drain",
|
|
13705
|
+
this._stdout.once("drain", resolve2);
|
|
13706
13706
|
}
|
|
13707
13707
|
});
|
|
13708
13708
|
}
|
|
@@ -14300,7 +14300,7 @@ var Protocol = class {
|
|
|
14300
14300
|
return;
|
|
14301
14301
|
}
|
|
14302
14302
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
14303
|
-
await new Promise((
|
|
14303
|
+
await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
|
|
14304
14304
|
options?.signal?.throwIfAborted();
|
|
14305
14305
|
}
|
|
14306
14306
|
} catch (error2) {
|
|
@@ -14317,7 +14317,7 @@ var Protocol = class {
|
|
|
14317
14317
|
*/
|
|
14318
14318
|
request(request, resultSchema, options) {
|
|
14319
14319
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
14320
|
-
return new Promise((
|
|
14320
|
+
return new Promise((resolve2, reject) => {
|
|
14321
14321
|
const earlyReject = (error2) => {
|
|
14322
14322
|
reject(error2);
|
|
14323
14323
|
};
|
|
@@ -14395,7 +14395,7 @@ var Protocol = class {
|
|
|
14395
14395
|
if (!parseResult.success) {
|
|
14396
14396
|
reject(parseResult.error);
|
|
14397
14397
|
} else {
|
|
14398
|
-
|
|
14398
|
+
resolve2(parseResult.data);
|
|
14399
14399
|
}
|
|
14400
14400
|
} catch (error2) {
|
|
14401
14401
|
reject(error2);
|
|
@@ -14611,21 +14611,21 @@ var Protocol = class {
|
|
|
14611
14611
|
* the error appropriately (e.g., by failing the task, logging, etc.). The Protocol layer
|
|
14612
14612
|
* simply propagates the error.
|
|
14613
14613
|
*/
|
|
14614
|
-
async _enqueueTaskMessage(taskId, message,
|
|
14614
|
+
async _enqueueTaskMessage(taskId, message, sessionId2) {
|
|
14615
14615
|
if (!this._taskStore || !this._taskMessageQueue) {
|
|
14616
14616
|
throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
|
|
14617
14617
|
}
|
|
14618
14618
|
const maxQueueSize = this._options?.maxTaskQueueSize;
|
|
14619
|
-
await this._taskMessageQueue.enqueue(taskId, message,
|
|
14619
|
+
await this._taskMessageQueue.enqueue(taskId, message, sessionId2, maxQueueSize);
|
|
14620
14620
|
}
|
|
14621
14621
|
/**
|
|
14622
14622
|
* Clears the message queue for a task and rejects any pending request resolvers.
|
|
14623
14623
|
* @param taskId The task ID whose queue should be cleared
|
|
14624
14624
|
* @param sessionId Optional session ID for binding the operation to a specific session
|
|
14625
14625
|
*/
|
|
14626
|
-
async _clearTaskQueue(taskId,
|
|
14626
|
+
async _clearTaskQueue(taskId, sessionId2) {
|
|
14627
14627
|
if (this._taskMessageQueue) {
|
|
14628
|
-
const messages = await this._taskMessageQueue.dequeueAll(taskId,
|
|
14628
|
+
const messages = await this._taskMessageQueue.dequeueAll(taskId, sessionId2);
|
|
14629
14629
|
for (const message of messages) {
|
|
14630
14630
|
if (message.type === "request" && isJSONRPCRequest(message.message)) {
|
|
14631
14631
|
const requestId = message.message.id;
|
|
@@ -14656,19 +14656,19 @@ var Protocol = class {
|
|
|
14656
14656
|
}
|
|
14657
14657
|
} catch {
|
|
14658
14658
|
}
|
|
14659
|
-
return new Promise((
|
|
14659
|
+
return new Promise((resolve2, reject) => {
|
|
14660
14660
|
if (signal.aborted) {
|
|
14661
14661
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
14662
14662
|
return;
|
|
14663
14663
|
}
|
|
14664
|
-
const timeoutId = setTimeout(
|
|
14664
|
+
const timeoutId = setTimeout(resolve2, interval);
|
|
14665
14665
|
signal.addEventListener("abort", () => {
|
|
14666
14666
|
clearTimeout(timeoutId);
|
|
14667
14667
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
14668
14668
|
}, { once: true });
|
|
14669
14669
|
});
|
|
14670
14670
|
}
|
|
14671
|
-
requestTaskStore(request,
|
|
14671
|
+
requestTaskStore(request, sessionId2) {
|
|
14672
14672
|
const taskStore = this._taskStore;
|
|
14673
14673
|
if (!taskStore) {
|
|
14674
14674
|
throw new Error("No task store configured");
|
|
@@ -14681,18 +14681,18 @@ var Protocol = class {
|
|
|
14681
14681
|
return await taskStore.createTask(taskParams, request.id, {
|
|
14682
14682
|
method: request.method,
|
|
14683
14683
|
params: request.params
|
|
14684
|
-
},
|
|
14684
|
+
}, sessionId2);
|
|
14685
14685
|
},
|
|
14686
14686
|
getTask: async (taskId) => {
|
|
14687
|
-
const task = await taskStore.getTask(taskId,
|
|
14687
|
+
const task = await taskStore.getTask(taskId, sessionId2);
|
|
14688
14688
|
if (!task) {
|
|
14689
14689
|
throw new McpError(ErrorCode.InvalidParams, "Failed to retrieve task: Task not found");
|
|
14690
14690
|
}
|
|
14691
14691
|
return task;
|
|
14692
14692
|
},
|
|
14693
14693
|
storeTaskResult: async (taskId, status, result) => {
|
|
14694
|
-
await taskStore.storeTaskResult(taskId, status, result,
|
|
14695
|
-
const task = await taskStore.getTask(taskId,
|
|
14694
|
+
await taskStore.storeTaskResult(taskId, status, result, sessionId2);
|
|
14695
|
+
const task = await taskStore.getTask(taskId, sessionId2);
|
|
14696
14696
|
if (task) {
|
|
14697
14697
|
const notification = TaskStatusNotificationSchema.parse({
|
|
14698
14698
|
method: "notifications/tasks/status",
|
|
@@ -14705,18 +14705,18 @@ var Protocol = class {
|
|
|
14705
14705
|
}
|
|
14706
14706
|
},
|
|
14707
14707
|
getTaskResult: (taskId) => {
|
|
14708
|
-
return taskStore.getTaskResult(taskId,
|
|
14708
|
+
return taskStore.getTaskResult(taskId, sessionId2);
|
|
14709
14709
|
},
|
|
14710
14710
|
updateTaskStatus: async (taskId, status, statusMessage) => {
|
|
14711
|
-
const task = await taskStore.getTask(taskId,
|
|
14711
|
+
const task = await taskStore.getTask(taskId, sessionId2);
|
|
14712
14712
|
if (!task) {
|
|
14713
14713
|
throw new McpError(ErrorCode.InvalidParams, `Task "${taskId}" not found - it may have been cleaned up`);
|
|
14714
14714
|
}
|
|
14715
14715
|
if (isTerminal(task.status)) {
|
|
14716
14716
|
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
14717
|
}
|
|
14718
|
-
await taskStore.updateTaskStatus(taskId, status, statusMessage,
|
|
14719
|
-
const updatedTask = await taskStore.getTask(taskId,
|
|
14718
|
+
await taskStore.updateTaskStatus(taskId, status, statusMessage, sessionId2);
|
|
14719
|
+
const updatedTask = await taskStore.getTask(taskId, sessionId2);
|
|
14720
14720
|
if (updatedTask) {
|
|
14721
14721
|
const notification = TaskStatusNotificationSchema.parse({
|
|
14722
14722
|
method: "notifications/tasks/status",
|
|
@@ -14729,7 +14729,7 @@ var Protocol = class {
|
|
|
14729
14729
|
}
|
|
14730
14730
|
},
|
|
14731
14731
|
listTasks: (cursor) => {
|
|
14732
|
-
return taskStore.listTasks(cursor,
|
|
14732
|
+
return taskStore.listTasks(cursor, sessionId2);
|
|
14733
14733
|
}
|
|
14734
14734
|
};
|
|
14735
14735
|
}
|
|
@@ -15080,8 +15080,8 @@ var Server = class extends Protocol {
|
|
|
15080
15080
|
this._serverInfo = _serverInfo;
|
|
15081
15081
|
this._loggingLevels = /* @__PURE__ */ new Map();
|
|
15082
15082
|
this.LOG_LEVEL_SEVERITY = new Map(LoggingLevelSchema.options.map((level, index) => [level, index]));
|
|
15083
|
-
this.isMessageIgnored = (level,
|
|
15084
|
-
const currentLevel = this._loggingLevels.get(
|
|
15083
|
+
this.isMessageIgnored = (level, sessionId2) => {
|
|
15084
|
+
const currentLevel = this._loggingLevels.get(sessionId2);
|
|
15085
15085
|
return currentLevel ? this.LOG_LEVEL_SEVERITY.get(level) < this.LOG_LEVEL_SEVERITY.get(currentLevel) : false;
|
|
15086
15086
|
};
|
|
15087
15087
|
this._capabilities = options?.capabilities ?? {};
|
|
@@ -15424,9 +15424,9 @@ var Server = class extends Protocol {
|
|
|
15424
15424
|
* @param params
|
|
15425
15425
|
* @param sessionId optional for stateless and backward compatibility
|
|
15426
15426
|
*/
|
|
15427
|
-
async sendLoggingMessage(params,
|
|
15427
|
+
async sendLoggingMessage(params, sessionId2) {
|
|
15428
15428
|
if (this._capabilities.logging) {
|
|
15429
|
-
if (!this.isMessageIgnored(params.level,
|
|
15429
|
+
if (!this.isMessageIgnored(params.level, sessionId2)) {
|
|
15430
15430
|
return this.notification({ method: "notifications/message", params });
|
|
15431
15431
|
}
|
|
15432
15432
|
}
|
|
@@ -15483,7 +15483,7 @@ function generateToken() {
|
|
|
15483
15483
|
return randomBytes(AUTH_TOKEN_BYTES).toString("hex");
|
|
15484
15484
|
}
|
|
15485
15485
|
function findFreePort() {
|
|
15486
|
-
return new Promise((
|
|
15486
|
+
return new Promise((resolve2, reject) => {
|
|
15487
15487
|
const srv = net.createServer();
|
|
15488
15488
|
srv.listen(0, "127.0.0.1", () => {
|
|
15489
15489
|
const addr = srv.address();
|
|
@@ -15494,7 +15494,7 @@ function findFreePort() {
|
|
|
15494
15494
|
const port = addr.port;
|
|
15495
15495
|
srv.close((err) => {
|
|
15496
15496
|
if (err) reject(err);
|
|
15497
|
-
else
|
|
15497
|
+
else resolve2(port);
|
|
15498
15498
|
});
|
|
15499
15499
|
});
|
|
15500
15500
|
srv.on("error", reject);
|
|
@@ -15536,7 +15536,7 @@ async function isToolsServerHealthy(port, host = "127.0.0.1", timeoutMs = 2e3, t
|
|
|
15536
15536
|
}
|
|
15537
15537
|
}
|
|
15538
15538
|
function spawnToolsServer(paths, port, options = {}) {
|
|
15539
|
-
return new Promise((
|
|
15539
|
+
return new Promise((resolve2, reject) => {
|
|
15540
15540
|
let logFd;
|
|
15541
15541
|
try {
|
|
15542
15542
|
fs.mkdirSync(STATE_DIR, { recursive: true });
|
|
@@ -15568,7 +15568,7 @@ function spawnToolsServer(paths, port, options = {}) {
|
|
|
15568
15568
|
const actualPort = parseInt(match[1], 10);
|
|
15569
15569
|
rl.close();
|
|
15570
15570
|
child.stdout?.resume();
|
|
15571
|
-
settle(() =>
|
|
15571
|
+
settle(() => resolve2({ port: actualPort, pid }));
|
|
15572
15572
|
}
|
|
15573
15573
|
});
|
|
15574
15574
|
child.on("error", (err) => {
|
|
@@ -15699,9 +15699,144 @@ async function isRemoteRouted() {
|
|
|
15699
15699
|
return url !== null;
|
|
15700
15700
|
}
|
|
15701
15701
|
|
|
15702
|
+
// ../argent-tools-client/src/artifacts.ts
|
|
15703
|
+
import { mkdir as mkdir3, readFile as readFile3, rm, stat, writeFile as writeFile3 } from "node:fs/promises";
|
|
15704
|
+
import { tmpdir } from "node:os";
|
|
15705
|
+
import { basename, join as join3 } from "node:path";
|
|
15706
|
+
import { createHash } from "node:crypto";
|
|
15707
|
+
import { execFile } from "node:child_process";
|
|
15708
|
+
import { promisify } from "node:util";
|
|
15709
|
+
var execFileAsync = promisify(execFile);
|
|
15710
|
+
var ARTIFACT_MARKER = "__argentArtifact";
|
|
15711
|
+
function isArtifactHandle(value) {
|
|
15712
|
+
return !!value && typeof value === "object" && value[ARTIFACT_MARKER] === true && typeof value.id === "string" && typeof value.filename === "string";
|
|
15713
|
+
}
|
|
15714
|
+
var SESSION_ID = null;
|
|
15715
|
+
function sessionId() {
|
|
15716
|
+
if (!SESSION_ID) {
|
|
15717
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:T]/g, (m) => m === "T" ? "-" : "").slice(0, 15);
|
|
15718
|
+
SESSION_ID = `${stamp}-${process.pid}`;
|
|
15719
|
+
}
|
|
15720
|
+
return SESSION_ID;
|
|
15721
|
+
}
|
|
15722
|
+
function sanitizeSegment(segment) {
|
|
15723
|
+
return segment.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
15724
|
+
}
|
|
15725
|
+
function projectSlug() {
|
|
15726
|
+
const cwd = process.cwd();
|
|
15727
|
+
const hash = createHash("sha1").update(cwd).digest("hex").slice(0, 6);
|
|
15728
|
+
const name = sanitizeSegment(basename(cwd)) || "root";
|
|
15729
|
+
return `${name}-${hash}`;
|
|
15730
|
+
}
|
|
15731
|
+
function artifactsRoot() {
|
|
15732
|
+
return process.env.ARGENT_ARTIFACTS_DIR ?? join3(tmpdir(), "argent-artifacts");
|
|
15733
|
+
}
|
|
15734
|
+
function artifactDir(deviceId) {
|
|
15735
|
+
const parts = [artifactsRoot(), projectSlug(), sessionId()];
|
|
15736
|
+
if (deviceId) parts.push(sanitizeSegment(deviceId));
|
|
15737
|
+
return join3(...parts);
|
|
15738
|
+
}
|
|
15739
|
+
async function resolveLocalFile(handle) {
|
|
15740
|
+
if (!handle.hostPath) return null;
|
|
15741
|
+
try {
|
|
15742
|
+
const st = await stat(handle.hostPath);
|
|
15743
|
+
if (handle.archive) {
|
|
15744
|
+
return st.isDirectory() ? handle.hostPath : null;
|
|
15745
|
+
}
|
|
15746
|
+
if (!st.isFile()) return null;
|
|
15747
|
+
if (st.size !== handle.size) return null;
|
|
15748
|
+
if (handle.mtimeMs != null && Math.round(st.mtimeMs) !== Math.round(handle.mtimeMs)) {
|
|
15749
|
+
return null;
|
|
15750
|
+
}
|
|
15751
|
+
return handle.hostPath;
|
|
15752
|
+
} catch {
|
|
15753
|
+
return null;
|
|
15754
|
+
}
|
|
15755
|
+
}
|
|
15756
|
+
async function downloadAndExtractArchive(handle, data, dir) {
|
|
15757
|
+
const tarball = join3(dir, `${sanitizeSegment(handle.filename)}.tar.gz`);
|
|
15758
|
+
try {
|
|
15759
|
+
await writeFile3(tarball, data);
|
|
15760
|
+
await execFileAsync("tar", ["-xzf", tarball, "-C", dir]);
|
|
15761
|
+
return join3(dir, handle.filename);
|
|
15762
|
+
} catch {
|
|
15763
|
+
return null;
|
|
15764
|
+
} finally {
|
|
15765
|
+
await rm(tarball, { force: true }).catch(() => {
|
|
15766
|
+
});
|
|
15767
|
+
}
|
|
15768
|
+
}
|
|
15769
|
+
async function materializeArtifacts(result, ctx) {
|
|
15770
|
+
const images = [];
|
|
15771
|
+
const fetchFn = ctx.fetchImpl ?? fetch;
|
|
15772
|
+
const authHeaders2 = ctx.authToken ? { Authorization: `Bearer ${ctx.authToken}` } : {};
|
|
15773
|
+
const dir = artifactDir(ctx.deviceId);
|
|
15774
|
+
let dirReady = false;
|
|
15775
|
+
async function ensureDir() {
|
|
15776
|
+
if (!dirReady) {
|
|
15777
|
+
await mkdir3(dir, { recursive: true });
|
|
15778
|
+
dirReady = true;
|
|
15779
|
+
}
|
|
15780
|
+
}
|
|
15781
|
+
async function walk(value) {
|
|
15782
|
+
if (isArtifactHandle(value)) {
|
|
15783
|
+
const localPath = await resolveLocalFile(value);
|
|
15784
|
+
if (localPath) {
|
|
15785
|
+
if (value.mimeType.startsWith("image/")) {
|
|
15786
|
+
images.push({ localPath, data: await readFile3(localPath), mimeType: value.mimeType });
|
|
15787
|
+
}
|
|
15788
|
+
return localPath;
|
|
15789
|
+
}
|
|
15790
|
+
try {
|
|
15791
|
+
const res = await fetchFn(`${ctx.toolsUrl}/artifacts/${value.id}`, {
|
|
15792
|
+
headers: authHeaders2
|
|
15793
|
+
});
|
|
15794
|
+
if (!res.ok) return null;
|
|
15795
|
+
const data = Buffer.from(await res.arrayBuffer());
|
|
15796
|
+
await ensureDir();
|
|
15797
|
+
if (value.archive === "tar.gz") {
|
|
15798
|
+
return await downloadAndExtractArchive(value, data, dir);
|
|
15799
|
+
}
|
|
15800
|
+
if (value.size > 0 && data.length !== value.size) return null;
|
|
15801
|
+
const downloadedPath = join3(dir, sanitizeSegment(value.filename));
|
|
15802
|
+
await writeFile3(downloadedPath, data);
|
|
15803
|
+
if (value.mimeType.startsWith("image/")) {
|
|
15804
|
+
images.push({ localPath: downloadedPath, data, mimeType: value.mimeType });
|
|
15805
|
+
}
|
|
15806
|
+
return downloadedPath;
|
|
15807
|
+
} catch {
|
|
15808
|
+
return null;
|
|
15809
|
+
}
|
|
15810
|
+
}
|
|
15811
|
+
if (Array.isArray(value)) {
|
|
15812
|
+
return Promise.all(value.map(walk));
|
|
15813
|
+
}
|
|
15814
|
+
if (value && typeof value === "object") {
|
|
15815
|
+
const out = {};
|
|
15816
|
+
for (const [k, v] of Object.entries(value)) {
|
|
15817
|
+
out[k] = await walk(v);
|
|
15818
|
+
}
|
|
15819
|
+
return out;
|
|
15820
|
+
}
|
|
15821
|
+
return value;
|
|
15822
|
+
}
|
|
15823
|
+
const rewritten = await walk(result);
|
|
15824
|
+
return { result: rewritten, images };
|
|
15825
|
+
}
|
|
15826
|
+
function getDeviceIdFromArgs(args) {
|
|
15827
|
+
if (!args || typeof args !== "object") return void 0;
|
|
15828
|
+
const rec = args;
|
|
15829
|
+
if (typeof rec.udid === "string") return rec.udid;
|
|
15830
|
+
if (typeof rec.device_id === "string") return rec.device_id;
|
|
15831
|
+
return void 0;
|
|
15832
|
+
}
|
|
15833
|
+
|
|
15702
15834
|
// ../argent-mcp/src/content.ts
|
|
15703
|
-
import { readFile as
|
|
15835
|
+
import { readFile as readFile4 } from "node:fs/promises";
|
|
15704
15836
|
var PNG_SIGNATURE = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
|
|
15837
|
+
function imageBlock(data, mimeType) {
|
|
15838
|
+
return { type: "image", data: data.toString("base64"), mimeType };
|
|
15839
|
+
}
|
|
15705
15840
|
async function fetchPngBytes(url) {
|
|
15706
15841
|
try {
|
|
15707
15842
|
const res = await fetch(url);
|
|
@@ -15714,22 +15849,38 @@ async function fetchPngBytes(url) {
|
|
|
15714
15849
|
return null;
|
|
15715
15850
|
}
|
|
15716
15851
|
}
|
|
15717
|
-
async function toMcpContent(result, outputHint, args) {
|
|
15718
|
-
|
|
15852
|
+
async function toMcpContent(result, outputHint, ctx, args) {
|
|
15853
|
+
const suppressImage = isRecord(args) && args.includeImageInContext === false;
|
|
15854
|
+
if (ctx) {
|
|
15855
|
+
const { result: rewritten, images } = await materializeArtifacts(result, ctx);
|
|
15856
|
+
if (outputHint === "image") {
|
|
15857
|
+
if (images.length > 0) {
|
|
15858
|
+
const saved = { type: "text", text: `Saved: ${images[0].localPath}` };
|
|
15859
|
+
if (suppressImage) return [saved];
|
|
15860
|
+
const blocks2 = images.map((img) => imageBlock(img.data, img.mimeType));
|
|
15861
|
+
blocks2.push(saved);
|
|
15862
|
+
return blocks2;
|
|
15863
|
+
}
|
|
15864
|
+
return legacyImageContent(rewritten, suppressImage);
|
|
15865
|
+
}
|
|
15866
|
+
const blocks = [{ type: "text", text: JSON.stringify(rewritten, null, 2) }];
|
|
15867
|
+
if (!suppressImage) for (const img of images) blocks.push(imageBlock(img.data, img.mimeType));
|
|
15868
|
+
return blocks;
|
|
15869
|
+
}
|
|
15870
|
+
if (outputHint === "image") {
|
|
15871
|
+
return legacyImageContent(result, suppressImage);
|
|
15872
|
+
}
|
|
15873
|
+
return [{ type: "text", text: JSON.stringify(result, null, 2) }];
|
|
15874
|
+
}
|
|
15875
|
+
async function legacyImageContent(result, suppressImage) {
|
|
15876
|
+
if (result && typeof result === "object" && "url" in result) {
|
|
15719
15877
|
const r = result;
|
|
15720
|
-
if (
|
|
15721
|
-
return [{ type: "text", text: `Saved: ${r.path}` }];
|
|
15878
|
+
if (suppressImage) {
|
|
15879
|
+
return [{ type: "text", text: `Saved: ${r.path ?? ""}` }];
|
|
15722
15880
|
}
|
|
15723
15881
|
const buf = await fetchPngBytes(r.url);
|
|
15724
15882
|
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
|
-
];
|
|
15883
|
+
return [imageBlock(buf, "image/png"), { type: "text", text: `Saved: ${r.path ?? ""}` }];
|
|
15733
15884
|
}
|
|
15734
15885
|
return [
|
|
15735
15886
|
{
|
|
@@ -15750,7 +15901,7 @@ function isScreenshotDiffResult(value) {
|
|
|
15750
15901
|
async function screenshotDiffToMcpContent(result) {
|
|
15751
15902
|
const blocks = [];
|
|
15752
15903
|
if (typeof result.contextDiffPath === "string") {
|
|
15753
|
-
const buf = await
|
|
15904
|
+
const buf = await readFile4(result.contextDiffPath);
|
|
15754
15905
|
blocks.push({
|
|
15755
15906
|
type: "image",
|
|
15756
15907
|
data: buf.toString("base64"),
|
|
@@ -15760,7 +15911,7 @@ async function screenshotDiffToMcpContent(result) {
|
|
|
15760
15911
|
blocks.push({ type: "text", text: result.summary });
|
|
15761
15912
|
return blocks;
|
|
15762
15913
|
}
|
|
15763
|
-
async function flowRunToMcpContent(result) {
|
|
15914
|
+
async function flowRunToMcpContent(result, ctx) {
|
|
15764
15915
|
const blocks = [];
|
|
15765
15916
|
if (result.executionPrerequisite) {
|
|
15766
15917
|
blocks.push({
|
|
@@ -15784,7 +15935,7 @@ async function flowRunToMcpContent(result) {
|
|
|
15784
15935
|
});
|
|
15785
15936
|
} else {
|
|
15786
15937
|
blocks.push({ type: "text", text: `[${num}] ${step.tool}` });
|
|
15787
|
-
const stepContent = await toMcpContent(step.result, step.outputHint, step.args);
|
|
15938
|
+
const stepContent = await toMcpContent(step.result, step.outputHint, ctx, step.args);
|
|
15788
15939
|
blocks.push(...stepContent);
|
|
15789
15940
|
}
|
|
15790
15941
|
}
|
|
@@ -15792,6 +15943,64 @@ async function flowRunToMcpContent(result) {
|
|
|
15792
15943
|
return blocks;
|
|
15793
15944
|
}
|
|
15794
15945
|
|
|
15946
|
+
// ../configuration-core/src/flags.ts
|
|
15947
|
+
import * as fs2 from "node:fs";
|
|
15948
|
+
import * as path3 from "node:path";
|
|
15949
|
+
import { homedir as homedir3 } from "node:os";
|
|
15950
|
+
var PROJECT_MARKERS = [".argent", ".git", "package.json"];
|
|
15951
|
+
function resolveProjectRoot(startDir) {
|
|
15952
|
+
const initial = path3.resolve(startDir);
|
|
15953
|
+
let current = initial;
|
|
15954
|
+
while (true) {
|
|
15955
|
+
for (const marker of PROJECT_MARKERS) {
|
|
15956
|
+
if (fs2.existsSync(path3.join(current, marker))) return current;
|
|
15957
|
+
}
|
|
15958
|
+
const parent = path3.dirname(current);
|
|
15959
|
+
if (parent === current) return initial;
|
|
15960
|
+
current = parent;
|
|
15961
|
+
}
|
|
15962
|
+
}
|
|
15963
|
+
function getFlagsPath(scope, options = {}) {
|
|
15964
|
+
const home = options.homeDir ?? homedir3();
|
|
15965
|
+
if (scope === "global") {
|
|
15966
|
+
return path3.join(home, ".argent", "flags.json");
|
|
15967
|
+
}
|
|
15968
|
+
const cwd = options.cwd ?? process.cwd();
|
|
15969
|
+
return path3.join(resolveProjectRoot(cwd), ".argent", "flags.json");
|
|
15970
|
+
}
|
|
15971
|
+
function readFlagsFile(filePath) {
|
|
15972
|
+
let raw;
|
|
15973
|
+
try {
|
|
15974
|
+
raw = fs2.readFileSync(filePath, "utf8");
|
|
15975
|
+
} catch {
|
|
15976
|
+
return {};
|
|
15977
|
+
}
|
|
15978
|
+
let parsed;
|
|
15979
|
+
try {
|
|
15980
|
+
parsed = JSON.parse(raw);
|
|
15981
|
+
} catch {
|
|
15982
|
+
return {};
|
|
15983
|
+
}
|
|
15984
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
15985
|
+
const flags = parsed.flags;
|
|
15986
|
+
if (!flags || typeof flags !== "object" || Array.isArray(flags)) return {};
|
|
15987
|
+
const out = {};
|
|
15988
|
+
for (const [k, v] of Object.entries(flags)) {
|
|
15989
|
+
if (typeof v === "boolean") out[k] = v;
|
|
15990
|
+
}
|
|
15991
|
+
return out;
|
|
15992
|
+
}
|
|
15993
|
+
function readFlags(scope, options = {}) {
|
|
15994
|
+
return readFlagsFile(getFlagsPath(scope, options));
|
|
15995
|
+
}
|
|
15996
|
+
function isFlagEnabled(name, options = {}) {
|
|
15997
|
+
const projectFlags = readFlags("project", options);
|
|
15998
|
+
if (Object.hasOwn(projectFlags, name)) return projectFlags[name];
|
|
15999
|
+
const globalFlags = readFlags("global", options);
|
|
16000
|
+
if (Object.hasOwn(globalFlags, name)) return globalFlags[name];
|
|
16001
|
+
return false;
|
|
16002
|
+
}
|
|
16003
|
+
|
|
15795
16004
|
// ../argent-mcp/src/auto-screenshot.ts
|
|
15796
16005
|
var AUTO_SCREENSHOT_TOOLS = /* @__PURE__ */ new Set([
|
|
15797
16006
|
"gesture-tap",
|
|
@@ -15824,9 +16033,8 @@ var AUTO_SCREENSHOT_DELAY_MS_BY_TOOL = {
|
|
|
15824
16033
|
"describe": 100
|
|
15825
16034
|
};
|
|
15826
16035
|
var DEFAULT_DELAY_MS = 1400;
|
|
15827
|
-
function autoScreenshotEnabled() {
|
|
15828
|
-
|
|
15829
|
-
return v === void 0 || v === "" || v === "1" || v.toLowerCase() === "true";
|
|
16036
|
+
function autoScreenshotEnabled(options) {
|
|
16037
|
+
return !isFlagEnabled("disable-auto-screenshot", options);
|
|
15830
16038
|
}
|
|
15831
16039
|
function getUdidFromArgs(args) {
|
|
15832
16040
|
if (args && typeof args === "object" && "udid" in args && typeof args.udid === "string") {
|
|
@@ -15897,6 +16105,7 @@ async function fetchWithReconnect(getUrl, reconnect, config2) {
|
|
|
15897
16105
|
throw lastError;
|
|
15898
16106
|
}
|
|
15899
16107
|
async function startMcpServer(options) {
|
|
16108
|
+
const autoScreenshotOn = autoScreenshotEnabled();
|
|
15900
16109
|
let TOOLS_URL;
|
|
15901
16110
|
let AUTH_TOKEN;
|
|
15902
16111
|
const resolved = await getResolvedToolsUrl();
|
|
@@ -15930,12 +16139,12 @@ async function startMcpServer(options) {
|
|
|
15930
16139
|
}
|
|
15931
16140
|
return reconnectPromise;
|
|
15932
16141
|
}
|
|
15933
|
-
const LOG_FILE2 = process.env.ARGENT_MCP_LOG ?? `${
|
|
16142
|
+
const LOG_FILE2 = process.env.ARGENT_MCP_LOG ?? `${homedir4()}/.argent/mcp-calls.log`;
|
|
15934
16143
|
let logDirReady = false;
|
|
15935
16144
|
async function spyLog(entry) {
|
|
15936
16145
|
try {
|
|
15937
16146
|
if (!logDirReady) {
|
|
15938
|
-
await
|
|
16147
|
+
await mkdir4(dirname2(LOG_FILE2), { recursive: true });
|
|
15939
16148
|
logDirReady = true;
|
|
15940
16149
|
}
|
|
15941
16150
|
await appendFile(LOG_FILE2, JSON.stringify(entry) + "\n");
|
|
@@ -16006,21 +16215,30 @@ async function startMcpServer(options) {
|
|
|
16006
16215
|
isError: false,
|
|
16007
16216
|
result
|
|
16008
16217
|
});
|
|
16218
|
+
const ctx = {
|
|
16219
|
+
toolsUrl: TOOLS_URL,
|
|
16220
|
+
authToken: AUTH_TOKEN,
|
|
16221
|
+
deviceId: getDeviceIdFromArgs(params.arguments)
|
|
16222
|
+
};
|
|
16009
16223
|
let content;
|
|
16010
16224
|
if (params.name === "flow-execute" && result && typeof result === "object" && "flow" in result && "steps" in result) {
|
|
16011
|
-
content = await flowRunToMcpContent(result);
|
|
16225
|
+
content = await flowRunToMcpContent(result, ctx);
|
|
16012
16226
|
} else if (params.name === "screenshot-diff" && isScreenshotDiffResult(result)) {
|
|
16013
16227
|
content = await screenshotDiffToMcpContent(result);
|
|
16014
16228
|
} else {
|
|
16015
|
-
content = await toMcpContent(result, outputHint, params.arguments);
|
|
16229
|
+
content = await toMcpContent(result, outputHint, ctx, params.arguments);
|
|
16016
16230
|
}
|
|
16017
16231
|
const udid = getUdidFromArgs(params.arguments);
|
|
16018
|
-
if (
|
|
16232
|
+
if (autoScreenshotOn && udid && shouldAutoScreenshot(params.name)) {
|
|
16019
16233
|
const delayMs = getAutoScreenshotDelayMs(params.name);
|
|
16020
16234
|
if (delayMs > 0) await new Promise((r) => setTimeout(r, delayMs));
|
|
16021
16235
|
try {
|
|
16022
16236
|
const screenshotResult = await callTool("screenshot", { udid });
|
|
16023
|
-
const screenshotContent = await toMcpContent(screenshotResult.result, "image", {
|
|
16237
|
+
const screenshotContent = await toMcpContent(screenshotResult.result, "image", {
|
|
16238
|
+
toolsUrl: TOOLS_URL,
|
|
16239
|
+
authToken: AUTH_TOKEN,
|
|
16240
|
+
deviceId: udid
|
|
16241
|
+
});
|
|
16024
16242
|
const hasImage = screenshotContent.some((b) => b.type === "image");
|
|
16025
16243
|
if (hasImage) {
|
|
16026
16244
|
content = [
|
|
@@ -16083,7 +16301,7 @@ async function startMcpServer(options) {
|
|
|
16083
16301
|
}, HEALTH_INTERVAL_MS);
|
|
16084
16302
|
healthInterval.unref();
|
|
16085
16303
|
}
|
|
16086
|
-
if (process.env.
|
|
16304
|
+
if (process.env.ARGENT_TOOL_SERVER_SHUTDOWN_ON_MCP_EXIT === "1") {
|
|
16087
16305
|
process.stdin.on("close", () => {
|
|
16088
16306
|
fetch(`${TOOLS_URL}/shutdown`, { method: "POST", headers: authHeader() }).catch(() => {
|
|
16089
16307
|
});
|