@swmansion/argent 0.22.1-next.5 → 0.22.1-next.7
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 +194 -63
- package/dist/installer.mjs +67 -33
- package/dist/mcp-server.mjs +48 -26
- package/dist/tool-server.cjs +279 -44
- package/package.json +1 -1
package/dist/cli-cmds.mjs
CHANGED
|
@@ -2675,11 +2675,13 @@ async function applyClientFileDirectives(result) {
|
|
|
2675
2675
|
var ToolInvocationError = class extends Error {
|
|
2676
2676
|
errorCode;
|
|
2677
2677
|
errorKind;
|
|
2678
|
+
issues;
|
|
2678
2679
|
constructor(message, signal) {
|
|
2679
2680
|
super(message);
|
|
2680
2681
|
this.name = "ToolInvocationError";
|
|
2681
2682
|
this.errorCode = signal?.errorCode;
|
|
2682
2683
|
this.errorKind = signal?.errorKind;
|
|
2684
|
+
this.issues = signal?.issues;
|
|
2683
2685
|
}
|
|
2684
2686
|
};
|
|
2685
2687
|
function authHeaders2(token) {
|
|
@@ -2727,6 +2729,10 @@ async function consumeToolStream(body, onProgress) {
|
|
|
2727
2729
|
const { result: data } = await applyClientFileDirectives(final.data);
|
|
2728
2730
|
return { data, note: final.note };
|
|
2729
2731
|
}
|
|
2732
|
+
function errorBodyMessage(body) {
|
|
2733
|
+
if (Array.isArray(body.issues) && typeof body.message === "string") return body.message;
|
|
2734
|
+
return body.error ?? body.message;
|
|
2735
|
+
}
|
|
2730
2736
|
function createToolsClient(options = {}) {
|
|
2731
2737
|
let cached2 = null;
|
|
2732
2738
|
async function baseUrl() {
|
|
@@ -2781,13 +2787,11 @@ function createToolsClient(options = {}) {
|
|
|
2781
2787
|
}
|
|
2782
2788
|
const json = await res.json().catch(() => ({}));
|
|
2783
2789
|
if (!res.ok) {
|
|
2784
|
-
throw new ToolInvocationError(
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
}
|
|
2790
|
-
);
|
|
2790
|
+
throw new ToolInvocationError(errorBodyMessage(json) ?? `${res.status} ${res.statusText}`, {
|
|
2791
|
+
errorCode: json.error_code,
|
|
2792
|
+
errorKind: json.error_kind,
|
|
2793
|
+
issues: Array.isArray(json.issues) ? json.issues : void 0
|
|
2794
|
+
});
|
|
2791
2795
|
}
|
|
2792
2796
|
const { result: data } = await applyClientFileDirectives(json.data);
|
|
2793
2797
|
return { data, note: json.note };
|
|
@@ -3270,8 +3274,8 @@ function describeExpectedValue(def) {
|
|
|
3270
3274
|
var CONFIG_SCHEMA = [
|
|
3271
3275
|
{
|
|
3272
3276
|
key: "telemetry.enabled",
|
|
3273
|
-
description: "Whether anonymous opt-out telemetry is enabled (on by default; environment opt-outs like DO_NOT_TRACK are not reflected here \u2014 `argent telemetry status` shows effective consent).",
|
|
3274
|
-
scopes: ["global"],
|
|
3277
|
+
description: "Whether anonymous opt-out telemetry is enabled (on by default; environment opt-outs like DO_NOT_TRACK are not reflected here \u2014 `argent telemetry status` shows effective consent). `false` in either scope wins, so a committed project opt-out holds for every teammate.",
|
|
3278
|
+
scopes: ["project", "global"],
|
|
3275
3279
|
parse: asBoolean,
|
|
3276
3280
|
merge: "prioritize-restrictive",
|
|
3277
3281
|
// Opt-out: consent.ts reads an unstored value as enabled, so the config
|
|
@@ -7206,7 +7210,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
7206
7210
|
var SESSION_ID2 = randomUUID5();
|
|
7207
7211
|
function readCliVersion() {
|
|
7208
7212
|
if (true) {
|
|
7209
|
-
return "0.22.1-next.
|
|
7213
|
+
return "0.22.1-next.7";
|
|
7210
7214
|
}
|
|
7211
7215
|
return "0.0.0";
|
|
7212
7216
|
}
|
|
@@ -7568,32 +7572,30 @@ function resolveHostFingerprintAsync() {
|
|
|
7568
7572
|
|
|
7569
7573
|
// ../telemetry/src/consent.ts
|
|
7570
7574
|
import * as fs9 from "node:fs";
|
|
7571
|
-
var cache =
|
|
7575
|
+
var cache = /* @__PURE__ */ new Map();
|
|
7572
7576
|
var sessionOverride = null;
|
|
7573
|
-
function
|
|
7577
|
+
function readConfigOverrideAt(filePath) {
|
|
7578
|
+
const miss = { mtimeMs: null, fingerprint: null, enabledOverride: null };
|
|
7574
7579
|
let stats;
|
|
7575
7580
|
try {
|
|
7576
|
-
stats = fs9.lstatSync(
|
|
7577
|
-
} catch
|
|
7578
|
-
|
|
7579
|
-
cache.current = { mtimeMs: null, fingerprint: null, enabledOverride: null };
|
|
7580
|
-
return null;
|
|
7581
|
-
}
|
|
7582
|
-
cache.current = { mtimeMs: null, fingerprint: null, enabledOverride: null };
|
|
7581
|
+
stats = fs9.lstatSync(filePath);
|
|
7582
|
+
} catch {
|
|
7583
|
+
cache.set(filePath, miss);
|
|
7583
7584
|
return null;
|
|
7584
7585
|
}
|
|
7585
7586
|
if (!stats.isFile()) {
|
|
7586
|
-
cache.
|
|
7587
|
+
cache.set(filePath, miss);
|
|
7587
7588
|
return null;
|
|
7588
7589
|
}
|
|
7589
7590
|
const fingerprint = `${stats.dev}:${stats.ino}:${stats.size}`;
|
|
7590
7591
|
const mtimeMs = stats.mtimeMs;
|
|
7591
|
-
|
|
7592
|
-
|
|
7592
|
+
const cached2 = cache.get(filePath);
|
|
7593
|
+
if (cached2 && cached2.fingerprint === fingerprint && cached2.mtimeMs === mtimeMs) {
|
|
7594
|
+
return cached2.enabledOverride;
|
|
7593
7595
|
}
|
|
7594
7596
|
let parsedEnabled = null;
|
|
7595
7597
|
try {
|
|
7596
|
-
const raw = fs9.readFileSync(
|
|
7598
|
+
const raw = fs9.readFileSync(filePath, "utf8");
|
|
7597
7599
|
const json = JSON.parse(raw);
|
|
7598
7600
|
if (json && typeof json === "object") {
|
|
7599
7601
|
const t2 = json.telemetry;
|
|
@@ -7604,9 +7606,27 @@ function readConfigOverride() {
|
|
|
7604
7606
|
}
|
|
7605
7607
|
} catch {
|
|
7606
7608
|
}
|
|
7607
|
-
cache.
|
|
7609
|
+
cache.set(filePath, { mtimeMs, fingerprint, enabledOverride: parsedEnabled });
|
|
7608
7610
|
return parsedEnabled;
|
|
7609
7611
|
}
|
|
7612
|
+
function readPersistedConsent(cwd) {
|
|
7613
|
+
const globalPath = configFilePath("global");
|
|
7614
|
+
const projectPath = configFilePath("project", { cwd });
|
|
7615
|
+
const global2 = readConfigOverrideAt(globalPath);
|
|
7616
|
+
const project = projectPath === globalPath ? null : readConfigOverrideAt(projectPath);
|
|
7617
|
+
if (project === false && global2 === false) {
|
|
7618
|
+
return { enabled: false, detail: "config.json (project and global)" };
|
|
7619
|
+
}
|
|
7620
|
+
if (project === false) return { enabled: false, detail: "config.json (project)" };
|
|
7621
|
+
if (global2 === false) return { enabled: false, detail: "config.json (global)" };
|
|
7622
|
+
if (project === true || global2 === true) {
|
|
7623
|
+
return {
|
|
7624
|
+
enabled: true,
|
|
7625
|
+
detail: project === true ? "config.json (project)" : "config.json (global)"
|
|
7626
|
+
};
|
|
7627
|
+
}
|
|
7628
|
+
return null;
|
|
7629
|
+
}
|
|
7610
7630
|
function parseFalsy(value) {
|
|
7611
7631
|
if (value === void 0) return false;
|
|
7612
7632
|
const v = value.trim().toLowerCase();
|
|
@@ -7616,7 +7636,7 @@ function isDoNotTrackSet(value) {
|
|
|
7616
7636
|
if (value === void 0 || value.trim() === "") return false;
|
|
7617
7637
|
return !parseFalsy(value);
|
|
7618
7638
|
}
|
|
7619
|
-
function getConsentState(env = process.env) {
|
|
7639
|
+
function getConsentState(env = process.env, cwd = process.cwd()) {
|
|
7620
7640
|
if (isDoNotTrackSet(env.DO_NOT_TRACK)) {
|
|
7621
7641
|
return {
|
|
7622
7642
|
enabled: false,
|
|
@@ -7633,24 +7653,28 @@ function getConsentState(env = process.env) {
|
|
|
7633
7653
|
if (sessionOverride !== null) {
|
|
7634
7654
|
return { enabled: sessionOverride, source: { source: "session_override" } };
|
|
7635
7655
|
}
|
|
7636
|
-
const persisted =
|
|
7637
|
-
if (persisted
|
|
7638
|
-
return {
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
|
|
7656
|
+
const persisted = readPersistedConsent(cwd);
|
|
7657
|
+
if (persisted !== null) {
|
|
7658
|
+
return {
|
|
7659
|
+
enabled: persisted.enabled,
|
|
7660
|
+
source: { source: "config_file", detail: persisted.detail }
|
|
7661
|
+
};
|
|
7642
7662
|
}
|
|
7643
7663
|
return { enabled: true, source: { source: "default" } };
|
|
7644
7664
|
}
|
|
7645
|
-
function isEnabled(env = process.env) {
|
|
7646
|
-
return getConsentState(env).enabled;
|
|
7665
|
+
function isEnabled(env = process.env, cwd) {
|
|
7666
|
+
return getConsentState(env, cwd).enabled;
|
|
7647
7667
|
}
|
|
7648
|
-
function writeConsentFlag(enabled) {
|
|
7649
|
-
updateConfig(
|
|
7650
|
-
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
|
|
7668
|
+
function writeConsentFlag(enabled, scope = "global", options = {}) {
|
|
7669
|
+
updateConfig(
|
|
7670
|
+
(config2) => {
|
|
7671
|
+
const telemetryBlock = typeof config2.telemetry === "object" && config2.telemetry ? config2.telemetry : {};
|
|
7672
|
+
config2.telemetry = { ...telemetryBlock, enabled };
|
|
7673
|
+
},
|
|
7674
|
+
scope,
|
|
7675
|
+
options
|
|
7676
|
+
);
|
|
7677
|
+
cache.clear();
|
|
7654
7678
|
}
|
|
7655
7679
|
|
|
7656
7680
|
// ../telemetry/src/notice.ts
|
|
@@ -7746,13 +7770,13 @@ async function shutdown(timeoutMs = SHORT_FLUSH_TIMEOUT_MS) {
|
|
|
7746
7770
|
state = null;
|
|
7747
7771
|
}
|
|
7748
7772
|
}
|
|
7749
|
-
function markEnabled() {
|
|
7750
|
-
writeConsentFlag(true);
|
|
7773
|
+
function markEnabled(scope = "global") {
|
|
7774
|
+
writeConsentFlag(true, scope);
|
|
7751
7775
|
}
|
|
7752
|
-
async function markDisabled() {
|
|
7776
|
+
async function markDisabled(scope = "global") {
|
|
7753
7777
|
try {
|
|
7754
7778
|
const client2 = getConstructedClient();
|
|
7755
|
-
writeConsentFlag(false);
|
|
7779
|
+
writeConsentFlag(false, scope);
|
|
7756
7780
|
if (client2) {
|
|
7757
7781
|
try {
|
|
7758
7782
|
await raceDrain(client2, SHORT_FLUSH_TIMEOUT_MS);
|
|
@@ -8009,7 +8033,11 @@ function findMissingRequired(payload, schema) {
|
|
|
8009
8033
|
}
|
|
8010
8034
|
return names.filter((name) => !Object.hasOwn(payload, name));
|
|
8011
8035
|
}
|
|
8012
|
-
function
|
|
8036
|
+
function serverIssueList(err) {
|
|
8037
|
+
const carried = err?.issues;
|
|
8038
|
+
if (Array.isArray(carried)) {
|
|
8039
|
+
return carried.length > 0 && carried.every(isValidationIssue) ? carried : null;
|
|
8040
|
+
}
|
|
8013
8041
|
const message = err instanceof Error ? err.message : typeof err === "string" ? err : null;
|
|
8014
8042
|
if (message === null) return null;
|
|
8015
8043
|
let parsed;
|
|
@@ -8019,7 +8047,11 @@ function describeServerValidationFailure(err, payload, schema) {
|
|
|
8019
8047
|
return null;
|
|
8020
8048
|
}
|
|
8021
8049
|
if (!Array.isArray(parsed) || parsed.length === 0) return null;
|
|
8022
|
-
|
|
8050
|
+
return parsed.every(isValidationIssue) ? parsed : null;
|
|
8051
|
+
}
|
|
8052
|
+
function describeServerValidationFailure(err, payload, schema) {
|
|
8053
|
+
const parsed = serverIssueList(err);
|
|
8054
|
+
if (parsed === null) return null;
|
|
8023
8055
|
const properties = schema?.properties ?? {};
|
|
8024
8056
|
const addressesThisTool = (issue) => issue.path.length === 0 || typeof issue.path[0] === "string" && Object.hasOwn(properties, issue.path[0]);
|
|
8025
8057
|
if (!parsed.every(addressesThisTool)) return null;
|
|
@@ -10791,8 +10823,8 @@ Options:
|
|
|
10791
10823
|
console.log("Feature flags (project overrides global):");
|
|
10792
10824
|
const maxName = registryView.reduce((m, f) => Math.max(m, f.name.length), 0);
|
|
10793
10825
|
for (const f of registryView) {
|
|
10794
|
-
const
|
|
10795
|
-
console.log(` ${f.name.padEnd(maxName, " ")} ${colorState(f.enabled)}${
|
|
10826
|
+
const scopeLabel3 = f.scope ? ` (${f.scope})` : "";
|
|
10827
|
+
console.log(` ${f.name.padEnd(maxName, " ")} ${colorState(f.enabled)}${scopeLabel3}`);
|
|
10796
10828
|
console.log(` ${" ".repeat(maxName)} ${f.description}`);
|
|
10797
10829
|
}
|
|
10798
10830
|
}
|
|
@@ -12792,8 +12824,80 @@ async function unlink3(argv) {
|
|
|
12792
12824
|
|
|
12793
12825
|
// ../argent-cli/src/telemetry.ts
|
|
12794
12826
|
var import_picocolors5 = __toESM(require_picocolors(), 1);
|
|
12827
|
+
|
|
12828
|
+
// ../argent-cli/src/command-args.ts
|
|
12829
|
+
var UsageError = class extends Error {
|
|
12830
|
+
constructor(message) {
|
|
12831
|
+
super(message);
|
|
12832
|
+
this.name = "UsageError";
|
|
12833
|
+
}
|
|
12834
|
+
};
|
|
12835
|
+
function parseCommandArgs(argv, specs) {
|
|
12836
|
+
const positionals = [];
|
|
12837
|
+
const options = {};
|
|
12838
|
+
for (let i2 = 0; i2 < argv.length; i2++) {
|
|
12839
|
+
const tok = argv[i2];
|
|
12840
|
+
if (tok === "--") {
|
|
12841
|
+
positionals.push(...argv.slice(i2 + 1));
|
|
12842
|
+
break;
|
|
12843
|
+
}
|
|
12844
|
+
if (!tok.startsWith("--")) {
|
|
12845
|
+
positionals.push(tok);
|
|
12846
|
+
continue;
|
|
12847
|
+
}
|
|
12848
|
+
const eq = tok.indexOf("=");
|
|
12849
|
+
const name = eq === -1 ? tok.slice(2) : tok.slice(2, eq);
|
|
12850
|
+
const inlineValue = eq === -1 ? void 0 : tok.slice(eq + 1);
|
|
12851
|
+
const spec = specs[name];
|
|
12852
|
+
if (!spec) throw new UsageError(`Unknown flag "${tok}".`);
|
|
12853
|
+
if (spec.kind === "boolean") {
|
|
12854
|
+
if (inlineValue !== void 0) throw new UsageError(`--${name} does not take a value.`);
|
|
12855
|
+
options[name] = true;
|
|
12856
|
+
continue;
|
|
12857
|
+
}
|
|
12858
|
+
let value = inlineValue;
|
|
12859
|
+
if (value === void 0) {
|
|
12860
|
+
const next = argv[i2 + 1];
|
|
12861
|
+
if (next !== void 0 && !next.startsWith("--")) {
|
|
12862
|
+
value = next;
|
|
12863
|
+
i2 += 1;
|
|
12864
|
+
}
|
|
12865
|
+
}
|
|
12866
|
+
if (value === void 0 || value === "") {
|
|
12867
|
+
throw new UsageError(
|
|
12868
|
+
`--${name} requires a value${spec.choices ? ` (${spec.choices.join("|")})` : ""}.`
|
|
12869
|
+
);
|
|
12870
|
+
}
|
|
12871
|
+
if (spec.choices && !spec.choices.includes(value)) {
|
|
12872
|
+
throw new UsageError(
|
|
12873
|
+
`--${name} must be one of ${spec.choices.map((c2) => `"${c2}"`).join(", ")} (got "${value}").`
|
|
12874
|
+
);
|
|
12875
|
+
}
|
|
12876
|
+
options[name] = value;
|
|
12877
|
+
}
|
|
12878
|
+
return { positionals, options };
|
|
12879
|
+
}
|
|
12880
|
+
|
|
12881
|
+
// ../argent-cli/src/telemetry.ts
|
|
12882
|
+
var SCOPES = ["global", "project"];
|
|
12883
|
+
var TELEMETRY_OPTIONS = {
|
|
12884
|
+
scope: { kind: "value", choices: SCOPES }
|
|
12885
|
+
};
|
|
12795
12886
|
async function telemetry(args) {
|
|
12796
12887
|
const sub = args[0];
|
|
12888
|
+
let scope = "global";
|
|
12889
|
+
try {
|
|
12890
|
+
const { positionals, options } = parseCommandArgs(args.slice(1), TELEMETRY_OPTIONS);
|
|
12891
|
+
if (positionals.length > 0) {
|
|
12892
|
+
throw new UsageError(`Unexpected argument "${positionals[0]}".`);
|
|
12893
|
+
}
|
|
12894
|
+
if (options.scope !== void 0) scope = options.scope;
|
|
12895
|
+
} catch (err) {
|
|
12896
|
+
if (!(err instanceof UsageError)) throw err;
|
|
12897
|
+
console.error(`Error: ${err.message}`);
|
|
12898
|
+
printUsage3();
|
|
12899
|
+
process.exit(2);
|
|
12900
|
+
}
|
|
12797
12901
|
init("cli");
|
|
12798
12902
|
switch (sub) {
|
|
12799
12903
|
case void 0:
|
|
@@ -12805,10 +12909,10 @@ async function telemetry(args) {
|
|
|
12805
12909
|
await shutdown();
|
|
12806
12910
|
return;
|
|
12807
12911
|
case "enable":
|
|
12808
|
-
await cmdEnable();
|
|
12912
|
+
await cmdEnable(scope);
|
|
12809
12913
|
return;
|
|
12810
12914
|
case "disable":
|
|
12811
|
-
await cmdDisable();
|
|
12915
|
+
await cmdDisable(scope);
|
|
12812
12916
|
return;
|
|
12813
12917
|
case "--help":
|
|
12814
12918
|
case "-h":
|
|
@@ -12823,37 +12927,64 @@ async function telemetry(args) {
|
|
|
12823
12927
|
}
|
|
12824
12928
|
function printUsage3() {
|
|
12825
12929
|
console.log(`Usage:
|
|
12826
|
-
argent telemetry status
|
|
12827
|
-
argent telemetry enable
|
|
12828
|
-
argent telemetry disable Disable telemetry
|
|
12930
|
+
argent telemetry status Show telemetry state and device id
|
|
12931
|
+
argent telemetry enable [--scope global|project] Enable telemetry
|
|
12932
|
+
argent telemetry disable [--scope global|project] Disable telemetry
|
|
12933
|
+
|
|
12934
|
+
The default scope is global (~/.argent/config.json). \`--scope project\` writes
|
|
12935
|
+
<project-root>/.argent/config.json instead \u2014 commit it and telemetry stays off
|
|
12936
|
+
for everyone who clones the repository. \`false\` in either scope wins.
|
|
12829
12937
|
`);
|
|
12830
12938
|
}
|
|
12939
|
+
function scopeLabel2(scope) {
|
|
12940
|
+
return scope === "project" ? "project scope" : "global scope";
|
|
12941
|
+
}
|
|
12831
12942
|
function printStatus() {
|
|
12832
12943
|
const s = status();
|
|
12833
12944
|
const idLabel = s.anonIdPrefix ? `${s.anonIdPrefix}...` : s.hasAnonIdOnDisk ? "present" : "not created";
|
|
12834
12945
|
console.log("telemetry:");
|
|
12835
12946
|
console.log(` state: ${s.enabled ? "enabled" : "disabled"}`);
|
|
12947
|
+
console.log(` source: ${describeSource(s.source)}`);
|
|
12836
12948
|
console.log(` device id: ${idLabel}`);
|
|
12837
12949
|
}
|
|
12838
|
-
|
|
12950
|
+
function describeSource(source) {
|
|
12951
|
+
switch (source.source) {
|
|
12952
|
+
case "env_do_not_track":
|
|
12953
|
+
case "env_argent_telemetry":
|
|
12954
|
+
return `environment (${source.detail ?? source.source})`;
|
|
12955
|
+
case "config_file":
|
|
12956
|
+
return source.detail ?? "config.json";
|
|
12957
|
+
case "session_override":
|
|
12958
|
+
return "this session";
|
|
12959
|
+
case "default":
|
|
12960
|
+
return "default (no opt-out set)";
|
|
12961
|
+
}
|
|
12962
|
+
}
|
|
12963
|
+
async function cmdEnable(scope) {
|
|
12839
12964
|
const wasEnabled = isEnabled();
|
|
12840
|
-
markEnabled();
|
|
12841
|
-
|
|
12842
|
-
|
|
12965
|
+
markEnabled(scope);
|
|
12966
|
+
const nowEnabled = isEnabled();
|
|
12967
|
+
if (!nowEnabled) {
|
|
12968
|
+
console.log(
|
|
12969
|
+
import_picocolors5.default.yellow(
|
|
12970
|
+
`Telemetry set to enabled at ${scopeLabel2(scope)}, but it stays disabled: ${describeSource(status().source)} still opts out.`
|
|
12971
|
+
)
|
|
12972
|
+
);
|
|
12973
|
+
} else if (wasEnabled) {
|
|
12974
|
+
console.log(import_picocolors5.default.dim(`Telemetry was already enabled (written at ${scopeLabel2(scope)}).`));
|
|
12843
12975
|
} else {
|
|
12844
|
-
console.log(import_picocolors5.default.green(
|
|
12976
|
+
console.log(import_picocolors5.default.green(`Telemetry enabled (${scopeLabel2(scope)}).`));
|
|
12845
12977
|
}
|
|
12846
12978
|
await shutdown();
|
|
12847
12979
|
}
|
|
12848
|
-
async function cmdDisable() {
|
|
12980
|
+
async function cmdDisable(scope) {
|
|
12849
12981
|
const wasEnabled = isEnabled();
|
|
12982
|
+
await markDisabled(scope);
|
|
12850
12983
|
if (!wasEnabled) {
|
|
12851
|
-
console.log(import_picocolors5.default.dim(
|
|
12852
|
-
|
|
12853
|
-
|
|
12984
|
+
console.log(import_picocolors5.default.dim(`Telemetry was already disabled (written at ${scopeLabel2(scope)}).`));
|
|
12985
|
+
} else {
|
|
12986
|
+
console.log(import_picocolors5.default.red(`Telemetry disabled (${scopeLabel2(scope)}).`));
|
|
12854
12987
|
}
|
|
12855
|
-
await markDisabled();
|
|
12856
|
-
console.log(import_picocolors5.default.red("Telemetry disabled."));
|
|
12857
12988
|
await shutdown();
|
|
12858
12989
|
}
|
|
12859
12990
|
export {
|
package/dist/installer.mjs
CHANGED
|
@@ -16428,7 +16428,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
16428
16428
|
var SESSION_ID = randomUUID4();
|
|
16429
16429
|
function readCliVersion() {
|
|
16430
16430
|
if (true) {
|
|
16431
|
-
return "0.22.1-next.
|
|
16431
|
+
return "0.22.1-next.7";
|
|
16432
16432
|
}
|
|
16433
16433
|
return "0.0.0";
|
|
16434
16434
|
}
|
|
@@ -16806,32 +16806,30 @@ function resolveHostFingerprintAsync() {
|
|
|
16806
16806
|
|
|
16807
16807
|
// ../telemetry/src/consent.ts
|
|
16808
16808
|
import * as fs8 from "node:fs";
|
|
16809
|
-
var cache =
|
|
16809
|
+
var cache = /* @__PURE__ */ new Map();
|
|
16810
16810
|
var sessionOverride = null;
|
|
16811
|
-
function
|
|
16811
|
+
function readConfigOverrideAt(filePath) {
|
|
16812
|
+
const miss = { mtimeMs: null, fingerprint: null, enabledOverride: null };
|
|
16812
16813
|
let stats;
|
|
16813
16814
|
try {
|
|
16814
|
-
stats = fs8.lstatSync(
|
|
16815
|
-
} catch
|
|
16816
|
-
|
|
16817
|
-
cache.current = { mtimeMs: null, fingerprint: null, enabledOverride: null };
|
|
16818
|
-
return null;
|
|
16819
|
-
}
|
|
16820
|
-
cache.current = { mtimeMs: null, fingerprint: null, enabledOverride: null };
|
|
16815
|
+
stats = fs8.lstatSync(filePath);
|
|
16816
|
+
} catch {
|
|
16817
|
+
cache.set(filePath, miss);
|
|
16821
16818
|
return null;
|
|
16822
16819
|
}
|
|
16823
16820
|
if (!stats.isFile()) {
|
|
16824
|
-
cache.
|
|
16821
|
+
cache.set(filePath, miss);
|
|
16825
16822
|
return null;
|
|
16826
16823
|
}
|
|
16827
16824
|
const fingerprint = `${stats.dev}:${stats.ino}:${stats.size}`;
|
|
16828
16825
|
const mtimeMs = stats.mtimeMs;
|
|
16829
|
-
|
|
16830
|
-
|
|
16826
|
+
const cached2 = cache.get(filePath);
|
|
16827
|
+
if (cached2 && cached2.fingerprint === fingerprint && cached2.mtimeMs === mtimeMs) {
|
|
16828
|
+
return cached2.enabledOverride;
|
|
16831
16829
|
}
|
|
16832
16830
|
let parsedEnabled = null;
|
|
16833
16831
|
try {
|
|
16834
|
-
const raw = fs8.readFileSync(
|
|
16832
|
+
const raw = fs8.readFileSync(filePath, "utf8");
|
|
16835
16833
|
const json = JSON.parse(raw);
|
|
16836
16834
|
if (json && typeof json === "object") {
|
|
16837
16835
|
const t2 = json.telemetry;
|
|
@@ -16842,9 +16840,27 @@ function readConfigOverride() {
|
|
|
16842
16840
|
}
|
|
16843
16841
|
} catch {
|
|
16844
16842
|
}
|
|
16845
|
-
cache.
|
|
16843
|
+
cache.set(filePath, { mtimeMs, fingerprint, enabledOverride: parsedEnabled });
|
|
16846
16844
|
return parsedEnabled;
|
|
16847
16845
|
}
|
|
16846
|
+
function readPersistedConsent(cwd) {
|
|
16847
|
+
const globalPath = configFilePath("global");
|
|
16848
|
+
const projectPath = configFilePath("project", { cwd });
|
|
16849
|
+
const global2 = readConfigOverrideAt(globalPath);
|
|
16850
|
+
const project = projectPath === globalPath ? null : readConfigOverrideAt(projectPath);
|
|
16851
|
+
if (project === false && global2 === false) {
|
|
16852
|
+
return { enabled: false, detail: "config.json (project and global)" };
|
|
16853
|
+
}
|
|
16854
|
+
if (project === false) return { enabled: false, detail: "config.json (project)" };
|
|
16855
|
+
if (global2 === false) return { enabled: false, detail: "config.json (global)" };
|
|
16856
|
+
if (project === true || global2 === true) {
|
|
16857
|
+
return {
|
|
16858
|
+
enabled: true,
|
|
16859
|
+
detail: project === true ? "config.json (project)" : "config.json (global)"
|
|
16860
|
+
};
|
|
16861
|
+
}
|
|
16862
|
+
return null;
|
|
16863
|
+
}
|
|
16848
16864
|
function parseFalsy(value) {
|
|
16849
16865
|
if (value === void 0) return false;
|
|
16850
16866
|
const v = value.trim().toLowerCase();
|
|
@@ -16854,7 +16870,7 @@ function isDoNotTrackSet(value) {
|
|
|
16854
16870
|
if (value === void 0 || value.trim() === "") return false;
|
|
16855
16871
|
return !parseFalsy(value);
|
|
16856
16872
|
}
|
|
16857
|
-
function getConsentState(env = process.env) {
|
|
16873
|
+
function getConsentState(env = process.env, cwd = process.cwd()) {
|
|
16858
16874
|
if (isDoNotTrackSet(env.DO_NOT_TRACK)) {
|
|
16859
16875
|
return {
|
|
16860
16876
|
enabled: false,
|
|
@@ -16871,24 +16887,28 @@ function getConsentState(env = process.env) {
|
|
|
16871
16887
|
if (sessionOverride !== null) {
|
|
16872
16888
|
return { enabled: sessionOverride, source: { source: "session_override" } };
|
|
16873
16889
|
}
|
|
16874
|
-
const persisted =
|
|
16875
|
-
if (persisted
|
|
16876
|
-
return {
|
|
16877
|
-
|
|
16878
|
-
|
|
16879
|
-
|
|
16890
|
+
const persisted = readPersistedConsent(cwd);
|
|
16891
|
+
if (persisted !== null) {
|
|
16892
|
+
return {
|
|
16893
|
+
enabled: persisted.enabled,
|
|
16894
|
+
source: { source: "config_file", detail: persisted.detail }
|
|
16895
|
+
};
|
|
16880
16896
|
}
|
|
16881
16897
|
return { enabled: true, source: { source: "default" } };
|
|
16882
16898
|
}
|
|
16883
|
-
function isEnabled(env = process.env) {
|
|
16884
|
-
return getConsentState(env).enabled;
|
|
16899
|
+
function isEnabled(env = process.env, cwd) {
|
|
16900
|
+
return getConsentState(env, cwd).enabled;
|
|
16885
16901
|
}
|
|
16886
|
-
function writeConsentFlag(enabled) {
|
|
16887
|
-
updateConfig(
|
|
16888
|
-
|
|
16889
|
-
|
|
16890
|
-
|
|
16891
|
-
|
|
16902
|
+
function writeConsentFlag(enabled, scope = "global", options = {}) {
|
|
16903
|
+
updateConfig(
|
|
16904
|
+
(config) => {
|
|
16905
|
+
const telemetryBlock = typeof config.telemetry === "object" && config.telemetry ? config.telemetry : {};
|
|
16906
|
+
config.telemetry = { ...telemetryBlock, enabled };
|
|
16907
|
+
},
|
|
16908
|
+
scope,
|
|
16909
|
+
options
|
|
16910
|
+
);
|
|
16911
|
+
cache.clear();
|
|
16892
16912
|
}
|
|
16893
16913
|
function setSessionConsentOverride(enabled) {
|
|
16894
16914
|
sessionOverride = enabled;
|
|
@@ -22455,6 +22475,18 @@ async function init2(args) {
|
|
|
22455
22475
|
}
|
|
22456
22476
|
tel.installMode = modeFromFlags ?? await promptInstallMode(recordedMode ?? "global");
|
|
22457
22477
|
track("installation:install_mode_decision", { install_mode: tel.installMode });
|
|
22478
|
+
let wroteProjectTelemetryOptOut = false;
|
|
22479
|
+
if (parsed.noTelemetry && tel.installMode === "local") {
|
|
22480
|
+
try {
|
|
22481
|
+
writeConsentFlag(false, "project", { cwd: initProjectRoot });
|
|
22482
|
+
wroteProjectTelemetryOptOut = true;
|
|
22483
|
+
log.info(
|
|
22484
|
+
`${import_picocolors10.default.bold("Telemetry")} ${import_picocolors10.default.dim("also disabled for this project \u2014")} ${import_picocolors10.default.cyan(".argent/config.json")} ${import_picocolors10.default.dim("(commit it so the opt-out applies to every clone).")}`
|
|
22485
|
+
);
|
|
22486
|
+
} catch (err) {
|
|
22487
|
+
log.warn(`Could not write the project telemetry opt-out: ${err}`);
|
|
22488
|
+
}
|
|
22489
|
+
}
|
|
22458
22490
|
version = await runInstall({
|
|
22459
22491
|
installMode: tel.installMode,
|
|
22460
22492
|
fromTar: parsed.fromTar,
|
|
@@ -22582,7 +22614,8 @@ async function init2(args) {
|
|
|
22582
22614
|
scope,
|
|
22583
22615
|
allowlistEnabled: allowlist.enabled,
|
|
22584
22616
|
skillsMethod,
|
|
22585
|
-
copiedRules: copyResults.length > 0
|
|
22617
|
+
copiedRules: copyResults.length > 0,
|
|
22618
|
+
wroteProjectTelemetryOptOut
|
|
22586
22619
|
});
|
|
22587
22620
|
note(
|
|
22588
22621
|
[
|
|
@@ -22620,7 +22653,8 @@ function printSummary({
|
|
|
22620
22653
|
scope,
|
|
22621
22654
|
allowlistEnabled,
|
|
22622
22655
|
skillsMethod,
|
|
22623
|
-
copiedRules
|
|
22656
|
+
copiedRules,
|
|
22657
|
+
wroteProjectTelemetryOptOut
|
|
22624
22658
|
}) {
|
|
22625
22659
|
const summaryLines = [
|
|
22626
22660
|
`${import_picocolors10.default.green("Install mode")} ${installMode === "local" ? "local (devDependency)" : "global"}`,
|
|
@@ -22638,7 +22672,7 @@ function printSummary({
|
|
|
22638
22672
|
`${import_picocolors10.default.bold("Commit")} so your team shares the same setup:`,
|
|
22639
22673
|
` ${import_picocolors10.default.cyan("package.json")} + your lockfile`,
|
|
22640
22674
|
` the written MCP config (.mcp.json, .cursor/mcp.json, \u2026)`,
|
|
22641
|
-
` ${import_picocolors10.default.cyan(".argent/install.json")}, and the skills/rules/agents files`,
|
|
22675
|
+
` ${import_picocolors10.default.cyan(".argent/install.json")}${wroteProjectTelemetryOptOut ? ` + ${import_picocolors10.default.cyan(".argent/config.json")}` : ""}, and the skills/rules/agents files`,
|
|
22642
22676
|
"",
|
|
22643
22677
|
`Teammates then get argent on ${import_picocolors10.default.cyan("npm install")} \u2014 no global install, no ${import_picocolors10.default.cyan("argent init")}.`,
|
|
22644
22678
|
import_picocolors10.default.dim(
|
package/dist/mcp-server.mjs
CHANGED
|
@@ -16855,6 +16855,12 @@ async function applyClientFileDirectives(result) {
|
|
|
16855
16855
|
return { result: rewritten, written };
|
|
16856
16856
|
}
|
|
16857
16857
|
|
|
16858
|
+
// ../argent-tools-client/src/tools-client.ts
|
|
16859
|
+
function errorBodyMessage(body) {
|
|
16860
|
+
if (Array.isArray(body.issues) && typeof body.message === "string") return body.message;
|
|
16861
|
+
return body.error ?? body.message;
|
|
16862
|
+
}
|
|
16863
|
+
|
|
16858
16864
|
// ../argent-tools-client/src/artifacts.ts
|
|
16859
16865
|
import { copyFile, mkdir as mkdir4, readFile as readFile4, realpath, rm as rm3, stat as stat3, writeFile as writeFile4 } from "node:fs/promises";
|
|
16860
16866
|
import { constants as fsConstants } from "node:fs";
|
|
@@ -17136,8 +17142,8 @@ function asStringArray(raw) {
|
|
|
17136
17142
|
var CONFIG_SCHEMA = [
|
|
17137
17143
|
{
|
|
17138
17144
|
key: "telemetry.enabled",
|
|
17139
|
-
description: "Whether anonymous opt-out telemetry is enabled (on by default; environment opt-outs like DO_NOT_TRACK are not reflected here \u2014 `argent telemetry status` shows effective consent).",
|
|
17140
|
-
scopes: ["global"],
|
|
17145
|
+
description: "Whether anonymous opt-out telemetry is enabled (on by default; environment opt-outs like DO_NOT_TRACK are not reflected here \u2014 `argent telemetry status` shows effective consent). `false` in either scope wins, so a committed project opt-out holds for every teammate.",
|
|
17146
|
+
scopes: ["project", "global"],
|
|
17141
17147
|
parse: asBoolean,
|
|
17142
17148
|
merge: "prioritize-restrictive",
|
|
17143
17149
|
// Opt-out: consent.ts reads an unstored value as enabled, so the config
|
|
@@ -18171,32 +18177,30 @@ var DYLIB_TVOS_DIR = path11.join(DYLIB_DIR, "tvos");
|
|
|
18171
18177
|
|
|
18172
18178
|
// ../telemetry/src/consent.ts
|
|
18173
18179
|
import * as fs8 from "node:fs";
|
|
18174
|
-
var cache =
|
|
18180
|
+
var cache = /* @__PURE__ */ new Map();
|
|
18175
18181
|
var sessionOverride = null;
|
|
18176
|
-
function
|
|
18182
|
+
function readConfigOverrideAt(filePath) {
|
|
18183
|
+
const miss = { mtimeMs: null, fingerprint: null, enabledOverride: null };
|
|
18177
18184
|
let stats;
|
|
18178
18185
|
try {
|
|
18179
|
-
stats = fs8.lstatSync(
|
|
18180
|
-
} catch
|
|
18181
|
-
|
|
18182
|
-
cache.current = { mtimeMs: null, fingerprint: null, enabledOverride: null };
|
|
18183
|
-
return null;
|
|
18184
|
-
}
|
|
18185
|
-
cache.current = { mtimeMs: null, fingerprint: null, enabledOverride: null };
|
|
18186
|
+
stats = fs8.lstatSync(filePath);
|
|
18187
|
+
} catch {
|
|
18188
|
+
cache.set(filePath, miss);
|
|
18186
18189
|
return null;
|
|
18187
18190
|
}
|
|
18188
18191
|
if (!stats.isFile()) {
|
|
18189
|
-
cache.
|
|
18192
|
+
cache.set(filePath, miss);
|
|
18190
18193
|
return null;
|
|
18191
18194
|
}
|
|
18192
18195
|
const fingerprint = `${stats.dev}:${stats.ino}:${stats.size}`;
|
|
18193
18196
|
const mtimeMs = stats.mtimeMs;
|
|
18194
|
-
|
|
18195
|
-
|
|
18197
|
+
const cached2 = cache.get(filePath);
|
|
18198
|
+
if (cached2 && cached2.fingerprint === fingerprint && cached2.mtimeMs === mtimeMs) {
|
|
18199
|
+
return cached2.enabledOverride;
|
|
18196
18200
|
}
|
|
18197
18201
|
let parsedEnabled = null;
|
|
18198
18202
|
try {
|
|
18199
|
-
const raw = fs8.readFileSync(
|
|
18203
|
+
const raw = fs8.readFileSync(filePath, "utf8");
|
|
18200
18204
|
const json = JSON.parse(raw);
|
|
18201
18205
|
if (json && typeof json === "object") {
|
|
18202
18206
|
const t = json.telemetry;
|
|
@@ -18207,9 +18211,27 @@ function readConfigOverride() {
|
|
|
18207
18211
|
}
|
|
18208
18212
|
} catch {
|
|
18209
18213
|
}
|
|
18210
|
-
cache.
|
|
18214
|
+
cache.set(filePath, { mtimeMs, fingerprint, enabledOverride: parsedEnabled });
|
|
18211
18215
|
return parsedEnabled;
|
|
18212
18216
|
}
|
|
18217
|
+
function readPersistedConsent(cwd) {
|
|
18218
|
+
const globalPath = configFilePath("global");
|
|
18219
|
+
const projectPath = configFilePath("project", { cwd });
|
|
18220
|
+
const global = readConfigOverrideAt(globalPath);
|
|
18221
|
+
const project = projectPath === globalPath ? null : readConfigOverrideAt(projectPath);
|
|
18222
|
+
if (project === false && global === false) {
|
|
18223
|
+
return { enabled: false, detail: "config.json (project and global)" };
|
|
18224
|
+
}
|
|
18225
|
+
if (project === false) return { enabled: false, detail: "config.json (project)" };
|
|
18226
|
+
if (global === false) return { enabled: false, detail: "config.json (global)" };
|
|
18227
|
+
if (project === true || global === true) {
|
|
18228
|
+
return {
|
|
18229
|
+
enabled: true,
|
|
18230
|
+
detail: project === true ? "config.json (project)" : "config.json (global)"
|
|
18231
|
+
};
|
|
18232
|
+
}
|
|
18233
|
+
return null;
|
|
18234
|
+
}
|
|
18213
18235
|
function parseFalsy(value) {
|
|
18214
18236
|
if (value === void 0) return false;
|
|
18215
18237
|
const v = value.trim().toLowerCase();
|
|
@@ -18219,7 +18241,7 @@ function isDoNotTrackSet(value) {
|
|
|
18219
18241
|
if (value === void 0 || value.trim() === "") return false;
|
|
18220
18242
|
return !parseFalsy(value);
|
|
18221
18243
|
}
|
|
18222
|
-
function getConsentState(env = process.env) {
|
|
18244
|
+
function getConsentState(env = process.env, cwd = process.cwd()) {
|
|
18223
18245
|
if (isDoNotTrackSet(env.DO_NOT_TRACK)) {
|
|
18224
18246
|
return {
|
|
18225
18247
|
enabled: false,
|
|
@@ -18236,17 +18258,17 @@ function getConsentState(env = process.env) {
|
|
|
18236
18258
|
if (sessionOverride !== null) {
|
|
18237
18259
|
return { enabled: sessionOverride, source: { source: "session_override" } };
|
|
18238
18260
|
}
|
|
18239
|
-
const persisted =
|
|
18240
|
-
if (persisted
|
|
18241
|
-
return {
|
|
18242
|
-
|
|
18243
|
-
|
|
18244
|
-
|
|
18261
|
+
const persisted = readPersistedConsent(cwd);
|
|
18262
|
+
if (persisted !== null) {
|
|
18263
|
+
return {
|
|
18264
|
+
enabled: persisted.enabled,
|
|
18265
|
+
source: { source: "config_file", detail: persisted.detail }
|
|
18266
|
+
};
|
|
18245
18267
|
}
|
|
18246
18268
|
return { enabled: true, source: { source: "default" } };
|
|
18247
18269
|
}
|
|
18248
|
-
function isEnabled(env = process.env) {
|
|
18249
|
-
return getConsentState(env).enabled;
|
|
18270
|
+
function isEnabled(env = process.env, cwd) {
|
|
18271
|
+
return getConsentState(env, cwd).enabled;
|
|
18250
18272
|
}
|
|
18251
18273
|
|
|
18252
18274
|
// ../telemetry/src/notice.ts
|
|
@@ -18685,7 +18707,7 @@ async function startMcpServer(options) {
|
|
|
18685
18707
|
fetchTimeoutMs: meta2?.longRunning ? null : FETCH_TIMEOUT_MS
|
|
18686
18708
|
});
|
|
18687
18709
|
const json = await res.json();
|
|
18688
|
-
if (!res.ok) throw new Error(json
|
|
18710
|
+
if (!res.ok) throw new Error(errorBodyMessage(json) ?? res.statusText);
|
|
18689
18711
|
const { result: data } = await applyClientFileDirectives(json.data);
|
|
18690
18712
|
return { result: data, outputHint: meta2?.outputHint, note: json.note };
|
|
18691
18713
|
}
|
package/dist/tool-server.cjs
CHANGED
|
@@ -16063,6 +16063,63 @@ function terminatingSignalCause(message) {
|
|
|
16063
16063
|
error_kind: "unknown"
|
|
16064
16064
|
});
|
|
16065
16065
|
}
|
|
16066
|
+
function valueAtPath(root, path41) {
|
|
16067
|
+
let current = root;
|
|
16068
|
+
for (const key2 of path41) {
|
|
16069
|
+
if (current === null || typeof current !== "object") return void 0;
|
|
16070
|
+
if (!Object.hasOwn(current, key2)) return void 0;
|
|
16071
|
+
current = current[key2];
|
|
16072
|
+
}
|
|
16073
|
+
return current;
|
|
16074
|
+
}
|
|
16075
|
+
function describeParamIssues(error52, params) {
|
|
16076
|
+
const allKeys = params !== null && typeof params === "object" && !Array.isArray(params) ? Object.keys(params) : [];
|
|
16077
|
+
const supplied = allKeys.slice(0, 24);
|
|
16078
|
+
const truncated = allKeys.length > supplied.length;
|
|
16079
|
+
const parts2 = error52.issues.map((issue2) => {
|
|
16080
|
+
const at = issue2.path.length > 0 ? issue2.path.join(".") : "(root)";
|
|
16081
|
+
if (issue2.code === "custom") {
|
|
16082
|
+
return issue2.path.length > 0 ? `\`${at}\`: ${issue2.message}` : issue2.message;
|
|
16083
|
+
}
|
|
16084
|
+
if (valueAtPath(params, issue2.path) === void 0) {
|
|
16085
|
+
const expected = issue2.expected;
|
|
16086
|
+
const kind = typeof expected === "string" ? ` (${expected})` : "";
|
|
16087
|
+
return `\`${at}\` is required${kind} and was not provided`;
|
|
16088
|
+
}
|
|
16089
|
+
if (issue2.code === "unrecognized_keys") {
|
|
16090
|
+
const keys = issue2.keys ?? [];
|
|
16091
|
+
const at2 = issue2.path.length > 0 ? `${issue2.path.join(".")}.` : "";
|
|
16092
|
+
return `unknown parameter${keys.length === 1 ? "" : "s"} ${keys.map((k) => `\`${at2}${k}\``).join(", ")}`;
|
|
16093
|
+
}
|
|
16094
|
+
if (issue2.code === "invalid_union") {
|
|
16095
|
+
const branches = issue2.errors ?? [];
|
|
16096
|
+
const alternatives = [];
|
|
16097
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16098
|
+
let moreAlternatives = false;
|
|
16099
|
+
for (const branch of branches) {
|
|
16100
|
+
for (const inner of branch) {
|
|
16101
|
+
const innerAt = inner.path.length > 0 ? `${at}.${inner.path.join(".")}: ` : "";
|
|
16102
|
+
const text = `${innerAt}${inner.message}`;
|
|
16103
|
+
if (seen.has(text)) continue;
|
|
16104
|
+
if (alternatives.length >= MAX_UNION_ALTERNATIVES) {
|
|
16105
|
+
moreAlternatives = true;
|
|
16106
|
+
break;
|
|
16107
|
+
}
|
|
16108
|
+
seen.add(text);
|
|
16109
|
+
alternatives.push(text);
|
|
16110
|
+
}
|
|
16111
|
+
if (moreAlternatives) break;
|
|
16112
|
+
}
|
|
16113
|
+
if (alternatives.length > 0) {
|
|
16114
|
+
return `\`${at}\`: ${alternatives.join("; or ")}${moreAlternatives ? "; or \u2026" : ""}`;
|
|
16115
|
+
}
|
|
16116
|
+
}
|
|
16117
|
+
return `\`${at}\`: ${issue2.message}`;
|
|
16118
|
+
});
|
|
16119
|
+
const sent = supplied.length > 0 ? ` You sent: ${supplied.map((k) => `\`${k}\``).join(", ")}${truncated ? ", \u2026" : ""}.` : "";
|
|
16120
|
+
const body = parts2.length > 0 ? `${parts2.map((p) => p.replace(/\.$/, "")).join("; ")}.` : "";
|
|
16121
|
+
return `${body}${sent}`.trim() || "invalid parameters";
|
|
16122
|
+
}
|
|
16066
16123
|
function formatInteractionMessage(format, fallback) {
|
|
16067
16124
|
try {
|
|
16068
16125
|
return format() ?? fallback;
|
|
@@ -16070,7 +16127,7 @@ function formatInteractionMessage(format, fallback) {
|
|
|
16070
16127
|
return fallback;
|
|
16071
16128
|
}
|
|
16072
16129
|
}
|
|
16073
|
-
var import_node_crypto2, Registry;
|
|
16130
|
+
var import_node_crypto2, Registry, MAX_UNION_ALTERNATIVES;
|
|
16074
16131
|
var init_registry = __esm({
|
|
16075
16132
|
"../registry/src/registry.ts"() {
|
|
16076
16133
|
"use strict";
|
|
@@ -16151,7 +16208,15 @@ var init_registry = __esm({
|
|
|
16151
16208
|
if (definition.zodSchema) {
|
|
16152
16209
|
const parsed = definition.zodSchema.safeParse(params ?? {});
|
|
16153
16210
|
if (!parsed.success) {
|
|
16154
|
-
throw new
|
|
16211
|
+
throw new FailureError(
|
|
16212
|
+
`Invalid params for tool "${id}": ${describeParamIssues(parsed.error, params)}`,
|
|
16213
|
+
{
|
|
16214
|
+
error_code: FAILURE_CODES.TOOL_INPUT_INVALID,
|
|
16215
|
+
failure_stage: "tool_params_parse",
|
|
16216
|
+
failure_area: "registry",
|
|
16217
|
+
error_kind: "validation"
|
|
16218
|
+
}
|
|
16219
|
+
);
|
|
16155
16220
|
}
|
|
16156
16221
|
effectiveParams = parsed.data;
|
|
16157
16222
|
}
|
|
@@ -16388,6 +16453,7 @@ var init_registry = __esm({
|
|
|
16388
16453
|
this._transition(node, cause ? "ERROR" /* ERROR */ : "IDLE" /* IDLE */, cause);
|
|
16389
16454
|
}
|
|
16390
16455
|
};
|
|
16456
|
+
MAX_UNION_ALTERNATIVES = 12;
|
|
16391
16457
|
}
|
|
16392
16458
|
});
|
|
16393
16459
|
|
|
@@ -92066,8 +92132,8 @@ function asStringArray(raw) {
|
|
|
92066
92132
|
var CONFIG_SCHEMA = [
|
|
92067
92133
|
{
|
|
92068
92134
|
key: "telemetry.enabled",
|
|
92069
|
-
description: "Whether anonymous opt-out telemetry is enabled (on by default; environment opt-outs like DO_NOT_TRACK are not reflected here \u2014 `argent telemetry status` shows effective consent).",
|
|
92070
|
-
scopes: ["global"],
|
|
92135
|
+
description: "Whether anonymous opt-out telemetry is enabled (on by default; environment opt-outs like DO_NOT_TRACK are not reflected here \u2014 `argent telemetry status` shows effective consent). `false` in either scope wins, so a committed project opt-out holds for every teammate.",
|
|
92136
|
+
scopes: ["project", "global"],
|
|
92071
92137
|
parse: asBoolean,
|
|
92072
92138
|
merge: "prioritize-restrictive",
|
|
92073
92139
|
// Opt-out: consent.ts reads an unstored value as enabled, so the config
|
|
@@ -95668,7 +95734,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
95668
95734
|
var SESSION_ID = (0, import_node_crypto3.randomUUID)();
|
|
95669
95735
|
function readCliVersion() {
|
|
95670
95736
|
if (true) {
|
|
95671
|
-
return "0.22.1-next.
|
|
95737
|
+
return "0.22.1-next.7";
|
|
95672
95738
|
}
|
|
95673
95739
|
return "0.0.0";
|
|
95674
95740
|
}
|
|
@@ -96135,32 +96201,30 @@ function resolveHostFingerprintAsync() {
|
|
|
96135
96201
|
|
|
96136
96202
|
// ../telemetry/src/consent.ts
|
|
96137
96203
|
var fs8 = __toESM(require("node:fs"));
|
|
96138
|
-
var cache =
|
|
96204
|
+
var cache = /* @__PURE__ */ new Map();
|
|
96139
96205
|
var sessionOverride = null;
|
|
96140
|
-
function
|
|
96206
|
+
function readConfigOverrideAt(filePath) {
|
|
96207
|
+
const miss = { mtimeMs: null, fingerprint: null, enabledOverride: null };
|
|
96141
96208
|
let stats;
|
|
96142
96209
|
try {
|
|
96143
|
-
stats = fs8.lstatSync(
|
|
96144
|
-
} catch
|
|
96145
|
-
|
|
96146
|
-
cache.current = { mtimeMs: null, fingerprint: null, enabledOverride: null };
|
|
96147
|
-
return null;
|
|
96148
|
-
}
|
|
96149
|
-
cache.current = { mtimeMs: null, fingerprint: null, enabledOverride: null };
|
|
96210
|
+
stats = fs8.lstatSync(filePath);
|
|
96211
|
+
} catch {
|
|
96212
|
+
cache.set(filePath, miss);
|
|
96150
96213
|
return null;
|
|
96151
96214
|
}
|
|
96152
96215
|
if (!stats.isFile()) {
|
|
96153
|
-
cache.
|
|
96216
|
+
cache.set(filePath, miss);
|
|
96154
96217
|
return null;
|
|
96155
96218
|
}
|
|
96156
96219
|
const fingerprint = `${stats.dev}:${stats.ino}:${stats.size}`;
|
|
96157
96220
|
const mtimeMs = stats.mtimeMs;
|
|
96158
|
-
|
|
96159
|
-
|
|
96221
|
+
const cached3 = cache.get(filePath);
|
|
96222
|
+
if (cached3 && cached3.fingerprint === fingerprint && cached3.mtimeMs === mtimeMs) {
|
|
96223
|
+
return cached3.enabledOverride;
|
|
96160
96224
|
}
|
|
96161
96225
|
let parsedEnabled = null;
|
|
96162
96226
|
try {
|
|
96163
|
-
const raw = fs8.readFileSync(
|
|
96227
|
+
const raw = fs8.readFileSync(filePath, "utf8");
|
|
96164
96228
|
const json2 = JSON.parse(raw);
|
|
96165
96229
|
if (json2 && typeof json2 === "object") {
|
|
96166
96230
|
const t = json2.telemetry;
|
|
@@ -96171,9 +96235,27 @@ function readConfigOverride() {
|
|
|
96171
96235
|
}
|
|
96172
96236
|
} catch {
|
|
96173
96237
|
}
|
|
96174
|
-
cache.
|
|
96238
|
+
cache.set(filePath, { mtimeMs, fingerprint, enabledOverride: parsedEnabled });
|
|
96175
96239
|
return parsedEnabled;
|
|
96176
96240
|
}
|
|
96241
|
+
function readPersistedConsent(cwd) {
|
|
96242
|
+
const globalPath = configFilePath("global");
|
|
96243
|
+
const projectPath = configFilePath("project", { cwd });
|
|
96244
|
+
const global2 = readConfigOverrideAt(globalPath);
|
|
96245
|
+
const project = projectPath === globalPath ? null : readConfigOverrideAt(projectPath);
|
|
96246
|
+
if (project === false && global2 === false) {
|
|
96247
|
+
return { enabled: false, detail: "config.json (project and global)" };
|
|
96248
|
+
}
|
|
96249
|
+
if (project === false) return { enabled: false, detail: "config.json (project)" };
|
|
96250
|
+
if (global2 === false) return { enabled: false, detail: "config.json (global)" };
|
|
96251
|
+
if (project === true || global2 === true) {
|
|
96252
|
+
return {
|
|
96253
|
+
enabled: true,
|
|
96254
|
+
detail: project === true ? "config.json (project)" : "config.json (global)"
|
|
96255
|
+
};
|
|
96256
|
+
}
|
|
96257
|
+
return null;
|
|
96258
|
+
}
|
|
96177
96259
|
function parseFalsy(value) {
|
|
96178
96260
|
if (value === void 0) return false;
|
|
96179
96261
|
const v = value.trim().toLowerCase();
|
|
@@ -96183,7 +96265,7 @@ function isDoNotTrackSet(value) {
|
|
|
96183
96265
|
if (value === void 0 || value.trim() === "") return false;
|
|
96184
96266
|
return !parseFalsy(value);
|
|
96185
96267
|
}
|
|
96186
|
-
function getConsentState(env = process.env) {
|
|
96268
|
+
function getConsentState(env = process.env, cwd = process.cwd()) {
|
|
96187
96269
|
if (isDoNotTrackSet(env.DO_NOT_TRACK)) {
|
|
96188
96270
|
return {
|
|
96189
96271
|
enabled: false,
|
|
@@ -96200,17 +96282,17 @@ function getConsentState(env = process.env) {
|
|
|
96200
96282
|
if (sessionOverride !== null) {
|
|
96201
96283
|
return { enabled: sessionOverride, source: { source: "session_override" } };
|
|
96202
96284
|
}
|
|
96203
|
-
const persisted =
|
|
96204
|
-
if (persisted
|
|
96205
|
-
return {
|
|
96206
|
-
|
|
96207
|
-
|
|
96208
|
-
|
|
96285
|
+
const persisted = readPersistedConsent(cwd);
|
|
96286
|
+
if (persisted !== null) {
|
|
96287
|
+
return {
|
|
96288
|
+
enabled: persisted.enabled,
|
|
96289
|
+
source: { source: "config_file", detail: persisted.detail }
|
|
96290
|
+
};
|
|
96209
96291
|
}
|
|
96210
96292
|
return { enabled: true, source: { source: "default" } };
|
|
96211
96293
|
}
|
|
96212
|
-
function isEnabled(env = process.env) {
|
|
96213
|
-
return getConsentState(env).enabled;
|
|
96294
|
+
function isEnabled(env = process.env, cwd) {
|
|
96295
|
+
return getConsentState(env, cwd).enabled;
|
|
96214
96296
|
}
|
|
96215
96297
|
|
|
96216
96298
|
// ../telemetry/src/notice.ts
|
|
@@ -113875,14 +113957,23 @@ async function resolveFileInputs(def, body, lookupUpload) {
|
|
|
113875
113957
|
};
|
|
113876
113958
|
const specs = def.fileInputs;
|
|
113877
113959
|
if (!specs || specs.length === 0 || typeof body !== "object" || body === null) {
|
|
113878
|
-
return {
|
|
113960
|
+
return {
|
|
113961
|
+
args: body ?? {},
|
|
113962
|
+
fileInputs: void 0,
|
|
113963
|
+
derivedTargets: [],
|
|
113964
|
+
cleanup
|
|
113965
|
+
};
|
|
113879
113966
|
}
|
|
113880
113967
|
const args = { ...body };
|
|
113881
113968
|
let resolved;
|
|
113969
|
+
const derivedTargets = [];
|
|
113882
113970
|
try {
|
|
113883
113971
|
for (const spec of specs) {
|
|
113884
113972
|
const value = args[spec.target];
|
|
113885
113973
|
if (!isFileInputWire(value)) continue;
|
|
113974
|
+
if (spec.path !== `\${${spec.target}}` && !derivedTargets.includes(spec.target)) {
|
|
113975
|
+
derivedTargets.push(spec.target);
|
|
113976
|
+
}
|
|
113886
113977
|
if (spec.unwrapWhenSet !== void 0 && isParamSet(args[spec.unwrapWhenSet])) {
|
|
113887
113978
|
args[spec.target] = value.path;
|
|
113888
113979
|
continue;
|
|
@@ -113899,7 +113990,7 @@ async function resolveFileInputs(def, body, lookupUpload) {
|
|
|
113899
113990
|
await cleanup();
|
|
113900
113991
|
throw err;
|
|
113901
113992
|
}
|
|
113902
|
-
return { args, fileInputs: resolved, cleanup };
|
|
113993
|
+
return { args, fileInputs: resolved, derivedTargets, cleanup };
|
|
113903
113994
|
}
|
|
113904
113995
|
|
|
113905
113996
|
// ../tool-server/src/utils/debugger/device-alias.ts
|
|
@@ -114190,6 +114281,14 @@ function isToolExposed(def) {
|
|
|
114190
114281
|
function findDependencyMissing(err) {
|
|
114191
114282
|
return findErrorInCauseChain(err, DependencyMissingError);
|
|
114192
114283
|
}
|
|
114284
|
+
function omitKeys(args, keys) {
|
|
114285
|
+
if (keys.length === 0 || args === null || typeof args !== "object" || Array.isArray(args)) {
|
|
114286
|
+
return args;
|
|
114287
|
+
}
|
|
114288
|
+
const copy = { ...args };
|
|
114289
|
+
for (const key2 of keys) delete copy[key2];
|
|
114290
|
+
return copy;
|
|
114291
|
+
}
|
|
114193
114292
|
function errorSignalFields(err) {
|
|
114194
114293
|
const signal = getFailureSignal(err);
|
|
114195
114294
|
return signal ? { error_code: signal.error_code, error_kind: signal.error_kind } : {};
|
|
@@ -114529,6 +114628,7 @@ function createHttpApp(registry2, options) {
|
|
|
114529
114628
|
}
|
|
114530
114629
|
let bodyArgs;
|
|
114531
114630
|
let resolvedFileInputs;
|
|
114631
|
+
let derivedTargets;
|
|
114532
114632
|
try {
|
|
114533
114633
|
const resolved = await resolveFileInputs(def, req.body, (id) => {
|
|
114534
114634
|
const entry = uploads.get(id);
|
|
@@ -114537,6 +114637,7 @@ function createHttpApp(registry2, options) {
|
|
|
114537
114637
|
});
|
|
114538
114638
|
bodyArgs = resolved.args;
|
|
114539
114639
|
resolvedFileInputs = resolved.fileInputs;
|
|
114640
|
+
derivedTargets = resolved.derivedTargets;
|
|
114540
114641
|
res.once("close", () => void resolved.cleanup());
|
|
114541
114642
|
} catch (err) {
|
|
114542
114643
|
if (err instanceof FileInputError) {
|
|
@@ -114560,7 +114661,11 @@ function createHttpApp(registry2, options) {
|
|
|
114560
114661
|
req.body,
|
|
114561
114662
|
{ invalid_params: deriveInvalidParams(parseResult.error, declared) }
|
|
114562
114663
|
);
|
|
114563
|
-
res.status(400).json({
|
|
114664
|
+
res.status(400).json({
|
|
114665
|
+
error: parseResult.error.message,
|
|
114666
|
+
message: describeParamIssues(parseResult.error, omitKeys(bodyArgs, derivedTargets)),
|
|
114667
|
+
issues: parseResult.error.issues
|
|
114668
|
+
});
|
|
114564
114669
|
return;
|
|
114565
114670
|
}
|
|
114566
114671
|
parsedData = parseResult.data;
|
|
@@ -114701,6 +114806,10 @@ function createHttpApp(registry2, options) {
|
|
|
114701
114806
|
res.status(400).json({ error: invalidInputErr.message, ...errorSignalFields(err) });
|
|
114702
114807
|
return;
|
|
114703
114808
|
}
|
|
114809
|
+
if (getFailureSignal(err)?.error_code === FAILURE_CODES.TOOL_INPUT_INVALID) {
|
|
114810
|
+
res.status(400).json({ error: formatErrorForAgent(err), ...errorSignalFields(err) });
|
|
114811
|
+
return;
|
|
114812
|
+
}
|
|
114704
114813
|
const notImplementedErr = findErrorInCauseChain(err, NotImplementedOnPlatformError);
|
|
114705
114814
|
if (notImplementedErr) {
|
|
114706
114815
|
res.status(501).json({
|
|
@@ -123254,6 +123363,7 @@ init_zod();
|
|
|
123254
123363
|
|
|
123255
123364
|
// ../tool-server/src/utils/sub-invoke.ts
|
|
123256
123365
|
var import_node_crypto7 = require("node:crypto");
|
|
123366
|
+
init_src();
|
|
123257
123367
|
async function invokeSubTool(registry2, ctx, toolId, args) {
|
|
123258
123368
|
const signal = ctx?.signal;
|
|
123259
123369
|
const recordChildInvocation = ctx?.recordChildInvocation;
|
|
@@ -123272,6 +123382,14 @@ async function invokeSubTool(registry2, ctx, toolId, args) {
|
|
|
123272
123382
|
release();
|
|
123273
123383
|
}
|
|
123274
123384
|
}
|
|
123385
|
+
function describeNestedParamError(registry2, err, toolId, dispatchedArgs, authoredArgs) {
|
|
123386
|
+
if (getFailureSignal(err)?.error_code !== FAILURE_CODES.TOOL_INPUT_INVALID) return void 0;
|
|
123387
|
+
const zodSchema76 = registry2.getTool(toolId)?.zodSchema;
|
|
123388
|
+
if (!zodSchema76) return void 0;
|
|
123389
|
+
const parsed = zodSchema76.safeParse(dispatchedArgs ?? {});
|
|
123390
|
+
if (parsed.success) return void 0;
|
|
123391
|
+
return `Invalid params for tool "${toolId}": ${describeParamIssues(parsed.error, authoredArgs)}`;
|
|
123392
|
+
}
|
|
123275
123393
|
|
|
123276
123394
|
// ../tool-server/src/tools/await-ui-element/index.ts
|
|
123277
123395
|
init_zod();
|
|
@@ -129750,8 +129868,8 @@ Stops on the first error (or unmet await-ui-element condition) and returns parti
|
|
|
129750
129868
|
throw err;
|
|
129751
129869
|
}
|
|
129752
129870
|
}
|
|
129871
|
+
const toolArgs = { ...step.args, udid };
|
|
129753
129872
|
try {
|
|
129754
|
-
const toolArgs = { ...step.args, udid };
|
|
129755
129873
|
const result = await invokeSubTool(registry2, ctx, step.tool, toolArgs);
|
|
129756
129874
|
if (isUnmetUiWaitResult(step.tool, result)) {
|
|
129757
129875
|
const note = result.note;
|
|
@@ -129763,9 +129881,16 @@ Stops on the first error (or unmet await-ui-element condition) and returns parti
|
|
|
129763
129881
|
}
|
|
129764
129882
|
results.push({ tool: step.tool, result });
|
|
129765
129883
|
} catch (err) {
|
|
129884
|
+
const reframed = describeNestedParamError(
|
|
129885
|
+
registry2,
|
|
129886
|
+
err,
|
|
129887
|
+
step.tool,
|
|
129888
|
+
toolArgs,
|
|
129889
|
+
step.args ?? {}
|
|
129890
|
+
);
|
|
129766
129891
|
results.push({
|
|
129767
129892
|
tool: step.tool,
|
|
129768
|
-
error: err instanceof Error ? err.message : String(err)
|
|
129893
|
+
error: reframed ?? (err instanceof Error ? err.message : String(err))
|
|
129769
129894
|
});
|
|
129770
129895
|
break;
|
|
129771
129896
|
}
|
|
@@ -145870,7 +145995,9 @@ var zodSchema63 = external_exports.object({
|
|
|
145870
145995
|
project_root: external_exports.string().describe(
|
|
145871
145996
|
"Absolute path to the project root of the flow being recorded \u2014 the same value passed to flow-start-recording. Together with `name` it identifies which recording this step belongs to."
|
|
145872
145997
|
),
|
|
145873
|
-
command: external_exports.string().describe(
|
|
145998
|
+
command: external_exports.string().describe(
|
|
145999
|
+
'MCP tool name (e.g. "gesture-tap", "screenshot", "launch-app") \u2014 a TOOL, not a flow directive. A flow-file directive name ("tap", "launch", "run", "type", "await", "assert", "pinch", "echo", "wait", "long-press", "scroll-to", "snapshot", "when") is answered with guidance, and nothing runs or is recorded: most name the tool that records the directive, while "wait", "long-press", "scroll-to", "snapshot" and "when" have no recording tool at all and are answered with what to do instead. A recording tool (flow-add-step, flow-add-echo, flow-start-recording, flow-finish-recording) is refused the same way, each for its own reason \u2014 nesting one would erase this flow at replay, end the take, or write the step twice.'
|
|
146000
|
+
),
|
|
145874
146001
|
args: external_exports.string().optional().describe(
|
|
145875
146002
|
`Tool arguments as a JSON string, e.g. '{"udid": "ABC", "x": 0.5, "y": 0.3}'. Omit for tools with no arguments.`
|
|
145876
146003
|
),
|
|
@@ -146070,6 +146197,77 @@ async function captureTapSelector(registry2, session, udid, point) {
|
|
|
146070
146197
|
};
|
|
146071
146198
|
}
|
|
146072
146199
|
}
|
|
146200
|
+
async function activeFlowState(session) {
|
|
146201
|
+
if (session.persist === "host") {
|
|
146202
|
+
try {
|
|
146203
|
+
session.flow = parseFlow(await fs48.readFile(session.filePath, "utf8"));
|
|
146204
|
+
} catch (err) {
|
|
146205
|
+
return {
|
|
146206
|
+
stepCount: session.flow.steps.length,
|
|
146207
|
+
note: `The persisted flow could not be read and parsed (${err instanceof Error ? err.message : String(err)}); the step count is from the last valid in-memory snapshot.`
|
|
146208
|
+
};
|
|
146209
|
+
}
|
|
146210
|
+
}
|
|
146211
|
+
return { stepCount: session.flow.steps.length };
|
|
146212
|
+
}
|
|
146213
|
+
async function recordNothing(session, guidance) {
|
|
146214
|
+
const { stepCount, note } = await activeFlowState(session);
|
|
146215
|
+
return {
|
|
146216
|
+
message: `${guidance} Nothing was executed and no step was recorded.${note ? ` ${note}` : ""}`,
|
|
146217
|
+
toolResult: void 0,
|
|
146218
|
+
stepCount,
|
|
146219
|
+
savedTo: session.filePath
|
|
146220
|
+
};
|
|
146221
|
+
}
|
|
146222
|
+
var DIRECTIVE_COMMAND_HINTS = {
|
|
146223
|
+
tap: { tool: "gesture-tap", rewritten: true },
|
|
146224
|
+
launch: {
|
|
146225
|
+
tool: "restart-app",
|
|
146226
|
+
rewritten: true,
|
|
146227
|
+
rewriteCondition: "when it carries only the bundle id (a call with an extra arg, e.g. an Android `activity`, is kept as a raw `tool: restart-app` step to convert during polish)"
|
|
146228
|
+
},
|
|
146229
|
+
run: {
|
|
146230
|
+
tool: "flow-execute",
|
|
146231
|
+
rewritten: true,
|
|
146232
|
+
rewriteCondition: "when the target resolves as a sibling flow in this recording's folder \u2014 a `name` that does not is kept as a raw `tool: flow-execute` step, and so is every target in a REMOTE recording (`run:` composition is host-resolved, so the host cannot validate the client's siblings); a `flow_path` that is not a sibling is refused outright and records nothing"
|
|
146233
|
+
},
|
|
146234
|
+
type: { tool: "keyboard", rewritten: false },
|
|
146235
|
+
await: { tool: AWAIT_UI_ELEMENT_TOOL_ID, rewritten: false },
|
|
146236
|
+
assert: { tool: AWAIT_UI_ELEMENT_TOOL_ID, rewritten: false },
|
|
146237
|
+
pinch: { tool: "gesture-pinch", rewritten: false }
|
|
146238
|
+
};
|
|
146239
|
+
var NESTED_RECORDER_TOOLS = {
|
|
146240
|
+
"flow-add-echo": "`flow-add-echo` records a step itself, so it must be called DIRECTLY, not through flow-add-step \u2014 nesting it would write the echo AND a `tool: flow-add-echo` step that fails on every replay.",
|
|
146241
|
+
"flow-add-step": "flow-add-step cannot record itself. Pass the MCP tool you want to execute as `command`.",
|
|
146242
|
+
"flow-start-recording": "`flow-start-recording` truncates the flow it names. Recording it as a step would erase this flow at replay; call it directly when you want to start a recording.",
|
|
146243
|
+
"flow-finish-recording": "`flow-finish-recording` ends the recording, so it cannot also be a step in it. Call it directly when the walkthrough is complete."
|
|
146244
|
+
};
|
|
146245
|
+
function isToolNotFound(err, command) {
|
|
146246
|
+
return err instanceof ToolNotFoundError && err.toolId === command;
|
|
146247
|
+
}
|
|
146248
|
+
function directiveCommandHint(command) {
|
|
146249
|
+
if (command === "echo") {
|
|
146250
|
+
return `"echo" is a flow directive, not a tool. Call \`flow-add-echo\` DIRECTLY \u2014 not through flow-add-step, which would run it as a nested tool AND record a \`tool: flow-add-echo\` step that fails on every replay.`;
|
|
146251
|
+
}
|
|
146252
|
+
if (command === "wait") {
|
|
146253
|
+
return `"wait" is a flow directive, not a tool, and there is no tool that records one \u2014 a fixed sleep is not a readiness signal. Record the thing you are actually waiting for with \`${AWAIT_UI_ELEMENT_TOOL_ID}\` instead.`;
|
|
146254
|
+
}
|
|
146255
|
+
if (command === "long-press") {
|
|
146256
|
+
return `"long-press" is a flow directive, not a tool, and no tool records one \u2014 there is no gesture-long-press. Record the rest of the path, then add the \`long-press:\` step by hand during polish and prove it with the replay.`;
|
|
146257
|
+
}
|
|
146258
|
+
if (command === "scroll-to") {
|
|
146259
|
+
return `"scroll-to" is a flow directive, not a tool, and no tool records one \u2014 it SEARCHES, scrolling until the target is visible, which no single recorded gesture reproduces. Record the movement with \`gesture-swipe\` (\`gesture-scroll\` on chromium) if the path needs it, then add the \`scroll-to:\` step by hand during polish and prove it with the replay.`;
|
|
146260
|
+
}
|
|
146261
|
+
if (command === "snapshot") {
|
|
146262
|
+
return `"snapshot" is a flow directive, not a tool, and no tool records one \u2014 it compares the screen against a stored baseline, which \`screenshot-diff\` does not manage. Add the \`snapshot:\` step by hand during polish, then adopt its baseline with a run that sets updateBaselines, and review the PNG before committing it.`;
|
|
146263
|
+
}
|
|
146264
|
+
if (command === "when") {
|
|
146265
|
+
return `"when" is a flow directive, not a tool, and no tool records one \u2014 it GUARDS the steps nested under it, so there is no action of its own to run. Record those steps, then wrap them in the \`when:\` block by hand during polish and prove both branches with the replay.`;
|
|
146266
|
+
}
|
|
146267
|
+
const hint = Object.hasOwn(DIRECTIVE_COMMAND_HINTS, command) ? DIRECTIVE_COMMAND_HINTS[command] : void 0;
|
|
146268
|
+
if (!hint) return void 0;
|
|
146269
|
+
return `"${command}" is a flow directive, not a tool. Record it by calling \`${hint.tool}\` through flow-add-step` + (hint.rewritten ? ` \u2014 the recorder rewrites it into the \`${command}:\` step ${hint.rewriteCondition ?? "for you"}. Where the call is recorded at all, a \`delayMs\` on it opts out of the rewrite: the step is then kept in its raw \`tool: ${hint.tool}\` form (a replay delay has no directive form), so leave \`delayMs\` off if you want the \`${command}:\` step.` : `. It is stored as a raw \`tool: ${hint.tool}\` step; converting it to \`${command}:\` is part of the polish pass.`);
|
|
146270
|
+
}
|
|
146073
146271
|
var RUN_TARGET_COMMAND = "flow-execute";
|
|
146074
146272
|
async function rewriteSiblingFlowPath(session, args) {
|
|
146075
146273
|
const flowPath = args.flow_path;
|
|
@@ -146187,12 +146385,12 @@ function createFlowAddStepTool(registry2) {
|
|
|
146187
146385
|
// Name the flow: recordings are concurrent, so several of these lines can
|
|
146188
146386
|
// interleave in one log and "the recorded flow" would not say which.
|
|
146189
146387
|
startedMsg: ({ params }) => `Adding ${params.command} step to flow ${params.name}`,
|
|
146190
|
-
completedMsg: ({ params }) => `Added ${params.command} step to flow ${params.name}`,
|
|
146388
|
+
completedMsg: ({ params, result }) => result.recorded === void 0 ? `Recorded no ${params.command} step in flow ${params.name}` : `Added ${params.command} step to flow ${params.name}`,
|
|
146191
146389
|
failedMsg: ({ params, failureSignal: failureSignal2 }) => `Failed to add ${params.command} step to flow ${params.name}: ${failureSignal2.error_code}`
|
|
146192
146390
|
},
|
|
146193
146391
|
description: `Execute a tool call and record it as a step in the flow named by \`name\` + \`project_root\` (the recording must already be open \u2014 see flow-start-recording). Use when recording a flow and you want to run and capture each action. A coordinate \`gesture-tap\` is recorded as a portable \`tap: { selector }\` step when the tapped element has stable text/identifier (otherwise coordinates are kept with a warning); a \`restart-app\` is recorded as a \`launch\` step (record one FIRST to make the flow a self-contained e2e flow; restart-app has no chromium support, so a chromium flow records as a fragment \u2014 add the \`launch: { chromium: <app path> }\` line to the YAML afterward, deleting the executionPrerequisite line if one was recorded: a flow that starts with a launch must not declare it).
|
|
146194
146392
|
A recorded \`await-ui-element\` that PASSED is re-probed against the tree the RUNNER resolves \`await:\`/\`assert:\` directives against, which is NOT the tree the live call read; a wait that came back \`{ success: false }\` is not probed at all, and its warning says so; when the condition does not hold there the step is still recorded and \`message\` carries a warning to read before converting \u2014 whether the conversion actually breaks depends on WHY the two disagree, since a screen that moved on between the live wait and the re-probe reads the same way. If that tree could not be read at all, the warning says so instead: the conversion is UNKNOWN, not known-bad. The probe judges the selector exactly as recorded, so write the conversion in the strict map spelling (\`{ visible: { text: Continue } }\`, copying the step's \`selector:\`) \u2014 the bare-string spelling (\`{ visible: Continue }\`) re-parses as a loose selector that resolves identifier-first and falls back to text, which is a different check. \`message\` also warns when the live wait itself came back \`{ success: false }\` \u2014 that tool reports a failed wait by returning rather than throwing, so the step is recorded either way. That warning names the cause, because only one of them judges the condition: a genuine miss will stop the run at replay, while a wait whose tree source was unreadable, or one that was cancelled, observed nothing and leaves the condition UNKNOWN.
|
|
146195
|
-
Returns { message, toolResult, stepCount, recorded, savedTo } on success \u2014 \`message\` is \`Step added to "<name>" flow\` plus any warning about what was recorded (read it; a warning never means the step was skipped). If it fails an error is returned and nothing is recorded.
|
|
146393
|
+
Returns { message, toolResult, stepCount, recorded, savedTo } on success \u2014 \`message\` is \`Step added to "<name>" flow\` plus any warning about what was recorded (read it; a warning never means the step was skipped). If it fails an error is returned and nothing is recorded. Two calls SUCCEED while recording nothing, and omit \`recorded\` to say so: a \`command\` naming a recording tool, and one naming a flow-file directive rather than a tool. Both answer with what to do instead \u2014 usually the call to make (the tool that records that directive, or the recording tool called directly), but \`wait\`, \`long-press\`, \`scroll-to\`, \`snapshot\` and \`when\` have no recording tool, so those name no call and say what to record or add by hand in its place. Either way nothing runs at the device and the take is left untouched \u2014 read \`recorded\`, not the status, to know whether a step was appended.
|
|
146196
146394
|
If a step was recorded by mistake, remove it from the .yaml after \`flow-finish-recording\` rather than during the recording: against a remote client the in-memory copy is authoritative and every write serializes it over your edit, and in host mode a mid-recording edit renumbers the steps, which costs the finish the cross-tree verdicts anchored to them.`,
|
|
146197
146395
|
// The recorded tool RUNS here, so this call lasts as long as whatever it
|
|
146198
146396
|
// wraps, and the three it most often wraps declare this too. Without it the
|
|
@@ -146204,7 +146402,19 @@ If a step was recorded by mistake, remove it from the .yaml after \`flow-finish-
|
|
|
146204
146402
|
services: () => ({}),
|
|
146205
146403
|
async execute(_services, params, ctx) {
|
|
146206
146404
|
const session = await requireRecordingSession(params.project_root, params.name);
|
|
146207
|
-
const
|
|
146405
|
+
const nested = Object.hasOwn(NESTED_RECORDER_TOOLS, params.command) ? NESTED_RECORDER_TOOLS[params.command] : void 0;
|
|
146406
|
+
if (nested) return recordNothing(session, nested);
|
|
146407
|
+
let args;
|
|
146408
|
+
try {
|
|
146409
|
+
args = params.args ? JSON.parse(params.args) : {};
|
|
146410
|
+
} catch (err) {
|
|
146411
|
+
if (registry2.getTool(params.command) === void 0) {
|
|
146412
|
+
const hint = directiveCommandHint(params.command);
|
|
146413
|
+
if (hint) return recordNothing(session, hint);
|
|
146414
|
+
}
|
|
146415
|
+
throw err;
|
|
146416
|
+
}
|
|
146417
|
+
const authoredArgs = { ...args };
|
|
146208
146418
|
if (params.command === RUN_TARGET_COMMAND) await rewriteSiblingFlowPath(session, args);
|
|
146209
146419
|
const isTap = params.command === "gesture-tap" && params.delayMs === void 0 && typeof args.udid === "string" && typeof args.x === "number" && typeof args.y === "number";
|
|
146210
146420
|
let captured;
|
|
@@ -146214,7 +146424,27 @@ If a step was recorded by mistake, remove it from the .yaml after \`flow-finish-
|
|
|
146214
146424
|
y: args.y
|
|
146215
146425
|
});
|
|
146216
146426
|
}
|
|
146217
|
-
|
|
146427
|
+
let toolResult;
|
|
146428
|
+
try {
|
|
146429
|
+
toolResult = await invokeSubTool(registry2, ctx, params.command, args);
|
|
146430
|
+
} catch (err) {
|
|
146431
|
+
const hint = isToolNotFound(err, params.command) ? directiveCommandHint(params.command) : void 0;
|
|
146432
|
+
if (hint) return recordNothing(session, hint);
|
|
146433
|
+
const reframed = describeNestedParamError(
|
|
146434
|
+
registry2,
|
|
146435
|
+
err,
|
|
146436
|
+
params.command,
|
|
146437
|
+
args,
|
|
146438
|
+
authoredArgs
|
|
146439
|
+
);
|
|
146440
|
+
if (reframed === void 0) throw err;
|
|
146441
|
+
throw new FailureError(reframed, {
|
|
146442
|
+
error_code: FAILURE_CODES.TOOL_INPUT_INVALID,
|
|
146443
|
+
failure_stage: "flow_add_step_nested_params",
|
|
146444
|
+
failure_area: "tool_server",
|
|
146445
|
+
error_kind: "validation"
|
|
146446
|
+
});
|
|
146447
|
+
}
|
|
146218
146448
|
let waitWarning;
|
|
146219
146449
|
if (params.command === AWAIT_UI_ELEMENT_TOOL_ID) {
|
|
146220
146450
|
if (isUnmetUiWaitResult(params.command, toolResult)) {
|
|
@@ -148756,8 +148986,10 @@ var zodSchema65 = external_exports.object({
|
|
|
148756
148986
|
if (params.name === void 0 === (params.flow_path === void 0)) {
|
|
148757
148987
|
ctx.addIssue({
|
|
148758
148988
|
code: external_exports.ZodIssueCode.custom,
|
|
148759
|
-
message: "Pass exactly one flow source: name or flow_path.",
|
|
148760
|
-
|
|
148989
|
+
message: params.name !== void 0 ? "Pass exactly one flow source: name or flow_path." : "Pass exactly one flow source: name or flow_path. flow-execute needs the flow's name in `name` \u2014 it resolves <project_root>/.argent/flows/<name>.yaml.",
|
|
148990
|
+
// The ROOT, not `flow_path`: the rule spans both source fields, and a
|
|
148991
|
+
// path would prefix the message with "`flow_path`:".
|
|
148992
|
+
path: []
|
|
148761
148993
|
});
|
|
148762
148994
|
}
|
|
148763
148995
|
});
|
|
@@ -149847,7 +150079,8 @@ async function execLeafStep(state3, step, index, scope) {
|
|
|
149847
150079
|
}
|
|
149848
150080
|
return { ...base, status: "pass", tool: step.name, result, outputHint, args };
|
|
149849
150081
|
} catch (err) {
|
|
149850
|
-
|
|
150082
|
+
const reframed = describeNestedParamError(registry2, err, step.name, args, step.args ?? {});
|
|
150083
|
+
return { ...base, status: "error", tool: step.name, reason: reframed ?? errMsg3(err) };
|
|
149851
150084
|
}
|
|
149852
150085
|
}
|
|
149853
150086
|
default:
|
|
@@ -149995,8 +150228,10 @@ var zodSchema66 = external_exports.object({
|
|
|
149995
150228
|
if (params.name === void 0 === (params.flow_path === void 0)) {
|
|
149996
150229
|
ctx.addIssue({
|
|
149997
150230
|
code: external_exports.ZodIssueCode.custom,
|
|
149998
|
-
message: "Pass exactly one flow source: name or flow_path.",
|
|
149999
|
-
|
|
150231
|
+
message: params.name !== void 0 ? "Pass exactly one flow source: name or flow_path." : "Pass exactly one flow source: name or flow_path. flow-read-prerequisite needs the flow's name in `name` \u2014 it resolves <project_root>/.argent/flows/<name>.yaml.",
|
|
150232
|
+
// The ROOT, matching flow-execute: the rule spans both source fields,
|
|
150233
|
+
// so it must not be anchored on one of them.
|
|
150234
|
+
path: []
|
|
150000
150235
|
});
|
|
150001
150236
|
}
|
|
150002
150237
|
});
|
|
@@ -150028,7 +150263,7 @@ Use when you need to check what app/simulator state is required before executing
|
|
|
150028
150263
|
source (name or flow_path) you will pass to flow-execute, so the prerequisite you read is the contract of
|
|
150029
150264
|
the flow that will actually run.
|
|
150030
150265
|
Fails if the flow file does not exist.
|
|
150031
|
-
Address the flow exactly as you will address it in flow-execute: name or flow_path, one and only one; supplying both or neither is rejected.`,
|
|
150266
|
+
Address the flow exactly as you will address it in flow-execute: name or flow_path, one and only one; supplying both or neither is rejected. The name goes in \`name\`, which resolves <project_root>/.argent/flows/<name>.yaml.`,
|
|
150032
150267
|
zodSchema: zodSchema66,
|
|
150033
150268
|
fileInputs: fileInputs4,
|
|
150034
150269
|
services: () => ({}),
|
package/package.json
CHANGED