@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/cli-cmds.mjs
CHANGED
|
@@ -9390,6 +9390,7 @@ function isRecord(value) {
|
|
|
9390
9390
|
}
|
|
9391
9391
|
function collectFlowRequests(doc) {
|
|
9392
9392
|
const runTargets = /* @__PURE__ */ new Set();
|
|
9393
|
+
const snapshots = /* @__PURE__ */ new Set();
|
|
9393
9394
|
const seen = /* @__PURE__ */ new Set();
|
|
9394
9395
|
const visit = (steps, depth) => {
|
|
9395
9396
|
if (!Array.isArray(steps) || depth > MAX_BLOCK_NESTING || seen.has(steps)) return;
|
|
@@ -9401,11 +9402,17 @@ function collectFlowRequests(doc) {
|
|
|
9401
9402
|
const target = completeRunExtension(run2);
|
|
9402
9403
|
if (FLOW_FILE_NAME_PATTERN.test(path2.posix.basename(target))) runTargets.add(target);
|
|
9403
9404
|
}
|
|
9405
|
+
const snapshot = isRecord(step.snapshot) ? step.snapshot.name : step.snapshot;
|
|
9406
|
+
if (typeof snapshot === "string" && FLOW_NAME_PATTERN.test(snapshot)) snapshots.add(snapshot);
|
|
9404
9407
|
visit(step.steps, depth + 1);
|
|
9405
9408
|
}
|
|
9406
9409
|
};
|
|
9407
9410
|
if (isRecord(doc)) visit(doc.steps, 0);
|
|
9408
|
-
return { runTargets: [...runTargets] };
|
|
9411
|
+
return { runTargets: [...runTargets], snapshots: [...snapshots] };
|
|
9412
|
+
}
|
|
9413
|
+
function baselineKeyFor(canonicalPath, flowName) {
|
|
9414
|
+
const stem = path2.basename(canonicalPath, ".yaml");
|
|
9415
|
+
return FLOW_NAME_PATTERN.test(stem) ? stem : flowName;
|
|
9409
9416
|
}
|
|
9410
9417
|
function flowMemberKey(anchorDir, target) {
|
|
9411
9418
|
return `${anchorDir}\0${target}`;
|
|
@@ -24461,7 +24468,17 @@ function parseLinkTarget(input) {
|
|
|
24461
24468
|
// ../argent-tools-client/src/file-inputs.ts
|
|
24462
24469
|
import { createHash as createHash2, randomUUID as randomUUID3 } from "node:crypto";
|
|
24463
24470
|
import { createReadStream, rmSync } from "node:fs";
|
|
24464
|
-
import {
|
|
24471
|
+
import {
|
|
24472
|
+
chmod as chmod3,
|
|
24473
|
+
lstat,
|
|
24474
|
+
mkdir as mkdir3,
|
|
24475
|
+
readFile as readFile3,
|
|
24476
|
+
realpath as realpath2,
|
|
24477
|
+
rename as rename2,
|
|
24478
|
+
rm as rm2,
|
|
24479
|
+
stat as stat2,
|
|
24480
|
+
writeFile as writeFile3
|
|
24481
|
+
} from "node:fs/promises";
|
|
24465
24482
|
import { constants, tmpdir } from "node:os";
|
|
24466
24483
|
import * as path4 from "node:path";
|
|
24467
24484
|
|
|
@@ -24770,9 +24787,61 @@ function isAllowedClientFilePath(p) {
|
|
|
24770
24787
|
function isClientFileDirective2(value) {
|
|
24771
24788
|
return !!value && typeof value === "object" && value[CLIENT_FILE_MARKER2] === true && typeof value.path === "string" && typeof value.content === "string";
|
|
24772
24789
|
}
|
|
24773
|
-
async function
|
|
24790
|
+
async function replaceFile(target, bytes, mode) {
|
|
24791
|
+
const temp = path4.join(path4.dirname(target), `.baseline-${randomUUID3()}.tmp`);
|
|
24792
|
+
try {
|
|
24793
|
+
await writeFile3(temp, bytes, { flag: "wx" });
|
|
24794
|
+
if (mode !== void 0) await chmod3(temp, mode & 511);
|
|
24795
|
+
await rename2(temp, target);
|
|
24796
|
+
} catch (err) {
|
|
24797
|
+
await rm2(temp, { force: true });
|
|
24798
|
+
throw err;
|
|
24799
|
+
}
|
|
24800
|
+
}
|
|
24801
|
+
async function writeBaselineFile(file2, bytes, allowedDirs) {
|
|
24802
|
+
if (!path4.isAbsolute(file2) || path4.normalize(file2) !== file2 || file2.split(/[\\/]/).includes("..") || !file2.endsWith(".png") || !allowedDirs.includes(path4.dirname(file2))) {
|
|
24803
|
+
return allowedDirs.length === 0 ? "this call writes no baselines" : `${file2} is not a baseline of this call (${allowedDirs.map((d) => `${d}/<name>.png`).join(", ")})`;
|
|
24804
|
+
}
|
|
24805
|
+
if (bytes.length > MAX_CONTENT_BYTES) {
|
|
24806
|
+
return `${file2}: the baseline is larger than the 32 MiB cap on a file this client writes`;
|
|
24807
|
+
}
|
|
24808
|
+
const dir = path4.dirname(file2);
|
|
24809
|
+
await mkdir3(dir, { recursive: true });
|
|
24810
|
+
const link2 = await lstat(file2).catch(() => null);
|
|
24811
|
+
const real = link2 === null ? null : await realpath2(file2).catch(() => null);
|
|
24812
|
+
if (link2 !== null && real === null) return `${file2} is a symbolic link to a missing file`;
|
|
24813
|
+
if (real !== null) {
|
|
24814
|
+
if (!real.endsWith(".png")) return `${file2} links to a file that is not a PNG file`;
|
|
24815
|
+
if (path4.dirname(real) !== await realpath2(dir)) {
|
|
24816
|
+
return `${file2} links outside its baseline directory`;
|
|
24817
|
+
}
|
|
24818
|
+
}
|
|
24819
|
+
const existing = real === null ? null : await stat2(real);
|
|
24820
|
+
if (existing !== null && !existing.isFile()) return `${file2} is not a regular file`;
|
|
24821
|
+
await replaceFile(
|
|
24822
|
+
real ?? path4.join(await realpath2(dir), path4.basename(file2)),
|
|
24823
|
+
bytes,
|
|
24824
|
+
existing?.mode
|
|
24825
|
+
);
|
|
24826
|
+
return null;
|
|
24827
|
+
}
|
|
24828
|
+
async function applyClientFileDirectives(result, opts = {}) {
|
|
24774
24829
|
const written = [];
|
|
24830
|
+
const failed = [];
|
|
24775
24831
|
async function walk(value) {
|
|
24832
|
+
if (isClientFileDirective2(value) && value.encoding === "base64") {
|
|
24833
|
+
const error52 = await writeBaselineFile(
|
|
24834
|
+
value.path,
|
|
24835
|
+
Buffer.from(value.content, "base64"),
|
|
24836
|
+
opts.allowedDirs ?? []
|
|
24837
|
+
).catch((err) => err instanceof Error ? err.message : String(err));
|
|
24838
|
+
if (error52 !== null) {
|
|
24839
|
+
failed.push({ path: value.path, error: error52 });
|
|
24840
|
+
return { path: value.path, error: error52 };
|
|
24841
|
+
}
|
|
24842
|
+
written.push(value.path);
|
|
24843
|
+
return value.path;
|
|
24844
|
+
}
|
|
24776
24845
|
if (isClientFileDirective2(value)) {
|
|
24777
24846
|
if (!isAllowedClientFilePath(value.path)) return null;
|
|
24778
24847
|
try {
|
|
@@ -24785,7 +24854,9 @@ async function applyClientFileDirectives(result) {
|
|
|
24785
24854
|
}
|
|
24786
24855
|
}
|
|
24787
24856
|
if (Array.isArray(value)) {
|
|
24788
|
-
|
|
24857
|
+
const out = [];
|
|
24858
|
+
for (const item of value) out.push(await walk(item));
|
|
24859
|
+
return out;
|
|
24789
24860
|
}
|
|
24790
24861
|
if (value && typeof value === "object") {
|
|
24791
24862
|
const out = {};
|
|
@@ -24797,12 +24868,12 @@ async function applyClientFileDirectives(result) {
|
|
|
24797
24868
|
return value;
|
|
24798
24869
|
}
|
|
24799
24870
|
const rewritten = await walk(result);
|
|
24800
|
-
return { result: rewritten, written };
|
|
24871
|
+
return { result: rewritten, written, failed };
|
|
24801
24872
|
}
|
|
24802
24873
|
|
|
24803
24874
|
// ../argent-tools-client/src/flow-files.ts
|
|
24804
24875
|
var import_yaml = __toESM(require_dist(), 1);
|
|
24805
|
-
import { readFile as readFile4, realpath as
|
|
24876
|
+
import { readdir as readdir4, readFile as readFile4, realpath as realpath3, stat as stat3 } from "node:fs/promises";
|
|
24806
24877
|
import * as path5 from "node:path";
|
|
24807
24878
|
var INLINE_MEMBERS_BYTES = 256 * 1024;
|
|
24808
24879
|
var FLOW_FILES_LOG_ENV = "ARGENT_FLOW_FILES_LOG";
|
|
@@ -24837,7 +24908,7 @@ function savedFlowProject(file2) {
|
|
|
24837
24908
|
}
|
|
24838
24909
|
async function landing(spelled) {
|
|
24839
24910
|
try {
|
|
24840
|
-
const canonical = await
|
|
24911
|
+
const canonical = await realpath3(spelled);
|
|
24841
24912
|
return { canonical, fence: canonical };
|
|
24842
24913
|
} catch (err) {
|
|
24843
24914
|
const failure = err.code === "ENOENT" ? { missing: true } : { error: err.message };
|
|
@@ -24846,7 +24917,7 @@ async function landing(spelled) {
|
|
|
24846
24917
|
for (; ; ) {
|
|
24847
24918
|
const parent = path5.dirname(at);
|
|
24848
24919
|
if (parent === at) return { canonical, fence: spelled, ...failure };
|
|
24849
|
-
const real = await
|
|
24920
|
+
const real = await realpath3(parent).catch(() => null);
|
|
24850
24921
|
if (real !== null) {
|
|
24851
24922
|
return { canonical, fence: path5.join(real, path5.basename(at)), ...failure };
|
|
24852
24923
|
}
|
|
@@ -24866,7 +24937,7 @@ async function closureRoots(rootPath, rootCanonical, projectRoot) {
|
|
|
24866
24937
|
}
|
|
24867
24938
|
const real = [];
|
|
24868
24939
|
for (const candidate of candidates) {
|
|
24869
|
-
const resolved = await
|
|
24940
|
+
const resolved = await realpath3(candidate).catch(() => null);
|
|
24870
24941
|
if (resolved !== null && !real.includes(resolved)) real.push(resolved);
|
|
24871
24942
|
}
|
|
24872
24943
|
return real.filter((root) => !real.some((other) => other !== root && isWithin(root, other)));
|
|
@@ -24904,31 +24975,96 @@ async function readFlowMember(anchorDir, target, roots, budget, opts) {
|
|
|
24904
24975
|
if (!/\.ya?ml$/i.test(path5.basename(canonical))) {
|
|
24905
24976
|
return refuse(`${target} links to a file that is not a YAML file`);
|
|
24906
24977
|
}
|
|
24907
|
-
const
|
|
24978
|
+
const sent = await sendBytes(member, canonical, budget, opts);
|
|
24979
|
+
return { ...sent, text: sent.bytes?.toString("utf8") };
|
|
24980
|
+
}
|
|
24981
|
+
function callPlatform(args) {
|
|
24982
|
+
if (typeof args.device === "string" && args.device.startsWith("chromium-cdp-")) return "chromium";
|
|
24983
|
+
if (typeof args.platform !== "string") return void 0;
|
|
24984
|
+
return args.platform === "ios-remote" ? "ios" : args.platform;
|
|
24985
|
+
}
|
|
24986
|
+
async function baselineEntry(file2, roots, forWrite) {
|
|
24987
|
+
const { canonical, error: error52 } = await landing(file2);
|
|
24988
|
+
if (!roots.some((root) => isWithin(canonical, root))) {
|
|
24989
|
+
return {
|
|
24990
|
+
state: "refused",
|
|
24991
|
+
error: `${file2} is outside every root this client serves (${roots.join(", ")})`
|
|
24992
|
+
};
|
|
24993
|
+
}
|
|
24994
|
+
if (error52 !== void 0) return { state: "refused", error: error52 };
|
|
24995
|
+
const st = await stat3(canonical).catch((err) => err);
|
|
24996
|
+
if (st instanceof Error) {
|
|
24997
|
+
if (st.code !== "ENOENT") return { state: "refused", error: st.message };
|
|
24998
|
+
return forWrite ? { state: "refused", error: `${file2} is a symbolic link to a missing file` } : { state: "missing" };
|
|
24999
|
+
}
|
|
25000
|
+
if (!canonical.endsWith(".png")) {
|
|
25001
|
+
return { state: "refused", error: `${file2} links to a file that is not a PNG file` };
|
|
25002
|
+
}
|
|
25003
|
+
if (forWrite && !st.isFile()) return { state: "refused", error: `${file2} is not a regular file` };
|
|
25004
|
+
if (st.isDirectory()) {
|
|
25005
|
+
return { state: "refused", error: "EISDIR: illegal operation on a directory, read" };
|
|
25006
|
+
}
|
|
25007
|
+
return st.isFile() ? { state: "ok", real: canonical } : { state: "missing" };
|
|
25008
|
+
}
|
|
25009
|
+
async function sendBytes(member, real, budget, opts) {
|
|
25010
|
+
const read = await readFileInputWire(real, { includeContent: true });
|
|
24908
25011
|
if (read?.contentOmitted) {
|
|
24909
|
-
|
|
25012
|
+
const error52 = `${real} is larger than the 32 MiB cap on a file sent to the tool-server`;
|
|
25013
|
+
return { member: { ...member, state: "refused", error: error52 }, sent: `refused (${error52})` };
|
|
24910
25014
|
}
|
|
24911
25015
|
if (read?.content === void 0) {
|
|
24912
|
-
|
|
24913
|
-
|
|
24914
|
-
|
|
24915
|
-
(err) => err instanceof Error ? err.message : String(err)
|
|
24916
|
-
)
|
|
25016
|
+
const error52 = await readFile4(real).then(
|
|
25017
|
+
() => `${real} could not be read on this client`,
|
|
25018
|
+
(err) => err instanceof Error ? err.message : String(err)
|
|
24917
25019
|
);
|
|
25020
|
+
return { member: { ...member, state: "refused", error: error52 }, sent: `refused (${error52})` };
|
|
24918
25021
|
}
|
|
24919
|
-
const
|
|
25022
|
+
const bytes = Buffer.from(read.content, "base64");
|
|
24920
25023
|
const size = read.size ?? 0;
|
|
24921
25024
|
if (budget.inline + size <= INLINE_MEMBERS_BYTES || !opts.uploadEndpoint) {
|
|
24922
25025
|
budget.inline += size;
|
|
24923
|
-
return { member: { ...member, ...read },
|
|
25026
|
+
return { member: { ...member, ...read }, sent: `inline ${size}`, bytes };
|
|
24924
25027
|
}
|
|
24925
|
-
const uploaded = await uploadFile(
|
|
25028
|
+
const uploaded = await uploadFile(real, opts.uploadEndpoint, opts.signal);
|
|
24926
25029
|
return {
|
|
24927
25030
|
member: { ...member, size: read.size, mtimeMs: read.mtimeMs, ...uploaded },
|
|
24928
|
-
|
|
24929
|
-
|
|
25031
|
+
sent: `upload ${size}`,
|
|
25032
|
+
bytes
|
|
24930
25033
|
};
|
|
24931
25034
|
}
|
|
25035
|
+
async function collectBaselineMembers(canonical, flowName, snapshots, args, roots, budget, opts, emit) {
|
|
25036
|
+
const dir = path5.join(
|
|
25037
|
+
path5.dirname(canonical),
|
|
25038
|
+
"__baselines__",
|
|
25039
|
+
baselineKeyFor(canonical, flowName)
|
|
25040
|
+
);
|
|
25041
|
+
const real = (await landing(dir)).canonical;
|
|
25042
|
+
if (!roots.some((root) => isWithin(real, root))) return;
|
|
25043
|
+
const updates = args.updateBaselines === true;
|
|
25044
|
+
if (updates) opts.baselineDirs?.push(dir);
|
|
25045
|
+
const platform = callPlatform(args);
|
|
25046
|
+
const prefixes = snapshots.map(
|
|
25047
|
+
(name) => `${name}__${platform === void 0 ? "" : `${platform}-`}`
|
|
25048
|
+
);
|
|
25049
|
+
const names = await readdir4(dir).catch(() => []);
|
|
25050
|
+
for (const name of names.sort()) {
|
|
25051
|
+
if (!name.endsWith(".png")) continue;
|
|
25052
|
+
if (!updates && !prefixes.some((prefix) => name.startsWith(prefix))) continue;
|
|
25053
|
+
const file2 = path5.join(dir, name);
|
|
25054
|
+
const member = { role: "baseline", key: file2, path: file2 };
|
|
25055
|
+
const entry = await baselineEntry(file2, roots, updates);
|
|
25056
|
+
if (entry.state === "refused") {
|
|
25057
|
+
emit({ ...member, state: "refused", error: entry.error }, `refused (${entry.error})`);
|
|
25058
|
+
} else if (entry.state === "missing") {
|
|
25059
|
+
emit({ ...member, state: "missing" }, "missing");
|
|
25060
|
+
} else if (updates) {
|
|
25061
|
+
emit({ ...member, state: "listed" }, "listed");
|
|
25062
|
+
} else {
|
|
25063
|
+
const sent = await sendBytes(member, entry.real, budget, opts);
|
|
25064
|
+
emit(sent.member, sent.sent);
|
|
25065
|
+
}
|
|
25066
|
+
}
|
|
25067
|
+
}
|
|
24932
25068
|
async function collectFlowMembers(rootPath, rootBytes, args, opts) {
|
|
24933
25069
|
if (!namesValidFlow(args)) return {};
|
|
24934
25070
|
const canonical = await canonicalFlowPath(rootPath);
|
|
@@ -24940,10 +25076,16 @@ async function collectFlowMembers(rootPath, rootBytes, args, opts) {
|
|
|
24940
25076
|
const roots = await closureRoots(rootPath, canonical, args.project_root);
|
|
24941
25077
|
const members = [];
|
|
24942
25078
|
const seen = /* @__PURE__ */ new Set();
|
|
25079
|
+
const snapshots = /* @__PURE__ */ new Set();
|
|
24943
25080
|
const budget = { inline: 0 };
|
|
24944
25081
|
const logging = process.env[FLOW_FILES_LOG_ENV] === "1";
|
|
24945
25082
|
const log2 = opts.log ?? ((line) => void process.stderr.write(`${line}
|
|
24946
25083
|
`));
|
|
25084
|
+
const emit = (member, sent) => {
|
|
25085
|
+
members.push(member);
|
|
25086
|
+
const subject = member.role === "flow" ? member.canonical : member.key;
|
|
25087
|
+
if (logging) log2(printable(`[flow-files] ${member.role} ${subject}: ${sent}`));
|
|
25088
|
+
};
|
|
24947
25089
|
const queue = [{ canonical, text: rootBytes.toString("utf8"), hop: 0 }];
|
|
24948
25090
|
for (let file2 = queue.shift(); file2 !== void 0; file2 = queue.shift()) {
|
|
24949
25091
|
let doc;
|
|
@@ -24952,19 +25094,33 @@ async function collectFlowMembers(rootPath, rootBytes, args, opts) {
|
|
|
24952
25094
|
} catch {
|
|
24953
25095
|
continue;
|
|
24954
25096
|
}
|
|
25097
|
+
const requests = collectFlowRequests(doc);
|
|
25098
|
+
for (const name of requests.snapshots) snapshots.add(name);
|
|
24955
25099
|
const anchorDir = path5.dirname(file2.canonical);
|
|
24956
|
-
for (const target of
|
|
25100
|
+
for (const target of requests.runTargets) {
|
|
24957
25101
|
const key = flowMemberKey(anchorDir, target);
|
|
24958
25102
|
if (seen.has(key)) continue;
|
|
24959
25103
|
seen.add(key);
|
|
24960
25104
|
const { member, text: text2, sent } = await readFlowMember(anchorDir, target, roots, budget, opts);
|
|
24961
|
-
|
|
24962
|
-
if (logging) log2(printable(`[flow-files] flow ${member.canonical}: ${sent}`));
|
|
25105
|
+
emit(member, sent);
|
|
24963
25106
|
if (text2 !== void 0 && file2.hop + 1 < MAX_RUN_DEPTH) {
|
|
24964
25107
|
queue.push({ canonical: member.canonical, text: text2, hop: file2.hop + 1 });
|
|
24965
25108
|
}
|
|
24966
25109
|
}
|
|
24967
25110
|
}
|
|
25111
|
+
if (snapshots.size > 0) {
|
|
25112
|
+
const flowName = path5.basename(rootPath, ".yaml");
|
|
25113
|
+
await collectBaselineMembers(
|
|
25114
|
+
canonical,
|
|
25115
|
+
flowName,
|
|
25116
|
+
[...snapshots],
|
|
25117
|
+
args,
|
|
25118
|
+
roots,
|
|
25119
|
+
budget,
|
|
25120
|
+
opts,
|
|
25121
|
+
emit
|
|
25122
|
+
);
|
|
25123
|
+
}
|
|
24968
25124
|
return { canonical, spelling, members };
|
|
24969
25125
|
}
|
|
24970
25126
|
|
|
@@ -24999,7 +25155,20 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
24999
25155
|
}
|
|
25000
25156
|
};
|
|
25001
25157
|
const decoder = new TextDecoder();
|
|
25002
|
-
let
|
|
25158
|
+
let pieces = [];
|
|
25159
|
+
const take = (text2) => {
|
|
25160
|
+
let start = 0;
|
|
25161
|
+
let newline;
|
|
25162
|
+
while ((newline = text2.indexOf("\n", start)) !== -1) {
|
|
25163
|
+
signal?.throwIfAborted();
|
|
25164
|
+
pieces.push(text2.slice(start, newline));
|
|
25165
|
+
const line = pieces.join("");
|
|
25166
|
+
pieces = [];
|
|
25167
|
+
start = newline + 1;
|
|
25168
|
+
handleLine(line);
|
|
25169
|
+
}
|
|
25170
|
+
if (start < text2.length) pieces.push(text2.slice(start));
|
|
25171
|
+
};
|
|
25003
25172
|
try {
|
|
25004
25173
|
for (; ; ) {
|
|
25005
25174
|
let chunk;
|
|
@@ -25011,17 +25180,11 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
25011
25180
|
}
|
|
25012
25181
|
const { done, value } = chunk;
|
|
25013
25182
|
if (done) break;
|
|
25014
|
-
|
|
25015
|
-
let newline;
|
|
25016
|
-
while ((newline = buffered.indexOf("\n")) !== -1) {
|
|
25017
|
-
signal?.throwIfAborted();
|
|
25018
|
-
const line = buffered.slice(0, newline);
|
|
25019
|
-
buffered = buffered.slice(newline + 1);
|
|
25020
|
-
handleLine(line);
|
|
25021
|
-
}
|
|
25183
|
+
take(decoder.decode(value, { stream: true }));
|
|
25022
25184
|
}
|
|
25023
|
-
|
|
25024
|
-
|
|
25185
|
+
take(decoder.decode());
|
|
25186
|
+
const last = pieces.join("");
|
|
25187
|
+
if (last.trim()) handleLine(last);
|
|
25025
25188
|
} catch (err) {
|
|
25026
25189
|
void reader.cancel().catch(() => {
|
|
25027
25190
|
});
|
|
@@ -25031,8 +25194,7 @@ async function consumeToolStream(name, body, onProgress, signal) {
|
|
|
25031
25194
|
if (!final) {
|
|
25032
25195
|
throw brokenStream(name, "the stream ended without a result", progress);
|
|
25033
25196
|
}
|
|
25034
|
-
|
|
25035
|
-
return { data, note: final.note };
|
|
25197
|
+
return { data: final.data, note: final.note };
|
|
25036
25198
|
}
|
|
25037
25199
|
function errorBodyMessage(body) {
|
|
25038
25200
|
if (Array.isArray(body.issues) && typeof body.message === "string") return body.message;
|
|
@@ -25121,16 +25283,28 @@ function createToolsClient(options = {}) {
|
|
|
25121
25283
|
const { url: url2, token, remote } = await route();
|
|
25122
25284
|
let finalArgs = args;
|
|
25123
25285
|
const meta3 = await fetchTool(name, { signal: opts?.signal });
|
|
25286
|
+
const baselineDirs = [];
|
|
25124
25287
|
if (meta3?.fileInputs?.length) {
|
|
25125
25288
|
if (remote) assertRequiredPresent(meta3, args);
|
|
25126
25289
|
finalArgs = await prepareFileInputs(meta3.fileInputs, args ?? {}, {
|
|
25127
25290
|
includeContent: remote,
|
|
25128
25291
|
uploadEndpoint: remote ? { url: url2, token } : void 0,
|
|
25129
25292
|
log: diagnose,
|
|
25293
|
+
baselineDirs,
|
|
25130
25294
|
collectMembers: collectFlowMembers,
|
|
25131
25295
|
signal: opts?.signal
|
|
25132
25296
|
});
|
|
25133
25297
|
}
|
|
25298
|
+
const settle = async (data) => {
|
|
25299
|
+
const applied = await applyClientFileDirectives(data, { allowedDirs: baselineDirs });
|
|
25300
|
+
for (const { path: file2, error: error52 } of applied.failed) {
|
|
25301
|
+
diagnose(`The baseline ${file2} was not written on this client: ${error52}`);
|
|
25302
|
+
}
|
|
25303
|
+
if (process.env.ARGENT_FLOW_FILES_LOG === "1") {
|
|
25304
|
+
for (const file2 of applied.written) diagnose(`[flow-files] baseline ${file2}: written`);
|
|
25305
|
+
}
|
|
25306
|
+
return applied.result;
|
|
25307
|
+
};
|
|
25134
25308
|
const stream = opts?.onProgress !== void 0 || carriesMembers(finalArgs);
|
|
25135
25309
|
const sentOnce = carriesUpload(finalArgs);
|
|
25136
25310
|
const res = await doFetch(
|
|
@@ -25162,7 +25336,11 @@ function createToolsClient(options = {}) {
|
|
|
25162
25336
|
}),
|
|
25163
25337
|
opts?.signal
|
|
25164
25338
|
);
|
|
25165
|
-
return {
|
|
25339
|
+
return {
|
|
25340
|
+
data: await settle(streamed.data),
|
|
25341
|
+
note: streamed.note,
|
|
25342
|
+
outputHint: meta3?.outputHint
|
|
25343
|
+
};
|
|
25166
25344
|
}
|
|
25167
25345
|
let json2;
|
|
25168
25346
|
try {
|
|
@@ -25186,17 +25364,16 @@ function createToolsClient(options = {}) {
|
|
|
25186
25364
|
});
|
|
25187
25365
|
}
|
|
25188
25366
|
opts?.signal?.throwIfAborted();
|
|
25189
|
-
|
|
25190
|
-
return { data, note: json2.note, outputHint: meta3?.outputHint };
|
|
25367
|
+
return { data: await settle(json2.data), note: json2.note, outputHint: meta3?.outputHint };
|
|
25191
25368
|
}
|
|
25192
25369
|
return { fetchTools, fetchTool, callTool, baseUrl };
|
|
25193
25370
|
}
|
|
25194
25371
|
|
|
25195
25372
|
// ../argent-tools-client/src/artifacts.ts
|
|
25196
|
-
import { copyFile, mkdir as mkdir4, readFile as readFile5, realpath as
|
|
25373
|
+
import { copyFile, mkdir as mkdir4, readFile as readFile5, realpath as realpath4, rm as rm3, stat as stat4, writeFile as writeFile4 } from "node:fs/promises";
|
|
25197
25374
|
import { constants as fsConstants } from "node:fs";
|
|
25198
25375
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
25199
|
-
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";
|
|
25376
|
+
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";
|
|
25200
25377
|
import { createHash as createHash3 } from "node:crypto";
|
|
25201
25378
|
|
|
25202
25379
|
// ../configuration-core/src/flags.ts
|
|
@@ -25935,8 +26112,8 @@ function durableBaseDir() {
|
|
|
25935
26112
|
const projectRoot = findProjectRoot(process.cwd());
|
|
25936
26113
|
return projectRoot ?? dirname7(argentHomeDir());
|
|
25937
26114
|
}
|
|
25938
|
-
var ALLOWED_SAVE_DIRS = /* @__PURE__ */ new Set([
|
|
25939
|
-
var RECORDINGS_SAVE_DIR =
|
|
26115
|
+
var ALLOWED_SAVE_DIRS = /* @__PURE__ */ new Set([normalize2(".argent/recordings")]);
|
|
26116
|
+
var RECORDINGS_SAVE_DIR = normalize2(".argent/recordings");
|
|
25940
26117
|
function configuredRecordingsDir() {
|
|
25941
26118
|
let value;
|
|
25942
26119
|
try {
|
|
@@ -25995,7 +26172,7 @@ async function writeDurableUnique(dir, filename, write) {
|
|
|
25995
26172
|
}
|
|
25996
26173
|
function durableSaveTarget(handle) {
|
|
25997
26174
|
if (typeof handle.saveDir !== "string" || !handle.saveDir || handle.archive) return null;
|
|
25998
|
-
const rel =
|
|
26175
|
+
const rel = normalize2(handle.saveDir);
|
|
25999
26176
|
if (isAbsolute5(rel) || rel === ".." || rel.startsWith(`..${sep4}`) || rel.split(sep4).includes("..")) {
|
|
26000
26177
|
return null;
|
|
26001
26178
|
}
|
|
@@ -26017,8 +26194,8 @@ function durableSaveTarget(handle) {
|
|
|
26017
26194
|
}
|
|
26018
26195
|
async function confineToRealBase(dir, base, rel) {
|
|
26019
26196
|
try {
|
|
26020
|
-
const realDir = await
|
|
26021
|
-
const realBase = await
|
|
26197
|
+
const realDir = await realpath4(dir);
|
|
26198
|
+
const realBase = await realpath4(base);
|
|
26022
26199
|
return realDir === join11(realBase, rel);
|
|
26023
26200
|
} catch {
|
|
26024
26201
|
return false;
|
|
@@ -29700,7 +29877,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
29700
29877
|
var SESSION_ID2 = randomUUID5();
|
|
29701
29878
|
function readCliVersion() {
|
|
29702
29879
|
if (true) {
|
|
29703
|
-
return "0.27.1-next.
|
|
29880
|
+
return "0.27.1-next.21";
|
|
29704
29881
|
}
|
|
29705
29882
|
return "0.0.0";
|
|
29706
29883
|
}
|
|
@@ -31053,10 +31230,11 @@ counts the remaining flows skipped.
|
|
|
31053
31230
|
|
|
31054
31231
|
The CLI sends a run to its tool-server: the local one that starts
|
|
31055
31232
|
automatically, or the one that \`argent link\` or ARGENT_TOOLS_URL names. Over
|
|
31056
|
-
a link, the CLI uploads the flow file
|
|
31057
|
-
|
|
31058
|
-
|
|
31059
|
-
|
|
31233
|
+
a link, the CLI uploads the flow file, the run: fragments that it reaches and
|
|
31234
|
+
the snapshot baselines that the run compares. The CLI writes the new baselines
|
|
31235
|
+
that the run returns. The tool-server rejects the flow before the first step
|
|
31236
|
+
when the flow or a fragment has one of these steps:
|
|
31237
|
+
- script:
|
|
31060
31238
|
- a tool: step that takes a file or records a flow
|
|
31061
31239
|
Without a link, all step kinds run.
|
|
31062
31240
|
|
|
@@ -31596,6 +31774,14 @@ function isFlowReport(data) {
|
|
|
31596
31774
|
const steps = data?.steps;
|
|
31597
31775
|
return Array.isArray(steps) && steps.every((step) => !!step && typeof step === "object");
|
|
31598
31776
|
}
|
|
31777
|
+
function unwrittenBaselines(report) {
|
|
31778
|
+
const writes = report.baselineWrites;
|
|
31779
|
+
if (!Array.isArray(writes)) return [];
|
|
31780
|
+
return writes.flatMap((write) => {
|
|
31781
|
+
const { path: file2, error: error52 } = write ?? {};
|
|
31782
|
+
return typeof file2 === "string" && typeof error52 === "string" ? [`${file2}: ${error52}`] : [];
|
|
31783
|
+
});
|
|
31784
|
+
}
|
|
31599
31785
|
async function runFlowDirectory(dir, args, projectRoot, options) {
|
|
31600
31786
|
const printError = (message, err = message) => {
|
|
31601
31787
|
console.error(args.json ? JSON.stringify(errorRecord(err, message)) : message);
|
|
@@ -31666,8 +31852,17 @@ async function runFlowDirectory(dir, args, projectRoot, options) {
|
|
|
31666
31852
|
flowPath,
|
|
31667
31853
|
baseUrl
|
|
31668
31854
|
);
|
|
31669
|
-
|
|
31855
|
+
const unwritten = unwrittenBaselines(report);
|
|
31856
|
+
results.push({ path: rel, status: report.ok && !unwritten.length ? "pass" : "fail", report });
|
|
31670
31857
|
if (!report.ok) failures.push({ path: rel, ...summarizeFailure(report), rerun });
|
|
31858
|
+
else if (unwritten.length) {
|
|
31859
|
+
failures.push({
|
|
31860
|
+
path: rel,
|
|
31861
|
+
headline: "baselines not written",
|
|
31862
|
+
detail: unwritten.join("\n"),
|
|
31863
|
+
rerun
|
|
31864
|
+
});
|
|
31865
|
+
}
|
|
31671
31866
|
if (!args.json) {
|
|
31672
31867
|
for (const line of renderFailedSteps(report)) console.log(line);
|
|
31673
31868
|
console.log(` ${renderSummary(report, { withDevice: true })}`);
|
|
@@ -31928,7 +32123,12 @@ ${renderSummary(report, { withDevice: true })}`);
|
|
|
31928
32123
|
} else {
|
|
31929
32124
|
console.log(renderReport(report));
|
|
31930
32125
|
}
|
|
31931
|
-
|
|
32126
|
+
const unwritten = unwrittenBaselines(report);
|
|
32127
|
+
if (!args.json && !args.jsonStream) {
|
|
32128
|
+
for (const line of unwritten)
|
|
32129
|
+
console.log(` ${STATUS_GLYPH.error} baseline not written: ${line}`);
|
|
32130
|
+
}
|
|
32131
|
+
return exitAfterFlush(report.ok && unwritten.length === 0 ? 0 : 1);
|
|
31932
32132
|
}
|
|
31933
32133
|
|
|
31934
32134
|
// ../argent-cli/src/tools.ts
|