@swmansion/argent 0.15.1-next.8 → 0.15.1-next.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -3
- package/dist/cli-cmds.mjs +2 -0
- package/dist/installer.mjs +410 -32
- package/dist/mcp-server.mjs +2 -0
- package/dist/tool-server.cjs +2 -0
- package/package.json +1 -1
- package/rules/argent.md +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
**[Argent](https://argent.swmansion.com)** is an **agentic toolkit** that gives your AI assistant direct access to iOS Simulators, Android emulators and physical devices, TVs (Apple TV, Android TV, Fire TV) and Electron/Chromium desktop and web apps. Ask it to tap a button, run a profiler or reproduce an issue manually - all from within your CLI, without switching context.
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
npx @swmansion/argent init
|
|
15
|
+
npx @swmansion/argent@latest init
|
|
16
|
+
# or, in a pnpm project (where npm's devEngines check may refuse to run npx):
|
|
17
|
+
pnpm dlx @swmansion/argent@latest init
|
|
16
18
|
```
|
|
17
19
|
|
|
18
20
|
## Supported platforms
|
|
@@ -98,7 +100,9 @@ Argent runs Android emulators on Linux but the default install can be slow if a
|
|
|
98
100
|
From your project root:
|
|
99
101
|
|
|
100
102
|
```bash
|
|
101
|
-
npx @swmansion/argent init
|
|
103
|
+
npx @swmansion/argent@latest init
|
|
104
|
+
# or, in a pnpm project (where npm's devEngines check may refuse to run npx):
|
|
105
|
+
pnpm dlx @swmansion/argent@latest init
|
|
102
106
|
```
|
|
103
107
|
|
|
104
108
|
This command triggers an installation wizard which:
|
|
@@ -121,9 +125,14 @@ teammate gets the same setup on `npm install` — no per-developer global instal
|
|
|
121
125
|
`argent init` — choose the local mode:
|
|
122
126
|
|
|
123
127
|
```bash
|
|
124
|
-
npx @swmansion/argent init --local
|
|
128
|
+
npx @swmansion/argent@latest init --local
|
|
129
|
+
# or, in a pnpm project:
|
|
130
|
+
pnpm dlx @swmansion/argent@latest init --local
|
|
125
131
|
```
|
|
126
132
|
|
|
133
|
+
> Note: in a freshly `pnpm init`-ed project, `npx` itself may refuse to run
|
|
134
|
+
> (npm's `devEngines` check) — use the `pnpm dlx` form there.
|
|
135
|
+
|
|
127
136
|
This adds `@swmansion/argent` to your project's `devDependencies` and writes MCP
|
|
128
137
|
configs that launch the project-local copy (`node node_modules/@swmansion/argent/dist/cli.js mcp`).
|
|
129
138
|
Commit `package.json` + your lockfile, the generated MCP config (`.mcp.json`,
|
package/dist/cli-cmds.mjs
CHANGED
package/dist/installer.mjs
CHANGED
|
@@ -16464,6 +16464,8 @@ var ALLOWED = {
|
|
|
16464
16464
|
action: PACKAGE_ACTION,
|
|
16465
16465
|
is_success: bool,
|
|
16466
16466
|
duration_ms: DURATION_MS,
|
|
16467
|
+
retry_count: COUNT,
|
|
16468
|
+
last_attempt_duration_ms: DURATION_MS,
|
|
16467
16469
|
...FAILURE_SIGNAL
|
|
16468
16470
|
},
|
|
16469
16471
|
"installation:cli_update_start": {},
|
|
@@ -20043,12 +20045,30 @@ function detectPackageManager() {
|
|
|
20043
20045
|
if (agent.startsWith("bun")) return "bun";
|
|
20044
20046
|
return "npm";
|
|
20045
20047
|
}
|
|
20048
|
+
function asKnownPm(name) {
|
|
20049
|
+
return name === "npm" || name === "yarn" || name === "pnpm" || name === "bun" ? name : null;
|
|
20050
|
+
}
|
|
20046
20051
|
function pmFromPackageManagerField(dir) {
|
|
20047
20052
|
try {
|
|
20048
20053
|
const pkg = JSON.parse(fs8.readFileSync(path8.join(dir, "package.json"), "utf8"));
|
|
20049
|
-
if (typeof pkg.packageManager
|
|
20050
|
-
|
|
20051
|
-
|
|
20054
|
+
if (typeof pkg.packageManager === "string") {
|
|
20055
|
+
return asKnownPm(pkg.packageManager.split("@")[0]);
|
|
20056
|
+
}
|
|
20057
|
+
return null;
|
|
20058
|
+
} catch {
|
|
20059
|
+
return null;
|
|
20060
|
+
}
|
|
20061
|
+
}
|
|
20062
|
+
function pmFromDevEngines(dir) {
|
|
20063
|
+
try {
|
|
20064
|
+
const pkg = JSON.parse(fs8.readFileSync(path8.join(dir, "package.json"), "utf8"));
|
|
20065
|
+
const devEnginesPm = pkg.devEngines?.packageManager;
|
|
20066
|
+
const names = /* @__PURE__ */ new Set();
|
|
20067
|
+
for (const entry of Array.isArray(devEnginesPm) ? devEnginesPm : [devEnginesPm]) {
|
|
20068
|
+
const name = asKnownPm(entry?.name);
|
|
20069
|
+
if (name) names.add(name);
|
|
20070
|
+
}
|
|
20071
|
+
return names.size === 1 ? [...names][0] : null;
|
|
20052
20072
|
} catch {
|
|
20053
20073
|
return null;
|
|
20054
20074
|
}
|
|
@@ -20061,10 +20081,13 @@ function pmFromLockfile(dir) {
|
|
|
20061
20081
|
if (has("package-lock.json") || has("npm-shrinkwrap.json")) return "npm";
|
|
20062
20082
|
return null;
|
|
20063
20083
|
}
|
|
20084
|
+
function pmFromWorkspaceMarker(dir) {
|
|
20085
|
+
return fs8.existsSync(path8.join(dir, "pnpm-workspace.yaml")) ? "pnpm" : null;
|
|
20086
|
+
}
|
|
20064
20087
|
function detectProjectPackageManager(projectRoot) {
|
|
20065
20088
|
let dir = path8.resolve(projectRoot);
|
|
20066
20089
|
for (; ; ) {
|
|
20067
|
-
const pm = pmFromPackageManagerField(dir) ?? pmFromLockfile(dir);
|
|
20090
|
+
const pm = pmFromPackageManagerField(dir) ?? pmFromLockfile(dir) ?? pmFromDevEngines(dir) ?? pmFromWorkspaceMarker(dir);
|
|
20068
20091
|
if (pm) return pm;
|
|
20069
20092
|
if (fs8.existsSync(path8.join(dir, ".git"))) break;
|
|
20070
20093
|
const parent = path8.dirname(dir);
|
|
@@ -20726,10 +20749,291 @@ function writeTomlOrRemove(filePath, data) {
|
|
|
20726
20749
|
}
|
|
20727
20750
|
writeToml(filePath, data);
|
|
20728
20751
|
}
|
|
20752
|
+
function dirHasEditorEvidence(dir, looksArgentOnly) {
|
|
20753
|
+
return dirExists(dir) && !looksArgentOnly(dir);
|
|
20754
|
+
}
|
|
20755
|
+
function fileHasEditorEvidence(filePath, looksArgentOnly) {
|
|
20756
|
+
return fs13.existsSync(filePath) && !looksArgentOnly(filePath);
|
|
20757
|
+
}
|
|
20758
|
+
function parseJsoncStrict(filePath) {
|
|
20759
|
+
let raw;
|
|
20760
|
+
try {
|
|
20761
|
+
raw = fs13.readFileSync(filePath, "utf8");
|
|
20762
|
+
} catch {
|
|
20763
|
+
return null;
|
|
20764
|
+
}
|
|
20765
|
+
if (raw.charCodeAt(0) === 65279) raw = raw.slice(1);
|
|
20766
|
+
const errors = [];
|
|
20767
|
+
const parsed = parse3(raw, errors, { allowTrailingComma: true });
|
|
20768
|
+
if (errors.length > 0 || parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
20769
|
+
return null;
|
|
20770
|
+
return parsed;
|
|
20771
|
+
}
|
|
20772
|
+
function parseTomlStrict(filePath) {
|
|
20773
|
+
try {
|
|
20774
|
+
return parse(fs13.readFileSync(filePath, "utf8"));
|
|
20775
|
+
} catch {
|
|
20776
|
+
return null;
|
|
20777
|
+
}
|
|
20778
|
+
}
|
|
20779
|
+
function parseYamlStrict(filePath) {
|
|
20780
|
+
try {
|
|
20781
|
+
const parsed = (0, import_yaml2.parse)(fs13.readFileSync(filePath, "utf8"));
|
|
20782
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
20783
|
+
return parsed;
|
|
20784
|
+
} catch {
|
|
20785
|
+
return null;
|
|
20786
|
+
}
|
|
20787
|
+
}
|
|
20788
|
+
function jsonLooksArgentServerOnly(filePath, containerKey) {
|
|
20789
|
+
const config = parseJsoncStrict(filePath);
|
|
20790
|
+
if (config === null) return false;
|
|
20791
|
+
const keys = Object.keys(config);
|
|
20792
|
+
if (keys.length !== 1 || keys[0] !== containerKey) return false;
|
|
20793
|
+
const servers = config[containerKey] ?? {};
|
|
20794
|
+
const serverKeys = Object.keys(servers);
|
|
20795
|
+
return serverKeys.length === 1 && serverKeys[0] === MCP_SERVER_KEY;
|
|
20796
|
+
}
|
|
20797
|
+
var bundledManagedNamesCache = null;
|
|
20798
|
+
function bundledManagedNames(kind) {
|
|
20799
|
+
if (!bundledManagedNamesCache) bundledManagedNamesCache = /* @__PURE__ */ new Map();
|
|
20800
|
+
const cached2 = bundledManagedNamesCache.get(kind);
|
|
20801
|
+
if (cached2) return cached2;
|
|
20802
|
+
let names;
|
|
20803
|
+
try {
|
|
20804
|
+
names = new Set(fs13.readdirSync(kind === "rules" ? RULES_DIR : AGENTS_DIR));
|
|
20805
|
+
} catch {
|
|
20806
|
+
names = /* @__PURE__ */ new Set();
|
|
20807
|
+
}
|
|
20808
|
+
bundledManagedNamesCache.set(kind, names);
|
|
20809
|
+
return names;
|
|
20810
|
+
}
|
|
20811
|
+
function managedDirLooksArgentOnly(dir, kind) {
|
|
20812
|
+
let entries;
|
|
20813
|
+
try {
|
|
20814
|
+
entries = fs13.readdirSync(dir);
|
|
20815
|
+
} catch {
|
|
20816
|
+
return false;
|
|
20817
|
+
}
|
|
20818
|
+
if (entries.length === 0) return false;
|
|
20819
|
+
if (kind === "skills") return entries.every((name) => name.startsWith(ARGENT_SKILL_PREFIX));
|
|
20820
|
+
const bundled = bundledManagedNames(kind);
|
|
20821
|
+
return entries.every((name) => bundled.has(name));
|
|
20822
|
+
}
|
|
20823
|
+
function cursorDirLooksArgentOnly(dir) {
|
|
20824
|
+
let entries;
|
|
20825
|
+
try {
|
|
20826
|
+
entries = fs13.readdirSync(dir);
|
|
20827
|
+
} catch {
|
|
20828
|
+
return false;
|
|
20829
|
+
}
|
|
20830
|
+
if (entries.length === 0) return false;
|
|
20831
|
+
return entries.every((entry) => {
|
|
20832
|
+
const full = path13.join(dir, entry);
|
|
20833
|
+
if (entry === "mcp.json") {
|
|
20834
|
+
return jsonLooksArgentServerOnly(full, "mcpServers");
|
|
20835
|
+
}
|
|
20836
|
+
if (entry === "permissions.json") {
|
|
20837
|
+
const config = parseJsoncStrict(full);
|
|
20838
|
+
if (config === null) return false;
|
|
20839
|
+
const keys = Object.keys(config);
|
|
20840
|
+
if (keys.length !== 1 || keys[0] !== "mcpAllowlist") return false;
|
|
20841
|
+
const list = config.mcpAllowlist;
|
|
20842
|
+
return Array.isArray(list) && list.length > 0 && list.every((rule) => rule === CURSOR_ALLOWLIST_PATTERN);
|
|
20843
|
+
}
|
|
20844
|
+
if (entry === "rules" || entry === "agents" || entry === "skills") {
|
|
20845
|
+
return managedDirLooksArgentOnly(full, entry);
|
|
20846
|
+
}
|
|
20847
|
+
return false;
|
|
20848
|
+
});
|
|
20849
|
+
}
|
|
20850
|
+
function claudeSettingsLooksArgentOnly(filePath) {
|
|
20851
|
+
const config = parseJsoncStrict(filePath);
|
|
20852
|
+
if (config === null) return false;
|
|
20853
|
+
const keys = Object.keys(config);
|
|
20854
|
+
if (keys.length !== 1 || keys[0] !== "permissions") return false;
|
|
20855
|
+
const permissions = config.permissions;
|
|
20856
|
+
if (!isRecord(permissions)) return false;
|
|
20857
|
+
const permKeys = Object.keys(permissions);
|
|
20858
|
+
if (permKeys.length !== 1 || permKeys[0] !== "allow") return false;
|
|
20859
|
+
const allow = permissions.allow;
|
|
20860
|
+
return Array.isArray(allow) && allow.length > 0 && allow.every((rule) => rule === PERMISSION_RULE);
|
|
20861
|
+
}
|
|
20862
|
+
function claudeDirLooksArgentOnly(dir) {
|
|
20863
|
+
let entries;
|
|
20864
|
+
try {
|
|
20865
|
+
entries = fs13.readdirSync(dir);
|
|
20866
|
+
} catch {
|
|
20867
|
+
return false;
|
|
20868
|
+
}
|
|
20869
|
+
if (entries.length === 0) return false;
|
|
20870
|
+
return entries.every((entry) => {
|
|
20871
|
+
const full = path13.join(dir, entry);
|
|
20872
|
+
if (entry === "settings.json") return claudeSettingsLooksArgentOnly(full);
|
|
20873
|
+
if (entry === "rules" || entry === "agents" || entry === "skills") {
|
|
20874
|
+
return managedDirLooksArgentOnly(full, entry);
|
|
20875
|
+
}
|
|
20876
|
+
return false;
|
|
20877
|
+
});
|
|
20878
|
+
}
|
|
20879
|
+
function vscodeDirLooksArgentOnly(dir) {
|
|
20880
|
+
let entries;
|
|
20881
|
+
try {
|
|
20882
|
+
entries = fs13.readdirSync(dir);
|
|
20883
|
+
} catch {
|
|
20884
|
+
return false;
|
|
20885
|
+
}
|
|
20886
|
+
if (entries.length === 0) return false;
|
|
20887
|
+
return entries.every(
|
|
20888
|
+
(entry) => entry === "mcp.json" && jsonLooksArgentServerOnly(path13.join(dir, entry), "servers")
|
|
20889
|
+
);
|
|
20890
|
+
}
|
|
20891
|
+
function windsurfDirLooksArgentOnly(dir) {
|
|
20892
|
+
let entries;
|
|
20893
|
+
try {
|
|
20894
|
+
entries = fs13.readdirSync(dir);
|
|
20895
|
+
} catch {
|
|
20896
|
+
return false;
|
|
20897
|
+
}
|
|
20898
|
+
if (entries.length === 0) return false;
|
|
20899
|
+
return entries.every(
|
|
20900
|
+
(entry) => entry === "mcp_config.json" && jsonLooksArgentServerOnly(path13.join(dir, entry), "mcpServers")
|
|
20901
|
+
);
|
|
20902
|
+
}
|
|
20903
|
+
function zedSettingsLooksArgentOnly(filePath) {
|
|
20904
|
+
const config = parseJsoncStrict(filePath);
|
|
20905
|
+
if (config === null) return false;
|
|
20906
|
+
const keys = Object.keys(config);
|
|
20907
|
+
if (keys.length === 0) return false;
|
|
20908
|
+
return keys.every((key) => {
|
|
20909
|
+
if (key === "context_servers") {
|
|
20910
|
+
const servers = config.context_servers;
|
|
20911
|
+
if (!isRecord(servers)) return false;
|
|
20912
|
+
const serverKeys = Object.keys(servers);
|
|
20913
|
+
return serverKeys.length === 1 && serverKeys[0] === MCP_SERVER_KEY;
|
|
20914
|
+
}
|
|
20915
|
+
if (key === "agent") {
|
|
20916
|
+
const agent = config.agent;
|
|
20917
|
+
if (!isRecord(agent)) return false;
|
|
20918
|
+
const agentKeys = Object.keys(agent);
|
|
20919
|
+
if (agentKeys.length !== 1 || agentKeys[0] !== "tool_permissions") return false;
|
|
20920
|
+
const perms = agent.tool_permissions;
|
|
20921
|
+
if (!isRecord(perms)) return false;
|
|
20922
|
+
const permKeys = Object.keys(perms);
|
|
20923
|
+
return permKeys.length === 1 && permKeys[0] === "default" && (perms.default === "allow" || perms.default === "confirm");
|
|
20924
|
+
}
|
|
20925
|
+
return false;
|
|
20926
|
+
});
|
|
20927
|
+
}
|
|
20928
|
+
function zedDirLooksArgentOnly(dir) {
|
|
20929
|
+
let entries;
|
|
20930
|
+
try {
|
|
20931
|
+
entries = fs13.readdirSync(dir);
|
|
20932
|
+
} catch {
|
|
20933
|
+
return false;
|
|
20934
|
+
}
|
|
20935
|
+
if (entries.length === 0) return false;
|
|
20936
|
+
return entries.every(
|
|
20937
|
+
(entry) => entry === "settings.json" && zedSettingsLooksArgentOnly(path13.join(dir, entry))
|
|
20938
|
+
);
|
|
20939
|
+
}
|
|
20940
|
+
function geminiDirLooksArgentOnly(dir) {
|
|
20941
|
+
let entries;
|
|
20942
|
+
try {
|
|
20943
|
+
entries = fs13.readdirSync(dir);
|
|
20944
|
+
} catch {
|
|
20945
|
+
return false;
|
|
20946
|
+
}
|
|
20947
|
+
if (entries.length === 0) return false;
|
|
20948
|
+
return entries.every((entry) => {
|
|
20949
|
+
const full = path13.join(dir, entry);
|
|
20950
|
+
if (entry === "settings.json") return jsonLooksArgentServerOnly(full, "mcpServers");
|
|
20951
|
+
if (entry === "rules" || entry === "agents") return managedDirLooksArgentOnly(full, entry);
|
|
20952
|
+
return false;
|
|
20953
|
+
});
|
|
20954
|
+
}
|
|
20955
|
+
function hermesConfigLooksArgentOnly(filePath) {
|
|
20956
|
+
const config = parseYamlStrict(filePath);
|
|
20957
|
+
if (config === null) return false;
|
|
20958
|
+
const keys = Object.keys(config);
|
|
20959
|
+
if (keys.length !== 1 || keys[0] !== "mcp_servers") return false;
|
|
20960
|
+
const servers = config.mcp_servers;
|
|
20961
|
+
if (!isRecord(servers)) return false;
|
|
20962
|
+
const serverKeys = Object.keys(servers);
|
|
20963
|
+
return serverKeys.length === 1 && serverKeys[0] === MCP_SERVER_KEY;
|
|
20964
|
+
}
|
|
20965
|
+
function hermesDirLooksArgentOnly(dir) {
|
|
20966
|
+
let entries;
|
|
20967
|
+
try {
|
|
20968
|
+
entries = fs13.readdirSync(dir);
|
|
20969
|
+
} catch {
|
|
20970
|
+
return false;
|
|
20971
|
+
}
|
|
20972
|
+
if (entries.length === 0) return false;
|
|
20973
|
+
return entries.every(
|
|
20974
|
+
(entry) => entry === "config.yaml" && hermesConfigLooksArgentOnly(path13.join(dir, entry))
|
|
20975
|
+
);
|
|
20976
|
+
}
|
|
20977
|
+
function kiroDirLooksArgentOnly(dir) {
|
|
20978
|
+
let entries;
|
|
20979
|
+
try {
|
|
20980
|
+
entries = fs13.readdirSync(dir);
|
|
20981
|
+
} catch {
|
|
20982
|
+
return false;
|
|
20983
|
+
}
|
|
20984
|
+
if (entries.length === 0) return false;
|
|
20985
|
+
return entries.every((entry) => {
|
|
20986
|
+
if (entry !== "settings") return false;
|
|
20987
|
+
const settingsDir = path13.join(dir, entry);
|
|
20988
|
+
let settingsEntries;
|
|
20989
|
+
try {
|
|
20990
|
+
settingsEntries = fs13.readdirSync(settingsDir);
|
|
20991
|
+
} catch {
|
|
20992
|
+
return false;
|
|
20993
|
+
}
|
|
20994
|
+
if (settingsEntries.length === 0) return false;
|
|
20995
|
+
return settingsEntries.every(
|
|
20996
|
+
(name) => name === "mcp.json" && jsonLooksArgentServerOnly(path13.join(settingsDir, name), "mcpServers")
|
|
20997
|
+
);
|
|
20998
|
+
});
|
|
20999
|
+
}
|
|
21000
|
+
function codexDirLooksArgentOnly(dir) {
|
|
21001
|
+
let entries;
|
|
21002
|
+
try {
|
|
21003
|
+
entries = fs13.readdirSync(dir);
|
|
21004
|
+
} catch {
|
|
21005
|
+
return false;
|
|
21006
|
+
}
|
|
21007
|
+
if (entries.length === 0) return false;
|
|
21008
|
+
return entries.every((entry) => {
|
|
21009
|
+
const full = path13.join(dir, entry);
|
|
21010
|
+
if (entry === "config.toml") {
|
|
21011
|
+
const config = parseTomlStrict(full);
|
|
21012
|
+
if (config === null) return false;
|
|
21013
|
+
const configEntries = Object.entries(config);
|
|
21014
|
+
if (configEntries.length === 0) return false;
|
|
21015
|
+
return configEntries.every(([key, value]) => {
|
|
21016
|
+
if (key === "mcp_servers") {
|
|
21017
|
+
const servers = value ?? {};
|
|
21018
|
+
const serverKeys = Object.keys(servers);
|
|
21019
|
+
return serverKeys.length === 1 && serverKeys[0] === MCP_SERVER_KEY;
|
|
21020
|
+
}
|
|
21021
|
+
if (key === "developer_instructions") {
|
|
21022
|
+
return typeof value === "string" && removeArgentSection(value) === "";
|
|
21023
|
+
}
|
|
21024
|
+
return false;
|
|
21025
|
+
});
|
|
21026
|
+
}
|
|
21027
|
+
if (entry === "rules" || entry === "agents" || entry === "skills") {
|
|
21028
|
+
return managedDirLooksArgentOnly(full, entry);
|
|
21029
|
+
}
|
|
21030
|
+
return false;
|
|
21031
|
+
});
|
|
21032
|
+
}
|
|
20729
21033
|
var cursorAdapter = {
|
|
20730
21034
|
name: "Cursor",
|
|
20731
21035
|
detect() {
|
|
20732
|
-
return
|
|
21036
|
+
return dirHasEditorEvidence(path13.join(homedir4(), ".cursor"), cursorDirLooksArgentOnly) || dirHasEditorEvidence(path13.join(process.cwd(), ".cursor"), cursorDirLooksArgentOnly);
|
|
20733
21037
|
},
|
|
20734
21038
|
projectPath(root) {
|
|
20735
21039
|
return path13.join(root, ".cursor", "mcp.json");
|
|
@@ -20833,7 +21137,8 @@ function claudeDisabledListFinding(settingsPath, label, projectConfined) {
|
|
|
20833
21137
|
var claudeAdapter = {
|
|
20834
21138
|
name: "Claude Code",
|
|
20835
21139
|
detect() {
|
|
20836
|
-
|
|
21140
|
+
const mcpJsonArgentOnly = (p) => jsonLooksArgentServerOnly(p, "mcpServers");
|
|
21141
|
+
return fileHasEditorEvidence(path13.join(process.cwd(), ".mcp.json"), mcpJsonArgentOnly) || fileHasEditorEvidence(path13.join(homedir4(), ".claude.json"), mcpJsonArgentOnly) || dirHasEditorEvidence(path13.join(process.cwd(), ".claude"), claudeDirLooksArgentOnly) || dirHasEditorEvidence(path13.join(homedir4(), ".claude"), claudeDirLooksArgentOnly);
|
|
20837
21142
|
},
|
|
20838
21143
|
projectPath(root) {
|
|
20839
21144
|
return path13.join(root, ".mcp.json");
|
|
@@ -20941,7 +21246,7 @@ var claudeAdapter = {
|
|
|
20941
21246
|
var vscodeAdapter = {
|
|
20942
21247
|
name: "VS Code",
|
|
20943
21248
|
detect() {
|
|
20944
|
-
return
|
|
21249
|
+
return dirHasEditorEvidence(path13.join(process.cwd(), ".vscode"), vscodeDirLooksArgentOnly) || dirExists(path13.join(homedir4(), ".vscode"));
|
|
20945
21250
|
},
|
|
20946
21251
|
projectPath(root) {
|
|
20947
21252
|
return path13.join(root, ".vscode", "mcp.json");
|
|
@@ -21024,7 +21329,10 @@ function vscodeUserDirs() {
|
|
|
21024
21329
|
var windsurfAdapter = {
|
|
21025
21330
|
name: "Windsurf",
|
|
21026
21331
|
detect() {
|
|
21027
|
-
return
|
|
21332
|
+
return dirHasEditorEvidence(
|
|
21333
|
+
path13.join(homedir4(), ".codeium", "windsurf"),
|
|
21334
|
+
windsurfDirLooksArgentOnly
|
|
21335
|
+
);
|
|
21028
21336
|
},
|
|
21029
21337
|
projectPath() {
|
|
21030
21338
|
return null;
|
|
@@ -21084,7 +21392,7 @@ var windsurfAdapter = {
|
|
|
21084
21392
|
var zedAdapter = {
|
|
21085
21393
|
name: "Zed",
|
|
21086
21394
|
detect() {
|
|
21087
|
-
return
|
|
21395
|
+
return dirHasEditorEvidence(path13.join(homedir4(), ".config", "zed"), zedDirLooksArgentOnly);
|
|
21088
21396
|
},
|
|
21089
21397
|
projectPath(root) {
|
|
21090
21398
|
return path13.join(root, ".zed", "settings.json");
|
|
@@ -21142,7 +21450,7 @@ var zedAdapter = {
|
|
|
21142
21450
|
var geminiAdapter = {
|
|
21143
21451
|
name: "Gemini",
|
|
21144
21452
|
detect() {
|
|
21145
|
-
return
|
|
21453
|
+
return dirHasEditorEvidence(path13.join(homedir4(), ".gemini"), geminiDirLooksArgentOnly) || dirHasEditorEvidence(path13.join(process.cwd(), ".gemini"), geminiDirLooksArgentOnly);
|
|
21146
21454
|
},
|
|
21147
21455
|
projectPath(root) {
|
|
21148
21456
|
return path13.join(root, ".gemini", "settings.json");
|
|
@@ -21207,7 +21515,7 @@ var CODEX_FILENAME = ".codex";
|
|
|
21207
21515
|
var codexAdapter = {
|
|
21208
21516
|
name: "Codex",
|
|
21209
21517
|
detect() {
|
|
21210
|
-
return
|
|
21518
|
+
return dirHasEditorEvidence(path13.join(homedir4(), CODEX_FILENAME), codexDirLooksArgentOnly) || dirHasEditorEvidence(path13.join(process.cwd(), CODEX_FILENAME), codexDirLooksArgentOnly);
|
|
21211
21519
|
},
|
|
21212
21520
|
projectPath(root) {
|
|
21213
21521
|
return path13.join(root, CODEX_FILENAME, "config.toml");
|
|
@@ -21285,7 +21593,7 @@ var codexAdapter = {
|
|
|
21285
21593
|
var hermesAdapter = {
|
|
21286
21594
|
name: "Hermes",
|
|
21287
21595
|
detect() {
|
|
21288
|
-
return
|
|
21596
|
+
return dirHasEditorEvidence(path13.join(homedir4(), ".hermes"), hermesDirLooksArgentOnly);
|
|
21289
21597
|
},
|
|
21290
21598
|
projectPath() {
|
|
21291
21599
|
return null;
|
|
@@ -21409,7 +21717,7 @@ var KIRO_AUTO_APPROVE_ALL = ["*"];
|
|
|
21409
21717
|
var kiroAdapter = {
|
|
21410
21718
|
name: "Kiro",
|
|
21411
21719
|
detect() {
|
|
21412
|
-
return
|
|
21720
|
+
return dirHasEditorEvidence(path13.join(homedir4(), ".kiro"), kiroDirLooksArgentOnly) || dirHasEditorEvidence(path13.join(process.cwd(), ".kiro"), kiroDirLooksArgentOnly);
|
|
21413
21721
|
},
|
|
21414
21722
|
projectPath(root) {
|
|
21415
21723
|
return path13.join(root, ".kiro", "settings", "mcp.json");
|
|
@@ -21773,16 +22081,19 @@ async function resolveTelemetryConsent(opts) {
|
|
|
21773
22081
|
}
|
|
21774
22082
|
|
|
21775
22083
|
// ../argent-installer/src/init-args.ts
|
|
21776
|
-
function extractFlag(args, flag) {
|
|
21777
|
-
const idx = args.indexOf(flag);
|
|
21778
|
-
if (idx === -1 || idx + 1 >= args.length) return null;
|
|
21779
|
-
return args[idx + 1];
|
|
21780
|
-
}
|
|
21781
22084
|
function parseInitArgs(args) {
|
|
22085
|
+
let fromTar = null;
|
|
22086
|
+
for (let i2 = 0; i2 < args.length; i2++) {
|
|
22087
|
+
const arg = args[i2];
|
|
22088
|
+
if (arg === "--from" || arg.startsWith("--from=")) {
|
|
22089
|
+
const value = arg === "--from" ? i2 + 1 < args.length ? args[++i2] : "" : arg.slice(7);
|
|
22090
|
+
if (value !== "" && fromTar === null) fromTar = value;
|
|
22091
|
+
}
|
|
22092
|
+
}
|
|
21782
22093
|
return {
|
|
21783
22094
|
nonInteractive: args.includes("--yes") || args.includes("-y"),
|
|
21784
22095
|
noTelemetry: args.includes("--no-telemetry"),
|
|
21785
|
-
fromTar
|
|
22096
|
+
fromTar,
|
|
21786
22097
|
wantsLocal: args.includes("--local"),
|
|
21787
22098
|
wantsGlobal: args.includes("--global")
|
|
21788
22099
|
};
|
|
@@ -21875,12 +22186,13 @@ var InitTelemetry = class {
|
|
|
21875
22186
|
});
|
|
21876
22187
|
});
|
|
21877
22188
|
}
|
|
21878
|
-
async trackPackageAction(action, startedAt, isSuccess, failureSignal2) {
|
|
22189
|
+
async trackPackageAction(action, startedAt, isSuccess, failureSignal2, attemptInfo) {
|
|
21879
22190
|
track("installation:package_action", {
|
|
21880
22191
|
trigger: "init",
|
|
21881
22192
|
action,
|
|
21882
22193
|
is_success: isSuccess,
|
|
21883
22194
|
duration_ms: performance.now() - startedAt,
|
|
22195
|
+
...attemptInfo ?? {},
|
|
21884
22196
|
...failureSignal2 ?? {}
|
|
21885
22197
|
});
|
|
21886
22198
|
}
|
|
@@ -21930,6 +22242,16 @@ function execShellCommandSync(cmd, opts = {}) {
|
|
|
21930
22242
|
...opts.env ? { env: opts.env } : {}
|
|
21931
22243
|
});
|
|
21932
22244
|
}
|
|
22245
|
+
var ShellCommandError = class extends Error {
|
|
22246
|
+
constructor(message, exitCode, signal) {
|
|
22247
|
+
super(message);
|
|
22248
|
+
this.exitCode = exitCode;
|
|
22249
|
+
this.signal = signal;
|
|
22250
|
+
this.name = "ShellCommandError";
|
|
22251
|
+
}
|
|
22252
|
+
exitCode;
|
|
22253
|
+
signal;
|
|
22254
|
+
};
|
|
21933
22255
|
function runShellCommand(cmd, opts = {}) {
|
|
21934
22256
|
return new Promise((resolve10, reject) => {
|
|
21935
22257
|
const child = spawn2(cmd.bin, cmd.args, {
|
|
@@ -21941,9 +22263,16 @@ function runShellCommand(cmd, opts = {}) {
|
|
|
21941
22263
|
child.stderr?.on("data", (chunk) => {
|
|
21942
22264
|
stderr += chunk.toString();
|
|
21943
22265
|
});
|
|
21944
|
-
child.on("close", (code) => {
|
|
22266
|
+
child.on("close", (code, signal) => {
|
|
21945
22267
|
if (code === 0) resolve10();
|
|
21946
|
-
else
|
|
22268
|
+
else
|
|
22269
|
+
reject(
|
|
22270
|
+
new ShellCommandError(
|
|
22271
|
+
stderr.trim() || (signal !== null ? `Command terminated by signal ${signal}` : `Command exited with code ${code}`),
|
|
22272
|
+
code,
|
|
22273
|
+
signal
|
|
22274
|
+
)
|
|
22275
|
+
);
|
|
21947
22276
|
});
|
|
21948
22277
|
child.on("error", reject);
|
|
21949
22278
|
});
|
|
@@ -22104,17 +22433,52 @@ async function installLocally(opts) {
|
|
|
22104
22433
|
materializeOnly ? `Installing project dependencies to materialize ${PACKAGE_NAME} (${pm})...` : `Adding ${PACKAGE_NAME} to devDependencies (${pm})...`
|
|
22105
22434
|
);
|
|
22106
22435
|
const startedAt = performance.now();
|
|
22107
|
-
const
|
|
22436
|
+
const attempt = () => runTrustingDisk(
|
|
22108
22437
|
() => runShellCommand(cmd, { cwd: projectRoot }),
|
|
22109
22438
|
() => isLocallyInstalled(projectRoot) || isYarnPnp(projectRoot)
|
|
22110
22439
|
);
|
|
22440
|
+
let lastAttemptStartedAt = performance.now();
|
|
22441
|
+
let retryCount = 0;
|
|
22442
|
+
let { landed, exitError: installError } = await attempt();
|
|
22443
|
+
const isMissingBinaryError = (err) => err !== null && (err.code === "ENOENT" || process.platform === "win32" && err instanceof ShellCommandError && err.exitCode === 9009);
|
|
22444
|
+
const missingBinary = !landed && isMissingBinaryError(installError);
|
|
22445
|
+
const wasInterrupted = (err) => err instanceof ShellCommandError && (err.signal !== null || err.exitCode === null);
|
|
22446
|
+
const interrupted = !landed && wasInterrupted(installError);
|
|
22447
|
+
if (!landed && installError && !missingBinary && !interrupted) {
|
|
22448
|
+
spinner2.message(`${pm} failed \u2014 retrying once...`);
|
|
22449
|
+
retryCount = 1;
|
|
22450
|
+
lastAttemptStartedAt = performance.now();
|
|
22451
|
+
({ landed, exitError: installError } = await attempt());
|
|
22452
|
+
}
|
|
22453
|
+
const attemptTelemetry = () => ({
|
|
22454
|
+
retry_count: retryCount,
|
|
22455
|
+
last_attempt_duration_ms: performance.now() - lastAttemptStartedAt
|
|
22456
|
+
});
|
|
22111
22457
|
if (!landed) {
|
|
22112
|
-
spinner2.stop(import_picocolors3.default.red("Local install failed."));
|
|
22113
|
-
|
|
22114
|
-
|
|
22458
|
+
spinner2.stop(import_picocolors3.default.red(interrupted ? "Local install interrupted." : "Local install failed."));
|
|
22459
|
+
if (missingBinary) {
|
|
22460
|
+
log.error(
|
|
22461
|
+
`This project uses ${import_picocolors3.default.cyan(pm)}, but the ${import_picocolors3.default.cyan(pm)} command was not found on PATH.`
|
|
22462
|
+
);
|
|
22463
|
+
log.info(
|
|
22464
|
+
`Install ${import_picocolors3.default.cyan(pm)} first` + (pm === "pnpm" || pm === "yarn" ? ` (e.g. ${import_picocolors3.default.cyan(`corepack enable ${pm}`)}, or see the ${pm} install docs)` : "") + `, then re-run ${import_picocolors3.default.cyan("argent init --local")}.`
|
|
22465
|
+
);
|
|
22466
|
+
} else if (interrupted) {
|
|
22467
|
+
log.error(`The ${import_picocolors3.default.cyan(pm)} install was interrupted before it finished.`);
|
|
22468
|
+
log.info(`Re-run ${import_picocolors3.default.cyan("argent init --local")} to try again.`);
|
|
22469
|
+
} else {
|
|
22470
|
+
log.error(
|
|
22471
|
+
installError ? `${installError}` : `The install reported success but ${import_picocolors3.default.cyan(PACKAGE_NAME)} is not in node_modules.`
|
|
22472
|
+
);
|
|
22473
|
+
log.info(`Install manually with: ${import_picocolors3.default.cyan(`cd ${projectRoot} && ${cmdStr}`)}`);
|
|
22474
|
+
}
|
|
22475
|
+
await tel.trackPackageAction(
|
|
22476
|
+
"fresh_install",
|
|
22477
|
+
startedAt,
|
|
22478
|
+
false,
|
|
22479
|
+
INSTALL_LOCAL_PACKAGE_FAILED,
|
|
22480
|
+
attemptTelemetry()
|
|
22115
22481
|
);
|
|
22116
|
-
log.info(`Install manually with: ${import_picocolors3.default.cyan(`cd ${projectRoot} && ${cmdStr}`)}`);
|
|
22117
|
-
await tel.trackPackageAction("fresh_install", startedAt, false, INSTALL_LOCAL_PACKAGE_FAILED);
|
|
22118
22482
|
await tel.finalize(INSTALL_LOCAL_PACKAGE_FAILED);
|
|
22119
22483
|
process.exit(1);
|
|
22120
22484
|
}
|
|
@@ -22133,7 +22497,7 @@ async function installLocally(opts) {
|
|
|
22133
22497
|
);
|
|
22134
22498
|
}
|
|
22135
22499
|
}
|
|
22136
|
-
await tel.trackPackageAction("fresh_install", startedAt, true);
|
|
22500
|
+
await tel.trackPackageAction("fresh_install", startedAt, true, void 0, attemptTelemetry());
|
|
22137
22501
|
}
|
|
22138
22502
|
async function runGlobal(opts) {
|
|
22139
22503
|
const { fromTar, nonInteractive, tel } = opts;
|
|
@@ -22279,6 +22643,12 @@ async function runGlobal(opts) {
|
|
|
22279
22643
|
|
|
22280
22644
|
// ../argent-installer/src/init-adapters.ts
|
|
22281
22645
|
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
22646
|
+
function previouslyConfiguredAdapters(eligible, installMode) {
|
|
22647
|
+
const wantedScope = installMode === "local" ? "project" : "global";
|
|
22648
|
+
const scopes = findConfiguredAdapterScopes(eligible, process.cwd());
|
|
22649
|
+
const configured = new Set(scopes.filter((s) => s.scope === wantedScope).map((s) => s.adapter));
|
|
22650
|
+
return eligible.filter((a3) => configured.has(a3));
|
|
22651
|
+
}
|
|
22282
22652
|
async function chooseAdapters(opts) {
|
|
22283
22653
|
let eligible = ALL_ADAPTERS;
|
|
22284
22654
|
if (opts.installMode === "local") {
|
|
@@ -22294,12 +22664,16 @@ async function chooseAdapters(opts) {
|
|
|
22294
22664
|
}
|
|
22295
22665
|
const detected = detectAdapters().filter((a3) => eligible.includes(a3));
|
|
22296
22666
|
const detectedNames = detected.map((a3) => a3.name);
|
|
22667
|
+
const previouslyConfigured = previouslyConfiguredAdapters(eligible, opts.installMode);
|
|
22668
|
+
const previouslyConfiguredNames = previouslyConfigured.map((a3) => a3.name);
|
|
22669
|
+
const preselected = [...detected, ...previouslyConfigured.filter((a3) => !detected.includes(a3))];
|
|
22297
22670
|
if (opts.nonInteractive) {
|
|
22298
|
-
return { selected:
|
|
22671
|
+
return { selected: preselected.length > 0 ? preselected : eligible, detected };
|
|
22299
22672
|
}
|
|
22300
22673
|
const choices = eligible.map((a3) => {
|
|
22301
22674
|
const parts = [];
|
|
22302
22675
|
if (detectedNames.includes(a3.name)) parts.push("detected");
|
|
22676
|
+
else if (previouslyConfiguredNames.includes(a3.name)) parts.push("already configured");
|
|
22303
22677
|
const hasProject = a3.projectPath(process.cwd()) != null;
|
|
22304
22678
|
const hasGlobal = a3.globalPath() != null;
|
|
22305
22679
|
if (!hasProject && hasGlobal) {
|
|
@@ -22317,7 +22691,7 @@ async function chooseAdapters(opts) {
|
|
|
22317
22691
|
const selected = await multiselect({
|
|
22318
22692
|
message: "Which editors should Argent be configured for?",
|
|
22319
22693
|
options: choices,
|
|
22320
|
-
initialValues:
|
|
22694
|
+
initialValues: preselected,
|
|
22321
22695
|
required: true
|
|
22322
22696
|
});
|
|
22323
22697
|
if (isCancel(selected)) throw new InitCancelled("editors");
|
|
@@ -22876,7 +23250,11 @@ async function init2(args) {
|
|
|
22876
23250
|
note(mcpLines.join("\n"), "MCP Configuration");
|
|
22877
23251
|
const staleCleanup = await cleanupStaleMcpConfigs({
|
|
22878
23252
|
writtenAdapters,
|
|
22879
|
-
|
|
23253
|
+
// Sweep EVERY adapter, not just the detected set: the sweep is fully
|
|
23254
|
+
// gated on an existing argent entry (getArgentEntry), and the stale
|
|
23255
|
+
// entries most worth pruning live in argent-only dirs (~/.cursor,
|
|
23256
|
+
// ~/.codex) that detection now deliberately ignores.
|
|
23257
|
+
detectedAdapters: ALL_ADAPTERS,
|
|
22880
23258
|
installMode: tel.installMode,
|
|
22881
23259
|
scope: normalizedScope,
|
|
22882
23260
|
effectiveRoot,
|
package/dist/mcp-server.mjs
CHANGED
|
@@ -18004,6 +18004,8 @@ var ALLOWED = {
|
|
|
18004
18004
|
action: PACKAGE_ACTION,
|
|
18005
18005
|
is_success: bool,
|
|
18006
18006
|
duration_ms: DURATION_MS,
|
|
18007
|
+
retry_count: COUNT,
|
|
18008
|
+
last_attempt_duration_ms: DURATION_MS,
|
|
18007
18009
|
...FAILURE_SIGNAL
|
|
18008
18010
|
},
|
|
18009
18011
|
"installation:cli_update_start": {},
|
package/dist/tool-server.cjs
CHANGED
|
@@ -103836,6 +103836,8 @@ var ALLOWED = {
|
|
|
103836
103836
|
action: PACKAGE_ACTION,
|
|
103837
103837
|
is_success: bool,
|
|
103838
103838
|
duration_ms: DURATION_MS,
|
|
103839
|
+
retry_count: COUNT,
|
|
103840
|
+
last_attempt_duration_ms: DURATION_MS,
|
|
103839
103841
|
...FAILURE_SIGNAL2
|
|
103840
103842
|
},
|
|
103841
103843
|
"installation:cli_update_start": {},
|
package/package.json
CHANGED
package/rules/argent.md
CHANGED
|
@@ -32,7 +32,7 @@ If argent IS available, ignore the rest of this block and follow this rule norma
|
|
|
32
32
|
|
|
33
33
|
If argent is ABSENT, treat it as an expected state, not an error to retry. Do not call `mcp__argent__*` tools, do not run `argent` commands, and do not attempt any argent workflow. Tell the user once, and ask if you should continue without argent:
|
|
34
34
|
|
|
35
|
-
> Argent isn't installed in this environment. To enable the mobile/Chromium tooling this repo is configured for, run `npx @swmansion/argent init -y` (or `npm i -g @swmansion/argent && argent init -y`).
|
|
35
|
+
> Argent isn't installed in this environment. To enable the mobile/Chromium tooling this repo is configured for, run `npx @swmansion/argent@latest init -y` (or `npm i -g @swmansion/argent@latest && argent init -y`).
|
|
36
36
|
> </availability_check>
|
|
37
37
|
|
|
38
38
|
<tapping_rule>
|