@swmansion/argent 0.27.1-next.20 → 0.27.1-next.21
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/dist/cli-cmds.mjs +254 -54
- package/dist/client.js +224 -47
- package/dist/installer.mjs +17 -7
- package/dist/mcp-server.mjs +234 -51
- package/dist/tool-args.generated.d.ts +1 -1
- package/dist/tool-server.cjs +721 -571
- package/package.json +1 -1
- package/skills/argent-create-flow/references/live-authoring.md +1 -1
package/dist/mcp-server.mjs
CHANGED
|
@@ -2241,8 +2241,8 @@ var require_resolve = __commonJS({
|
|
|
2241
2241
|
}
|
|
2242
2242
|
return count;
|
|
2243
2243
|
}
|
|
2244
|
-
function getFullPath(resolver, id = "",
|
|
2245
|
-
if (
|
|
2244
|
+
function getFullPath(resolver, id = "", normalize3) {
|
|
2245
|
+
if (normalize3 !== false)
|
|
2246
2246
|
id = normalizeId(id);
|
|
2247
2247
|
const p = resolver.parse(id);
|
|
2248
2248
|
return _getFullPath(resolver, p);
|
|
@@ -3638,7 +3638,7 @@ var require_fast_uri = __commonJS({
|
|
|
3638
3638
|
"use strict";
|
|
3639
3639
|
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3640
3640
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
3641
|
-
function
|
|
3641
|
+
function normalize3(uri, options) {
|
|
3642
3642
|
if (typeof uri === "string") {
|
|
3643
3643
|
uri = /** @type {T} */
|
|
3644
3644
|
normalizeString(uri, options);
|
|
@@ -3905,7 +3905,7 @@ var require_fast_uri = __commonJS({
|
|
|
3905
3905
|
}
|
|
3906
3906
|
var fastUri = {
|
|
3907
3907
|
SCHEMES,
|
|
3908
|
-
normalize:
|
|
3908
|
+
normalize: normalize3,
|
|
3909
3909
|
resolve: resolve8,
|
|
3910
3910
|
resolveComponent,
|
|
3911
3911
|
equal,
|
|
@@ -23628,6 +23628,7 @@ function isRecord(value) {
|
|
|
23628
23628
|
}
|
|
23629
23629
|
function collectFlowRequests(doc) {
|
|
23630
23630
|
const runTargets = /* @__PURE__ */ new Set();
|
|
23631
|
+
const snapshots = /* @__PURE__ */ new Set();
|
|
23631
23632
|
const seen = /* @__PURE__ */ new Set();
|
|
23632
23633
|
const visit = (steps, depth) => {
|
|
23633
23634
|
if (!Array.isArray(steps) || depth > MAX_BLOCK_NESTING || seen.has(steps)) return;
|
|
@@ -23639,11 +23640,17 @@ function collectFlowRequests(doc) {
|
|
|
23639
23640
|
const target = completeRunExtension(run);
|
|
23640
23641
|
if (FLOW_FILE_NAME_PATTERN.test(path2.posix.basename(target))) runTargets.add(target);
|
|
23641
23642
|
}
|
|
23643
|
+
const snapshot = isRecord(step.snapshot) ? step.snapshot.name : step.snapshot;
|
|
23644
|
+
if (typeof snapshot === "string" && FLOW_NAME_PATTERN.test(snapshot)) snapshots.add(snapshot);
|
|
23642
23645
|
visit(step.steps, depth + 1);
|
|
23643
23646
|
}
|
|
23644
23647
|
};
|
|
23645
23648
|
if (isRecord(doc)) visit(doc.steps, 0);
|
|
23646
|
-
return { runTargets: [...runTargets] };
|
|
23649
|
+
return { runTargets: [...runTargets], snapshots: [...snapshots] };
|
|
23650
|
+
}
|
|
23651
|
+
function baselineKeyFor(canonicalPath, flowName) {
|
|
23652
|
+
const stem = path2.basename(canonicalPath, ".yaml");
|
|
23653
|
+
return FLOW_NAME_PATTERN.test(stem) ? stem : flowName;
|
|
23647
23654
|
}
|
|
23648
23655
|
function flowMemberKey(anchorDir, target) {
|
|
23649
23656
|
return `${anchorDir}\0${target}`;
|
|
@@ -24119,7 +24126,17 @@ async function getResolvedToolsUrl() {
|
|
|
24119
24126
|
// ../argent-tools-client/src/file-inputs.ts
|
|
24120
24127
|
import { createHash as createHash2, randomUUID as randomUUID3 } from "node:crypto";
|
|
24121
24128
|
import { createReadStream, rmSync } from "node:fs";
|
|
24122
|
-
import {
|
|
24129
|
+
import {
|
|
24130
|
+
chmod as chmod3,
|
|
24131
|
+
lstat,
|
|
24132
|
+
mkdir as mkdir3,
|
|
24133
|
+
readFile as readFile3,
|
|
24134
|
+
realpath as realpath2,
|
|
24135
|
+
rename as rename2,
|
|
24136
|
+
rm as rm2,
|
|
24137
|
+
stat as stat2,
|
|
24138
|
+
writeFile as writeFile3
|
|
24139
|
+
} from "node:fs/promises";
|
|
24123
24140
|
import { constants, tmpdir } from "node:os";
|
|
24124
24141
|
import * as path4 from "node:path";
|
|
24125
24142
|
|
|
@@ -24428,9 +24445,61 @@ function isAllowedClientFilePath(p) {
|
|
|
24428
24445
|
function isClientFileDirective2(value) {
|
|
24429
24446
|
return !!value && typeof value === "object" && value[CLIENT_FILE_MARKER2] === true && typeof value.path === "string" && typeof value.content === "string";
|
|
24430
24447
|
}
|
|
24431
|
-
async function
|
|
24448
|
+
async function replaceFile(target, bytes, mode) {
|
|
24449
|
+
const temp = path4.join(path4.dirname(target), `.baseline-${randomUUID3()}.tmp`);
|
|
24450
|
+
try {
|
|
24451
|
+
await writeFile3(temp, bytes, { flag: "wx" });
|
|
24452
|
+
if (mode !== void 0) await chmod3(temp, mode & 511);
|
|
24453
|
+
await rename2(temp, target);
|
|
24454
|
+
} catch (err) {
|
|
24455
|
+
await rm2(temp, { force: true });
|
|
24456
|
+
throw err;
|
|
24457
|
+
}
|
|
24458
|
+
}
|
|
24459
|
+
async function writeBaselineFile(file, bytes, allowedDirs) {
|
|
24460
|
+
if (!path4.isAbsolute(file) || path4.normalize(file) !== file || file.split(/[\\/]/).includes("..") || !file.endsWith(".png") || !allowedDirs.includes(path4.dirname(file))) {
|
|
24461
|
+
return allowedDirs.length === 0 ? "this call writes no baselines" : `${file} is not a baseline of this call (${allowedDirs.map((d) => `${d}/<name>.png`).join(", ")})`;
|
|
24462
|
+
}
|
|
24463
|
+
if (bytes.length > MAX_CONTENT_BYTES) {
|
|
24464
|
+
return `${file}: the baseline is larger than the 32 MiB cap on a file this client writes`;
|
|
24465
|
+
}
|
|
24466
|
+
const dir = path4.dirname(file);
|
|
24467
|
+
await mkdir3(dir, { recursive: true });
|
|
24468
|
+
const link = await lstat(file).catch(() => null);
|
|
24469
|
+
const real = link === null ? null : await realpath2(file).catch(() => null);
|
|
24470
|
+
if (link !== null && real === null) return `${file} is a symbolic link to a missing file`;
|
|
24471
|
+
if (real !== null) {
|
|
24472
|
+
if (!real.endsWith(".png")) return `${file} links to a file that is not a PNG file`;
|
|
24473
|
+
if (path4.dirname(real) !== await realpath2(dir)) {
|
|
24474
|
+
return `${file} links outside its baseline directory`;
|
|
24475
|
+
}
|
|
24476
|
+
}
|
|
24477
|
+
const existing = real === null ? null : await stat2(real);
|
|
24478
|
+
if (existing !== null && !existing.isFile()) return `${file} is not a regular file`;
|
|
24479
|
+
await replaceFile(
|
|
24480
|
+
real ?? path4.join(await realpath2(dir), path4.basename(file)),
|
|
24481
|
+
bytes,
|
|
24482
|
+
existing?.mode
|
|
24483
|
+
);
|
|
24484
|
+
return null;
|
|
24485
|
+
}
|
|
24486
|
+
async function applyClientFileDirectives(result, opts = {}) {
|
|
24432
24487
|
const written = [];
|
|
24488
|
+
const failed = [];
|
|
24433
24489
|
async function walk(value) {
|
|
24490
|
+
if (isClientFileDirective2(value) && value.encoding === "base64") {
|
|
24491
|
+
const error2 = await writeBaselineFile(
|
|
24492
|
+
value.path,
|
|
24493
|
+
Buffer.from(value.content, "base64"),
|
|
24494
|
+
opts.allowedDirs ?? []
|
|
24495
|
+
).catch((err) => err instanceof Error ? err.message : String(err));
|
|
24496
|
+
if (error2 !== null) {
|
|
24497
|
+
failed.push({ path: value.path, error: error2 });
|
|
24498
|
+
return { path: value.path, error: error2 };
|
|
24499
|
+
}
|
|
24500
|
+
written.push(value.path);
|
|
24501
|
+
return value.path;
|
|
24502
|
+
}
|
|
24434
24503
|
if (isClientFileDirective2(value)) {
|
|
24435
24504
|
if (!isAllowedClientFilePath(value.path)) return null;
|
|
24436
24505
|
try {
|
|
@@ -24443,7 +24512,9 @@ async function applyClientFileDirectives(result) {
|
|
|
24443
24512
|
}
|
|
24444
24513
|
}
|
|
24445
24514
|
if (Array.isArray(value)) {
|
|
24446
|
-
|
|
24515
|
+
const out = [];
|
|
24516
|
+
for (const item of value) out.push(await walk(item));
|
|
24517
|
+
return out;
|
|
24447
24518
|
}
|
|
24448
24519
|
if (value && typeof value === "object") {
|
|
24449
24520
|
const out = {};
|
|
@@ -24455,12 +24526,12 @@ async function applyClientFileDirectives(result) {
|
|
|
24455
24526
|
return value;
|
|
24456
24527
|
}
|
|
24457
24528
|
const rewritten = await walk(result);
|
|
24458
|
-
return { result: rewritten, written };
|
|
24529
|
+
return { result: rewritten, written, failed };
|
|
24459
24530
|
}
|
|
24460
24531
|
|
|
24461
24532
|
// ../argent-tools-client/src/flow-files.ts
|
|
24462
24533
|
var import_yaml = __toESM(require_dist2(), 1);
|
|
24463
|
-
import { readFile as readFile4, realpath as
|
|
24534
|
+
import { readdir as readdir4, readFile as readFile4, realpath as realpath3, stat as stat3 } from "node:fs/promises";
|
|
24464
24535
|
import * as path5 from "node:path";
|
|
24465
24536
|
var INLINE_MEMBERS_BYTES = 256 * 1024;
|
|
24466
24537
|
var FLOW_FILES_LOG_ENV = "ARGENT_FLOW_FILES_LOG";
|
|
@@ -24495,7 +24566,7 @@ function savedFlowProject(file) {
|
|
|
24495
24566
|
}
|
|
24496
24567
|
async function landing(spelled) {
|
|
24497
24568
|
try {
|
|
24498
|
-
const canonical = await
|
|
24569
|
+
const canonical = await realpath3(spelled);
|
|
24499
24570
|
return { canonical, fence: canonical };
|
|
24500
24571
|
} catch (err) {
|
|
24501
24572
|
const failure = err.code === "ENOENT" ? { missing: true } : { error: err.message };
|
|
@@ -24504,7 +24575,7 @@ async function landing(spelled) {
|
|
|
24504
24575
|
for (; ; ) {
|
|
24505
24576
|
const parent = path5.dirname(at);
|
|
24506
24577
|
if (parent === at) return { canonical, fence: spelled, ...failure };
|
|
24507
|
-
const real = await
|
|
24578
|
+
const real = await realpath3(parent).catch(() => null);
|
|
24508
24579
|
if (real !== null) {
|
|
24509
24580
|
return { canonical, fence: path5.join(real, path5.basename(at)), ...failure };
|
|
24510
24581
|
}
|
|
@@ -24524,7 +24595,7 @@ async function closureRoots(rootPath, rootCanonical, projectRoot) {
|
|
|
24524
24595
|
}
|
|
24525
24596
|
const real = [];
|
|
24526
24597
|
for (const candidate of candidates) {
|
|
24527
|
-
const resolved = await
|
|
24598
|
+
const resolved = await realpath3(candidate).catch(() => null);
|
|
24528
24599
|
if (resolved !== null && !real.includes(resolved)) real.push(resolved);
|
|
24529
24600
|
}
|
|
24530
24601
|
return real.filter((root) => !real.some((other) => other !== root && isWithin(root, other)));
|
|
@@ -24562,31 +24633,96 @@ async function readFlowMember(anchorDir, target, roots, budget, opts) {
|
|
|
24562
24633
|
if (!/\.ya?ml$/i.test(path5.basename(canonical))) {
|
|
24563
24634
|
return refuse(`${target} links to a file that is not a YAML file`);
|
|
24564
24635
|
}
|
|
24565
|
-
const
|
|
24636
|
+
const sent = await sendBytes(member, canonical, budget, opts);
|
|
24637
|
+
return { ...sent, text: sent.bytes?.toString("utf8") };
|
|
24638
|
+
}
|
|
24639
|
+
function callPlatform(args) {
|
|
24640
|
+
if (typeof args.device === "string" && args.device.startsWith("chromium-cdp-")) return "chromium";
|
|
24641
|
+
if (typeof args.platform !== "string") return void 0;
|
|
24642
|
+
return args.platform === "ios-remote" ? "ios" : args.platform;
|
|
24643
|
+
}
|
|
24644
|
+
async function baselineEntry(file, roots, forWrite) {
|
|
24645
|
+
const { canonical, error: error2 } = await landing(file);
|
|
24646
|
+
if (!roots.some((root) => isWithin(canonical, root))) {
|
|
24647
|
+
return {
|
|
24648
|
+
state: "refused",
|
|
24649
|
+
error: `${file} is outside every root this client serves (${roots.join(", ")})`
|
|
24650
|
+
};
|
|
24651
|
+
}
|
|
24652
|
+
if (error2 !== void 0) return { state: "refused", error: error2 };
|
|
24653
|
+
const st = await stat3(canonical).catch((err) => err);
|
|
24654
|
+
if (st instanceof Error) {
|
|
24655
|
+
if (st.code !== "ENOENT") return { state: "refused", error: st.message };
|
|
24656
|
+
return forWrite ? { state: "refused", error: `${file} is a symbolic link to a missing file` } : { state: "missing" };
|
|
24657
|
+
}
|
|
24658
|
+
if (!canonical.endsWith(".png")) {
|
|
24659
|
+
return { state: "refused", error: `${file} links to a file that is not a PNG file` };
|
|
24660
|
+
}
|
|
24661
|
+
if (forWrite && !st.isFile()) return { state: "refused", error: `${file} is not a regular file` };
|
|
24662
|
+
if (st.isDirectory()) {
|
|
24663
|
+
return { state: "refused", error: "EISDIR: illegal operation on a directory, read" };
|
|
24664
|
+
}
|
|
24665
|
+
return st.isFile() ? { state: "ok", real: canonical } : { state: "missing" };
|
|
24666
|
+
}
|
|
24667
|
+
async function sendBytes(member, real, budget, opts) {
|
|
24668
|
+
const read = await readFileInputWire(real, { includeContent: true });
|
|
24566
24669
|
if (read?.contentOmitted) {
|
|
24567
|
-
|
|
24670
|
+
const error2 = `${real} is larger than the 32 MiB cap on a file sent to the tool-server`;
|
|
24671
|
+
return { member: { ...member, state: "refused", error: error2 }, sent: `refused (${error2})` };
|
|
24568
24672
|
}
|
|
24569
24673
|
if (read?.content === void 0) {
|
|
24570
|
-
|
|
24571
|
-
|
|
24572
|
-
|
|
24573
|
-
(err) => err instanceof Error ? err.message : String(err)
|
|
24574
|
-
)
|
|
24674
|
+
const error2 = await readFile4(real).then(
|
|
24675
|
+
() => `${real} could not be read on this client`,
|
|
24676
|
+
(err) => err instanceof Error ? err.message : String(err)
|
|
24575
24677
|
);
|
|
24678
|
+
return { member: { ...member, state: "refused", error: error2 }, sent: `refused (${error2})` };
|
|
24576
24679
|
}
|
|
24577
|
-
const
|
|
24680
|
+
const bytes = Buffer.from(read.content, "base64");
|
|
24578
24681
|
const size = read.size ?? 0;
|
|
24579
24682
|
if (budget.inline + size <= INLINE_MEMBERS_BYTES || !opts.uploadEndpoint) {
|
|
24580
24683
|
budget.inline += size;
|
|
24581
|
-
return { member: { ...member, ...read },
|
|
24684
|
+
return { member: { ...member, ...read }, sent: `inline ${size}`, bytes };
|
|
24582
24685
|
}
|
|
24583
|
-
const uploaded = await uploadFile(
|
|
24686
|
+
const uploaded = await uploadFile(real, opts.uploadEndpoint, opts.signal);
|
|
24584
24687
|
return {
|
|
24585
24688
|
member: { ...member, size: read.size, mtimeMs: read.mtimeMs, ...uploaded },
|
|
24586
|
-
|
|
24587
|
-
|
|
24689
|
+
sent: `upload ${size}`,
|
|
24690
|
+
bytes
|
|
24588
24691
|
};
|
|
24589
24692
|
}
|
|
24693
|
+
async function collectBaselineMembers(canonical, flowName, snapshots, args, roots, budget, opts, emit) {
|
|
24694
|
+
const dir = path5.join(
|
|
24695
|
+
path5.dirname(canonical),
|
|
24696
|
+
"__baselines__",
|
|
24697
|
+
baselineKeyFor(canonical, flowName)
|
|
24698
|
+
);
|
|
24699
|
+
const real = (await landing(dir)).canonical;
|
|
24700
|
+
if (!roots.some((root) => isWithin(real, root))) return;
|
|
24701
|
+
const updates = args.updateBaselines === true;
|
|
24702
|
+
if (updates) opts.baselineDirs?.push(dir);
|
|
24703
|
+
const platform = callPlatform(args);
|
|
24704
|
+
const prefixes = snapshots.map(
|
|
24705
|
+
(name) => `${name}__${platform === void 0 ? "" : `${platform}-`}`
|
|
24706
|
+
);
|
|
24707
|
+
const names = await readdir4(dir).catch(() => []);
|
|
24708
|
+
for (const name of names.sort()) {
|
|
24709
|
+
if (!name.endsWith(".png")) continue;
|
|
24710
|
+
if (!updates && !prefixes.some((prefix) => name.startsWith(prefix))) continue;
|
|
24711
|
+
const file = path5.join(dir, name);
|
|
24712
|
+
const member = { role: "baseline", key: file, path: file };
|
|
24713
|
+
const entry = await baselineEntry(file, roots, updates);
|
|
24714
|
+
if (entry.state === "refused") {
|
|
24715
|
+
emit({ ...member, state: "refused", error: entry.error }, `refused (${entry.error})`);
|
|
24716
|
+
} else if (entry.state === "missing") {
|
|
24717
|
+
emit({ ...member, state: "missing" }, "missing");
|
|
24718
|
+
} else if (updates) {
|
|
24719
|
+
emit({ ...member, state: "listed" }, "listed");
|
|
24720
|
+
} else {
|
|
24721
|
+
const sent = await sendBytes(member, entry.real, budget, opts);
|
|
24722
|
+
emit(sent.member, sent.sent);
|
|
24723
|
+
}
|
|
24724
|
+
}
|
|
24725
|
+
}
|
|
24590
24726
|
async function collectFlowMembers(rootPath, rootBytes, args, opts) {
|
|
24591
24727
|
if (!namesValidFlow(args)) return {};
|
|
24592
24728
|
const canonical = await canonicalFlowPath(rootPath);
|
|
@@ -24598,10 +24734,16 @@ async function collectFlowMembers(rootPath, rootBytes, args, opts) {
|
|
|
24598
24734
|
const roots = await closureRoots(rootPath, canonical, args.project_root);
|
|
24599
24735
|
const members = [];
|
|
24600
24736
|
const seen = /* @__PURE__ */ new Set();
|
|
24737
|
+
const snapshots = /* @__PURE__ */ new Set();
|
|
24601
24738
|
const budget = { inline: 0 };
|
|
24602
24739
|
const logging = process.env[FLOW_FILES_LOG_ENV] === "1";
|
|
24603
24740
|
const log = opts.log ?? ((line) => void process.stderr.write(`${line}
|
|
24604
24741
|
`));
|
|
24742
|
+
const emit = (member, sent) => {
|
|
24743
|
+
members.push(member);
|
|
24744
|
+
const subject = member.role === "flow" ? member.canonical : member.key;
|
|
24745
|
+
if (logging) log(printable(`[flow-files] ${member.role} ${subject}: ${sent}`));
|
|
24746
|
+
};
|
|
24605
24747
|
const queue = [{ canonical, text: rootBytes.toString("utf8"), hop: 0 }];
|
|
24606
24748
|
for (let file = queue.shift(); file !== void 0; file = queue.shift()) {
|
|
24607
24749
|
let doc;
|
|
@@ -24610,19 +24752,33 @@ async function collectFlowMembers(rootPath, rootBytes, args, opts) {
|
|
|
24610
24752
|
} catch {
|
|
24611
24753
|
continue;
|
|
24612
24754
|
}
|
|
24755
|
+
const requests = collectFlowRequests(doc);
|
|
24756
|
+
for (const name of requests.snapshots) snapshots.add(name);
|
|
24613
24757
|
const anchorDir = path5.dirname(file.canonical);
|
|
24614
|
-
for (const target of
|
|
24758
|
+
for (const target of requests.runTargets) {
|
|
24615
24759
|
const key = flowMemberKey(anchorDir, target);
|
|
24616
24760
|
if (seen.has(key)) continue;
|
|
24617
24761
|
seen.add(key);
|
|
24618
24762
|
const { member, text, sent } = await readFlowMember(anchorDir, target, roots, budget, opts);
|
|
24619
|
-
|
|
24620
|
-
if (logging) log(printable(`[flow-files] flow ${member.canonical}: ${sent}`));
|
|
24763
|
+
emit(member, sent);
|
|
24621
24764
|
if (text !== void 0 && file.hop + 1 < MAX_RUN_DEPTH) {
|
|
24622
24765
|
queue.push({ canonical: member.canonical, text, hop: file.hop + 1 });
|
|
24623
24766
|
}
|
|
24624
24767
|
}
|
|
24625
24768
|
}
|
|
24769
|
+
if (snapshots.size > 0) {
|
|
24770
|
+
const flowName = path5.basename(rootPath, ".yaml");
|
|
24771
|
+
await collectBaselineMembers(
|
|
24772
|
+
canonical,
|
|
24773
|
+
flowName,
|
|
24774
|
+
[...snapshots],
|
|
24775
|
+
args,
|
|
24776
|
+
roots,
|
|
24777
|
+
budget,
|
|
24778
|
+
opts,
|
|
24779
|
+
emit
|
|
24780
|
+
);
|
|
24781
|
+
}
|
|
24626
24782
|
return { canonical, spelling, members };
|
|
24627
24783
|
}
|
|
24628
24784
|
|
|
@@ -24657,7 +24813,20 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
24657
24813
|
}
|
|
24658
24814
|
};
|
|
24659
24815
|
const decoder = new TextDecoder();
|
|
24660
|
-
let
|
|
24816
|
+
let pieces = [];
|
|
24817
|
+
const take = (text) => {
|
|
24818
|
+
let start = 0;
|
|
24819
|
+
let newline;
|
|
24820
|
+
while ((newline = text.indexOf("\n", start)) !== -1) {
|
|
24821
|
+
signal?.throwIfAborted();
|
|
24822
|
+
pieces.push(text.slice(start, newline));
|
|
24823
|
+
const line = pieces.join("");
|
|
24824
|
+
pieces = [];
|
|
24825
|
+
start = newline + 1;
|
|
24826
|
+
handleLine(line);
|
|
24827
|
+
}
|
|
24828
|
+
if (start < text.length) pieces.push(text.slice(start));
|
|
24829
|
+
};
|
|
24661
24830
|
try {
|
|
24662
24831
|
for (; ; ) {
|
|
24663
24832
|
let chunk;
|
|
@@ -24669,17 +24838,11 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
24669
24838
|
}
|
|
24670
24839
|
const { done, value } = chunk;
|
|
24671
24840
|
if (done) break;
|
|
24672
|
-
|
|
24673
|
-
let newline;
|
|
24674
|
-
while ((newline = buffered.indexOf("\n")) !== -1) {
|
|
24675
|
-
signal?.throwIfAborted();
|
|
24676
|
-
const line = buffered.slice(0, newline);
|
|
24677
|
-
buffered = buffered.slice(newline + 1);
|
|
24678
|
-
handleLine(line);
|
|
24679
|
-
}
|
|
24841
|
+
take(decoder.decode(value, { stream: true }));
|
|
24680
24842
|
}
|
|
24681
|
-
|
|
24682
|
-
|
|
24843
|
+
take(decoder.decode());
|
|
24844
|
+
const last = pieces.join("");
|
|
24845
|
+
if (last.trim()) handleLine(last);
|
|
24683
24846
|
} catch (err) {
|
|
24684
24847
|
void reader.cancel().catch(() => {
|
|
24685
24848
|
});
|
|
@@ -24689,8 +24852,7 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
24689
24852
|
if (!final) {
|
|
24690
24853
|
throw brokenStream(name, "the stream ended without a result", progress);
|
|
24691
24854
|
}
|
|
24692
|
-
|
|
24693
|
-
return { data, note: final.note };
|
|
24855
|
+
return { data: final.data, note: final.note };
|
|
24694
24856
|
}
|
|
24695
24857
|
function errorBodyMessage(body) {
|
|
24696
24858
|
if (Array.isArray(body.issues) && typeof body.message === "string") return body.message;
|
|
@@ -24779,16 +24941,28 @@ function createToolsClient(options = {}) {
|
|
|
24779
24941
|
const { url, token, remote } = await route();
|
|
24780
24942
|
let finalArgs = args;
|
|
24781
24943
|
const meta2 = await fetchTool(name, { signal: opts?.signal });
|
|
24944
|
+
const baselineDirs = [];
|
|
24782
24945
|
if (meta2?.fileInputs?.length) {
|
|
24783
24946
|
if (remote) assertRequiredPresent(meta2, args);
|
|
24784
24947
|
finalArgs = await prepareFileInputs(meta2.fileInputs, args ?? {}, {
|
|
24785
24948
|
includeContent: remote,
|
|
24786
24949
|
uploadEndpoint: remote ? { url, token } : void 0,
|
|
24787
24950
|
log: diagnose,
|
|
24951
|
+
baselineDirs,
|
|
24788
24952
|
collectMembers: collectFlowMembers,
|
|
24789
24953
|
signal: opts?.signal
|
|
24790
24954
|
});
|
|
24791
24955
|
}
|
|
24956
|
+
const settle = async (data) => {
|
|
24957
|
+
const applied = await applyClientFileDirectives(data, { allowedDirs: baselineDirs });
|
|
24958
|
+
for (const { path: file, error: error2 } of applied.failed) {
|
|
24959
|
+
diagnose(`The baseline ${file} was not written on this client: ${error2}`);
|
|
24960
|
+
}
|
|
24961
|
+
if (process.env.ARGENT_FLOW_FILES_LOG === "1") {
|
|
24962
|
+
for (const file of applied.written) diagnose(`[flow-files] baseline ${file}: written`);
|
|
24963
|
+
}
|
|
24964
|
+
return applied.result;
|
|
24965
|
+
};
|
|
24792
24966
|
const stream = opts?.onProgress !== void 0 || carriesMembers(finalArgs);
|
|
24793
24967
|
const sentOnce = carriesUpload(finalArgs);
|
|
24794
24968
|
const res = await doFetch(
|
|
@@ -24820,7 +24994,11 @@ function createToolsClient(options = {}) {
|
|
|
24820
24994
|
}),
|
|
24821
24995
|
opts?.signal
|
|
24822
24996
|
);
|
|
24823
|
-
return {
|
|
24997
|
+
return {
|
|
24998
|
+
data: await settle(streamed.data),
|
|
24999
|
+
note: streamed.note,
|
|
25000
|
+
outputHint: meta2?.outputHint
|
|
25001
|
+
};
|
|
24824
25002
|
}
|
|
24825
25003
|
let json;
|
|
24826
25004
|
try {
|
|
@@ -24844,17 +25022,16 @@ function createToolsClient(options = {}) {
|
|
|
24844
25022
|
});
|
|
24845
25023
|
}
|
|
24846
25024
|
opts?.signal?.throwIfAborted();
|
|
24847
|
-
|
|
24848
|
-
return { data, note: json.note, outputHint: meta2?.outputHint };
|
|
25025
|
+
return { data: await settle(json.data), note: json.note, outputHint: meta2?.outputHint };
|
|
24849
25026
|
}
|
|
24850
25027
|
return { fetchTools, fetchTool, callTool, baseUrl };
|
|
24851
25028
|
}
|
|
24852
25029
|
|
|
24853
25030
|
// ../argent-tools-client/src/artifacts.ts
|
|
24854
|
-
import { copyFile, mkdir as mkdir4, readFile as readFile5, realpath as
|
|
25031
|
+
import { copyFile, mkdir as mkdir4, readFile as readFile5, realpath as realpath4, rm as rm3, stat as stat4, writeFile as writeFile4 } from "node:fs/promises";
|
|
24855
25032
|
import { constants as fsConstants } from "node:fs";
|
|
24856
25033
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
24857
|
-
import { basename as basename6, dirname as dirname7, extname as extname2, isAbsolute as isAbsolute5, join as join11, normalize, resolve as resolve6, sep as sep4 } from "node:path";
|
|
25034
|
+
import { basename as basename6, dirname as dirname7, extname as extname2, isAbsolute as isAbsolute5, join as join11, normalize as normalize2, resolve as resolve6, sep as sep4 } from "node:path";
|
|
24858
25035
|
import { createHash as createHash3 } from "node:crypto";
|
|
24859
25036
|
|
|
24860
25037
|
// ../configuration-core/src/flags.ts
|
|
@@ -25298,8 +25475,8 @@ function durableBaseDir() {
|
|
|
25298
25475
|
const projectRoot = findProjectRoot(process.cwd());
|
|
25299
25476
|
return projectRoot ?? dirname7(argentHomeDir());
|
|
25300
25477
|
}
|
|
25301
|
-
var ALLOWED_SAVE_DIRS = /* @__PURE__ */ new Set([
|
|
25302
|
-
var RECORDINGS_SAVE_DIR =
|
|
25478
|
+
var ALLOWED_SAVE_DIRS = /* @__PURE__ */ new Set([normalize2(".argent/recordings")]);
|
|
25479
|
+
var RECORDINGS_SAVE_DIR = normalize2(".argent/recordings");
|
|
25303
25480
|
function configuredRecordingsDir() {
|
|
25304
25481
|
let value;
|
|
25305
25482
|
try {
|
|
@@ -25358,7 +25535,7 @@ async function writeDurableUnique(dir, filename, write) {
|
|
|
25358
25535
|
}
|
|
25359
25536
|
function durableSaveTarget(handle) {
|
|
25360
25537
|
if (typeof handle.saveDir !== "string" || !handle.saveDir || handle.archive) return null;
|
|
25361
|
-
const rel =
|
|
25538
|
+
const rel = normalize2(handle.saveDir);
|
|
25362
25539
|
if (isAbsolute5(rel) || rel === ".." || rel.startsWith(`..${sep4}`) || rel.split(sep4).includes("..")) {
|
|
25363
25540
|
return null;
|
|
25364
25541
|
}
|
|
@@ -25380,8 +25557,8 @@ function durableSaveTarget(handle) {
|
|
|
25380
25557
|
}
|
|
25381
25558
|
async function confineToRealBase(dir, base, rel) {
|
|
25382
25559
|
try {
|
|
25383
|
-
const realDir = await
|
|
25384
|
-
const realBase = await
|
|
25560
|
+
const realDir = await realpath4(dir);
|
|
25561
|
+
const realBase = await realpath4(base);
|
|
25385
25562
|
return realDir === join11(realBase, rel);
|
|
25386
25563
|
} catch {
|
|
25387
25564
|
return false;
|
|
@@ -26534,6 +26711,12 @@ async function flowRunToMcpContent(result, ctx) {
|
|
|
26534
26711
|
blocks.push(...await stepArtifactBlocks(step.artifacts, step.status, ctx, step.depth));
|
|
26535
26712
|
}
|
|
26536
26713
|
}
|
|
26714
|
+
for (const write of result.baselineWrites ?? []) {
|
|
26715
|
+
const { path: path15, error: error2 } = isRecord2(write) ? write : {};
|
|
26716
|
+
if (typeof path15 === "string" && typeof error2 === "string") {
|
|
26717
|
+
blocks.push({ type: "text", text: `\u2717 baseline not written: ${path15}: ${error2}` });
|
|
26718
|
+
}
|
|
26719
|
+
}
|
|
26537
26720
|
if (result.ok !== void 0) {
|
|
26538
26721
|
const counted = (result.passed ?? 0) + (result.failed ?? 0) + (result.errored ?? 0) + (result.skipped ?? 0);
|
|
26539
26722
|
const note = result.ok && counted === 0 ? " (no test steps)" : "";
|
|
@@ -225,7 +225,7 @@ export interface ArgentToolArgs {
|
|
|
225
225
|
project_root: string;
|
|
226
226
|
/** Path to the flow .yaml as readable by the tool-server. Internal — the argent client derives it from project_root and name automatically; leave unset. */
|
|
227
227
|
flow_file?: string;
|
|
228
|
-
/** Omit when name is set. Absolute path to a flow .yaml on the client. Over a link (argent link or ARGENT_TOOLS_URL), the argent client uploads the file
|
|
228
|
+
/** Omit when name is set. Absolute path to a flow .yaml on the client. Over a link (argent link or ARGENT_TOOLS_URL), the argent client uploads the file, its run: fragments and the snapshot baselines that the run compares, and the tool-server runs those copies. Keep run: fragments under project_root or beside the flow file. With updateBaselines, the client writes the new baselines when the run ends. Over a link, the flow and its fragments must not have script: steps, or tool: steps that take a file or record a flow. Without a link, the tool-server reads the files in place and all step kinds run. */
|
|
229
229
|
flow_path?: string;
|
|
230
230
|
/** Device id to run against (iOS UDID, Android/Vega serial, Chromium id) — the id list-devices reports. Auto-detected when omitted, but only when exactly one booted device matches (optionally narrowed by `platform`); with several booted the run fails and lists them, so pass this explicitly whenever more than one device is up. */
|
|
231
231
|
device?: string;
|