@glasstrace/sdk 1.10.2 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -8
- package/dist/async-context/index.cjs +1189 -440
- package/dist/async-context/index.cjs.map +1 -1
- package/dist/async-context/index.js +2 -2
- package/dist/{capture-error-BeuEXXJO.d.cts → capture-error-CRQSqKgd.d.cts} +2 -2
- package/dist/{capture-error-D02pzB7q.d.ts → capture-error-CqCbjoMq.d.ts} +2 -2
- package/dist/{chunk-OXM2BZMF.js → chunk-4YRYR32D.js} +2 -2
- package/dist/{chunk-XG6WR2KS.js → chunk-6NKMAKMI.js} +3 -3
- package/dist/{chunk-6RKS3DNA.js → chunk-BN5DVIUO.js} +1176 -424
- package/dist/chunk-BN5DVIUO.js.map +1 -0
- package/dist/{chunk-QS5RZ2TC.js → chunk-CZQN6G4I.js} +28 -22
- package/dist/chunk-CZQN6G4I.js.map +1 -0
- package/dist/{chunk-D54FMQHF.js → chunk-FFNGE5RR.js} +2 -2
- package/dist/{chunk-RL43PU2X.js → chunk-J3ZCVE67.js} +2 -2
- package/dist/{chunk-BSVWJSVX.js → chunk-KBHGPQZ2.js} +2 -2
- package/dist/{chunk-CIKPFJOM.js → chunk-KOYZJN6G.js} +310 -20
- package/dist/chunk-KOYZJN6G.js.map +1 -0
- package/dist/{chunk-M5GO2SSO.js → chunk-M3ZTG4P5.js} +2 -2
- package/dist/{chunk-UMGZJYC4.js → chunk-V75ZB4G4.js} +10 -5
- package/dist/chunk-V75ZB4G4.js.map +1 -0
- package/dist/{chunk-ZBQQXVHD.js → chunk-YIEXKQYP.js} +2 -67
- package/dist/chunk-YIEXKQYP.js.map +1 -0
- package/dist/{chunk-QVTONMVZ.js → chunk-ZIL2IY4C.js} +2 -2
- package/dist/cli/init.cjs +1672 -576
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.js +33 -20
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/mcp-add.cjs +1509 -521
- package/dist/cli/mcp-add.cjs.map +1 -1
- package/dist/cli/mcp-add.js +34 -16
- package/dist/cli/mcp-add.js.map +1 -1
- package/dist/cli/status.cjs +6 -1
- package/dist/cli/status.cjs.map +1 -1
- package/dist/cli/status.js +7 -2
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/uninit.cjs +6 -1
- package/dist/cli/uninit.cjs.map +1 -1
- package/dist/cli/uninit.js +4 -4
- package/dist/cli/upgrade-instructions.cjs +383 -112
- package/dist/cli/upgrade-instructions.cjs.map +1 -1
- package/dist/cli/upgrade-instructions.js +72 -20
- package/dist/cli/upgrade-instructions.js.map +1 -1
- package/dist/cli/validate.cjs +1168 -422
- package/dist/cli/validate.cjs.map +1 -1
- package/dist/cli/validate.js +2 -2
- package/dist/{correlation-id-NAapJ5jn.d.cts → correlation-id-CFpyJsKv.d.cts} +1 -1
- package/dist/{correlation-id-B_K8adD6.d.ts → correlation-id-DPXyY9-3.d.ts} +1 -1
- package/dist/edge-entry.cjs +1197 -448
- package/dist/edge-entry.cjs.map +1 -1
- package/dist/edge-entry.d.cts +2 -2
- package/dist/edge-entry.d.ts +2 -2
- package/dist/edge-entry.js +4 -4
- package/dist/index.cjs +1341 -553
- package/dist/index.cjs.map +1 -1
- package/dist/{index.d-CkTf_boH.d.cts → index.d-D-jdiIPU.d.cts} +1 -1
- package/dist/{index.d-CkTf_boH.d.ts → index.d-D-jdiIPU.d.ts} +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +14 -7
- package/dist/index.js.map +1 -1
- package/dist/middleware/index.cjs +1192 -443
- package/dist/middleware/index.cjs.map +1 -1
- package/dist/middleware/index.js +2 -2
- package/dist/node-entry.cjs +1329 -551
- package/dist/node-entry.cjs.map +1 -1
- package/dist/node-entry.d.cts +3 -3
- package/dist/node-entry.d.ts +3 -3
- package/dist/node-entry.js +8 -8
- package/dist/node-subpath.cjs +1168 -422
- package/dist/node-subpath.cjs.map +1 -1
- package/dist/node-subpath.d.cts +1 -1
- package/dist/node-subpath.d.ts +1 -1
- package/dist/node-subpath.js +3 -3
- package/dist/{source-map-uploader-CLYCE2TZ.js → source-map-uploader-K67LTPBG.js} +3 -3
- package/dist/trpc/index.cjs +1187 -438
- package/dist/trpc/index.cjs.map +1 -1
- package/dist/trpc/index.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-6RKS3DNA.js.map +0 -1
- package/dist/chunk-CIKPFJOM.js.map +0 -1
- package/dist/chunk-QS5RZ2TC.js.map +0 -1
- package/dist/chunk-UMGZJYC4.js.map +0 -1
- package/dist/chunk-ZBQQXVHD.js.map +0 -1
- /package/dist/{chunk-OXM2BZMF.js.map → chunk-4YRYR32D.js.map} +0 -0
- /package/dist/{chunk-XG6WR2KS.js.map → chunk-6NKMAKMI.js.map} +0 -0
- /package/dist/{chunk-D54FMQHF.js.map → chunk-FFNGE5RR.js.map} +0 -0
- /package/dist/{chunk-RL43PU2X.js.map → chunk-J3ZCVE67.js.map} +0 -0
- /package/dist/{chunk-BSVWJSVX.js.map → chunk-KBHGPQZ2.js.map} +0 -0
- /package/dist/{chunk-M5GO2SSO.js.map → chunk-M3ZTG4P5.js.map} +0 -0
- /package/dist/{chunk-QVTONMVZ.js.map → chunk-ZIL2IY4C.js.map} +0 -0
- /package/dist/{source-map-uploader-CLYCE2TZ.js.map → source-map-uploader-K67LTPBG.js.map} +0 -0
package/dist/cli/uninit.js
CHANGED
|
@@ -12,11 +12,11 @@ import {
|
|
|
12
12
|
unwrapCJSExport,
|
|
13
13
|
unwrapExport,
|
|
14
14
|
writeShutdownMarker
|
|
15
|
-
} from "../chunk-
|
|
16
|
-
import "../chunk-
|
|
17
|
-
import "../chunk-
|
|
15
|
+
} from "../chunk-V75ZB4G4.js";
|
|
16
|
+
import "../chunk-J3ZCVE67.js";
|
|
17
|
+
import "../chunk-BN5DVIUO.js";
|
|
18
18
|
import "../chunk-NB7GJE4S.js";
|
|
19
|
-
import "../chunk-
|
|
19
|
+
import "../chunk-YIEXKQYP.js";
|
|
20
20
|
import "../chunk-NSBPE2FW.js";
|
|
21
21
|
export {
|
|
22
22
|
findMatchingDelimiter,
|
|
@@ -46,33 +46,61 @@ var AGENT_RULES = [
|
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
name: "codex",
|
|
49
|
+
// Codex 2026 default discovery is `AGENTS.override.md` → `AGENTS.md` →
|
|
50
|
+
// opt-in `project_doc_fallback_filenames`; `codex.md` is NOT in the
|
|
51
|
+
// default fallback list. Detection requires Codex-specific markers
|
|
52
|
+
// (`codex.md` legacy, `.codex/` config dir) — `AGENTS.md` is NOT
|
|
53
|
+
// included as a marker because the SDK now writes `AGENTS.md`
|
|
54
|
+
// broadly via the multi-target dispatcher's companion writes; if
|
|
55
|
+
// `AGENTS.md` were a Codex marker, every project with the SDK's
|
|
56
|
+
// own companion AGENTS.md would re-classify as Codex on subsequent
|
|
57
|
+
// detect runs and trigger unintended `.codex/config.toml` writes
|
|
58
|
+
// (Codex P1 + Copilot P1 review of Wave 18 PR #274). The canonical
|
|
59
|
+
// write destination remains AGENTS.md regardless of which marker
|
|
60
|
+
// classified the project.
|
|
49
61
|
markers: ["codex.md", ".codex"],
|
|
50
62
|
mcpConfigPath: (dir) => (0, import_node_path.join)(dir, ".codex", "config.toml"),
|
|
51
|
-
infoFilePath: (dir) => (0, import_node_path.join)(dir, "
|
|
63
|
+
infoFilePath: (dir) => (0, import_node_path.join)(dir, "AGENTS.md"),
|
|
52
64
|
cliBinary: "codex",
|
|
53
65
|
registrationCommand: "npx glasstrace mcp add --agent codex"
|
|
54
66
|
},
|
|
55
67
|
{
|
|
56
68
|
name: "gemini",
|
|
57
|
-
markers: [".gemini"],
|
|
69
|
+
markers: [".gemini", "GEMINI.md"],
|
|
58
70
|
mcpConfigPath: (dir) => (0, import_node_path.join)(dir, ".gemini", "settings.json"),
|
|
59
|
-
infoFilePath: () =>
|
|
71
|
+
infoFilePath: (dir) => (0, import_node_path.join)(dir, "GEMINI.md"),
|
|
60
72
|
cliBinary: "gemini",
|
|
61
73
|
registrationCommand: "npx glasstrace mcp add --agent gemini"
|
|
62
74
|
},
|
|
63
75
|
{
|
|
64
76
|
name: "cursor",
|
|
77
|
+
// `.cursor/rules/*.mdc` is the current canonical format per Cursor's
|
|
78
|
+
// 2026 docs. `.cursorrules` (single file) is supported-but-deprecated
|
|
79
|
+
// and stays as a transitional fallback that the multi-target write
|
|
80
|
+
// helper writes unconditionally alongside the .mdc canonical.
|
|
65
81
|
markers: [".cursor", ".cursorrules"],
|
|
66
82
|
mcpConfigPath: (dir) => (0, import_node_path.join)(dir, ".cursor", "mcp.json"),
|
|
67
|
-
infoFilePath: (dir) => (0, import_node_path.join)(dir, ".
|
|
83
|
+
infoFilePath: (dir) => (0, import_node_path.join)(dir, ".cursor", "rules", "glasstrace.mdc"),
|
|
68
84
|
cliBinary: null,
|
|
69
85
|
registrationCommand: "npx glasstrace mcp add --agent cursor"
|
|
70
86
|
},
|
|
71
87
|
{
|
|
72
88
|
name: "windsurf",
|
|
73
|
-
|
|
89
|
+
// Windsurf's current canonical workspace-rules format is
|
|
90
|
+
// `.windsurf/rules/*.md`. AGENTS.md is a parallel cross-tool
|
|
91
|
+
// mechanism Windsurf also reads BUT is NOT included as a Windsurf
|
|
92
|
+
// detection marker — the SDK writes `AGENTS.md` broadly via the
|
|
93
|
+
// multi-target dispatcher's companion writes, so treating
|
|
94
|
+
// `AGENTS.md` as a Windsurf marker would re-classify every
|
|
95
|
+
// SDK-managed project as Windsurf and cause `glasstrace uninit`
|
|
96
|
+
// to mutate the global `~/.codeium/windsurf/mcp_config.json` for
|
|
97
|
+
// non-Windsurf projects (Codex P1 + Copilot P1 review of Wave 18
|
|
98
|
+
// PR #274). The single-file `.windsurfrules` is the deprecated
|
|
99
|
+
// legacy form — recognized as a marker so legacy projects classify
|
|
100
|
+
// correctly, but the SDK no longer writes to it.
|
|
101
|
+
markers: [".windsurf", ".windsurfrules"],
|
|
74
102
|
mcpConfigPath: () => (0, import_node_path.join)((0, import_node_os.homedir)(), ".codeium", "windsurf", "mcp_config.json"),
|
|
75
|
-
infoFilePath: (dir) => (0, import_node_path.join)(dir, ".
|
|
103
|
+
infoFilePath: (dir) => (0, import_node_path.join)(dir, ".windsurf", "rules", "glasstrace.md"),
|
|
76
104
|
cliBinary: null,
|
|
77
105
|
registrationCommand: "npx glasstrace mcp add --agent windsurf"
|
|
78
106
|
}
|
|
@@ -159,10 +187,7 @@ async function detectAgents(projectRoot) {
|
|
|
159
187
|
continue;
|
|
160
188
|
}
|
|
161
189
|
seenAgents.add(rule.name);
|
|
162
|
-
|
|
163
|
-
if (infoFilePath !== null && !await pathExists(infoFilePath)) {
|
|
164
|
-
infoFilePath = null;
|
|
165
|
-
}
|
|
190
|
+
const infoFilePath = rule.infoFilePath(foundDir);
|
|
166
191
|
const cliAvailable = rule.cliBinary ? await isCliAvailable(rule.cliBinary) : false;
|
|
167
192
|
detected.push({
|
|
168
193
|
name: rule.name,
|
|
@@ -175,13 +200,62 @@ async function detectAgents(projectRoot) {
|
|
|
175
200
|
detected.push({
|
|
176
201
|
name: "generic",
|
|
177
202
|
mcpConfigPath: (0, import_node_path.join)(resolvedRoot, ".glasstrace", "mcp.json"),
|
|
178
|
-
infoFilePath:
|
|
203
|
+
infoFilePath: (0, import_node_path.join)(resolvedRoot, "AGENTS.md"),
|
|
179
204
|
cliAvailable: false,
|
|
180
205
|
registrationCommand: null
|
|
181
206
|
});
|
|
182
207
|
return detected;
|
|
183
208
|
}
|
|
184
209
|
|
|
210
|
+
// src/agent-detection/inject.ts
|
|
211
|
+
var import_promises2 = require("node:fs/promises");
|
|
212
|
+
var HTML_START_RE = /^<!--\s*glasstrace:mcp:start(?:\s+v=([^\s>]+))?\s*-->$/;
|
|
213
|
+
var HTML_END = "<!-- glasstrace:mcp:end -->";
|
|
214
|
+
var HASH_START_RE = /^#\s*glasstrace:mcp:start(?:\s+v=(\S+))?$/;
|
|
215
|
+
var HASH_END = "# glasstrace:mcp:end";
|
|
216
|
+
function parseStartMarkerLine(line) {
|
|
217
|
+
const trimmed = line.trim();
|
|
218
|
+
const html = HTML_START_RE.exec(trimmed);
|
|
219
|
+
if (html !== null) {
|
|
220
|
+
return { kind: "html", stamp: html[1] ?? null };
|
|
221
|
+
}
|
|
222
|
+
const hash = HASH_START_RE.exec(trimmed);
|
|
223
|
+
if (hash !== null) {
|
|
224
|
+
return { kind: "hash", stamp: hash[1] ?? null };
|
|
225
|
+
}
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
function isEndMarker(line) {
|
|
229
|
+
const trimmed = line.trim();
|
|
230
|
+
return trimmed === HTML_END || trimmed === HASH_END;
|
|
231
|
+
}
|
|
232
|
+
function findMarkerBoundaries(lines) {
|
|
233
|
+
let startIdx = -1;
|
|
234
|
+
for (let i = 0; i < lines.length; i++) {
|
|
235
|
+
if (parseStartMarkerLine(lines[i]) !== null) {
|
|
236
|
+
startIdx = i;
|
|
237
|
+
} else if (startIdx !== -1 && isEndMarker(lines[i])) {
|
|
238
|
+
return { startIdx, endIdx: i };
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
async function hasManagedSection(filePath) {
|
|
244
|
+
let content;
|
|
245
|
+
try {
|
|
246
|
+
content = await (0, import_promises2.readFile)(filePath, "utf-8");
|
|
247
|
+
} catch (err) {
|
|
248
|
+
const code = err.code;
|
|
249
|
+
if (code === "ENOENT") return false;
|
|
250
|
+
throw err;
|
|
251
|
+
}
|
|
252
|
+
return findMarkerBoundaries(content.split("\n")) !== null;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// src/agent-detection/inject-all-targets.ts
|
|
256
|
+
var import_promises3 = require("node:fs/promises");
|
|
257
|
+
var import_node_path2 = require("node:path");
|
|
258
|
+
|
|
185
259
|
// src/agent-detection/agent-instruction-text.ts
|
|
186
260
|
function buildAgentInstructionBody() {
|
|
187
261
|
return [
|
|
@@ -253,110 +327,235 @@ function generateInfoSection(agent, endpoint, sdkVersion) {
|
|
|
253
327
|
}
|
|
254
328
|
const content = buildAgentInstructionBody();
|
|
255
329
|
switch (agent.name) {
|
|
256
|
-
case "claude":
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
}
|
|
262
|
-
case "codex": {
|
|
330
|
+
case "claude":
|
|
331
|
+
case "codex":
|
|
332
|
+
case "gemini":
|
|
333
|
+
case "windsurf":
|
|
334
|
+
case "generic": {
|
|
263
335
|
const m = htmlMarkers(sdkVersion);
|
|
264
336
|
return `${m.start}
|
|
265
337
|
${content}${m.end}
|
|
266
338
|
`;
|
|
267
339
|
}
|
|
268
340
|
case "cursor": {
|
|
269
|
-
const m =
|
|
341
|
+
const m = htmlMarkers(sdkVersion);
|
|
270
342
|
return `${m.start}
|
|
271
343
|
${content}${m.end}
|
|
272
344
|
`;
|
|
273
345
|
}
|
|
274
|
-
case "gemini":
|
|
275
|
-
case "windsurf":
|
|
276
|
-
case "generic":
|
|
277
|
-
return "";
|
|
278
346
|
default: {
|
|
279
347
|
const _exhaustive = agent.name;
|
|
280
348
|
throw new Error(`Unknown agent: ${_exhaustive}`);
|
|
281
349
|
}
|
|
282
350
|
}
|
|
283
351
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
var import_node_path2 = require("node:path");
|
|
288
|
-
var HTML_START_RE = /^<!--\s*glasstrace:mcp:start(?:\s+v=([^\s>]+))?\s*-->$/;
|
|
289
|
-
var HTML_END = "<!-- glasstrace:mcp:end -->";
|
|
290
|
-
var HASH_START_RE = /^#\s*glasstrace:mcp:start(?:\s+v=(\S+))?$/;
|
|
291
|
-
var HASH_END = "# glasstrace:mcp:end";
|
|
292
|
-
function parseStartMarkerLine(line) {
|
|
293
|
-
const trimmed = line.trim();
|
|
294
|
-
const html = HTML_START_RE.exec(trimmed);
|
|
295
|
-
if (html !== null) {
|
|
296
|
-
return { kind: "html", stamp: html[1] ?? null };
|
|
352
|
+
function generateInfoSectionForCursorrulesLegacy(endpoint, sdkVersion) {
|
|
353
|
+
if (!endpoint || endpoint.trim() === "") {
|
|
354
|
+
throw new Error("endpoint must not be empty");
|
|
297
355
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
return { kind: "hash", stamp: hash[1] ?? null };
|
|
356
|
+
if (!sdkVersion || sdkVersion.trim() === "") {
|
|
357
|
+
throw new Error("sdkVersion must not be empty");
|
|
301
358
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
359
|
+
if (!SDK_VERSION_STAMP_PATTERN.test(sdkVersion)) {
|
|
360
|
+
throw new Error(
|
|
361
|
+
"sdkVersion must match [A-Za-z0-9.+\\-]+ (semver-shaped, no whitespace, no angle brackets)"
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
const content = buildAgentInstructionBody();
|
|
365
|
+
const m = hashMarkers(sdkVersion);
|
|
366
|
+
return `${m.start}
|
|
367
|
+
${content}${m.end}
|
|
368
|
+
`;
|
|
307
369
|
}
|
|
308
|
-
function
|
|
309
|
-
|
|
310
|
-
|
|
370
|
+
function generateInfoSectionForCursorMdc(endpoint, sdkVersion) {
|
|
371
|
+
if (!endpoint || endpoint.trim() === "") {
|
|
372
|
+
throw new Error("endpoint must not be empty");
|
|
373
|
+
}
|
|
374
|
+
if (!sdkVersion || sdkVersion.trim() === "") {
|
|
375
|
+
throw new Error("sdkVersion must not be empty");
|
|
376
|
+
}
|
|
377
|
+
if (!SDK_VERSION_STAMP_PATTERN.test(sdkVersion)) {
|
|
378
|
+
throw new Error(
|
|
379
|
+
"sdkVersion must match [A-Za-z0-9.+\\-]+ (semver-shaped, no whitespace, no angle brackets)"
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
const content = buildAgentInstructionBody();
|
|
383
|
+
const m = htmlMarkers(sdkVersion);
|
|
384
|
+
return [
|
|
385
|
+
"---",
|
|
386
|
+
"description: Glasstrace MCP runtime debugging tools \u2014 runtime evidence the agent reads when source alone cannot resolve a bug",
|
|
387
|
+
"alwaysApply: true",
|
|
388
|
+
"---",
|
|
389
|
+
"",
|
|
390
|
+
`${m.start}
|
|
391
|
+
${content}${m.end}
|
|
392
|
+
`
|
|
393
|
+
].join("\n");
|
|
311
394
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
395
|
+
|
|
396
|
+
// src/agent-detection/inject-all-targets.ts
|
|
397
|
+
async function injectAllTargets(agents, endpoint, sdkVersion, projectRoot) {
|
|
398
|
+
const writtenAgentsMd = /* @__PURE__ */ new Set();
|
|
399
|
+
for (const agent of agents) {
|
|
400
|
+
const targets = computeTargets(agent, projectRoot);
|
|
401
|
+
for (const target of targets) {
|
|
402
|
+
if (target.isAgentsMdCompanion) {
|
|
403
|
+
if (writtenAgentsMd.has(target.path)) {
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
writtenAgentsMd.add(target.path);
|
|
407
|
+
}
|
|
408
|
+
let createContent;
|
|
409
|
+
let managedSectionOnly;
|
|
410
|
+
if (target.kind === "cursor-mdc") {
|
|
411
|
+
createContent = generateInfoSectionForCursorMdc(endpoint, sdkVersion);
|
|
412
|
+
managedSectionOnly = generateInfoSection(agent, endpoint, sdkVersion);
|
|
413
|
+
} else if (target.kind === "cursorrules-legacy") {
|
|
414
|
+
createContent = generateInfoSectionForCursorrulesLegacy(
|
|
415
|
+
endpoint,
|
|
416
|
+
sdkVersion
|
|
417
|
+
);
|
|
418
|
+
managedSectionOnly = createContent;
|
|
419
|
+
} else {
|
|
420
|
+
createContent = generateInfoSection(agent, endpoint, sdkVersion);
|
|
421
|
+
managedSectionOnly = createContent;
|
|
422
|
+
}
|
|
423
|
+
if (managedSectionOnly === "") continue;
|
|
424
|
+
await writeManagedSectionToTarget(
|
|
425
|
+
target.path,
|
|
426
|
+
createContent,
|
|
427
|
+
managedSectionOnly
|
|
428
|
+
);
|
|
319
429
|
}
|
|
320
430
|
}
|
|
321
|
-
return null;
|
|
322
431
|
}
|
|
323
|
-
|
|
324
|
-
if (agent.infoFilePath === null)
|
|
325
|
-
|
|
432
|
+
function foundDirFromAgent(agent) {
|
|
433
|
+
if (agent.infoFilePath === null) return null;
|
|
434
|
+
switch (agent.name) {
|
|
435
|
+
case "claude":
|
|
436
|
+
case "codex":
|
|
437
|
+
case "gemini":
|
|
438
|
+
case "generic":
|
|
439
|
+
return (0, import_node_path2.dirname)(agent.infoFilePath);
|
|
440
|
+
case "cursor":
|
|
441
|
+
return (0, import_node_path2.dirname)((0, import_node_path2.dirname)((0, import_node_path2.dirname)(agent.infoFilePath)));
|
|
442
|
+
case "windsurf":
|
|
443
|
+
return (0, import_node_path2.dirname)((0, import_node_path2.dirname)((0, import_node_path2.dirname)(agent.infoFilePath)));
|
|
326
444
|
}
|
|
327
|
-
|
|
328
|
-
|
|
445
|
+
}
|
|
446
|
+
function computeTargets(agent, projectRoot) {
|
|
447
|
+
const targets = [];
|
|
448
|
+
const foundDir = foundDirFromAgent(agent) ?? projectRoot;
|
|
449
|
+
switch (agent.name) {
|
|
450
|
+
case "claude": {
|
|
451
|
+
if (agent.infoFilePath) {
|
|
452
|
+
targets.push({
|
|
453
|
+
path: agent.infoFilePath,
|
|
454
|
+
kind: "primary",
|
|
455
|
+
isAgentsMdCompanion: false
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
targets.push({
|
|
459
|
+
path: (0, import_node_path2.join)(foundDir, "AGENTS.md"),
|
|
460
|
+
kind: "agents-md-companion",
|
|
461
|
+
isAgentsMdCompanion: true
|
|
462
|
+
});
|
|
463
|
+
return targets;
|
|
464
|
+
}
|
|
465
|
+
case "codex": {
|
|
466
|
+
if (agent.infoFilePath) {
|
|
467
|
+
targets.push({
|
|
468
|
+
path: agent.infoFilePath,
|
|
469
|
+
kind: "primary",
|
|
470
|
+
isAgentsMdCompanion: true
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
return targets;
|
|
474
|
+
}
|
|
475
|
+
case "gemini": {
|
|
476
|
+
if (agent.infoFilePath) {
|
|
477
|
+
targets.push({
|
|
478
|
+
path: agent.infoFilePath,
|
|
479
|
+
kind: "primary",
|
|
480
|
+
isAgentsMdCompanion: false
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
targets.push({
|
|
484
|
+
path: (0, import_node_path2.join)(foundDir, "AGENTS.md"),
|
|
485
|
+
kind: "agents-md-companion",
|
|
486
|
+
isAgentsMdCompanion: true
|
|
487
|
+
});
|
|
488
|
+
return targets;
|
|
489
|
+
}
|
|
490
|
+
case "cursor": {
|
|
491
|
+
if (agent.infoFilePath) {
|
|
492
|
+
targets.push({
|
|
493
|
+
path: agent.infoFilePath,
|
|
494
|
+
kind: "cursor-mdc",
|
|
495
|
+
isAgentsMdCompanion: false
|
|
496
|
+
});
|
|
497
|
+
targets.push({
|
|
498
|
+
path: (0, import_node_path2.join)(foundDir, ".cursorrules"),
|
|
499
|
+
kind: "cursorrules-legacy",
|
|
500
|
+
isAgentsMdCompanion: false
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
targets.push({
|
|
504
|
+
path: (0, import_node_path2.join)(foundDir, "AGENTS.md"),
|
|
505
|
+
kind: "agents-md-companion",
|
|
506
|
+
isAgentsMdCompanion: true
|
|
507
|
+
});
|
|
508
|
+
return targets;
|
|
509
|
+
}
|
|
510
|
+
case "windsurf": {
|
|
511
|
+
if (agent.infoFilePath) {
|
|
512
|
+
targets.push({
|
|
513
|
+
path: agent.infoFilePath,
|
|
514
|
+
kind: "primary",
|
|
515
|
+
isAgentsMdCompanion: false
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
targets.push({
|
|
519
|
+
path: (0, import_node_path2.join)(foundDir, "AGENTS.md"),
|
|
520
|
+
kind: "agents-md-companion",
|
|
521
|
+
isAgentsMdCompanion: true
|
|
522
|
+
});
|
|
523
|
+
return targets;
|
|
524
|
+
}
|
|
525
|
+
case "generic": {
|
|
526
|
+
if (agent.infoFilePath) {
|
|
527
|
+
targets.push({
|
|
528
|
+
path: agent.infoFilePath,
|
|
529
|
+
kind: "primary",
|
|
530
|
+
isAgentsMdCompanion: true
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
return targets;
|
|
534
|
+
}
|
|
535
|
+
default: {
|
|
536
|
+
const _exhaustive = agent.name;
|
|
537
|
+
throw new Error(`Unknown agent: ${_exhaustive}`);
|
|
538
|
+
}
|
|
329
539
|
}
|
|
330
|
-
|
|
540
|
+
}
|
|
541
|
+
async function writeManagedSectionToTarget(filePath, createContent, managedSectionOnly) {
|
|
331
542
|
let existingContent = null;
|
|
332
543
|
try {
|
|
333
|
-
existingContent = await (0,
|
|
544
|
+
existingContent = await (0, import_promises3.readFile)(filePath, "utf-8");
|
|
334
545
|
} catch (err) {
|
|
335
546
|
const code = err.code;
|
|
336
547
|
if (code !== "ENOENT") {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
`Warning: cannot read info file ${filePath}: permission denied
|
|
340
|
-
`
|
|
341
|
-
);
|
|
342
|
-
return;
|
|
343
|
-
}
|
|
344
|
-
throw err;
|
|
548
|
+
emitTargetWarning(filePath, "read", err);
|
|
549
|
+
return;
|
|
345
550
|
}
|
|
346
551
|
}
|
|
347
552
|
if (existingContent === null) {
|
|
348
553
|
try {
|
|
349
|
-
await (0,
|
|
350
|
-
await (0,
|
|
554
|
+
await (0, import_promises3.mkdir)((0, import_node_path2.dirname)(filePath), { recursive: true });
|
|
555
|
+
await (0, import_promises3.writeFile)(filePath, createContent, "utf-8");
|
|
351
556
|
} catch (err) {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
`Warning: cannot write info file ${filePath}: permission denied
|
|
355
|
-
`
|
|
356
|
-
);
|
|
357
|
-
return;
|
|
358
|
-
}
|
|
359
|
-
throw err;
|
|
557
|
+
emitTargetWarning(filePath, "write", err);
|
|
558
|
+
return;
|
|
360
559
|
}
|
|
361
560
|
return;
|
|
362
561
|
}
|
|
@@ -366,38 +565,89 @@ async function injectInfoSection(agent, content, projectRoot) {
|
|
|
366
565
|
if (boundaries !== null) {
|
|
367
566
|
const before = lines.slice(0, boundaries.startIdx);
|
|
368
567
|
const after = lines.slice(boundaries.endIdx + 1);
|
|
369
|
-
const contentWithoutTrailingNewline =
|
|
370
|
-
newContent = [...before, contentWithoutTrailingNewline, ...after].join(
|
|
568
|
+
const contentWithoutTrailingNewline = managedSectionOnly.endsWith("\n") ? managedSectionOnly.slice(0, -1) : managedSectionOnly;
|
|
569
|
+
newContent = [...before, contentWithoutTrailingNewline, ...after].join(
|
|
570
|
+
"\n"
|
|
571
|
+
);
|
|
371
572
|
} else {
|
|
372
573
|
const separator = existingContent.endsWith("\n") ? "\n" : "\n\n";
|
|
373
|
-
newContent = existingContent + separator +
|
|
574
|
+
newContent = existingContent + separator + managedSectionOnly;
|
|
374
575
|
}
|
|
375
576
|
try {
|
|
376
|
-
await (0,
|
|
577
|
+
await (0, import_promises3.writeFile)(filePath, newContent, "utf-8");
|
|
377
578
|
} catch (err) {
|
|
378
|
-
|
|
379
|
-
process.stderr.write(
|
|
380
|
-
`Warning: cannot write info file ${filePath}: permission denied
|
|
381
|
-
`
|
|
382
|
-
);
|
|
383
|
-
return;
|
|
384
|
-
}
|
|
385
|
-
throw err;
|
|
579
|
+
emitTargetWarning(filePath, "write", err);
|
|
386
580
|
}
|
|
387
581
|
}
|
|
388
|
-
|
|
389
|
-
|
|
582
|
+
function emitTargetWarning(filePath, op, err) {
|
|
583
|
+
const code = err.code;
|
|
584
|
+
let qualifier;
|
|
585
|
+
switch (code) {
|
|
586
|
+
case "EACCES":
|
|
587
|
+
case "EPERM":
|
|
588
|
+
qualifier = "permission denied";
|
|
589
|
+
break;
|
|
590
|
+
case "EROFS":
|
|
591
|
+
qualifier = "filesystem read-only";
|
|
592
|
+
break;
|
|
593
|
+
case "ENOSPC":
|
|
594
|
+
qualifier = "disk full";
|
|
595
|
+
break;
|
|
596
|
+
case "ENAMETOOLONG":
|
|
597
|
+
qualifier = "path too long";
|
|
598
|
+
break;
|
|
599
|
+
case "ENOTDIR":
|
|
600
|
+
qualifier = "not a directory";
|
|
601
|
+
break;
|
|
602
|
+
case "EISDIR":
|
|
603
|
+
qualifier = "is a directory";
|
|
604
|
+
break;
|
|
605
|
+
default:
|
|
606
|
+
qualifier = "I/O error";
|
|
607
|
+
break;
|
|
608
|
+
}
|
|
390
609
|
try {
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
610
|
+
process.stderr.write(
|
|
611
|
+
`Warning: cannot ${op} info file ${filePath}: ${qualifier}
|
|
612
|
+
`
|
|
613
|
+
);
|
|
614
|
+
} catch {
|
|
396
615
|
}
|
|
397
|
-
return findMarkerBoundaries(content.split("\n")) !== null;
|
|
398
616
|
}
|
|
399
617
|
|
|
400
618
|
// src/cli/upgrade-instructions.ts
|
|
619
|
+
function legacyDestinationsForAgent(agent) {
|
|
620
|
+
if (agent.infoFilePath === null) {
|
|
621
|
+
return [];
|
|
622
|
+
}
|
|
623
|
+
switch (agent.name) {
|
|
624
|
+
case "codex":
|
|
625
|
+
return [(0, import_node_path3.join)((0, import_node_path3.dirname)(agent.infoFilePath), "codex.md")];
|
|
626
|
+
case "cursor":
|
|
627
|
+
return [
|
|
628
|
+
(0, import_node_path3.join)((0, import_node_path3.dirname)((0, import_node_path3.dirname)((0, import_node_path3.dirname)(agent.infoFilePath))), ".cursorrules")
|
|
629
|
+
];
|
|
630
|
+
case "windsurf":
|
|
631
|
+
return [
|
|
632
|
+
(0, import_node_path3.join)(
|
|
633
|
+
(0, import_node_path3.dirname)((0, import_node_path3.dirname)((0, import_node_path3.dirname)(agent.infoFilePath))),
|
|
634
|
+
".windsurfrules"
|
|
635
|
+
)
|
|
636
|
+
];
|
|
637
|
+
case "claude":
|
|
638
|
+
case "gemini":
|
|
639
|
+
case "generic":
|
|
640
|
+
return [];
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
async function anyHasManagedSection(paths) {
|
|
644
|
+
for (const p of paths) {
|
|
645
|
+
if (await hasManagedSection(p)) {
|
|
646
|
+
return true;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
return false;
|
|
650
|
+
}
|
|
401
651
|
function formatPathForOutput(filePath, projectRoot) {
|
|
402
652
|
const rel = (0, import_node_path3.relative)(projectRoot, filePath);
|
|
403
653
|
if (rel === "" || rel.startsWith("..") || (0, import_node_path3.isAbsolute)(rel)) {
|
|
@@ -419,7 +669,8 @@ async function runUpgradeInstructions(options) {
|
|
|
419
669
|
);
|
|
420
670
|
return { exitCode: 1, refreshed, skipped, warnings, errors };
|
|
421
671
|
}
|
|
422
|
-
const sdkVersion = true ? "1.
|
|
672
|
+
const sdkVersion = true ? "1.12.0" : "0.0.0-dev";
|
|
673
|
+
const optedInAgents = [];
|
|
423
674
|
for (const agent of agents) {
|
|
424
675
|
if (agent.infoFilePath === null) {
|
|
425
676
|
continue;
|
|
@@ -428,34 +679,54 @@ async function runUpgradeInstructions(options) {
|
|
|
428
679
|
agent.infoFilePath,
|
|
429
680
|
options.projectRoot
|
|
430
681
|
);
|
|
431
|
-
|
|
682
|
+
const legacyDestinations = legacyDestinationsForAgent(agent);
|
|
683
|
+
let optedIn;
|
|
432
684
|
try {
|
|
433
|
-
|
|
685
|
+
optedIn = await anyHasManagedSection([
|
|
686
|
+
agent.infoFilePath,
|
|
687
|
+
...legacyDestinations
|
|
688
|
+
]);
|
|
434
689
|
} catch (err) {
|
|
435
690
|
warnings.push(
|
|
436
691
|
`Could not inspect ${displayPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
437
692
|
);
|
|
438
693
|
continue;
|
|
439
694
|
}
|
|
440
|
-
if (!
|
|
695
|
+
if (!optedIn) {
|
|
441
696
|
skipped.push(displayPath);
|
|
442
697
|
continue;
|
|
443
698
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
}
|
|
699
|
+
optedInAgents.push(agent);
|
|
700
|
+
}
|
|
701
|
+
if (optedInAgents.length > 0) {
|
|
448
702
|
try {
|
|
449
|
-
await
|
|
450
|
-
|
|
703
|
+
await injectAllTargets(
|
|
704
|
+
optedInAgents,
|
|
705
|
+
MCP_ENDPOINT,
|
|
706
|
+
sdkVersion,
|
|
707
|
+
options.projectRoot
|
|
708
|
+
);
|
|
709
|
+
for (const a of optedInAgents) {
|
|
710
|
+
if (a.infoFilePath !== null) {
|
|
711
|
+
refreshed.push(formatPathForOutput(a.infoFilePath, options.projectRoot));
|
|
712
|
+
}
|
|
713
|
+
}
|
|
451
714
|
} catch (err) {
|
|
452
715
|
errors.push(
|
|
453
|
-
`Failed to refresh
|
|
716
|
+
`Failed to refresh agent-instruction files: ${err instanceof Error ? err.message : String(err)}`
|
|
454
717
|
);
|
|
455
718
|
}
|
|
456
719
|
}
|
|
720
|
+
const refreshedSet = new Set(refreshed);
|
|
721
|
+
const dedupedSkipped = skipped.filter((p) => !refreshedSet.has(p));
|
|
457
722
|
const exitCode = errors.length === 0 ? 0 : 1;
|
|
458
|
-
return {
|
|
723
|
+
return {
|
|
724
|
+
exitCode,
|
|
725
|
+
refreshed,
|
|
726
|
+
skipped: dedupedSkipped,
|
|
727
|
+
warnings,
|
|
728
|
+
errors
|
|
729
|
+
};
|
|
459
730
|
}
|
|
460
731
|
// Annotate the CommonJS export names for ESM import in node:
|
|
461
732
|
0 && (module.exports = {
|