@alessandroraffa/tangyr 0.16.0 → 0.16.1
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/index.js +1425 -721
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -17834,8 +17834,8 @@ async function runCacheClearCommand(options, logger) {
|
|
|
17834
17834
|
}
|
|
17835
17835
|
|
|
17836
17836
|
// src/commands/cleanup.ts
|
|
17837
|
-
import
|
|
17838
|
-
import
|
|
17837
|
+
import fs24 from "fs";
|
|
17838
|
+
import path22 from "path";
|
|
17839
17839
|
|
|
17840
17840
|
// node_modules/glob/dist/esm/index.min.js
|
|
17841
17841
|
import { fileURLToPath as Wi } from "url";
|
|
@@ -20832,6 +20832,7 @@ var KNOWN_COMPONENTS = /* @__PURE__ */ new Set([
|
|
|
20832
20832
|
"hooks",
|
|
20833
20833
|
"output-styles"
|
|
20834
20834
|
]);
|
|
20835
|
+
var KNOWN_INSTRUCTION_FILES = /* @__PURE__ */ new Set(["AGENTS.md", "CLAUDE.md"]);
|
|
20835
20836
|
var LEGACY_SOURCE_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
20836
20837
|
"operational-framework",
|
|
20837
20838
|
"operational-machinery"
|
|
@@ -20891,7 +20892,7 @@ function isOurStaleSymlink(linkPath, managedPaths, config) {
|
|
|
20891
20892
|
const lastSegment = path17.basename(linkTarget);
|
|
20892
20893
|
const parentSegment = path17.basename(path17.dirname(linkTarget));
|
|
20893
20894
|
if (isBroken) {
|
|
20894
|
-
return KNOWN_COMPONENTS.has(lastSegment) || KNOWN_COMPONENTS.has(parentSegment) || knownFiles.has(lastSegment);
|
|
20895
|
+
return KNOWN_COMPONENTS.has(lastSegment) || KNOWN_COMPONENTS.has(parentSegment) || KNOWN_INSTRUCTION_FILES.has(lastSegment) || knownFiles.has(lastSegment);
|
|
20895
20896
|
}
|
|
20896
20897
|
const targetSegments = absoluteTarget.split(path17.sep);
|
|
20897
20898
|
const traversesLegacyRoot = targetSegments.some(
|
|
@@ -20980,8 +20981,8 @@ function removeManagedEntries(filePath, parser, serializer, removeManaged, logge
|
|
|
20980
20981
|
}
|
|
20981
20982
|
|
|
20982
20983
|
// src/commands/uninstall.ts
|
|
20983
|
-
import
|
|
20984
|
-
import
|
|
20984
|
+
import fs23 from "fs";
|
|
20985
|
+
import path21 from "path";
|
|
20985
20986
|
|
|
20986
20987
|
// src/core/managed-sources.ts
|
|
20987
20988
|
var import_yaml5 = __toESM(require_dist(), 1);
|
|
@@ -21047,38 +21048,195 @@ function normalizeManagedSourcePath(rawPath) {
|
|
|
21047
21048
|
return normalized.startsWith("./") ? normalized.slice(2) : normalized;
|
|
21048
21049
|
}
|
|
21049
21050
|
|
|
21050
|
-
// src/
|
|
21051
|
+
// src/compiler/hook-components.ts
|
|
21052
|
+
var import_yaml6 = __toESM(require_dist(), 1);
|
|
21051
21053
|
import fs21 from "fs";
|
|
21054
|
+
import path20 from "path";
|
|
21055
|
+
function parseHookDeclaration(filePath) {
|
|
21056
|
+
let raw;
|
|
21057
|
+
try {
|
|
21058
|
+
raw = fs21.readFileSync(filePath, "utf8");
|
|
21059
|
+
} catch {
|
|
21060
|
+
return null;
|
|
21061
|
+
}
|
|
21062
|
+
const fm = extractFrontmatter(raw);
|
|
21063
|
+
if (!fm) {
|
|
21064
|
+
return null;
|
|
21065
|
+
}
|
|
21066
|
+
const { name, description, events } = fm;
|
|
21067
|
+
if (typeof name !== "string" || !name.trim()) {
|
|
21068
|
+
return null;
|
|
21069
|
+
}
|
|
21070
|
+
if (typeof description !== "string" || !description.trim()) {
|
|
21071
|
+
return null;
|
|
21072
|
+
}
|
|
21073
|
+
if (!Array.isArray(events) || events.length === 0) {
|
|
21074
|
+
return null;
|
|
21075
|
+
}
|
|
21076
|
+
const parsedEvents = [];
|
|
21077
|
+
for (const entry of events) {
|
|
21078
|
+
if (!entry || typeof entry !== "object") {
|
|
21079
|
+
return null;
|
|
21080
|
+
}
|
|
21081
|
+
const ev = entry;
|
|
21082
|
+
if (typeof ev.event !== "string" || !ev.event.trim()) {
|
|
21083
|
+
return null;
|
|
21084
|
+
}
|
|
21085
|
+
if (typeof ev.timeout !== "number") {
|
|
21086
|
+
return null;
|
|
21087
|
+
}
|
|
21088
|
+
if (typeof ev.statusMessage !== "string" || !ev.statusMessage.trim()) {
|
|
21089
|
+
return null;
|
|
21090
|
+
}
|
|
21091
|
+
const parsed = {
|
|
21092
|
+
event: ev.event,
|
|
21093
|
+
timeout: ev.timeout,
|
|
21094
|
+
statusMessage: ev.statusMessage
|
|
21095
|
+
};
|
|
21096
|
+
if (typeof ev.matcher === "string" && ev.matcher.trim()) {
|
|
21097
|
+
parsed.matcher = ev.matcher;
|
|
21098
|
+
}
|
|
21099
|
+
parsedEvents.push(parsed);
|
|
21100
|
+
}
|
|
21101
|
+
return {
|
|
21102
|
+
name: name.trim(),
|
|
21103
|
+
description: description.trim(),
|
|
21104
|
+
events: parsedEvents
|
|
21105
|
+
};
|
|
21106
|
+
}
|
|
21107
|
+
function hookCommand(name) {
|
|
21108
|
+
return `npx tsx ~/.agents/hooks/scripts/${name}.ts`;
|
|
21109
|
+
}
|
|
21110
|
+
function synthesizeHooksJson(declarations) {
|
|
21111
|
+
const hooks = {};
|
|
21112
|
+
for (const decl of declarations) {
|
|
21113
|
+
for (const ev of decl.events) {
|
|
21114
|
+
if (!hooks[ev.event]) {
|
|
21115
|
+
hooks[ev.event] = [];
|
|
21116
|
+
}
|
|
21117
|
+
const entry = {
|
|
21118
|
+
hooks: [
|
|
21119
|
+
{
|
|
21120
|
+
type: "command",
|
|
21121
|
+
command: hookCommand(decl.name),
|
|
21122
|
+
timeout: ev.timeout,
|
|
21123
|
+
statusMessage: ev.statusMessage
|
|
21124
|
+
}
|
|
21125
|
+
]
|
|
21126
|
+
};
|
|
21127
|
+
if (ev.matcher !== void 0) {
|
|
21128
|
+
const ordered = {
|
|
21129
|
+
matcher: ev.matcher,
|
|
21130
|
+
hooks: entry.hooks
|
|
21131
|
+
};
|
|
21132
|
+
hooks[ev.event].push(ordered);
|
|
21133
|
+
} else {
|
|
21134
|
+
hooks[ev.event].push(entry);
|
|
21135
|
+
}
|
|
21136
|
+
}
|
|
21137
|
+
}
|
|
21138
|
+
return { hooks };
|
|
21139
|
+
}
|
|
21140
|
+
function loadSourceHooks(hooksDir, hookNames) {
|
|
21141
|
+
const hooksJsonPath = path20.join(hooksDir, "hooks.json");
|
|
21142
|
+
if (fs21.existsSync(hooksJsonPath)) {
|
|
21143
|
+
const raw = fs21.readFileSync(hooksJsonPath, "utf8");
|
|
21144
|
+
return JSON.parse(raw);
|
|
21145
|
+
}
|
|
21146
|
+
const declarations = loadHookDeclarations(hooksDir, hookNames);
|
|
21147
|
+
return synthesizeHooksJson(declarations);
|
|
21148
|
+
}
|
|
21149
|
+
function loadHookDeclarations(hooksDir, hookNames) {
|
|
21150
|
+
let names;
|
|
21151
|
+
if (hookNames && hookNames.length > 0) {
|
|
21152
|
+
names = hookNames;
|
|
21153
|
+
} else {
|
|
21154
|
+
if (!fs21.existsSync(hooksDir) || !fs21.statSync(hooksDir).isDirectory()) {
|
|
21155
|
+
return [];
|
|
21156
|
+
}
|
|
21157
|
+
names = fs21.readdirSync(hooksDir).filter((f) => f.endsWith(".md") && !f.startsWith(".")).map((f) => f.slice(0, -3)).sort();
|
|
21158
|
+
}
|
|
21159
|
+
const declarations = [];
|
|
21160
|
+
for (const name of names) {
|
|
21161
|
+
const filePath = path20.join(hooksDir, `${name}.md`);
|
|
21162
|
+
const decl = parseHookDeclaration(filePath);
|
|
21163
|
+
if (decl) {
|
|
21164
|
+
declarations.push(decl);
|
|
21165
|
+
}
|
|
21166
|
+
}
|
|
21167
|
+
return declarations;
|
|
21168
|
+
}
|
|
21169
|
+
function extractFrontmatter(content) {
|
|
21170
|
+
if (!content.startsWith("---\n")) {
|
|
21171
|
+
return null;
|
|
21172
|
+
}
|
|
21173
|
+
const endIndex = content.indexOf("\n---", 4);
|
|
21174
|
+
if (endIndex === -1) {
|
|
21175
|
+
return null;
|
|
21176
|
+
}
|
|
21177
|
+
const rawFm = content.slice(4, endIndex);
|
|
21178
|
+
let parsed;
|
|
21179
|
+
try {
|
|
21180
|
+
parsed = (0, import_yaml6.parse)(rawFm);
|
|
21181
|
+
} catch {
|
|
21182
|
+
return null;
|
|
21183
|
+
}
|
|
21184
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
21185
|
+
return null;
|
|
21186
|
+
}
|
|
21187
|
+
return parsed;
|
|
21188
|
+
}
|
|
21189
|
+
|
|
21190
|
+
// src/core/remove.ts
|
|
21191
|
+
import fs22 from "fs";
|
|
21052
21192
|
function removeManagedPath(managedPath) {
|
|
21053
21193
|
let stat;
|
|
21054
21194
|
try {
|
|
21055
|
-
stat =
|
|
21195
|
+
stat = fs22.lstatSync(managedPath);
|
|
21056
21196
|
} catch {
|
|
21057
21197
|
return;
|
|
21058
21198
|
}
|
|
21059
21199
|
if (stat.isSymbolicLink() || stat.isFile()) {
|
|
21060
|
-
|
|
21200
|
+
fs22.unlinkSync(managedPath);
|
|
21061
21201
|
return;
|
|
21062
21202
|
}
|
|
21063
21203
|
if (stat.isDirectory()) {
|
|
21064
|
-
|
|
21204
|
+
fs22.rmSync(managedPath, { recursive: true, force: true });
|
|
21065
21205
|
}
|
|
21066
21206
|
}
|
|
21067
21207
|
|
|
21068
21208
|
// src/commands/uninstall.ts
|
|
21069
21209
|
var codexManagedMcpStart = "# tangyr: managed mcp start";
|
|
21070
21210
|
var codexManagedMcpEnd = "# tangyr: managed mcp end";
|
|
21211
|
+
var legacyClaudeSharedPermission = "Read(~/.agents/**)";
|
|
21212
|
+
var legacyOperatingGuideSignature = "# Agent Coding \u2014 Operating Guide\n\n_Structured authoring with LLM agents across the full artifact continuum._";
|
|
21071
21213
|
var SHARED_CLAUDE_SLOTS = /* @__PURE__ */ new Set([
|
|
21072
21214
|
"mcp_shared_file",
|
|
21073
21215
|
"hooks"
|
|
21074
21216
|
]);
|
|
21217
|
+
function resolveClaudeCodePathsForRoots(roots, mappings) {
|
|
21218
|
+
return roots.map((root) => resolveClaudeCodeProfileForRoot(root, mappings));
|
|
21219
|
+
}
|
|
21075
21220
|
async function runUninstallCommand(options, logger) {
|
|
21076
21221
|
const scope = options.scope === "global" ? "global" : "project";
|
|
21077
21222
|
const scopePath = resolveScopePath(
|
|
21078
21223
|
scope,
|
|
21079
21224
|
scope === "project" ? process.cwd() : void 0
|
|
21080
21225
|
);
|
|
21081
|
-
const
|
|
21226
|
+
const runtime = resolveRuntimeIfAvailable(options, logger);
|
|
21227
|
+
const persistedManifest = readStrictManifest(scopePath);
|
|
21228
|
+
const manifestWasPresent = persistedManifest !== null;
|
|
21229
|
+
let manifest = persistedManifest;
|
|
21230
|
+
if (!manifest && scope === "global" && runtime?.kitInfo) {
|
|
21231
|
+
manifest = createEmptyManifest(
|
|
21232
|
+
runtime.kitInfo.archetype,
|
|
21233
|
+
runtime.kitInfo.kitFormat,
|
|
21234
|
+
"global"
|
|
21235
|
+
);
|
|
21236
|
+
logger.warn(
|
|
21237
|
+
`No Tangyr manifest found in ${scope} scope; reconciling ownership evidence on disk.`
|
|
21238
|
+
);
|
|
21239
|
+
}
|
|
21082
21240
|
if (!manifest) {
|
|
21083
21241
|
logger.error(
|
|
21084
21242
|
`No Tangyr installation found in ${scope} scope (${scopePath}).`
|
|
@@ -21086,15 +21244,25 @@ async function runUninstallCommand(options, logger) {
|
|
|
21086
21244
|
logger.info("Nothing to uninstall.");
|
|
21087
21245
|
process.exit(1);
|
|
21088
21246
|
}
|
|
21089
|
-
const runtime = resolveRuntimeIfAvailable(options, logger);
|
|
21090
21247
|
const selectedTools = resolveSelectedTools(options.tools, manifest, runtime);
|
|
21091
21248
|
const manifestArtifacts = manifest.artifacts.filter(
|
|
21092
21249
|
(file) => shouldRemoveManifestFile(file.relativePath, selectedTools)
|
|
21093
21250
|
);
|
|
21094
|
-
const kitArtifacts = runtime ? resolveKitManagedArtifacts(
|
|
21095
|
-
|
|
21096
|
-
|
|
21097
|
-
|
|
21251
|
+
const kitArtifacts = runtime ? resolveKitManagedArtifacts(
|
|
21252
|
+
runtime,
|
|
21253
|
+
scope,
|
|
21254
|
+
selectedTools,
|
|
21255
|
+
manifest,
|
|
21256
|
+
options.claudeConfigDir
|
|
21257
|
+
).filter((artifact) => isKitManagedArtifact(artifact, runtime)) : [];
|
|
21258
|
+
const useManifestPathRemoval = scope !== "global" || runtime === void 0;
|
|
21259
|
+
if (manifestWasPresent) {
|
|
21260
|
+
logger.info(
|
|
21261
|
+
`Found Tangyr installation: archetype ${manifest.archetype}, version ${manifest.version}`
|
|
21262
|
+
);
|
|
21263
|
+
} else {
|
|
21264
|
+
logger.info(`Scanning Tangyr residue for archetype ${manifest.archetype}`);
|
|
21265
|
+
}
|
|
21098
21266
|
logger.info(`Scope: ${scope} (${scopePath})`);
|
|
21099
21267
|
logger.info(
|
|
21100
21268
|
`Tools: ${Array.from(selectedTools).join(", ") || manifest.tools.join(", ") || "(none)"}`
|
|
@@ -21105,8 +21273,10 @@ async function runUninstallCommand(options, logger) {
|
|
|
21105
21273
|
}
|
|
21106
21274
|
if (options.dryRun) {
|
|
21107
21275
|
logger.info("\n[dry-run] Would remove:");
|
|
21108
|
-
|
|
21109
|
-
|
|
21276
|
+
if (useManifestPathRemoval) {
|
|
21277
|
+
for (const file of manifestArtifacts) {
|
|
21278
|
+
logger.info(` ${file.relativePath}`);
|
|
21279
|
+
}
|
|
21110
21280
|
}
|
|
21111
21281
|
for (const artifact of kitArtifacts) {
|
|
21112
21282
|
logger.info(` ${artifact.path}`);
|
|
@@ -21121,7 +21291,7 @@ async function runUninstallCommand(options, logger) {
|
|
|
21121
21291
|
}
|
|
21122
21292
|
if (!options.yes) {
|
|
21123
21293
|
const proceed = await dist_default5({
|
|
21124
|
-
message: `Remove Tangyr from ${scope} scope? This will delete ${manifestArtifacts.length + kitArtifacts.length} managed file(s).`
|
|
21294
|
+
message: `Remove Tangyr from ${scope} scope? This will delete ${(useManifestPathRemoval ? manifestArtifacts.length : 0) + kitArtifacts.length} managed file(s).`
|
|
21125
21295
|
});
|
|
21126
21296
|
if (!proceed) {
|
|
21127
21297
|
logger.info("Uninstallation aborted.");
|
|
@@ -21130,7 +21300,7 @@ async function runUninstallCommand(options, logger) {
|
|
|
21130
21300
|
}
|
|
21131
21301
|
const claudeRoots = scope === "global" && selectedTools.has("claude-code") ? resolveClaudeRootsForUninstall(manifest, runtime) : [];
|
|
21132
21302
|
let removedCount = 0;
|
|
21133
|
-
for (const file of manifestArtifacts) {
|
|
21303
|
+
for (const file of useManifestPathRemoval ? manifestArtifacts : []) {
|
|
21134
21304
|
const isClaudeGlobal = file.relativePath.startsWith("claude-code/") && scope === "global";
|
|
21135
21305
|
if (isClaudeGlobal && claudeRoots.length > 0) {
|
|
21136
21306
|
const paths = resolveManifestKeyToMultiPaths(
|
|
@@ -21139,7 +21309,7 @@ async function runUninstallCommand(options, logger) {
|
|
|
21139
21309
|
runtime
|
|
21140
21310
|
);
|
|
21141
21311
|
for (const actualPath of paths) {
|
|
21142
|
-
if (actualPath && (
|
|
21312
|
+
if (actualPath && (fs23.existsSync(actualPath) || isSymlink(actualPath))) {
|
|
21143
21313
|
removeManagedPath(actualPath);
|
|
21144
21314
|
logger.verbose(` removed: ${actualPath}`);
|
|
21145
21315
|
removedCount++;
|
|
@@ -21153,7 +21323,7 @@ async function runUninstallCommand(options, logger) {
|
|
|
21153
21323
|
scope,
|
|
21154
21324
|
runtime
|
|
21155
21325
|
);
|
|
21156
|
-
if (actualPath && (
|
|
21326
|
+
if (actualPath && (fs23.existsSync(actualPath) || isSymlink(actualPath))) {
|
|
21157
21327
|
removeManagedPath(actualPath);
|
|
21158
21328
|
logger.verbose(` removed: ${actualPath}`);
|
|
21159
21329
|
removedCount++;
|
|
@@ -21168,32 +21338,46 @@ async function runUninstallCommand(options, logger) {
|
|
|
21168
21338
|
removedCount++;
|
|
21169
21339
|
}
|
|
21170
21340
|
}
|
|
21341
|
+
const residuals = resolveKitManagedArtifacts(
|
|
21342
|
+
runtime,
|
|
21343
|
+
scope,
|
|
21344
|
+
selectedTools,
|
|
21345
|
+
manifest,
|
|
21346
|
+
options.claudeConfigDir
|
|
21347
|
+
).filter((artifact) => isKitManagedArtifact(artifact, runtime));
|
|
21348
|
+
if (residuals.length > 0) {
|
|
21349
|
+
throw new Error(
|
|
21350
|
+
`Uninstall incomplete: ${residuals.length} managed artifact(s) remain: ${residuals.map((artifact) => artifact.path).join(", ")}`
|
|
21351
|
+
);
|
|
21352
|
+
}
|
|
21171
21353
|
}
|
|
21172
21354
|
const fullUninstall = isFullToolUninstall(manifest, selectedTools);
|
|
21173
21355
|
if (fullUninstall) {
|
|
21174
21356
|
for (const backup of manifest.backups) {
|
|
21175
21357
|
restoreBackup(backup, logger);
|
|
21176
21358
|
}
|
|
21177
|
-
const manifestPath =
|
|
21178
|
-
if (
|
|
21179
|
-
|
|
21359
|
+
const manifestPath = path21.join(scopePath, "manifest.json");
|
|
21360
|
+
if (fs23.existsSync(manifestPath)) {
|
|
21361
|
+
fs23.unlinkSync(manifestPath);
|
|
21180
21362
|
logger.verbose(` removed manifest: ${manifestPath}`);
|
|
21181
21363
|
}
|
|
21182
21364
|
try {
|
|
21183
|
-
const remaining =
|
|
21365
|
+
const remaining = fs23.readdirSync(scopePath);
|
|
21184
21366
|
if (remaining.length === 0) {
|
|
21185
|
-
|
|
21367
|
+
fs23.rmdirSync(scopePath);
|
|
21186
21368
|
logger.verbose(` removed empty scope directory: ${scopePath}`);
|
|
21187
21369
|
}
|
|
21188
21370
|
} catch {
|
|
21189
21371
|
}
|
|
21190
|
-
} else {
|
|
21372
|
+
} else if (manifestWasPresent) {
|
|
21191
21373
|
manifest.artifacts = manifest.artifacts.filter(
|
|
21192
21374
|
(file) => !shouldRemoveManifestFile(file.relativePath, selectedTools)
|
|
21193
21375
|
);
|
|
21194
21376
|
manifest.tools = manifest.tools.filter((tool) => !selectedTools.has(tool));
|
|
21195
21377
|
writeManifest(scopePath, manifest);
|
|
21196
21378
|
logger.verbose(" updated manifest for partial uninstall");
|
|
21379
|
+
} else {
|
|
21380
|
+
logger.verbose(" no manifest to update after partial residue cleanup");
|
|
21197
21381
|
}
|
|
21198
21382
|
logger.info(`
|
|
21199
21383
|
Uninstallation complete: ${removedCount} file(s) removed.`);
|
|
@@ -21220,7 +21404,7 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21220
21404
|
if (!slotPath) {
|
|
21221
21405
|
return null;
|
|
21222
21406
|
}
|
|
21223
|
-
return subPath ?
|
|
21407
|
+
return subPath ? path21.join(slotPath, subPath) : slotPath;
|
|
21224
21408
|
}
|
|
21225
21409
|
if (tool === "copilot") {
|
|
21226
21410
|
const copilotPaths = resolveCopilotPaths(runtime, scope, projectRoot);
|
|
@@ -21228,18 +21412,18 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21228
21412
|
return copilotPaths.skills;
|
|
21229
21413
|
}
|
|
21230
21414
|
if (component.startsWith("agents/")) {
|
|
21231
|
-
return
|
|
21415
|
+
return path21.join(copilotPaths.agents, component.slice("agents/".length));
|
|
21232
21416
|
}
|
|
21233
21417
|
if (component.startsWith("prompts/")) {
|
|
21234
|
-
return
|
|
21418
|
+
return path21.join(
|
|
21235
21419
|
copilotPaths.prompts,
|
|
21236
21420
|
component.slice("prompts/".length)
|
|
21237
21421
|
);
|
|
21238
21422
|
}
|
|
21239
21423
|
if (component.startsWith("hooks/")) {
|
|
21240
|
-
return
|
|
21424
|
+
return path21.join(copilotPaths.hooks, component.slice("hooks/".length));
|
|
21241
21425
|
}
|
|
21242
|
-
if (component ===
|
|
21426
|
+
if (component === path21.basename(copilotPaths.mcpSharedFile)) {
|
|
21243
21427
|
return copilotPaths.mcpSharedFile;
|
|
21244
21428
|
}
|
|
21245
21429
|
return null;
|
|
@@ -21253,15 +21437,15 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21253
21437
|
return codexPaths.skills;
|
|
21254
21438
|
}
|
|
21255
21439
|
if (component.startsWith("agents/")) {
|
|
21256
|
-
return
|
|
21440
|
+
return path21.join(codexPaths.agents, component.slice("agents/".length));
|
|
21257
21441
|
}
|
|
21258
21442
|
if (component.startsWith("rules/")) {
|
|
21259
|
-
return
|
|
21443
|
+
return path21.join(codexPaths.rules, component.slice("rules/".length));
|
|
21260
21444
|
}
|
|
21261
|
-
if (component ===
|
|
21445
|
+
if (component === path21.basename(codexPaths.hooksSharedFile)) {
|
|
21262
21446
|
return codexPaths.hooksSharedFile;
|
|
21263
21447
|
}
|
|
21264
|
-
if (component ===
|
|
21448
|
+
if (component === path21.basename(codexPaths.mcpSharedFile)) {
|
|
21265
21449
|
return codexPaths.mcpSharedFile;
|
|
21266
21450
|
}
|
|
21267
21451
|
return null;
|
|
@@ -21278,15 +21462,15 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21278
21462
|
return opencodePaths.skillsShared;
|
|
21279
21463
|
}
|
|
21280
21464
|
if (component.startsWith("agents/")) {
|
|
21281
|
-
return
|
|
21465
|
+
return path21.join(opencodePaths.agents, component.slice("agents/".length));
|
|
21282
21466
|
}
|
|
21283
21467
|
if (component.startsWith("commands/")) {
|
|
21284
|
-
return
|
|
21468
|
+
return path21.join(
|
|
21285
21469
|
opencodePaths.commands,
|
|
21286
21470
|
component.slice("commands/".length)
|
|
21287
21471
|
);
|
|
21288
21472
|
}
|
|
21289
|
-
if (component ===
|
|
21473
|
+
if (component === path21.basename(opencodePaths.configDoc)) {
|
|
21290
21474
|
return opencodePaths.configDoc;
|
|
21291
21475
|
}
|
|
21292
21476
|
return null;
|
|
@@ -21312,13 +21496,13 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21312
21496
|
return cursorPaths.permissionsFile;
|
|
21313
21497
|
}
|
|
21314
21498
|
if (component.startsWith("agents/")) {
|
|
21315
|
-
return
|
|
21499
|
+
return path21.join(cursorPaths.agents, component.slice("agents/".length));
|
|
21316
21500
|
}
|
|
21317
21501
|
if (component.startsWith("rules/")) {
|
|
21318
|
-
return
|
|
21502
|
+
return path21.join(cursorPaths.rules, component.slice("rules/".length));
|
|
21319
21503
|
}
|
|
21320
21504
|
if (component.startsWith("skills/")) {
|
|
21321
|
-
return
|
|
21505
|
+
return path21.join(cursorPaths.skills, component.slice("skills/".length));
|
|
21322
21506
|
}
|
|
21323
21507
|
return null;
|
|
21324
21508
|
}
|
|
@@ -21334,10 +21518,10 @@ function resolveManifestKeyToPath(key, scope, runtime) {
|
|
|
21334
21518
|
return clinePaths.mcpFile;
|
|
21335
21519
|
}
|
|
21336
21520
|
if (component.startsWith("rules/")) {
|
|
21337
|
-
return
|
|
21521
|
+
return path21.join(clinePaths.rules, component.slice("rules/".length));
|
|
21338
21522
|
}
|
|
21339
21523
|
if (component.startsWith("workflows/")) {
|
|
21340
|
-
return
|
|
21524
|
+
return path21.join(
|
|
21341
21525
|
clinePaths.workflows,
|
|
21342
21526
|
component.slice("workflows/".length)
|
|
21343
21527
|
);
|
|
@@ -21371,22 +21555,22 @@ function resolveClaudeCodePaths(runtime, scope, projectRoot) {
|
|
|
21371
21555
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
21372
21556
|
if (scope === "global") {
|
|
21373
21557
|
return {
|
|
21374
|
-
instructions:
|
|
21375
|
-
agents:
|
|
21376
|
-
skills:
|
|
21377
|
-
commands:
|
|
21378
|
-
rules:
|
|
21379
|
-
output_styles:
|
|
21558
|
+
instructions: path21.join(home, ".claude", "CLAUDE.md"),
|
|
21559
|
+
agents: path21.join(home, ".claude", "agents"),
|
|
21560
|
+
skills: path21.join(home, ".claude", "skills"),
|
|
21561
|
+
commands: path21.join(home, ".claude", "commands"),
|
|
21562
|
+
rules: path21.join(home, ".claude", "rules"),
|
|
21563
|
+
output_styles: path21.join(home, ".claude", "output-styles")
|
|
21380
21564
|
};
|
|
21381
21565
|
}
|
|
21382
21566
|
const root = projectRoot ?? process.cwd();
|
|
21383
21567
|
return {
|
|
21384
|
-
instructions:
|
|
21385
|
-
agents:
|
|
21386
|
-
skills:
|
|
21387
|
-
commands:
|
|
21388
|
-
rules:
|
|
21389
|
-
output_styles:
|
|
21568
|
+
instructions: path21.join(root, "CLAUDE.md"),
|
|
21569
|
+
agents: path21.join(root, ".claude", "agents"),
|
|
21570
|
+
skills: path21.join(root, ".claude", "skills"),
|
|
21571
|
+
commands: path21.join(root, ".claude", "commands"),
|
|
21572
|
+
rules: path21.join(root, ".claude", "rules"),
|
|
21573
|
+
output_styles: path21.join(root, ".claude", "output-styles")
|
|
21390
21574
|
};
|
|
21391
21575
|
}
|
|
21392
21576
|
function resolveClaudeRootsForUninstall(manifest, runtime) {
|
|
@@ -21405,12 +21589,36 @@ function resolveClaudeRootsForUninstall(manifest, runtime) {
|
|
|
21405
21589
|
projectRoot: void 0,
|
|
21406
21590
|
mappings: mappings.platformPaths
|
|
21407
21591
|
})["claude-code"];
|
|
21408
|
-
return [
|
|
21592
|
+
return [path21.dirname(profile.agents)];
|
|
21409
21593
|
} catch {
|
|
21410
21594
|
}
|
|
21411
21595
|
}
|
|
21412
21596
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
21413
|
-
return [
|
|
21597
|
+
return [path21.resolve(expandHome(`${home}/.claude`))];
|
|
21598
|
+
}
|
|
21599
|
+
function resolveAllClaudeRoots(manifest, runtime, claudeConfigDirs) {
|
|
21600
|
+
const home = process.env.HOME ?? process.env.USERPROFILE;
|
|
21601
|
+
const roots = new Set(
|
|
21602
|
+
[
|
|
21603
|
+
...resolveClaudeRootsForUninstall(manifest, runtime),
|
|
21604
|
+
...resolveClaudeGlobalRoots({
|
|
21605
|
+
flag: claudeConfigDirs,
|
|
21606
|
+
env: process.env.TANGYR_CLAUDE_CONFIG_DIRS,
|
|
21607
|
+
config: runtime.config.claudeCodeGlobalPaths
|
|
21608
|
+
})
|
|
21609
|
+
].map((root) => path21.resolve(root))
|
|
21610
|
+
);
|
|
21611
|
+
if (home && fs23.existsSync(home)) {
|
|
21612
|
+
try {
|
|
21613
|
+
for (const entry of fs23.readdirSync(home, { withFileTypes: true })) {
|
|
21614
|
+
if (entry.isDirectory() && entry.name.startsWith(".claude-")) {
|
|
21615
|
+
roots.add(path21.resolve(home, entry.name));
|
|
21616
|
+
}
|
|
21617
|
+
}
|
|
21618
|
+
} catch {
|
|
21619
|
+
}
|
|
21620
|
+
}
|
|
21621
|
+
return Array.from(roots).sort();
|
|
21414
21622
|
}
|
|
21415
21623
|
function resolveManifestKeyToMultiPaths(key, claudeRoots, runtime) {
|
|
21416
21624
|
if (claudeRoots.length === 0) {
|
|
@@ -21423,13 +21631,13 @@ function resolveManifestKeyToMultiPaths(key, claudeRoots, runtime) {
|
|
|
21423
21631
|
const rootsToResolve = isShared ? [claudeRoots[0]] : claudeRoots;
|
|
21424
21632
|
if (!runtime) {
|
|
21425
21633
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
21426
|
-
const defaultRoot =
|
|
21634
|
+
const defaultRoot = path21.resolve(expandHome(`${home}/.claude`));
|
|
21427
21635
|
return rootsToResolve.flatMap((root) => {
|
|
21428
21636
|
const hardcoded = resolveHardcodedClaudeSlot(root, defaultRoot, slotName);
|
|
21429
21637
|
if (!hardcoded) {
|
|
21430
21638
|
return [];
|
|
21431
21639
|
}
|
|
21432
|
-
return [subPath ?
|
|
21640
|
+
return [subPath ? path21.join(hardcoded, subPath) : hardcoded];
|
|
21433
21641
|
});
|
|
21434
21642
|
}
|
|
21435
21643
|
try {
|
|
@@ -21448,17 +21656,17 @@ function resolveManifestKeyToMultiPaths(key, claudeRoots, runtime) {
|
|
|
21448
21656
|
if (!slotPath) {
|
|
21449
21657
|
return [];
|
|
21450
21658
|
}
|
|
21451
|
-
return [subPath ?
|
|
21659
|
+
return [subPath ? path21.join(slotPath, subPath) : slotPath];
|
|
21452
21660
|
});
|
|
21453
21661
|
} catch {
|
|
21454
21662
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
21455
|
-
const defaultRoot =
|
|
21663
|
+
const defaultRoot = path21.resolve(expandHome(`${home}/.claude`));
|
|
21456
21664
|
return rootsToResolve.flatMap((root) => {
|
|
21457
21665
|
const hardcoded = resolveHardcodedClaudeSlot(root, defaultRoot, slotName);
|
|
21458
21666
|
if (!hardcoded) {
|
|
21459
21667
|
return [];
|
|
21460
21668
|
}
|
|
21461
|
-
return [subPath ?
|
|
21669
|
+
return [subPath ? path21.join(hardcoded, subPath) : hardcoded];
|
|
21462
21670
|
});
|
|
21463
21671
|
}
|
|
21464
21672
|
}
|
|
@@ -21481,9 +21689,9 @@ function resolveHardcodedClaudeSlot(root, defaultRoot, slotName) {
|
|
|
21481
21689
|
return null;
|
|
21482
21690
|
}
|
|
21483
21691
|
if (root === defaultRoot) {
|
|
21484
|
-
return
|
|
21692
|
+
return path21.join(root, relative);
|
|
21485
21693
|
}
|
|
21486
|
-
return
|
|
21694
|
+
return path21.join(root, relative);
|
|
21487
21695
|
}
|
|
21488
21696
|
function resolveRuntimeIfAvailable(options, logger) {
|
|
21489
21697
|
try {
|
|
@@ -21502,6 +21710,9 @@ function resolveSelectedTools(rawTools, manifest, runtime) {
|
|
|
21502
21710
|
);
|
|
21503
21711
|
}
|
|
21504
21712
|
const selectedTools = new Set(manifest.tools);
|
|
21713
|
+
if (selectedTools.size === 0) {
|
|
21714
|
+
return new Set(ALL_TARGETS);
|
|
21715
|
+
}
|
|
21505
21716
|
if (runtime) {
|
|
21506
21717
|
for (const tool of activeTargets(runtime.config)) {
|
|
21507
21718
|
selectedTools.add(tool);
|
|
@@ -21514,9 +21725,93 @@ function shouldRemoveManifestFile(relativePath, selectedTools) {
|
|
|
21514
21725
|
return selectedTools.has(tool);
|
|
21515
21726
|
}
|
|
21516
21727
|
function isFullToolUninstall(manifest, selectedTools) {
|
|
21728
|
+
if (manifest.tools.length === 0) {
|
|
21729
|
+
return ALL_TARGETS.every((tool) => selectedTools.has(tool));
|
|
21730
|
+
}
|
|
21517
21731
|
return manifest.tools.every((tool) => selectedTools.has(tool));
|
|
21518
21732
|
}
|
|
21519
|
-
function
|
|
21733
|
+
function addCompiledPathPlan(artifacts, artifactPath, expectedTarget, component) {
|
|
21734
|
+
addCompiledGlobPlans(artifacts, artifactPath, expectedTarget, component);
|
|
21735
|
+
}
|
|
21736
|
+
function addCompiledGlobPlans(artifacts, pattern, expectedTarget, component) {
|
|
21737
|
+
for (const artifactPath of ts(pattern).sort()) {
|
|
21738
|
+
let marker = null;
|
|
21739
|
+
try {
|
|
21740
|
+
marker = extractProvenanceMarker(fs23.readFileSync(artifactPath, "utf8"));
|
|
21741
|
+
} catch {
|
|
21742
|
+
continue;
|
|
21743
|
+
}
|
|
21744
|
+
if (marker?.target !== expectedTarget) {
|
|
21745
|
+
continue;
|
|
21746
|
+
}
|
|
21747
|
+
artifacts.push({
|
|
21748
|
+
component,
|
|
21749
|
+
path: artifactPath,
|
|
21750
|
+
kind: "compiled",
|
|
21751
|
+
expectedTarget,
|
|
21752
|
+
expectedSource: marker.source,
|
|
21753
|
+
observed: true
|
|
21754
|
+
});
|
|
21755
|
+
}
|
|
21756
|
+
}
|
|
21757
|
+
function addManagedSymlinkChildren(artifacts, directory, runtime, component) {
|
|
21758
|
+
let entries;
|
|
21759
|
+
try {
|
|
21760
|
+
entries = fs23.readdirSync(directory, { withFileTypes: true });
|
|
21761
|
+
} catch {
|
|
21762
|
+
return;
|
|
21763
|
+
}
|
|
21764
|
+
for (const entry of entries) {
|
|
21765
|
+
const artifactPath = path21.join(directory, entry.name);
|
|
21766
|
+
const artifactClass = classifyArtifact(
|
|
21767
|
+
artifactPath,
|
|
21768
|
+
runtime.config,
|
|
21769
|
+
runtime.sourceRoot
|
|
21770
|
+
);
|
|
21771
|
+
if (artifactClass === "managed-symlink" || artifactClass === "managed-stale") {
|
|
21772
|
+
artifacts.push({ component, path: artifactPath, kind: "direct" });
|
|
21773
|
+
}
|
|
21774
|
+
}
|
|
21775
|
+
}
|
|
21776
|
+
function resolveLegacyClaudeHookCommands(runtime) {
|
|
21777
|
+
const parsed = loadSourceHooks(
|
|
21778
|
+
resolveHooksSourceDir(runtime.sourceRoot, runtime.config),
|
|
21779
|
+
resolveKitHookNames(runtime.sourceRoot)
|
|
21780
|
+
);
|
|
21781
|
+
const commands = /* @__PURE__ */ new Set();
|
|
21782
|
+
collectStringValuesByKey(parsed, "command", commands);
|
|
21783
|
+
return Array.from(commands).sort();
|
|
21784
|
+
}
|
|
21785
|
+
function collectStringValuesByKey(value, keyName, values) {
|
|
21786
|
+
if (Array.isArray(value)) {
|
|
21787
|
+
for (const entry of value) {
|
|
21788
|
+
collectStringValuesByKey(entry, keyName, values);
|
|
21789
|
+
}
|
|
21790
|
+
return;
|
|
21791
|
+
}
|
|
21792
|
+
if (!isRecord(value)) {
|
|
21793
|
+
return;
|
|
21794
|
+
}
|
|
21795
|
+
if (typeof value[keyName] === "string") {
|
|
21796
|
+
values.add(value[keyName]);
|
|
21797
|
+
}
|
|
21798
|
+
for (const entry of Object.values(value)) {
|
|
21799
|
+
collectStringValuesByKey(entry, keyName, values);
|
|
21800
|
+
}
|
|
21801
|
+
}
|
|
21802
|
+
function addLegacyOperatingGuideCopies(artifacts, claudeRoot) {
|
|
21803
|
+
for (const artifactPath of [
|
|
21804
|
+
...ts(path21.join(claudeRoot, "CLAUDE.md.bak.*")),
|
|
21805
|
+
...ts(path21.join(claudeRoot, "AGENTS.md.bak.*"))
|
|
21806
|
+
].sort()) {
|
|
21807
|
+
artifacts.push({
|
|
21808
|
+
component: "claude-code legacy operating guide backup",
|
|
21809
|
+
path: artifactPath,
|
|
21810
|
+
kind: "legacy-kit-copy"
|
|
21811
|
+
});
|
|
21812
|
+
}
|
|
21813
|
+
}
|
|
21814
|
+
function resolveKitManagedArtifacts(runtime, scope, selectedTools, manifest, claudeConfigDirs) {
|
|
21520
21815
|
if (!runtime.kitInfo || scope !== "global") {
|
|
21521
21816
|
return [];
|
|
21522
21817
|
}
|
|
@@ -21526,11 +21821,97 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21526
21821
|
const opencodePaths = resolveOpenCodePaths(runtime);
|
|
21527
21822
|
const cursorPaths = resolveCursorPaths(runtime);
|
|
21528
21823
|
const clinePaths = resolveClinePaths(runtime);
|
|
21824
|
+
if (selectedTools.has("claude-code")) {
|
|
21825
|
+
const mappings = loadMappings(
|
|
21826
|
+
runtime.sourceRoot,
|
|
21827
|
+
runtime.config,
|
|
21828
|
+
runtime.configDir
|
|
21829
|
+
);
|
|
21830
|
+
const claudeRoots = resolveAllClaudeRoots(
|
|
21831
|
+
manifest,
|
|
21832
|
+
runtime,
|
|
21833
|
+
claudeConfigDirs
|
|
21834
|
+
);
|
|
21835
|
+
const profiles = resolveClaudeCodePathsForRoots(
|
|
21836
|
+
claudeRoots,
|
|
21837
|
+
mappings.platformPaths
|
|
21838
|
+
);
|
|
21839
|
+
const legacyHookCommands = resolveLegacyClaudeHookCommands(runtime);
|
|
21840
|
+
for (const profile of profiles) {
|
|
21841
|
+
for (const [component, artifactPath] of [
|
|
21842
|
+
["instructions", profile.instructions],
|
|
21843
|
+
["instructions shim", profile.instructions_shim],
|
|
21844
|
+
["agents", profile.agents],
|
|
21845
|
+
["commands", profile.commands],
|
|
21846
|
+
["rules", profile.rules],
|
|
21847
|
+
["output styles", profile.output_styles],
|
|
21848
|
+
["skills", profile.skills]
|
|
21849
|
+
]) {
|
|
21850
|
+
artifacts.push({
|
|
21851
|
+
component: `claude-code ${component}`,
|
|
21852
|
+
path: artifactPath,
|
|
21853
|
+
kind: "direct"
|
|
21854
|
+
});
|
|
21855
|
+
}
|
|
21856
|
+
for (const skill of runtime.kitInfo.components.skills.declared) {
|
|
21857
|
+
artifacts.push({
|
|
21858
|
+
component: "claude-code skill",
|
|
21859
|
+
path: path21.join(profile.skills, skill),
|
|
21860
|
+
kind: "direct"
|
|
21861
|
+
});
|
|
21862
|
+
}
|
|
21863
|
+
addManagedSymlinkChildren(
|
|
21864
|
+
artifacts,
|
|
21865
|
+
profile.skills,
|
|
21866
|
+
runtime,
|
|
21867
|
+
"claude-code skill residue"
|
|
21868
|
+
);
|
|
21869
|
+
artifacts.push({
|
|
21870
|
+
component: "claude-code settings",
|
|
21871
|
+
path: profile.hooks_shared_file,
|
|
21872
|
+
kind: "claude-hooks",
|
|
21873
|
+
legacyHookCommands
|
|
21874
|
+
});
|
|
21875
|
+
if (isFullToolUninstall(manifest, selectedTools)) {
|
|
21876
|
+
addLegacyOperatingGuideCopies(
|
|
21877
|
+
artifacts,
|
|
21878
|
+
path21.dirname(profile.instructions)
|
|
21879
|
+
);
|
|
21880
|
+
}
|
|
21881
|
+
}
|
|
21882
|
+
const sharedProfile = profiles[0];
|
|
21883
|
+
if (sharedProfile) {
|
|
21884
|
+
artifacts.push(
|
|
21885
|
+
{
|
|
21886
|
+
component: "claude-code hooks bridge",
|
|
21887
|
+
path: sharedProfile.hooks,
|
|
21888
|
+
kind: "direct"
|
|
21889
|
+
},
|
|
21890
|
+
{
|
|
21891
|
+
component: "claude-code mcp",
|
|
21892
|
+
path: sharedProfile.mcp_shared_file,
|
|
21893
|
+
kind: "claude-mcp"
|
|
21894
|
+
}
|
|
21895
|
+
);
|
|
21896
|
+
}
|
|
21897
|
+
}
|
|
21529
21898
|
if (selectedTools.has("copilot")) {
|
|
21899
|
+
addCompiledGlobPlans(
|
|
21900
|
+
artifacts,
|
|
21901
|
+
path21.join(copilotPaths.agents, "*.agent.md"),
|
|
21902
|
+
"copilot",
|
|
21903
|
+
"copilot agent residue"
|
|
21904
|
+
);
|
|
21905
|
+
addCompiledGlobPlans(
|
|
21906
|
+
artifacts,
|
|
21907
|
+
path21.join(copilotPaths.prompts, "*.prompt.md"),
|
|
21908
|
+
"copilot",
|
|
21909
|
+
"copilot prompt residue"
|
|
21910
|
+
);
|
|
21530
21911
|
for (const agentEntry of runtime.kitInfo.components.agents.declared) {
|
|
21531
21912
|
artifacts.push({
|
|
21532
21913
|
component: "copilot agent",
|
|
21533
|
-
path:
|
|
21914
|
+
path: path21.join(copilotPaths.agents, `${agentEntry}.agent.md`),
|
|
21534
21915
|
kind: "compiled",
|
|
21535
21916
|
expectedTarget: "copilot",
|
|
21536
21917
|
expectedSource: `agents/${agentEntry}.md`
|
|
@@ -21539,7 +21920,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21539
21920
|
for (const commandEntry of runtime.kitInfo.components.commands.declared) {
|
|
21540
21921
|
artifacts.push({
|
|
21541
21922
|
component: "copilot prompt",
|
|
21542
|
-
path:
|
|
21923
|
+
path: path21.join(copilotPaths.prompts, `${commandEntry}.prompt.md`),
|
|
21543
21924
|
kind: "compiled",
|
|
21544
21925
|
expectedTarget: "copilot",
|
|
21545
21926
|
expectedSource: `commands/${commandEntry}.md`
|
|
@@ -21552,15 +21933,29 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21552
21933
|
kind: "direct"
|
|
21553
21934
|
});
|
|
21554
21935
|
}
|
|
21936
|
+
artifacts.push(
|
|
21937
|
+
{
|
|
21938
|
+
component: "copilot hooks",
|
|
21939
|
+
path: path21.join(copilotPaths.hooks, "tangyr-managed.json"),
|
|
21940
|
+
kind: "managed-json",
|
|
21941
|
+
expectedTarget: "copilot"
|
|
21942
|
+
},
|
|
21943
|
+
{
|
|
21944
|
+
component: "copilot legacy hooks",
|
|
21945
|
+
path: path21.join(copilotPaths.hooks, "proteus-managed.json"),
|
|
21946
|
+
kind: "managed-json",
|
|
21947
|
+
expectedTarget: "copilot"
|
|
21948
|
+
}
|
|
21949
|
+
);
|
|
21555
21950
|
const hooksSourcePath = resolveHooksSourceFile(
|
|
21556
21951
|
runtime.sourceRoot,
|
|
21557
21952
|
runtime.config
|
|
21558
21953
|
);
|
|
21559
21954
|
const hooksSource = hooksSourceLabel(runtime.config);
|
|
21560
|
-
if (
|
|
21955
|
+
if (fs23.existsSync(hooksSourcePath)) {
|
|
21561
21956
|
artifacts.push({
|
|
21562
21957
|
component: "copilot hooks",
|
|
21563
|
-
path:
|
|
21958
|
+
path: path21.join(copilotPaths.hooks, "tangyr-managed.json"),
|
|
21564
21959
|
kind: "compiled",
|
|
21565
21960
|
expectedTarget: "copilot",
|
|
21566
21961
|
expectedSource: hooksSource
|
|
@@ -21571,7 +21966,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21571
21966
|
runtime.config
|
|
21572
21967
|
);
|
|
21573
21968
|
const mcpSource = mcpSourceLabel(runtime.config);
|
|
21574
|
-
if (
|
|
21969
|
+
if (fs23.existsSync(mcpSourcePath)) {
|
|
21575
21970
|
artifacts.push({
|
|
21576
21971
|
component: "copilot mcp",
|
|
21577
21972
|
path: copilotPaths.mcpSharedFile,
|
|
@@ -21582,6 +21977,24 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21582
21977
|
}
|
|
21583
21978
|
}
|
|
21584
21979
|
if (selectedTools.has("codex")) {
|
|
21980
|
+
addCompiledPathPlan(
|
|
21981
|
+
artifacts,
|
|
21982
|
+
codexPaths.instructions,
|
|
21983
|
+
"codex",
|
|
21984
|
+
"codex instruction residue"
|
|
21985
|
+
);
|
|
21986
|
+
addCompiledGlobPlans(
|
|
21987
|
+
artifacts,
|
|
21988
|
+
path21.join(codexPaths.agents, "*.toml"),
|
|
21989
|
+
"codex",
|
|
21990
|
+
"codex agent residue"
|
|
21991
|
+
);
|
|
21992
|
+
addCompiledGlobPlans(
|
|
21993
|
+
artifacts,
|
|
21994
|
+
path21.join(codexPaths.rules, "*.rules"),
|
|
21995
|
+
"codex",
|
|
21996
|
+
"codex rule residue"
|
|
21997
|
+
);
|
|
21585
21998
|
artifacts.push({
|
|
21586
21999
|
component: "codex instructions",
|
|
21587
22000
|
path: codexPaths.instructions,
|
|
@@ -21592,7 +22005,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21592
22005
|
for (const agentEntry of runtime.kitInfo.components.agents.declared) {
|
|
21593
22006
|
artifacts.push({
|
|
21594
22007
|
component: "codex agent",
|
|
21595
|
-
path:
|
|
22008
|
+
path: path21.join(codexPaths.agents, `${agentEntry}.toml`),
|
|
21596
22009
|
kind: "compiled",
|
|
21597
22010
|
expectedTarget: "codex",
|
|
21598
22011
|
expectedSource: `agents/${agentEntry}.md`
|
|
@@ -21601,7 +22014,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21601
22014
|
for (const ruleEntry of runtime.kitInfo.components.rules.declared) {
|
|
21602
22015
|
artifacts.push({
|
|
21603
22016
|
component: "codex rule",
|
|
21604
|
-
path:
|
|
22017
|
+
path: path21.join(codexPaths.rules, `${ruleEntry}.rules`),
|
|
21605
22018
|
kind: "compiled",
|
|
21606
22019
|
expectedTarget: "codex",
|
|
21607
22020
|
expectedSource: `rules/${ruleEntry}.md`
|
|
@@ -21619,7 +22032,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21619
22032
|
runtime.config
|
|
21620
22033
|
);
|
|
21621
22034
|
const hooksSource = hooksSourceLabel(runtime.config);
|
|
21622
|
-
if (
|
|
22035
|
+
if (fs23.existsSync(hooksSourcePath)) {
|
|
21623
22036
|
artifacts.push({
|
|
21624
22037
|
component: "codex hooks",
|
|
21625
22038
|
path: codexPaths.hooksSharedFile,
|
|
@@ -21632,7 +22045,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21632
22045
|
runtime.config
|
|
21633
22046
|
);
|
|
21634
22047
|
const mcpSource = mcpSourceLabel(runtime.config);
|
|
21635
|
-
if (
|
|
22048
|
+
if (fs23.existsSync(mcpSourcePath)) {
|
|
21636
22049
|
artifacts.push({
|
|
21637
22050
|
component: "codex mcp",
|
|
21638
22051
|
path: codexPaths.mcpSharedFile,
|
|
@@ -21643,8 +22056,37 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21643
22056
|
}
|
|
21644
22057
|
}
|
|
21645
22058
|
if (selectedTools.has("opencode")) {
|
|
21646
|
-
|
|
21647
|
-
|
|
22059
|
+
addCompiledPathPlan(
|
|
22060
|
+
artifacts,
|
|
22061
|
+
opencodePaths.instructions,
|
|
22062
|
+
"opencode",
|
|
22063
|
+
"opencode instruction residue"
|
|
22064
|
+
);
|
|
22065
|
+
addCompiledPathPlan(
|
|
22066
|
+
artifacts,
|
|
22067
|
+
opencodePaths.configDoc,
|
|
22068
|
+
"opencode",
|
|
22069
|
+
"opencode config residue"
|
|
22070
|
+
);
|
|
22071
|
+
addCompiledGlobPlans(
|
|
22072
|
+
artifacts,
|
|
22073
|
+
path21.join(opencodePaths.agents, "*.md"),
|
|
22074
|
+
"opencode",
|
|
22075
|
+
"opencode agent residue"
|
|
22076
|
+
);
|
|
22077
|
+
addCompiledGlobPlans(
|
|
22078
|
+
artifacts,
|
|
22079
|
+
path21.join(opencodePaths.commands, "*.md"),
|
|
22080
|
+
"opencode",
|
|
22081
|
+
"opencode command residue"
|
|
22082
|
+
);
|
|
22083
|
+
artifacts.push({
|
|
22084
|
+
component: "opencode shared skills",
|
|
22085
|
+
path: opencodePaths.skillsShared,
|
|
22086
|
+
kind: "direct"
|
|
22087
|
+
});
|
|
22088
|
+
artifacts.push({
|
|
22089
|
+
component: "opencode instructions",
|
|
21648
22090
|
path: opencodePaths.instructions,
|
|
21649
22091
|
kind: "compiled",
|
|
21650
22092
|
expectedTarget: "opencode",
|
|
@@ -21653,7 +22095,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21653
22095
|
for (const agentEntry of runtime.kitInfo.components.agents.declared) {
|
|
21654
22096
|
artifacts.push({
|
|
21655
22097
|
component: "opencode agent",
|
|
21656
|
-
path:
|
|
22098
|
+
path: path21.join(opencodePaths.agents, `${agentEntry}.md`),
|
|
21657
22099
|
kind: "compiled",
|
|
21658
22100
|
expectedTarget: "opencode",
|
|
21659
22101
|
expectedSource: `agents/${agentEntry}.md`
|
|
@@ -21662,7 +22104,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21662
22104
|
for (const commandEntry of runtime.kitInfo.components.commands.declared) {
|
|
21663
22105
|
artifacts.push({
|
|
21664
22106
|
component: "opencode command",
|
|
21665
|
-
path:
|
|
22107
|
+
path: path21.join(opencodePaths.commands, `${commandEntry}.md`),
|
|
21666
22108
|
kind: "compiled",
|
|
21667
22109
|
expectedTarget: "opencode",
|
|
21668
22110
|
expectedSource: `commands/${commandEntry}.md`
|
|
@@ -21680,7 +22122,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21680
22122
|
runtime.config
|
|
21681
22123
|
);
|
|
21682
22124
|
const mcpSource = mcpSourceLabel(runtime.config);
|
|
21683
|
-
if (
|
|
22125
|
+
if (fs23.existsSync(mcpSourcePath)) {
|
|
21684
22126
|
artifacts.push({
|
|
21685
22127
|
component: "opencode config",
|
|
21686
22128
|
path: opencodePaths.configDoc,
|
|
@@ -21691,6 +22133,48 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21691
22133
|
}
|
|
21692
22134
|
}
|
|
21693
22135
|
if (selectedTools.has("cursor")) {
|
|
22136
|
+
addCompiledPathPlan(
|
|
22137
|
+
artifacts,
|
|
22138
|
+
cursorPaths.instructions,
|
|
22139
|
+
"cursor",
|
|
22140
|
+
"cursor instruction residue"
|
|
22141
|
+
);
|
|
22142
|
+
addCompiledPathPlan(
|
|
22143
|
+
artifacts,
|
|
22144
|
+
cursorPaths.mcpFile,
|
|
22145
|
+
"cursor",
|
|
22146
|
+
"cursor mcp residue"
|
|
22147
|
+
);
|
|
22148
|
+
artifacts.push(
|
|
22149
|
+
{
|
|
22150
|
+
component: "cursor agent directory residue",
|
|
22151
|
+
path: cursorPaths.agents,
|
|
22152
|
+
kind: "direct"
|
|
22153
|
+
},
|
|
22154
|
+
{
|
|
22155
|
+
component: "cursor shared skills",
|
|
22156
|
+
path: cursorPaths.skillsShared,
|
|
22157
|
+
kind: "direct"
|
|
22158
|
+
}
|
|
22159
|
+
);
|
|
22160
|
+
addCompiledGlobPlans(
|
|
22161
|
+
artifacts,
|
|
22162
|
+
path21.join(cursorPaths.agents, "*.md"),
|
|
22163
|
+
"cursor",
|
|
22164
|
+
"cursor agent residue"
|
|
22165
|
+
);
|
|
22166
|
+
addCompiledGlobPlans(
|
|
22167
|
+
artifacts,
|
|
22168
|
+
path21.join(cursorPaths.rules, "*.mdc"),
|
|
22169
|
+
"cursor",
|
|
22170
|
+
"cursor rule residue"
|
|
22171
|
+
);
|
|
22172
|
+
addCompiledGlobPlans(
|
|
22173
|
+
artifacts,
|
|
22174
|
+
path21.join(cursorPaths.skills, "*", "SKILL.md"),
|
|
22175
|
+
"cursor",
|
|
22176
|
+
"cursor command residue"
|
|
22177
|
+
);
|
|
21694
22178
|
artifacts.push({
|
|
21695
22179
|
component: "cursor instructions",
|
|
21696
22180
|
path: cursorPaths.instructions,
|
|
@@ -21701,7 +22185,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21701
22185
|
for (const agentEntry of runtime.kitInfo.components.agents.declared) {
|
|
21702
22186
|
artifacts.push({
|
|
21703
22187
|
component: "cursor agent",
|
|
21704
|
-
path:
|
|
22188
|
+
path: path21.join(cursorPaths.agents, `${agentEntry}.md`),
|
|
21705
22189
|
kind: "compiled",
|
|
21706
22190
|
expectedTarget: "cursor",
|
|
21707
22191
|
expectedSource: `agents/${agentEntry}.md`
|
|
@@ -21719,7 +22203,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21719
22203
|
runtime.config
|
|
21720
22204
|
);
|
|
21721
22205
|
const mcpSource = mcpSourceLabel(runtime.config);
|
|
21722
|
-
if (
|
|
22206
|
+
if (fs23.existsSync(mcpSourcePath)) {
|
|
21723
22207
|
artifacts.push({
|
|
21724
22208
|
component: "cursor mcp",
|
|
21725
22209
|
path: cursorPaths.mcpFile,
|
|
@@ -21730,6 +22214,36 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21730
22214
|
}
|
|
21731
22215
|
}
|
|
21732
22216
|
if (selectedTools.has("cline")) {
|
|
22217
|
+
addCompiledPathPlan(
|
|
22218
|
+
artifacts,
|
|
22219
|
+
clinePaths.mcpFile,
|
|
22220
|
+
"cline",
|
|
22221
|
+
"cline mcp residue"
|
|
22222
|
+
);
|
|
22223
|
+
addCompiledGlobPlans(
|
|
22224
|
+
artifacts,
|
|
22225
|
+
path21.join(clinePaths.rules, "*.md"),
|
|
22226
|
+
"cline",
|
|
22227
|
+
"cline rule residue"
|
|
22228
|
+
);
|
|
22229
|
+
addCompiledGlobPlans(
|
|
22230
|
+
artifacts,
|
|
22231
|
+
path21.join(clinePaths.workflows, "*.md"),
|
|
22232
|
+
"cline",
|
|
22233
|
+
"cline workflow residue"
|
|
22234
|
+
);
|
|
22235
|
+
addManagedSymlinkChildren(
|
|
22236
|
+
artifacts,
|
|
22237
|
+
clinePaths.rules,
|
|
22238
|
+
runtime,
|
|
22239
|
+
"cline rule symlink residue"
|
|
22240
|
+
);
|
|
22241
|
+
addManagedSymlinkChildren(
|
|
22242
|
+
artifacts,
|
|
22243
|
+
clinePaths.workflows,
|
|
22244
|
+
runtime,
|
|
22245
|
+
"cline workflow symlink residue"
|
|
22246
|
+
);
|
|
21733
22247
|
if (clinePaths.instructions !== null) {
|
|
21734
22248
|
artifacts.push({
|
|
21735
22249
|
component: "cline instructions",
|
|
@@ -21742,7 +22256,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21742
22256
|
for (const ruleEntry of runtime.kitInfo.components.rules.declared) {
|
|
21743
22257
|
artifacts.push({
|
|
21744
22258
|
component: "cline rule",
|
|
21745
|
-
path:
|
|
22259
|
+
path: path21.join(clinePaths.rules, `${ruleEntry}.md`),
|
|
21746
22260
|
kind: "compiled",
|
|
21747
22261
|
expectedTarget: "cline",
|
|
21748
22262
|
expectedSource: `rules/${ruleEntry}.md`
|
|
@@ -21751,7 +22265,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21751
22265
|
for (const commandEntry of runtime.kitInfo.components.commands.declared) {
|
|
21752
22266
|
artifacts.push({
|
|
21753
22267
|
component: "cline workflow",
|
|
21754
|
-
path:
|
|
22268
|
+
path: path21.join(clinePaths.workflows, `${commandEntry}.md`),
|
|
21755
22269
|
kind: "compiled",
|
|
21756
22270
|
expectedTarget: "cline",
|
|
21757
22271
|
expectedSource: `commands/${commandEntry}.md`
|
|
@@ -21769,7 +22283,7 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21769
22283
|
runtime.config
|
|
21770
22284
|
);
|
|
21771
22285
|
const mcpSource = mcpSourceLabel(runtime.config);
|
|
21772
|
-
if (
|
|
22286
|
+
if (fs23.existsSync(mcpSourcePath)) {
|
|
21773
22287
|
artifacts.push({
|
|
21774
22288
|
component: "cline mcp",
|
|
21775
22289
|
path: clinePaths.mcpFile,
|
|
@@ -21779,12 +22293,57 @@ function resolveKitManagedArtifacts(runtime, scope, selectedTools) {
|
|
|
21779
22293
|
});
|
|
21780
22294
|
}
|
|
21781
22295
|
}
|
|
22296
|
+
if (isFullToolUninstall(manifest, selectedTools)) {
|
|
22297
|
+
for (const pointerName of [".operating-kit-root", ".framework-root"]) {
|
|
22298
|
+
artifacts.push({
|
|
22299
|
+
component: `shared kit pointer ${pointerName}`,
|
|
22300
|
+
path: resolveTargetPath(`~/.agents/${pointerName}`),
|
|
22301
|
+
kind: "kit-pointer",
|
|
22302
|
+
expectedPath: runtime.sourceRoot
|
|
22303
|
+
});
|
|
22304
|
+
}
|
|
22305
|
+
}
|
|
22306
|
+
addRecordedManifestPlans(artifacts, manifest, selectedTools, runtime);
|
|
21782
22307
|
return dedupeArtifacts(artifacts);
|
|
21783
22308
|
}
|
|
22309
|
+
function addRecordedManifestPlans(artifacts, manifest, selectedTools, runtime) {
|
|
22310
|
+
for (const file of manifest.artifacts) {
|
|
22311
|
+
if (file.origin !== "tangyr-managed" || !shouldRemoveManifestFile(file.relativePath, selectedTools)) {
|
|
22312
|
+
continue;
|
|
22313
|
+
}
|
|
22314
|
+
const artifactPath = resolveManifestKeyToPath(
|
|
22315
|
+
file.relativePath,
|
|
22316
|
+
"global",
|
|
22317
|
+
runtime
|
|
22318
|
+
);
|
|
22319
|
+
if (artifactPath) {
|
|
22320
|
+
artifacts.push({
|
|
22321
|
+
component: `${file.relativePath} (manifest)`,
|
|
22322
|
+
path: artifactPath,
|
|
22323
|
+
kind: "recorded"
|
|
22324
|
+
});
|
|
22325
|
+
}
|
|
22326
|
+
}
|
|
22327
|
+
}
|
|
21784
22328
|
function removeKitManagedArtifact(artifact, runtime, logger) {
|
|
21785
22329
|
if (artifact.kind === "compiled") {
|
|
21786
22330
|
return removeManagedCompiledArtifact(artifact, logger);
|
|
21787
22331
|
}
|
|
22332
|
+
if (artifact.kind === "claude-hooks") {
|
|
22333
|
+
return removeManagedClaudeHooksArtifact(artifact, logger);
|
|
22334
|
+
}
|
|
22335
|
+
if (artifact.kind === "claude-mcp") {
|
|
22336
|
+
return removeManagedClaudeMcpArtifact(artifact, logger);
|
|
22337
|
+
}
|
|
22338
|
+
if (artifact.kind === "managed-json") {
|
|
22339
|
+
return removeManagedJsonArtifact(artifact, logger);
|
|
22340
|
+
}
|
|
22341
|
+
if (artifact.kind === "recorded") {
|
|
22342
|
+
return removeRecordedArtifact(artifact, logger);
|
|
22343
|
+
}
|
|
22344
|
+
if (artifact.kind === "kit-pointer" || artifact.kind === "legacy-kit-copy") {
|
|
22345
|
+
return removeExactManagedFile(artifact, logger);
|
|
22346
|
+
}
|
|
21788
22347
|
if (artifact.kind === "copilot-mcp") {
|
|
21789
22348
|
return removeManagedCopilotMcpArtifact(artifact, logger);
|
|
21790
22349
|
}
|
|
@@ -21796,17 +22355,78 @@ function removeKitManagedArtifact(artifact, runtime, logger) {
|
|
|
21796
22355
|
}
|
|
21797
22356
|
return removeManagedDirectArtifact(artifact, runtime, logger);
|
|
21798
22357
|
}
|
|
22358
|
+
function isKitManagedArtifact(artifact, runtime) {
|
|
22359
|
+
if (artifact.kind === "direct") {
|
|
22360
|
+
const artifactClass = classifyArtifact(
|
|
22361
|
+
artifact.path,
|
|
22362
|
+
runtime.config,
|
|
22363
|
+
runtime.sourceRoot
|
|
22364
|
+
);
|
|
22365
|
+
return artifactClass === "managed-symlink" || artifactClass === "managed-stale" || artifactClass === "managed-compiled";
|
|
22366
|
+
}
|
|
22367
|
+
if (artifact.kind === "compiled") {
|
|
22368
|
+
if (!fs23.existsSync(artifact.path)) {
|
|
22369
|
+
return false;
|
|
22370
|
+
}
|
|
22371
|
+
try {
|
|
22372
|
+
const marker = extractProvenanceMarker(
|
|
22373
|
+
fs23.readFileSync(artifact.path, "utf8")
|
|
22374
|
+
);
|
|
22375
|
+
return marker?.target === artifact.expectedTarget && marker?.source === artifact.expectedSource;
|
|
22376
|
+
} catch {
|
|
22377
|
+
return false;
|
|
22378
|
+
}
|
|
22379
|
+
}
|
|
22380
|
+
if (artifact.kind === "recorded") {
|
|
22381
|
+
return fs23.existsSync(artifact.path) || isSymlink(artifact.path);
|
|
22382
|
+
}
|
|
22383
|
+
if (artifact.kind === "kit-pointer") {
|
|
22384
|
+
return isKitPointer(artifact);
|
|
22385
|
+
}
|
|
22386
|
+
if (artifact.kind === "legacy-kit-copy") {
|
|
22387
|
+
return isLegacyOperatingGuideCopy(artifact.path);
|
|
22388
|
+
}
|
|
22389
|
+
if (artifact.kind === "codex-mcp") {
|
|
22390
|
+
if (!fs23.existsSync(artifact.path)) {
|
|
22391
|
+
return false;
|
|
22392
|
+
}
|
|
22393
|
+
const section = readManagedTomlSection(
|
|
22394
|
+
fs23.readFileSync(artifact.path, "utf8")
|
|
22395
|
+
);
|
|
22396
|
+
const marker = section ? extractProvenanceMarker(section) : null;
|
|
22397
|
+
return marker?.target === artifact.expectedTarget && marker?.source === artifact.expectedSource;
|
|
22398
|
+
}
|
|
22399
|
+
const parsed = readJsonObject2(artifact.path);
|
|
22400
|
+
if (!parsed) {
|
|
22401
|
+
return false;
|
|
22402
|
+
}
|
|
22403
|
+
if (artifact.kind === "claude-hooks") {
|
|
22404
|
+
return containsValueByKey(parsed.hooks, "_tangyr", true) || containsValueByKey(parsed.hooks, "_proteus", true) || (artifact.legacyHookCommands ?? []).some(
|
|
22405
|
+
(command) => containsValueByKey(parsed.hooks, "command", command)
|
|
22406
|
+
) || hasLegacyClaudeSharedPermission(parsed);
|
|
22407
|
+
}
|
|
22408
|
+
if (artifact.kind === "claude-mcp") {
|
|
22409
|
+
return hasManagedClaudeMcpServer(parsed);
|
|
22410
|
+
}
|
|
22411
|
+
if (artifact.kind === "managed-json") {
|
|
22412
|
+
return hasManagedRootMetadata(parsed, artifact.expectedTarget);
|
|
22413
|
+
}
|
|
22414
|
+
if (artifact.kind === "copilot-mcp") {
|
|
22415
|
+
return matchesManagedMetadata(metadataRecord(parsed._tangyr), artifact) || matchesManagedMetadata(metadataRecord(parsed._proteus), artifact);
|
|
22416
|
+
}
|
|
22417
|
+
return hasManagedCodexHooks(parsed, artifact.expectedSource);
|
|
22418
|
+
}
|
|
21799
22419
|
function removeManagedCompiledArtifact(artifact, logger) {
|
|
21800
|
-
if (!
|
|
22420
|
+
if (!fs23.existsSync(artifact.path)) {
|
|
21801
22421
|
return false;
|
|
21802
22422
|
}
|
|
21803
22423
|
const marker = extractProvenanceMarker(
|
|
21804
|
-
|
|
22424
|
+
fs23.readFileSync(artifact.path, "utf8")
|
|
21805
22425
|
);
|
|
21806
22426
|
if (marker?.target !== artifact.expectedTarget || marker?.source !== artifact.expectedSource) {
|
|
21807
22427
|
return false;
|
|
21808
22428
|
}
|
|
21809
|
-
|
|
22429
|
+
fs23.rmSync(artifact.path, { force: true });
|
|
21810
22430
|
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
21811
22431
|
return true;
|
|
21812
22432
|
}
|
|
@@ -21823,6 +22443,80 @@ function removeManagedDirectArtifact(artifact, runtime, logger) {
|
|
|
21823
22443
|
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
21824
22444
|
return true;
|
|
21825
22445
|
}
|
|
22446
|
+
function removeManagedClaudeHooksArtifact(artifact, logger) {
|
|
22447
|
+
const parsed = readJsonObject2(artifact.path);
|
|
22448
|
+
if (!parsed) {
|
|
22449
|
+
return false;
|
|
22450
|
+
}
|
|
22451
|
+
const legacyHookCommands = new Set(artifact.legacyHookCommands ?? []);
|
|
22452
|
+
const hooks = removeManagedClaudeHookEntries(parsed.hooks, (entry) => {
|
|
22453
|
+
return entry._tangyr === true || entry._proteus === true || typeof entry.command === "string" && legacyHookCommands.has(entry.command);
|
|
22454
|
+
});
|
|
22455
|
+
const permissions = removeLegacyClaudeSharedPermission(parsed.permissions);
|
|
22456
|
+
const cleaned = { ...parsed };
|
|
22457
|
+
if (hooks === void 0) {
|
|
22458
|
+
delete cleaned.hooks;
|
|
22459
|
+
} else {
|
|
22460
|
+
cleaned.hooks = hooks;
|
|
22461
|
+
}
|
|
22462
|
+
if (permissions === void 0) {
|
|
22463
|
+
delete cleaned.permissions;
|
|
22464
|
+
} else {
|
|
22465
|
+
cleaned.permissions = permissions;
|
|
22466
|
+
}
|
|
22467
|
+
if (JSON.stringify(cleaned) === JSON.stringify(parsed)) {
|
|
22468
|
+
return false;
|
|
22469
|
+
}
|
|
22470
|
+
writeJsonOrRemove(artifact.path, cleaned);
|
|
22471
|
+
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
22472
|
+
return true;
|
|
22473
|
+
}
|
|
22474
|
+
function removeManagedClaudeMcpArtifact(artifact, logger) {
|
|
22475
|
+
const parsed = readJsonObject2(artifact.path);
|
|
22476
|
+
if (!parsed || !isRecord(parsed.mcpServers)) {
|
|
22477
|
+
return false;
|
|
22478
|
+
}
|
|
22479
|
+
const retainedServers = Object.fromEntries(
|
|
22480
|
+
Object.entries(parsed.mcpServers).filter(([, server]) => {
|
|
22481
|
+
if (!isRecord(server)) {
|
|
22482
|
+
return true;
|
|
22483
|
+
}
|
|
22484
|
+
return !isRecord(server._tangyr) && !isRecord(server._proteus);
|
|
22485
|
+
})
|
|
22486
|
+
);
|
|
22487
|
+
if (Object.keys(retainedServers).length === Object.keys(parsed.mcpServers).length) {
|
|
22488
|
+
return false;
|
|
22489
|
+
}
|
|
22490
|
+
const cleaned = { ...parsed, mcpServers: retainedServers };
|
|
22491
|
+
writeJsonOrRemove(artifact.path, cleaned);
|
|
22492
|
+
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
22493
|
+
return true;
|
|
22494
|
+
}
|
|
22495
|
+
function removeManagedJsonArtifact(artifact, logger) {
|
|
22496
|
+
const parsed = readJsonObject2(artifact.path);
|
|
22497
|
+
if (!parsed || !hasManagedRootMetadata(parsed, artifact.expectedTarget)) {
|
|
22498
|
+
return false;
|
|
22499
|
+
}
|
|
22500
|
+
fs23.rmSync(artifact.path, { force: true });
|
|
22501
|
+
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
22502
|
+
return true;
|
|
22503
|
+
}
|
|
22504
|
+
function removeRecordedArtifact(artifact, logger) {
|
|
22505
|
+
if (!fs23.existsSync(artifact.path) && !isSymlink(artifact.path)) {
|
|
22506
|
+
return false;
|
|
22507
|
+
}
|
|
22508
|
+
removeManagedPath(artifact.path);
|
|
22509
|
+
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
22510
|
+
return true;
|
|
22511
|
+
}
|
|
22512
|
+
function removeExactManagedFile(artifact, logger) {
|
|
22513
|
+
if (!fs23.existsSync(artifact.path)) {
|
|
22514
|
+
return false;
|
|
22515
|
+
}
|
|
22516
|
+
fs23.rmSync(artifact.path, { force: true });
|
|
22517
|
+
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
22518
|
+
return true;
|
|
22519
|
+
}
|
|
21826
22520
|
function removeManagedCopilotMcpArtifact(artifact, logger) {
|
|
21827
22521
|
const parsed = readJsonObject2(artifact.path);
|
|
21828
22522
|
if (!parsed) {
|
|
@@ -21853,10 +22547,10 @@ function removeManagedCodexHooksArtifact(artifact, logger) {
|
|
|
21853
22547
|
return true;
|
|
21854
22548
|
}
|
|
21855
22549
|
function removeManagedCodexMcpArtifact(artifact, logger) {
|
|
21856
|
-
if (!
|
|
22550
|
+
if (!fs23.existsSync(artifact.path)) {
|
|
21857
22551
|
return false;
|
|
21858
22552
|
}
|
|
21859
|
-
const content =
|
|
22553
|
+
const content = fs23.readFileSync(artifact.path, "utf8");
|
|
21860
22554
|
const managedSection = readManagedTomlSection(content);
|
|
21861
22555
|
if (!managedSection) {
|
|
21862
22556
|
return false;
|
|
@@ -21871,9 +22565,9 @@ function removeManagedCodexMcpArtifact(artifact, logger) {
|
|
|
21871
22565
|
codexManagedMcpEnd
|
|
21872
22566
|
);
|
|
21873
22567
|
if (cleaned.trim().length === 0) {
|
|
21874
|
-
|
|
22568
|
+
fs23.rmSync(artifact.path, { force: true });
|
|
21875
22569
|
} else {
|
|
21876
|
-
|
|
22570
|
+
fs23.writeFileSync(artifact.path, cleaned);
|
|
21877
22571
|
}
|
|
21878
22572
|
logger.verbose(` removed ${artifact.component}: ${artifact.path}`);
|
|
21879
22573
|
return true;
|
|
@@ -22046,16 +22740,31 @@ function resolveClinePaths(runtime, scope = "global", projectRoot) {
|
|
|
22046
22740
|
function dedupeArtifacts(artifacts) {
|
|
22047
22741
|
const byPath = /* @__PURE__ */ new Map();
|
|
22048
22742
|
for (const artifact of artifacts) {
|
|
22049
|
-
byPath.
|
|
22743
|
+
const current = byPath.get(artifact.path);
|
|
22744
|
+
if (!current || managedArtifactPlanPriority(artifact) > managedArtifactPlanPriority(current)) {
|
|
22745
|
+
byPath.set(artifact.path, artifact);
|
|
22746
|
+
}
|
|
22050
22747
|
}
|
|
22051
22748
|
return Array.from(byPath.values());
|
|
22052
22749
|
}
|
|
22750
|
+
function managedArtifactPlanPriority(artifact) {
|
|
22751
|
+
if (artifact.observed) {
|
|
22752
|
+
return 3;
|
|
22753
|
+
}
|
|
22754
|
+
if (artifact.kind === "compiled") {
|
|
22755
|
+
return 0;
|
|
22756
|
+
}
|
|
22757
|
+
if (artifact.kind === "recorded") {
|
|
22758
|
+
return 1;
|
|
22759
|
+
}
|
|
22760
|
+
return 2;
|
|
22761
|
+
}
|
|
22053
22762
|
function readJsonObject2(filePath) {
|
|
22054
|
-
if (!
|
|
22763
|
+
if (!fs23.existsSync(filePath)) {
|
|
22055
22764
|
return null;
|
|
22056
22765
|
}
|
|
22057
22766
|
try {
|
|
22058
|
-
const parsed = JSON.parse(
|
|
22767
|
+
const parsed = JSON.parse(fs23.readFileSync(filePath, "utf8"));
|
|
22059
22768
|
return isRecord(parsed) ? parsed : null;
|
|
22060
22769
|
} catch {
|
|
22061
22770
|
return null;
|
|
@@ -22064,15 +22773,86 @@ function readJsonObject2(filePath) {
|
|
|
22064
22773
|
function metadataRecord(value) {
|
|
22065
22774
|
return isRecord(value) ? value : void 0;
|
|
22066
22775
|
}
|
|
22776
|
+
function containsValueByKey(value, keyName, keyValue) {
|
|
22777
|
+
if (Array.isArray(value)) {
|
|
22778
|
+
return value.some((entry) => containsValueByKey(entry, keyName, keyValue));
|
|
22779
|
+
}
|
|
22780
|
+
if (!isRecord(value)) {
|
|
22781
|
+
return false;
|
|
22782
|
+
}
|
|
22783
|
+
if (value[keyName] === keyValue) {
|
|
22784
|
+
return true;
|
|
22785
|
+
}
|
|
22786
|
+
return Object.values(value).some(
|
|
22787
|
+
(entry) => containsValueByKey(entry, keyName, keyValue)
|
|
22788
|
+
);
|
|
22789
|
+
}
|
|
22790
|
+
function hasLegacyClaudeSharedPermission(parsed) {
|
|
22791
|
+
if (!isRecord(parsed.permissions) || !Array.isArray(parsed.permissions.allow)) {
|
|
22792
|
+
return false;
|
|
22793
|
+
}
|
|
22794
|
+
return parsed.permissions.allow.includes(legacyClaudeSharedPermission);
|
|
22795
|
+
}
|
|
22796
|
+
function removeLegacyClaudeSharedPermission(value) {
|
|
22797
|
+
if (!isRecord(value) || !Array.isArray(value.allow)) {
|
|
22798
|
+
return value;
|
|
22799
|
+
}
|
|
22800
|
+
const retainedAllow = value.allow.filter(
|
|
22801
|
+
(entry) => entry !== legacyClaudeSharedPermission
|
|
22802
|
+
);
|
|
22803
|
+
if (retainedAllow.length === value.allow.length) {
|
|
22804
|
+
return value;
|
|
22805
|
+
}
|
|
22806
|
+
const cleaned = { ...value };
|
|
22807
|
+
if (retainedAllow.length === 0) {
|
|
22808
|
+
delete cleaned.allow;
|
|
22809
|
+
} else {
|
|
22810
|
+
cleaned.allow = retainedAllow;
|
|
22811
|
+
}
|
|
22812
|
+
return Object.keys(cleaned).length === 0 ? void 0 : cleaned;
|
|
22813
|
+
}
|
|
22814
|
+
function isKitPointer(artifact) {
|
|
22815
|
+
if (!artifact.expectedPath || !fs23.existsSync(artifact.path)) {
|
|
22816
|
+
return false;
|
|
22817
|
+
}
|
|
22818
|
+
try {
|
|
22819
|
+
const recordedPath = fs23.readFileSync(artifact.path, "utf8").trim();
|
|
22820
|
+
return recordedPath.length > 0 && path21.resolve(recordedPath) === path21.resolve(artifact.expectedPath);
|
|
22821
|
+
} catch {
|
|
22822
|
+
return false;
|
|
22823
|
+
}
|
|
22824
|
+
}
|
|
22825
|
+
function isLegacyOperatingGuideCopy(filePath) {
|
|
22826
|
+
if (!fs23.existsSync(filePath)) {
|
|
22827
|
+
return false;
|
|
22828
|
+
}
|
|
22829
|
+
try {
|
|
22830
|
+
return fs23.readFileSync(filePath, "utf8").startsWith(legacyOperatingGuideSignature);
|
|
22831
|
+
} catch {
|
|
22832
|
+
return false;
|
|
22833
|
+
}
|
|
22834
|
+
}
|
|
22835
|
+
function hasManagedClaudeMcpServer(parsed) {
|
|
22836
|
+
if (!isRecord(parsed.mcpServers)) {
|
|
22837
|
+
return false;
|
|
22838
|
+
}
|
|
22839
|
+
return Object.values(parsed.mcpServers).some(
|
|
22840
|
+
(server) => isRecord(server) && (isRecord(server._tangyr) || isRecord(server._proteus))
|
|
22841
|
+
);
|
|
22842
|
+
}
|
|
22843
|
+
function hasManagedRootMetadata(parsed, expectedTarget) {
|
|
22844
|
+
const metadata = [parsed._tangyr, parsed._proteus].map(metadataRecord).find((entry) => entry?.target === expectedTarget);
|
|
22845
|
+
return metadata !== void 0;
|
|
22846
|
+
}
|
|
22067
22847
|
function matchesManagedMetadata(metadata, artifact) {
|
|
22068
22848
|
return metadata?.source === artifact.expectedSource && metadata?.target === artifact.expectedTarget;
|
|
22069
22849
|
}
|
|
22070
22850
|
function writeJsonOrRemove(filePath, parsed) {
|
|
22071
22851
|
if (isEmptyJsonValue(parsed)) {
|
|
22072
|
-
|
|
22852
|
+
fs23.rmSync(filePath, { force: true });
|
|
22073
22853
|
return;
|
|
22074
22854
|
}
|
|
22075
|
-
|
|
22855
|
+
fs23.writeFileSync(filePath, `${JSON.stringify(parsed, null, 2)}
|
|
22076
22856
|
`);
|
|
22077
22857
|
}
|
|
22078
22858
|
function isEmptyJsonValue(value) {
|
|
@@ -22152,6 +22932,31 @@ function removeManagedValueByKey(value, keyName, keyValue) {
|
|
|
22152
22932
|
});
|
|
22153
22933
|
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
22154
22934
|
}
|
|
22935
|
+
function removeManagedClaudeHookEntries(value, isManagedEntry) {
|
|
22936
|
+
if (Array.isArray(value)) {
|
|
22937
|
+
const retained = value.flatMap((entry) => {
|
|
22938
|
+
const cleaned2 = removeManagedClaudeHookEntries(entry, isManagedEntry);
|
|
22939
|
+
return cleaned2 === void 0 ? [] : [cleaned2];
|
|
22940
|
+
});
|
|
22941
|
+
return retained.length > 0 ? retained : void 0;
|
|
22942
|
+
}
|
|
22943
|
+
if (!isRecord(value)) {
|
|
22944
|
+
return value;
|
|
22945
|
+
}
|
|
22946
|
+
if (isManagedEntry(value)) {
|
|
22947
|
+
return void 0;
|
|
22948
|
+
}
|
|
22949
|
+
const hadHookChildren = Object.hasOwn(value, "hooks");
|
|
22950
|
+
const entries = Object.entries(value).flatMap(([key, entry]) => {
|
|
22951
|
+
const cleaned2 = removeManagedClaudeHookEntries(entry, isManagedEntry);
|
|
22952
|
+
return cleaned2 === void 0 ? [] : [[key, cleaned2]];
|
|
22953
|
+
});
|
|
22954
|
+
const cleaned = entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
22955
|
+
if (hadHookChildren && (!cleaned || !("hooks" in cleaned))) {
|
|
22956
|
+
return void 0;
|
|
22957
|
+
}
|
|
22958
|
+
return cleaned;
|
|
22959
|
+
}
|
|
22155
22960
|
function readManagedTomlSection(content) {
|
|
22156
22961
|
const start = content.indexOf(codexManagedMcpStart);
|
|
22157
22962
|
const end = content.indexOf(codexManagedMcpEnd);
|
|
@@ -22173,20 +22978,20 @@ function removeDelimitedManagedSection(content, startMarker, endMarker) {
|
|
|
22173
22978
|
return `${content.slice(0, start)}${content.slice(removalEnd)}`;
|
|
22174
22979
|
}
|
|
22175
22980
|
function restoreBackup(backup, logger) {
|
|
22176
|
-
if (!
|
|
22981
|
+
if (!fs23.existsSync(backup.backupLocation)) {
|
|
22177
22982
|
logger.warn(` backup not found: ${backup.backupLocation}`);
|
|
22178
22983
|
return;
|
|
22179
22984
|
}
|
|
22180
|
-
const destDir =
|
|
22181
|
-
|
|
22182
|
-
|
|
22985
|
+
const destDir = path21.dirname(backup.originalPath);
|
|
22986
|
+
fs23.mkdirSync(destDir, { recursive: true });
|
|
22987
|
+
fs23.renameSync(backup.backupLocation, backup.originalPath);
|
|
22183
22988
|
logger.verbose(
|
|
22184
22989
|
` restored: ${backup.backupLocation} \u2192 ${backup.originalPath}`
|
|
22185
22990
|
);
|
|
22186
22991
|
}
|
|
22187
22992
|
function isSymlink(p) {
|
|
22188
22993
|
try {
|
|
22189
|
-
return
|
|
22994
|
+
return fs23.lstatSync(p).isSymbolicLink();
|
|
22190
22995
|
} catch {
|
|
22191
22996
|
return false;
|
|
22192
22997
|
}
|
|
@@ -22260,7 +23065,7 @@ function cleanupClaudeCode(config, sourceRoot, configDir, logger, scope) {
|
|
|
22260
23065
|
)) {
|
|
22261
23066
|
const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
|
|
22262
23067
|
if (artifactClass === "managed-symlink" || artifactClass === "managed-compiled" || artifactClass === "managed-stale") {
|
|
22263
|
-
|
|
23068
|
+
fs24.rmSync(artifact.path, { recursive: true, force: true });
|
|
22264
23069
|
logger.info(`${artifact.component}: removed ${artifact.path}`);
|
|
22265
23070
|
}
|
|
22266
23071
|
}
|
|
@@ -22316,7 +23121,7 @@ function cleanupCopilot(config, sourceRoot, configDir, logger) {
|
|
|
22316
23121
|
logger
|
|
22317
23122
|
);
|
|
22318
23123
|
removeManagedJsonFile(
|
|
22319
|
-
|
|
23124
|
+
path22.join(resolveTargetPath(paths.hooks ?? ""), "tangyr-managed.json"),
|
|
22320
23125
|
"_tangyr",
|
|
22321
23126
|
logger
|
|
22322
23127
|
);
|
|
@@ -22473,40 +23278,40 @@ function removeManagedValueByKey2(value, keyName, keyValue) {
|
|
|
22473
23278
|
function removeManagedDirectPath(artifactPath, config, sourceRoot, component, logger) {
|
|
22474
23279
|
const artifactClass = classifyArtifact(artifactPath, config, sourceRoot);
|
|
22475
23280
|
if (artifactClass === "managed-symlink" || artifactClass === "managed-compiled" || artifactClass === "managed-stale") {
|
|
22476
|
-
|
|
23281
|
+
fs24.rmSync(artifactPath, { recursive: true, force: true });
|
|
22477
23282
|
logger.info(`${component}: removed ${artifactPath}`);
|
|
22478
23283
|
}
|
|
22479
23284
|
}
|
|
22480
23285
|
function removeManagedCompiledFiles(dir, pattern, expectedTarget, logger) {
|
|
22481
|
-
for (const filePath of ts(
|
|
23286
|
+
for (const filePath of ts(path22.join(dir, pattern)).sort()) {
|
|
22482
23287
|
removeManagedCompiledFile(filePath, expectedTarget, logger);
|
|
22483
23288
|
}
|
|
22484
23289
|
}
|
|
22485
23290
|
function removeManagedCompiledFile(filePath, expectedTarget, logger) {
|
|
22486
|
-
if (!
|
|
23291
|
+
if (!fs24.existsSync(filePath)) {
|
|
22487
23292
|
return;
|
|
22488
23293
|
}
|
|
22489
|
-
const marker = extractProvenanceMarker(
|
|
23294
|
+
const marker = extractProvenanceMarker(fs24.readFileSync(filePath, "utf8"));
|
|
22490
23295
|
if (marker?.target === expectedTarget) {
|
|
22491
|
-
|
|
23296
|
+
fs24.rmSync(filePath, { force: true });
|
|
22492
23297
|
logger.info(`removed ${filePath}`);
|
|
22493
23298
|
}
|
|
22494
23299
|
}
|
|
22495
23300
|
function removeManagedJsonFile(filePath, markerKey, logger) {
|
|
22496
|
-
if (!
|
|
23301
|
+
if (!fs24.existsSync(filePath)) {
|
|
22497
23302
|
return;
|
|
22498
23303
|
}
|
|
22499
23304
|
const parsed = readJsonObject(filePath);
|
|
22500
23305
|
if (isRecord(parsed[markerKey])) {
|
|
22501
|
-
|
|
23306
|
+
fs24.rmSync(filePath, { force: true });
|
|
22502
23307
|
logger.info(`removed ${filePath}`);
|
|
22503
23308
|
}
|
|
22504
23309
|
}
|
|
22505
23310
|
function removeCodexManagedTomlSection(filePath, logger) {
|
|
22506
|
-
if (!
|
|
23311
|
+
if (!fs24.existsSync(filePath)) {
|
|
22507
23312
|
return;
|
|
22508
23313
|
}
|
|
22509
|
-
const content =
|
|
23314
|
+
const content = fs24.readFileSync(filePath, "utf8");
|
|
22510
23315
|
const next = removeDelimitedManagedSection2(
|
|
22511
23316
|
content,
|
|
22512
23317
|
codexManagedMcpStart2,
|
|
@@ -22515,7 +23320,7 @@ function removeCodexManagedTomlSection(filePath, logger) {
|
|
|
22515
23320
|
if (next === content) {
|
|
22516
23321
|
return;
|
|
22517
23322
|
}
|
|
22518
|
-
|
|
23323
|
+
fs24.writeFileSync(filePath, next);
|
|
22519
23324
|
logger.info(`mcp: removed managed section from ${filePath}`);
|
|
22520
23325
|
}
|
|
22521
23326
|
function removeDelimitedManagedSection2(content, startMarker, endMarker) {
|
|
@@ -22587,9 +23392,9 @@ function toVerbosity(value) {
|
|
|
22587
23392
|
}
|
|
22588
23393
|
|
|
22589
23394
|
// src/commands/detect.ts
|
|
22590
|
-
import
|
|
23395
|
+
import fs25 from "fs";
|
|
22591
23396
|
import os5 from "os";
|
|
22592
|
-
import
|
|
23397
|
+
import path23 from "path";
|
|
22593
23398
|
import { spawnSync } from "child_process";
|
|
22594
23399
|
var copilotEditorCommands = [
|
|
22595
23400
|
"code",
|
|
@@ -22623,18 +23428,27 @@ var bundledCopilotManifestPathsByPlatform = {
|
|
|
22623
23428
|
"/Applications/Windsurf.app/Contents/Resources/app/extensions/copilot/package.json"
|
|
22624
23429
|
]
|
|
22625
23430
|
};
|
|
22626
|
-
|
|
23431
|
+
var bundledCursorExecutablePathsByPlatform = {
|
|
23432
|
+
darwin: ["/Applications/Cursor.app/Contents/Resources/app/bin/cursor"]
|
|
23433
|
+
};
|
|
23434
|
+
function detectTargets(logger, dependencies = {}) {
|
|
23435
|
+
const spawnSyncImpl = dependencies.spawnSyncImpl ?? defaultSpawnSync;
|
|
23436
|
+
const pathExists = dependencies.pathExists ?? fs25.existsSync;
|
|
23437
|
+
const homeDirectory = dependencies.homeDirectory ?? os5.homedir();
|
|
23438
|
+
const platform = dependencies.platform ?? process.platform;
|
|
23439
|
+
const locator = platform === "win32" ? "where.exe" : "which";
|
|
23440
|
+
const hasCommand = (command) => commandExists(locator, [command], logger, spawnSyncImpl);
|
|
22627
23441
|
const result = {
|
|
22628
|
-
"claude-code":
|
|
22629
|
-
|
|
22630
|
-
|
|
22631
|
-
|
|
22632
|
-
),
|
|
22633
|
-
|
|
22634
|
-
|
|
22635
|
-
|
|
22636
|
-
|
|
22637
|
-
|
|
23442
|
+
"claude-code": hasCommand("claude"),
|
|
23443
|
+
copilot: detectsCopilot(logger, dependencies),
|
|
23444
|
+
codex: hasCommand("codex"),
|
|
23445
|
+
opencode: hasCommand("opencode"),
|
|
23446
|
+
cursor: hasCommand("cursor") || cursorExecutablePaths(platform, homeDirectory).some(pathExists),
|
|
23447
|
+
cline: hasCommand("cline") || detectEditorExtension(
|
|
23448
|
+
"Cline",
|
|
23449
|
+
isClineExtensionEntry,
|
|
23450
|
+
logger,
|
|
23451
|
+
dependencies
|
|
22638
23452
|
)
|
|
22639
23453
|
};
|
|
22640
23454
|
return result;
|
|
@@ -22650,14 +23464,41 @@ function runDetectCommand(options, logger) {
|
|
|
22650
23464
|
}
|
|
22651
23465
|
process.exitCode = Object.values(result).some(Boolean) ? 0 : 3;
|
|
22652
23466
|
}
|
|
22653
|
-
function detectsCopilot(logger) {
|
|
22654
|
-
return detectCopilot(logger);
|
|
23467
|
+
function detectsCopilot(logger, dependencies = {}) {
|
|
23468
|
+
return detectCopilot(logger, dependencies);
|
|
22655
23469
|
}
|
|
22656
23470
|
function detectCopilot(logger, dependencies = {}) {
|
|
23471
|
+
const pathExists = dependencies.pathExists ?? fs25.existsSync;
|
|
23472
|
+
const readFile = dependencies.readFile ?? ((filePath) => fs25.readFileSync(filePath, "utf8"));
|
|
23473
|
+
const platform = dependencies.platform ?? process.platform;
|
|
23474
|
+
if (detectEditorExtension(
|
|
23475
|
+
"Copilot",
|
|
23476
|
+
isCopilotExtensionEntry,
|
|
23477
|
+
logger,
|
|
23478
|
+
dependencies
|
|
23479
|
+
)) {
|
|
23480
|
+
return true;
|
|
23481
|
+
}
|
|
23482
|
+
for (const manifestPath of bundledCopilotManifestPathsByPlatform[platform] ?? []) {
|
|
23483
|
+
if (!pathExists(manifestPath)) {
|
|
23484
|
+
continue;
|
|
23485
|
+
}
|
|
23486
|
+
try {
|
|
23487
|
+
if (isBundledCopilotManifest(readFile(manifestPath))) {
|
|
23488
|
+
return true;
|
|
23489
|
+
}
|
|
23490
|
+
} catch (error) {
|
|
23491
|
+
logger?.verbose(
|
|
23492
|
+
`${manifestPath}: failed to inspect bundled Copilot runtime (${formatReadError(error)})`
|
|
23493
|
+
);
|
|
23494
|
+
}
|
|
23495
|
+
}
|
|
23496
|
+
return false;
|
|
23497
|
+
}
|
|
23498
|
+
function detectEditorExtension(label, matchesExtension, logger, dependencies = {}) {
|
|
22657
23499
|
const spawnSyncImpl = dependencies.spawnSyncImpl ?? defaultSpawnSync;
|
|
22658
|
-
const pathExists = dependencies.pathExists ??
|
|
22659
|
-
const readDirectory = dependencies.readDirectory ??
|
|
22660
|
-
const readFile = dependencies.readFile ?? ((filePath) => fs24.readFileSync(filePath, "utf8"));
|
|
23500
|
+
const pathExists = dependencies.pathExists ?? fs25.existsSync;
|
|
23501
|
+
const readDirectory = dependencies.readDirectory ?? fs25.readdirSync;
|
|
22661
23502
|
const homeDirectory = dependencies.homeDirectory ?? os5.homedir();
|
|
22662
23503
|
const platform = dependencies.platform ?? process.platform;
|
|
22663
23504
|
const commandCandidates = [
|
|
@@ -22680,41 +23521,40 @@ function detectCopilot(logger, dependencies = {}) {
|
|
|
22680
23521
|
if (result.status !== 0) {
|
|
22681
23522
|
continue;
|
|
22682
23523
|
}
|
|
22683
|
-
if (splitOutputEntries(result.stdout).some(
|
|
23524
|
+
if (splitOutputEntries(result.stdout).some(matchesExtension)) {
|
|
22684
23525
|
return true;
|
|
22685
23526
|
}
|
|
22686
23527
|
}
|
|
22687
23528
|
for (const relativeDirectory of copilotExtensionDirectories) {
|
|
22688
|
-
const extensionDirectory =
|
|
23529
|
+
const extensionDirectory = path23.join(homeDirectory, relativeDirectory);
|
|
22689
23530
|
if (!pathExists(extensionDirectory)) {
|
|
22690
23531
|
continue;
|
|
22691
23532
|
}
|
|
22692
23533
|
try {
|
|
22693
|
-
if (readDirectory(extensionDirectory).some(
|
|
22694
|
-
return true;
|
|
22695
|
-
}
|
|
22696
|
-
} catch (error) {
|
|
22697
|
-
logger?.verbose(
|
|
22698
|
-
`${extensionDirectory}: failed to inspect Copilot extensions (${formatReadError(error)})`
|
|
22699
|
-
);
|
|
22700
|
-
}
|
|
22701
|
-
}
|
|
22702
|
-
for (const manifestPath of bundledCopilotManifestPathsByPlatform[platform] ?? []) {
|
|
22703
|
-
if (!pathExists(manifestPath)) {
|
|
22704
|
-
continue;
|
|
22705
|
-
}
|
|
22706
|
-
try {
|
|
22707
|
-
if (isBundledCopilotManifest(readFile(manifestPath))) {
|
|
23534
|
+
if (readDirectory(extensionDirectory).some(matchesExtension)) {
|
|
22708
23535
|
return true;
|
|
22709
23536
|
}
|
|
22710
23537
|
} catch (error) {
|
|
22711
23538
|
logger?.verbose(
|
|
22712
|
-
`${
|
|
23539
|
+
`${extensionDirectory}: failed to inspect ${label} extensions (${formatReadError(error)})`
|
|
22713
23540
|
);
|
|
22714
23541
|
}
|
|
22715
23542
|
}
|
|
22716
23543
|
return false;
|
|
22717
23544
|
}
|
|
23545
|
+
function cursorExecutablePaths(platform, homeDirectory) {
|
|
23546
|
+
const systemPaths = bundledCursorExecutablePathsByPlatform[platform] ?? [];
|
|
23547
|
+
if (platform !== "darwin") {
|
|
23548
|
+
return [...systemPaths];
|
|
23549
|
+
}
|
|
23550
|
+
return [
|
|
23551
|
+
...systemPaths,
|
|
23552
|
+
path23.join(
|
|
23553
|
+
homeDirectory,
|
|
23554
|
+
"Applications/Cursor.app/Contents/Resources/app/bin/cursor"
|
|
23555
|
+
)
|
|
23556
|
+
];
|
|
23557
|
+
}
|
|
22718
23558
|
function defaultSpawnSync(command, args) {
|
|
22719
23559
|
return spawnSync(command, args, { encoding: "utf8" });
|
|
22720
23560
|
}
|
|
@@ -22727,6 +23567,9 @@ function splitOutputEntries(stdout) {
|
|
|
22727
23567
|
function isCopilotExtensionEntry(entry) {
|
|
22728
23568
|
return /^github\.copilot(?:-chat)?(?:@|-)/u.test(entry);
|
|
22729
23569
|
}
|
|
23570
|
+
function isClineExtensionEntry(entry) {
|
|
23571
|
+
return /^saoudrizwan\.claude-dev(?:@|-)/u.test(entry);
|
|
23572
|
+
}
|
|
22730
23573
|
function isBundledCopilotManifest(rawManifest) {
|
|
22731
23574
|
const parsed = JSON.parse(rawManifest);
|
|
22732
23575
|
if (!isRecord2(parsed)) {
|
|
@@ -22745,8 +23588,8 @@ function formatReadError(error) {
|
|
|
22745
23588
|
}
|
|
22746
23589
|
return String(error);
|
|
22747
23590
|
}
|
|
22748
|
-
function commandExists(command, args, logger) {
|
|
22749
|
-
const result =
|
|
23591
|
+
function commandExists(command, args, logger, spawnSyncImpl = defaultSpawnSync) {
|
|
23592
|
+
const result = spawnSyncImpl(command, args);
|
|
22750
23593
|
if (result.error) {
|
|
22751
23594
|
logDetectionError(`${command} ${args.join(" ")}`, result.error, logger);
|
|
22752
23595
|
return false;
|
|
@@ -22766,25 +23609,25 @@ function logDetectionError(attemptedCommand, error, logger) {
|
|
|
22766
23609
|
}
|
|
22767
23610
|
|
|
22768
23611
|
// src/commands/doctor.ts
|
|
22769
|
-
import
|
|
22770
|
-
import
|
|
23612
|
+
import fs27 from "fs";
|
|
23613
|
+
import path25 from "path";
|
|
22771
23614
|
|
|
22772
23615
|
// src/utils/fs.ts
|
|
22773
|
-
import
|
|
22774
|
-
import
|
|
23616
|
+
import fs26 from "fs";
|
|
23617
|
+
import path24 from "path";
|
|
22775
23618
|
function ensureDir(dirPath) {
|
|
22776
|
-
|
|
23619
|
+
fs26.mkdirSync(dirPath, { recursive: true });
|
|
22777
23620
|
}
|
|
22778
23621
|
function createRelativeSymlink(source, destination, type, options) {
|
|
22779
|
-
const absoluteSource =
|
|
22780
|
-
const relative =
|
|
23622
|
+
const absoluteSource = path24.resolve(source);
|
|
23623
|
+
const relative = path24.relative(realPathOrInput(path24.dirname(destination)), absoluteSource);
|
|
22781
23624
|
if (process.platform === "win32" && type === "dir") {
|
|
22782
|
-
|
|
23625
|
+
fs26.symlinkSync(absoluteSource, destination, "junction");
|
|
22783
23626
|
return;
|
|
22784
23627
|
}
|
|
22785
23628
|
if (process.platform === "win32" && type === "file") {
|
|
22786
23629
|
try {
|
|
22787
|
-
|
|
23630
|
+
fs26.symlinkSync(relative, destination, "file");
|
|
22788
23631
|
} catch (error) {
|
|
22789
23632
|
if (!hasErrorCode(error, "EPERM")) {
|
|
22790
23633
|
throw error;
|
|
@@ -22799,12 +23642,12 @@ function createRelativeSymlink(source, destination, type, options) {
|
|
|
22799
23642
|
}
|
|
22800
23643
|
return;
|
|
22801
23644
|
}
|
|
22802
|
-
|
|
23645
|
+
fs26.symlinkSync(relative, destination, type);
|
|
22803
23646
|
}
|
|
22804
23647
|
function createManagedCopy(source, destination, provenanceMarker, _logger) {
|
|
22805
|
-
ensureDir(
|
|
22806
|
-
const content =
|
|
22807
|
-
|
|
23648
|
+
ensureDir(path24.dirname(destination));
|
|
23649
|
+
const content = fs26.readFileSync(source, "utf8");
|
|
23650
|
+
fs26.writeFileSync(destination, `${provenanceMarker}
|
|
22808
23651
|
${content}`);
|
|
22809
23652
|
}
|
|
22810
23653
|
function hasErrorCode(error, expectedCode) {
|
|
@@ -22812,7 +23655,7 @@ function hasErrorCode(error, expectedCode) {
|
|
|
22812
23655
|
}
|
|
22813
23656
|
function realPathOrInput(filePath) {
|
|
22814
23657
|
try {
|
|
22815
|
-
return
|
|
23658
|
+
return fs26.realpathSync(filePath);
|
|
22816
23659
|
} catch {
|
|
22817
23660
|
return filePath;
|
|
22818
23661
|
}
|
|
@@ -22825,17 +23668,17 @@ function runDoctorCommand(options, logger) {
|
|
|
22825
23668
|
import.meta.url
|
|
22826
23669
|
);
|
|
22827
23670
|
const findings = [];
|
|
22828
|
-
if (!
|
|
23671
|
+
if (!fs27.existsSync(configPath)) {
|
|
22829
23672
|
findings.push(`${configPath}: missing`);
|
|
22830
23673
|
}
|
|
22831
|
-
const hooksJsonPath =
|
|
23674
|
+
const hooksJsonPath = path25.join(
|
|
22832
23675
|
sourceRoot,
|
|
22833
23676
|
config.source.hooks,
|
|
22834
23677
|
"hooks.json"
|
|
22835
23678
|
);
|
|
22836
|
-
if (
|
|
23679
|
+
if (fs27.existsSync(hooksJsonPath)) {
|
|
22837
23680
|
try {
|
|
22838
|
-
JSON.parse(
|
|
23681
|
+
JSON.parse(fs27.readFileSync(hooksJsonPath, "utf8"));
|
|
22839
23682
|
} catch (err) {
|
|
22840
23683
|
findings.push(
|
|
22841
23684
|
`hooks/hooks.json: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -22900,19 +23743,19 @@ function checkClaudeCode(options, findings, config, sourceRoot, configDir, logge
|
|
|
22900
23743
|
projectRoot
|
|
22901
23744
|
)) {
|
|
22902
23745
|
const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
|
|
22903
|
-
const sourcePath = artifact.sourceKey ?
|
|
23746
|
+
const sourcePath = artifact.sourceKey ? path25.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
|
|
22904
23747
|
if (artifactClass === "managed-stale") {
|
|
22905
23748
|
findings.push(
|
|
22906
23749
|
`${artifact.component}: managed stale artifact at ${artifact.path}`
|
|
22907
23750
|
);
|
|
22908
23751
|
if (options.fix && sourcePath && isOurStaleSymlink(
|
|
22909
23752
|
artifact.path,
|
|
22910
|
-
/* @__PURE__ */ new Set([
|
|
23753
|
+
/* @__PURE__ */ new Set([path25.resolve(artifact.path)]),
|
|
22911
23754
|
config
|
|
22912
23755
|
)) {
|
|
22913
|
-
|
|
22914
|
-
ensureDir(
|
|
22915
|
-
const symlinkType =
|
|
23756
|
+
fs27.unlinkSync(artifact.path);
|
|
23757
|
+
ensureDir(path25.dirname(artifact.path));
|
|
23758
|
+
const symlinkType = fs27.statSync(sourcePath).isDirectory() ? "dir" : "file";
|
|
22916
23759
|
createRelativeSymlink(sourcePath, artifact.path, symlinkType, {
|
|
22917
23760
|
logger,
|
|
22918
23761
|
provenanceMarker: symlinkType === "file" && artifact.sourceKey ? formatProvenanceMarker(
|
|
@@ -22925,8 +23768,8 @@ function checkClaudeCode(options, findings, config, sourceRoot, configDir, logge
|
|
|
22925
23768
|
logger.info(`${artifact.component}: recreated managed symlink`);
|
|
22926
23769
|
}
|
|
22927
23770
|
}
|
|
22928
|
-
if (options.fix && !
|
|
22929
|
-
ensureDir(
|
|
23771
|
+
if (options.fix && !fs27.existsSync(path25.dirname(artifact.path))) {
|
|
23772
|
+
ensureDir(path25.dirname(artifact.path));
|
|
22930
23773
|
}
|
|
22931
23774
|
checkParentWritablePath(artifact.path, artifact.component, findings);
|
|
22932
23775
|
}
|
|
@@ -22941,7 +23784,7 @@ function checkCopilot(config, sourceRoot, configDir, findings) {
|
|
|
22941
23784
|
continue;
|
|
22942
23785
|
}
|
|
22943
23786
|
const label = `copilot: ${rawPath}`;
|
|
22944
|
-
if (key.endsWith("_shared_file") ||
|
|
23787
|
+
if (key.endsWith("_shared_file") || path25.extname(rawPath).length > 0) {
|
|
22945
23788
|
checkParentWritablePath(resolveTargetPath(rawPath), label, findings);
|
|
22946
23789
|
continue;
|
|
22947
23790
|
}
|
|
@@ -22961,7 +23804,7 @@ function checkCodex(config, sourceRoot, configDir, findings, logger) {
|
|
|
22961
23804
|
continue;
|
|
22962
23805
|
}
|
|
22963
23806
|
const label = `codex: ${rawPath}`;
|
|
22964
|
-
if (key.endsWith("_shared_file") ||
|
|
23807
|
+
if (key.endsWith("_shared_file") || path25.extname(rawPath).length > 0) {
|
|
22965
23808
|
checkParentWritablePath(resolveTargetPath(rawPath), label, findings);
|
|
22966
23809
|
continue;
|
|
22967
23810
|
}
|
|
@@ -22978,33 +23821,33 @@ function resolveHooksScriptPath(config, sourceRoot, configDir) {
|
|
|
22978
23821
|
scope: "global",
|
|
22979
23822
|
mappings: mappings.platformPaths
|
|
22980
23823
|
});
|
|
22981
|
-
return
|
|
23824
|
+
return path25.join(profile["claude-code"].hooks, "scripts");
|
|
22982
23825
|
} catch {
|
|
22983
23826
|
return resolveTargetPath("~/.agents/hooks/scripts");
|
|
22984
23827
|
}
|
|
22985
23828
|
}
|
|
22986
23829
|
function checkParentWritablePath(targetPath, label, findings) {
|
|
22987
|
-
checkWritablePath(
|
|
23830
|
+
checkWritablePath(path25.dirname(targetPath), `${label} parent`, findings);
|
|
22988
23831
|
}
|
|
22989
23832
|
function checkWritablePath(checkPath, label, findings) {
|
|
22990
|
-
if (!
|
|
23833
|
+
if (!fs27.existsSync(checkPath)) {
|
|
22991
23834
|
findings.push(`${label}: path does not exist`);
|
|
22992
23835
|
return;
|
|
22993
23836
|
}
|
|
22994
23837
|
try {
|
|
22995
|
-
|
|
23838
|
+
fs27.accessSync(checkPath, fs27.constants.R_OK | fs27.constants.W_OK);
|
|
22996
23839
|
} catch {
|
|
22997
23840
|
findings.push(`${label}: path is not readable and writable`);
|
|
22998
23841
|
}
|
|
22999
23842
|
}
|
|
23000
23843
|
function walkHookScripts(dir) {
|
|
23001
|
-
if (!
|
|
23844
|
+
if (!fs27.existsSync(dir)) {
|
|
23002
23845
|
return [];
|
|
23003
23846
|
}
|
|
23004
|
-
return
|
|
23847
|
+
return fs27.readdirSync(dir).map((entry) => path25.join(dir, entry)).filter((entryPath) => fs27.statSync(entryPath).isFile());
|
|
23005
23848
|
}
|
|
23006
23849
|
function fixManagedHookScriptModes(scriptRoot, sourceRoot, logger) {
|
|
23007
|
-
if (!
|
|
23850
|
+
if (!fs27.existsSync(scriptRoot)) {
|
|
23008
23851
|
return;
|
|
23009
23852
|
}
|
|
23010
23853
|
if (hasSymlinkAncestor(scriptRoot, resolveTargetPath("~/.agents")) || isInside(realPathOrInput2(scriptRoot), realPathOrInput2(sourceRoot))) {
|
|
@@ -23014,49 +23857,49 @@ function fixManagedHookScriptModes(scriptRoot, sourceRoot, logger) {
|
|
|
23014
23857
|
return;
|
|
23015
23858
|
}
|
|
23016
23859
|
for (const scriptPath of walkHookScripts(scriptRoot)) {
|
|
23017
|
-
|
|
23860
|
+
fs27.chmodSync(scriptPath, 493);
|
|
23018
23861
|
}
|
|
23019
23862
|
}
|
|
23020
23863
|
function hasSymlinkAncestor(targetPath, stopAt) {
|
|
23021
|
-
const relative =
|
|
23022
|
-
|
|
23023
|
-
|
|
23864
|
+
const relative = path25.relative(
|
|
23865
|
+
path25.resolve(stopAt),
|
|
23866
|
+
path25.resolve(targetPath)
|
|
23024
23867
|
);
|
|
23025
|
-
if (relative.startsWith("..") ||
|
|
23868
|
+
if (relative.startsWith("..") || path25.isAbsolute(relative)) {
|
|
23026
23869
|
return false;
|
|
23027
23870
|
}
|
|
23028
|
-
return relative.split(
|
|
23029
|
-
const candidate =
|
|
23030
|
-
|
|
23871
|
+
return relative.split(path25.sep).some((_segment, index, segments) => {
|
|
23872
|
+
const candidate = path25.join(
|
|
23873
|
+
path25.resolve(stopAt),
|
|
23031
23874
|
...segments.slice(0, index + 1)
|
|
23032
23875
|
);
|
|
23033
23876
|
try {
|
|
23034
|
-
return
|
|
23877
|
+
return fs27.lstatSync(candidate).isSymbolicLink();
|
|
23035
23878
|
} catch {
|
|
23036
23879
|
return false;
|
|
23037
23880
|
}
|
|
23038
23881
|
});
|
|
23039
23882
|
}
|
|
23040
23883
|
function isInside(childPath, parentPath) {
|
|
23041
|
-
const relative =
|
|
23042
|
-
return relative.length === 0 || !relative.startsWith("..") && !
|
|
23884
|
+
const relative = path25.relative(parentPath, childPath);
|
|
23885
|
+
return relative.length === 0 || !relative.startsWith("..") && !path25.isAbsolute(relative);
|
|
23043
23886
|
}
|
|
23044
23887
|
function realPathOrInput2(filePath) {
|
|
23045
23888
|
try {
|
|
23046
|
-
return
|
|
23889
|
+
return fs27.realpathSync(filePath);
|
|
23047
23890
|
} catch {
|
|
23048
23891
|
return filePath;
|
|
23049
23892
|
}
|
|
23050
23893
|
}
|
|
23051
23894
|
|
|
23052
23895
|
// src/commands/init.ts
|
|
23053
|
-
import
|
|
23054
|
-
import
|
|
23055
|
-
var
|
|
23896
|
+
import fs28 from "fs";
|
|
23897
|
+
import path26 from "path";
|
|
23898
|
+
var import_yaml7 = __toESM(require_dist(), 1);
|
|
23056
23899
|
async function runInitCommand(_options, logger) {
|
|
23057
23900
|
const sourceRoot = await dist_default6({
|
|
23058
23901
|
message: "Canonical Tangyr kit root",
|
|
23059
|
-
default:
|
|
23902
|
+
default: path26.resolve("projects/tangyr/agent-coding")
|
|
23060
23903
|
});
|
|
23061
23904
|
const componentCount = [
|
|
23062
23905
|
"CLAUDE.md",
|
|
@@ -23066,7 +23909,7 @@ async function runInitCommand(_options, logger) {
|
|
|
23066
23909
|
"rules",
|
|
23067
23910
|
"hooks"
|
|
23068
23911
|
].filter(
|
|
23069
|
-
(relativePath) =>
|
|
23912
|
+
(relativePath) => fs28.existsSync(path26.join(sourceRoot, relativePath))
|
|
23070
23913
|
).length;
|
|
23071
23914
|
const detectedTargets = detectTargets(logger);
|
|
23072
23915
|
const enabledTargets = await dist_default4({
|
|
@@ -23084,8 +23927,8 @@ async function runInitCommand(_options, logger) {
|
|
|
23084
23927
|
value
|
|
23085
23928
|
}))
|
|
23086
23929
|
});
|
|
23087
|
-
const configPath =
|
|
23088
|
-
if (
|
|
23930
|
+
const configPath = path26.join(sourceRoot, "tangyr.config.yaml");
|
|
23931
|
+
if (fs28.existsSync(configPath)) {
|
|
23089
23932
|
const overwrite = await dist_default5({
|
|
23090
23933
|
message: `${configPath} exists. Overwrite?`,
|
|
23091
23934
|
default: false
|
|
@@ -23095,9 +23938,9 @@ async function runInitCommand(_options, logger) {
|
|
|
23095
23938
|
return;
|
|
23096
23939
|
}
|
|
23097
23940
|
}
|
|
23098
|
-
|
|
23941
|
+
fs28.writeFileSync(
|
|
23099
23942
|
configPath,
|
|
23100
|
-
(0,
|
|
23943
|
+
(0, import_yaml7.stringify)({
|
|
23101
23944
|
schema: 1,
|
|
23102
23945
|
kitPath: ".",
|
|
23103
23946
|
source: {
|
|
@@ -23138,15 +23981,15 @@ function toConflictPolicy2(value) {
|
|
|
23138
23981
|
}
|
|
23139
23982
|
|
|
23140
23983
|
// src/commands/install.ts
|
|
23141
|
-
import
|
|
23142
|
-
import
|
|
23984
|
+
import fs37 from "fs";
|
|
23985
|
+
import path37 from "path";
|
|
23143
23986
|
|
|
23144
23987
|
// src/core/channel-state.ts
|
|
23145
|
-
import
|
|
23146
|
-
import
|
|
23988
|
+
import fs29 from "fs";
|
|
23989
|
+
import path27 from "path";
|
|
23147
23990
|
var CHANNEL_STATE_FILENAME = ".tangyr-channels.json";
|
|
23148
23991
|
function stateFilePath(cacheRoot) {
|
|
23149
|
-
return
|
|
23992
|
+
return path27.join(cacheRoot, CHANNEL_STATE_FILENAME);
|
|
23150
23993
|
}
|
|
23151
23994
|
function channelKey(kit, channel) {
|
|
23152
23995
|
return `${kit}/${channel}`;
|
|
@@ -23155,7 +23998,7 @@ function readState(cacheRoot) {
|
|
|
23155
23998
|
const filePath = stateFilePath(cacheRoot);
|
|
23156
23999
|
let raw;
|
|
23157
24000
|
try {
|
|
23158
|
-
raw =
|
|
24001
|
+
raw = fs29.readFileSync(filePath, "utf8");
|
|
23159
24002
|
} catch (err) {
|
|
23160
24003
|
if (err.code === "ENOENT") {
|
|
23161
24004
|
return { state: {} };
|
|
@@ -23202,13 +24045,13 @@ function writeChannelSequence(params) {
|
|
|
23202
24045
|
[key]: { sequence, version, seenAt: now.toISOString() }
|
|
23203
24046
|
};
|
|
23204
24047
|
const filePath = stateFilePath(cacheRoot);
|
|
23205
|
-
|
|
24048
|
+
fs29.mkdirSync(path27.dirname(filePath), { recursive: true, mode: 448 });
|
|
23206
24049
|
const tempPath = `${filePath}.${process.pid}.tmp`;
|
|
23207
|
-
|
|
24050
|
+
fs29.writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}
|
|
23208
24051
|
`, {
|
|
23209
24052
|
mode: 384
|
|
23210
24053
|
});
|
|
23211
|
-
|
|
24054
|
+
fs29.renameSync(tempPath, filePath);
|
|
23212
24055
|
}
|
|
23213
24056
|
function assertChannelNotRolledBack(params) {
|
|
23214
24057
|
const { originUrl, kit, channel, seen, seenVersion, incoming } = params;
|
|
@@ -23224,8 +24067,8 @@ var CHANNEL_POINTER_TYPE = "tangyr.channel-pointer.v1";
|
|
|
23224
24067
|
var DEFAULT_CHANNEL = "stable";
|
|
23225
24068
|
|
|
23226
24069
|
// src/core/materialize.ts
|
|
23227
|
-
import
|
|
23228
|
-
import
|
|
24070
|
+
import fs30 from "fs";
|
|
24071
|
+
import path28 from "path";
|
|
23229
24072
|
|
|
23230
24073
|
// src/core/integrity.ts
|
|
23231
24074
|
import crypto3 from "crypto";
|
|
@@ -23561,7 +24404,7 @@ function assertFileWithinCeiling(entryPath, byteLength) {
|
|
|
23561
24404
|
}
|
|
23562
24405
|
var WINDOWS_DRIVE_ABSOLUTE = /^[a-zA-Z]:[\\/]/u;
|
|
23563
24406
|
function sanitizeBundleFilePath(entryPath, stagingDir) {
|
|
23564
|
-
if (
|
|
24407
|
+
if (path28.isAbsolute(entryPath) || WINDOWS_DRIVE_ABSOLUTE.test(entryPath)) {
|
|
23565
24408
|
throw new IntegrityError(
|
|
23566
24409
|
`Bundle file path "${entryPath}" is absolute \u2014 every file inside a bundle must use a relative path (REQ-INT-004).`
|
|
23567
24410
|
);
|
|
@@ -23577,13 +24420,13 @@ function sanitizeBundleFilePath(entryPath, stagingDir) {
|
|
|
23577
24420
|
`Bundle file path "${entryPath}" contains a ".." segment \u2014 directory traversal is rejected (REQ-INT-004).`
|
|
23578
24421
|
);
|
|
23579
24422
|
}
|
|
23580
|
-
const resolved =
|
|
24423
|
+
const resolved = path28.resolve(stagingDir, entryPath);
|
|
23581
24424
|
if (resolved === stagingDir) {
|
|
23582
24425
|
throw new IntegrityError(
|
|
23583
24426
|
`Bundle file path "${entryPath}" resolves to the staging directory itself \u2014 every entry must be a file inside it (REQ-INT-004).`
|
|
23584
24427
|
);
|
|
23585
24428
|
}
|
|
23586
|
-
if (!resolved.startsWith(stagingDir +
|
|
24429
|
+
if (!resolved.startsWith(stagingDir + path28.sep)) {
|
|
23587
24430
|
throw new IntegrityError(
|
|
23588
24431
|
`Bundle file path "${entryPath}" escapes the staging directory \u2014 refusing to write (REQ-INT-004).`
|
|
23589
24432
|
);
|
|
@@ -23635,10 +24478,10 @@ function verifyBundleFileHashes(bundle) {
|
|
|
23635
24478
|
function writeStagedFiles(stagingDir, decoded) {
|
|
23636
24479
|
for (const [rawPath, bytes] of decoded) {
|
|
23637
24480
|
const target = sanitizeBundleFilePath(rawPath, stagingDir);
|
|
23638
|
-
|
|
24481
|
+
fs30.mkdirSync(path28.dirname(target), { recursive: true, mode: 448 });
|
|
23639
24482
|
let existingStat;
|
|
23640
24483
|
try {
|
|
23641
|
-
existingStat =
|
|
24484
|
+
existingStat = fs30.lstatSync(target);
|
|
23642
24485
|
} catch (error) {
|
|
23643
24486
|
if (error.code !== "ENOENT") {
|
|
23644
24487
|
throw error;
|
|
@@ -23649,7 +24492,7 @@ function writeStagedFiles(stagingDir, decoded) {
|
|
|
23649
24492
|
`Refusing to write "${rawPath}" \u2014 a symbolic link already exists at the target path.`
|
|
23650
24493
|
);
|
|
23651
24494
|
}
|
|
23652
|
-
|
|
24495
|
+
fs30.writeFileSync(target, bytes, { mode: 384, flag: "wx" });
|
|
23653
24496
|
}
|
|
23654
24497
|
}
|
|
23655
24498
|
function verifyWarmCacheEntry(entryDir, reference, keys, now) {
|
|
@@ -23705,14 +24548,14 @@ async function materializeRemoteKit(params) {
|
|
|
23705
24548
|
writeStagedFiles(stagingDir, decoded);
|
|
23706
24549
|
writeBundleDocument(stagingDir, bundle);
|
|
23707
24550
|
writeCompletionMarker(stagingDir, reference);
|
|
23708
|
-
if (replace &&
|
|
23709
|
-
|
|
24551
|
+
if (replace && fs30.existsSync(entryDir)) {
|
|
24552
|
+
fs30.rmSync(entryDir, { recursive: true, force: true });
|
|
23710
24553
|
}
|
|
23711
24554
|
publishCacheEntry(stagingDir, entryDir);
|
|
23712
24555
|
return entryDir;
|
|
23713
24556
|
} catch (error) {
|
|
23714
24557
|
if (stagingDir !== void 0) {
|
|
23715
|
-
|
|
24558
|
+
fs30.rmSync(stagingDir, { recursive: true, force: true });
|
|
23716
24559
|
}
|
|
23717
24560
|
throw error;
|
|
23718
24561
|
}
|
|
@@ -24048,13 +24891,13 @@ function sleep(ms2) {
|
|
|
24048
24891
|
// src/adapters/codex.ts
|
|
24049
24892
|
var TOML3 = __toESM(require_toml(), 1);
|
|
24050
24893
|
import crypto5 from "crypto";
|
|
24051
|
-
import
|
|
24052
|
-
import
|
|
24894
|
+
import fs32 from "fs";
|
|
24895
|
+
import path31 from "path";
|
|
24053
24896
|
|
|
24054
24897
|
// src/compiler/agents.ts
|
|
24055
24898
|
var TOML = __toESM(require_toml(), 1);
|
|
24056
|
-
var
|
|
24057
|
-
import
|
|
24899
|
+
var import_yaml8 = __toESM(require_dist(), 1);
|
|
24900
|
+
import path29 from "path";
|
|
24058
24901
|
|
|
24059
24902
|
// src/compiler/loss-report.ts
|
|
24060
24903
|
function createLossReport() {
|
|
@@ -24118,7 +24961,7 @@ var copilotToolAliasesByClass = {
|
|
|
24118
24961
|
};
|
|
24119
24962
|
function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
24120
24963
|
const { data, body } = parseMarkdownFrontmatter(sourceFile);
|
|
24121
|
-
const relativeSource = `agents/${
|
|
24964
|
+
const relativeSource = `agents/${path29.basename(sourceFile)}`;
|
|
24122
24965
|
if (target === "opencode") {
|
|
24123
24966
|
return compileOpenCodeAgent(
|
|
24124
24967
|
sourceFile,
|
|
@@ -24159,7 +25002,7 @@ function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
|
24159
25002
|
mappings,
|
|
24160
25003
|
lossReport
|
|
24161
25004
|
);
|
|
24162
|
-
const overlayKey = `agents/${
|
|
25005
|
+
const overlayKey = `agents/${path29.basename(sourceFile, ".md")}.${target}.yaml`;
|
|
24163
25006
|
const targetFields = {
|
|
24164
25007
|
...translated.fields,
|
|
24165
25008
|
...extensions[overlayKey] ?? {}
|
|
@@ -24179,7 +25022,7 @@ function compileAgent(sourceFile, target, mappings, extensions, lossReport) {
|
|
|
24179
25022
|
if (target === "copilot") {
|
|
24180
25023
|
return `${marker}
|
|
24181
25024
|
---
|
|
24182
|
-
${(0,
|
|
25025
|
+
${(0, import_yaml8.stringify)(targetFields).trim()}
|
|
24183
25026
|
---
|
|
24184
25027
|
|
|
24185
25028
|
${body}`;
|
|
@@ -24193,7 +25036,7 @@ ${TOML.stringify({
|
|
|
24193
25036
|
function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport) {
|
|
24194
25037
|
if (typeof data.description !== "string" || data.description.trim() === "") {
|
|
24195
25038
|
throw new Error(
|
|
24196
|
-
`${
|
|
25039
|
+
`${path29.basename(sourceFile)}: OpenCode agent requires a non-empty description field`
|
|
24197
25040
|
);
|
|
24198
25041
|
}
|
|
24199
25042
|
const frontmatter = {
|
|
@@ -24247,7 +25090,7 @@ function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport
|
|
|
24247
25090
|
"permission",
|
|
24248
25091
|
"permission-coarsening"
|
|
24249
25092
|
),
|
|
24250
|
-
detail: `${
|
|
25093
|
+
detail: `${path29.basename(sourceFile)}: per-tool permission '${tool}' mapped to coarse allow|deny action`
|
|
24251
25094
|
}
|
|
24252
25095
|
]
|
|
24253
25096
|
});
|
|
@@ -24265,14 +25108,14 @@ function compileOpenCodeAgent(sourceFile, data, body, relativeSource, lossReport
|
|
|
24265
25108
|
);
|
|
24266
25109
|
return `${marker}
|
|
24267
25110
|
---
|
|
24268
|
-
${(0,
|
|
25111
|
+
${(0, import_yaml8.stringify)(frontmatter).trim()}
|
|
24269
25112
|
---
|
|
24270
25113
|
`;
|
|
24271
25114
|
}
|
|
24272
25115
|
function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport) {
|
|
24273
25116
|
if (typeof data.description !== "string" || data.description.trim() === "") {
|
|
24274
25117
|
throw new Error(
|
|
24275
|
-
`${
|
|
25118
|
+
`${path29.basename(sourceFile)}: Cursor agent requires a non-empty description field`
|
|
24276
25119
|
);
|
|
24277
25120
|
}
|
|
24278
25121
|
const frontmatter = {
|
|
@@ -24309,7 +25152,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
|
|
|
24309
25152
|
"permission",
|
|
24310
25153
|
"permission-coarsening"
|
|
24311
25154
|
),
|
|
24312
|
-
detail: `${
|
|
25155
|
+
detail: `${path29.basename(sourceFile)}: per-agent tool allow set coarsened to readonly=${readonly} boolean (Cursor only exposes readonly control)`
|
|
24313
25156
|
}
|
|
24314
25157
|
]
|
|
24315
25158
|
});
|
|
@@ -24328,7 +25171,7 @@ function compileCursorAgent(sourceFile, data, body, relativeSource, lossReport)
|
|
|
24328
25171
|
"provider",
|
|
24329
25172
|
"provider-not-representable"
|
|
24330
25173
|
),
|
|
24331
|
-
detail: `${
|
|
25174
|
+
detail: `${path29.basename(sourceFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
|
|
24332
25175
|
}
|
|
24333
25176
|
]
|
|
24334
25177
|
});
|
|
@@ -24344,7 +25187,7 @@ ${body.trim()}
|
|
|
24344
25187
|
` : "";
|
|
24345
25188
|
return `${marker}
|
|
24346
25189
|
---
|
|
24347
|
-
${(0,
|
|
25190
|
+
${(0, import_yaml8.stringify)(frontmatter).trim()}
|
|
24348
25191
|
---
|
|
24349
25192
|
${bodySection}`;
|
|
24350
25193
|
}
|
|
@@ -24360,7 +25203,7 @@ function compileClineAgent(sourceFile, _data, _body, relativeSource, lossReport)
|
|
|
24360
25203
|
"persona",
|
|
24361
25204
|
"persona-not-representable"
|
|
24362
25205
|
),
|
|
24363
|
-
detail: `${
|
|
25206
|
+
detail: `${path29.basename(sourceFile)}: Cline has no committable per-agent persona file for the VSCode extension target; configure the agent through Cline Settings \u2192 Agent.`
|
|
24364
25207
|
}
|
|
24365
25208
|
]
|
|
24366
25209
|
});
|
|
@@ -24408,7 +25251,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
24408
25251
|
field,
|
|
24409
25252
|
"model-not-representable"
|
|
24410
25253
|
),
|
|
24411
|
-
detail: `${
|
|
25254
|
+
detail: `${path29.basename(sourceFile)}: model tier '${String(value)}' has no stable Copilot model literal; omitted so VS Code uses the selected model.`
|
|
24412
25255
|
});
|
|
24413
25256
|
return;
|
|
24414
25257
|
}
|
|
@@ -24426,9 +25269,9 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
24426
25269
|
lossReport,
|
|
24427
25270
|
target,
|
|
24428
25271
|
"agents",
|
|
24429
|
-
`agents/${
|
|
25272
|
+
`agents/${path29.basename(sourceFile)}`,
|
|
24430
25273
|
"info",
|
|
24431
|
-
`${
|
|
25274
|
+
`${path29.basename(sourceFile)}: ${field} is delivered through another managed surface.`
|
|
24432
25275
|
);
|
|
24433
25276
|
return;
|
|
24434
25277
|
}
|
|
@@ -24437,7 +25280,7 @@ function applyFieldAction(sourceFile, field, value, action, target, mappings, tr
|
|
|
24437
25280
|
field,
|
|
24438
25281
|
action: entryType,
|
|
24439
25282
|
severity: resolveLossSeverity("agent-field", field, entryType),
|
|
24440
|
-
detail: `${
|
|
25283
|
+
detail: `${path29.basename(sourceFile)}: ${field} has no emitted field for this target.`
|
|
24441
25284
|
});
|
|
24442
25285
|
}
|
|
24443
25286
|
function mapToolsToCapabilities(value, mappings) {
|
|
@@ -25034,9 +25877,9 @@ function compileOpenCodeMcp(sourceMcpJson, lossReport, sourceLabel) {
|
|
|
25034
25877
|
}
|
|
25035
25878
|
|
|
25036
25879
|
// src/compiler/rules.ts
|
|
25037
|
-
import
|
|
25038
|
-
var
|
|
25039
|
-
import
|
|
25880
|
+
import path30 from "path";
|
|
25881
|
+
var import_yaml9 = __toESM(require_dist(), 1);
|
|
25882
|
+
import fs31 from "fs";
|
|
25040
25883
|
function compileRules(sourceRulesDir, target, _mappings, lossReport) {
|
|
25041
25884
|
if (target === "copilot") {
|
|
25042
25885
|
addLoss(lossReport, "copilot", "rules", {
|
|
@@ -25073,13 +25916,13 @@ function compileRules(sourceRulesDir, target, _mappings, lossReport) {
|
|
|
25073
25916
|
}
|
|
25074
25917
|
const appendixParts = [];
|
|
25075
25918
|
const dotRulesFiles = [];
|
|
25076
|
-
for (const ruleFile of ts(
|
|
25919
|
+
for (const ruleFile of ts(path30.join(sourceRulesDir, "*.md")).sort()) {
|
|
25077
25920
|
const parsed = parseRule(ruleFile);
|
|
25078
|
-
const name =
|
|
25921
|
+
const name = path30.basename(ruleFile, ".md");
|
|
25079
25922
|
if (parsed.mode === "exec-policy") {
|
|
25080
25923
|
dotRulesFiles.push({
|
|
25081
25924
|
name: `${name}.rules`,
|
|
25082
|
-
content: `${formatProvenanceMarker("toml", `rules/${
|
|
25925
|
+
content: `${formatProvenanceMarker("toml", `rules/${path30.basename(ruleFile)}`, computeSourceHash(ruleFile), "codex")}
|
|
25083
25926
|
${parsed.body}`
|
|
25084
25927
|
});
|
|
25085
25928
|
continue;
|
|
@@ -25088,7 +25931,7 @@ ${parsed.body}`
|
|
|
25088
25931
|
|
|
25089
25932
|
${parsed.body.trim()}`);
|
|
25090
25933
|
addLoss(lossReport, "codex", "rules", {
|
|
25091
|
-
source: `rules/${
|
|
25934
|
+
source: `rules/${path30.basename(ruleFile)}`,
|
|
25092
25935
|
fields: [
|
|
25093
25936
|
{
|
|
25094
25937
|
field: "mode",
|
|
@@ -25098,7 +25941,7 @@ ${parsed.body.trim()}`);
|
|
|
25098
25941
|
"mode",
|
|
25099
25942
|
"rule-as-instruction"
|
|
25100
25943
|
),
|
|
25101
|
-
detail: `${
|
|
25944
|
+
detail: `${path30.basename(ruleFile)} is appended to the managed Codex instructions file as guidance.`
|
|
25102
25945
|
}
|
|
25103
25946
|
]
|
|
25104
25947
|
});
|
|
@@ -25106,7 +25949,7 @@ ${parsed.body.trim()}`);
|
|
|
25106
25949
|
return { agentsAppendix: appendixParts.join("\n\n"), dotRulesFiles };
|
|
25107
25950
|
}
|
|
25108
25951
|
function parseRule(ruleFile) {
|
|
25109
|
-
const content =
|
|
25952
|
+
const content = fs31.readFileSync(ruleFile, "utf8");
|
|
25110
25953
|
if (!content.startsWith("---\n")) {
|
|
25111
25954
|
return { mode: "guidance", body: content };
|
|
25112
25955
|
}
|
|
@@ -25114,7 +25957,7 @@ function parseRule(ruleFile) {
|
|
|
25114
25957
|
if (endIndex === -1) {
|
|
25115
25958
|
throw new Error(`${ruleFile}: frontmatter is not closed`);
|
|
25116
25959
|
}
|
|
25117
|
-
const frontmatter = (0,
|
|
25960
|
+
const frontmatter = (0, import_yaml9.parse)(content.slice(4, endIndex));
|
|
25118
25961
|
const mode = isRuleMode(frontmatter) ? frontmatter.mode : "guidance";
|
|
25119
25962
|
return {
|
|
25120
25963
|
mode,
|
|
@@ -25130,14 +25973,14 @@ function isRuleMode(value) {
|
|
|
25130
25973
|
}
|
|
25131
25974
|
function compileOpenCodeRules(sourceRulesDir, lossReport) {
|
|
25132
25975
|
const appendixParts = [];
|
|
25133
|
-
for (const ruleFile of ts(
|
|
25976
|
+
for (const ruleFile of ts(path30.join(sourceRulesDir, "*.md")).sort()) {
|
|
25134
25977
|
const parsed = parseRule(ruleFile);
|
|
25135
|
-
const name =
|
|
25978
|
+
const name = path30.basename(ruleFile, ".md");
|
|
25136
25979
|
appendixParts.push(`## ${name}
|
|
25137
25980
|
|
|
25138
25981
|
${parsed.body.trim()}`);
|
|
25139
25982
|
addLoss(lossReport, "opencode", "rules", {
|
|
25140
|
-
source: `rules/${
|
|
25983
|
+
source: `rules/${path30.basename(ruleFile)}`,
|
|
25141
25984
|
fields: [
|
|
25142
25985
|
{
|
|
25143
25986
|
field: "rule",
|
|
@@ -25147,7 +25990,7 @@ ${parsed.body.trim()}`);
|
|
|
25147
25990
|
"rule",
|
|
25148
25991
|
"rule-path-scoping"
|
|
25149
25992
|
),
|
|
25150
|
-
detail: `${
|
|
25993
|
+
detail: `${path30.basename(ruleFile)}: OpenCode has no per-agent rule scoping \u2014 rule appended to AGENTS.md instructions`
|
|
25151
25994
|
}
|
|
25152
25995
|
]
|
|
25153
25996
|
});
|
|
@@ -25156,9 +25999,9 @@ ${parsed.body.trim()}`);
|
|
|
25156
25999
|
}
|
|
25157
26000
|
function compileCursorRules(sourceRulesDir, _lossReport) {
|
|
25158
26001
|
const dotRulesFiles = [];
|
|
25159
|
-
for (const ruleFile of ts(
|
|
25160
|
-
const content =
|
|
25161
|
-
const name =
|
|
26002
|
+
for (const ruleFile of ts(path30.join(sourceRulesDir, "*.md")).sort()) {
|
|
26003
|
+
const content = fs31.readFileSync(ruleFile, "utf8");
|
|
26004
|
+
const name = path30.basename(ruleFile, ".md");
|
|
25162
26005
|
let frontmatterData = {};
|
|
25163
26006
|
let body = content;
|
|
25164
26007
|
if (content.startsWith("---\n")) {
|
|
@@ -25166,7 +26009,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
|
|
|
25166
26009
|
if (endIndex !== -1) {
|
|
25167
26010
|
const frontmatterStr = content.slice(4, endIndex);
|
|
25168
26011
|
try {
|
|
25169
|
-
frontmatterData = (0,
|
|
26012
|
+
frontmatterData = (0, import_yaml9.parse)(frontmatterStr) ?? {};
|
|
25170
26013
|
} catch {
|
|
25171
26014
|
frontmatterData = {};
|
|
25172
26015
|
}
|
|
@@ -25187,7 +26030,7 @@ function compileCursorRules(sourceRulesDir, _lossReport) {
|
|
|
25187
26030
|
}
|
|
25188
26031
|
const marker = formatProvenanceMarker(
|
|
25189
26032
|
"markdown",
|
|
25190
|
-
`rules/${
|
|
26033
|
+
`rules/${path30.basename(ruleFile)}`,
|
|
25191
26034
|
computeSourceHash(ruleFile),
|
|
25192
26035
|
"cursor"
|
|
25193
26036
|
);
|
|
@@ -25203,9 +26046,9 @@ ${body}`;
|
|
|
25203
26046
|
}
|
|
25204
26047
|
function compileClineRules(sourceRulesDir, lossReport) {
|
|
25205
26048
|
const dotRulesFiles = [];
|
|
25206
|
-
for (const ruleFile of ts(
|
|
25207
|
-
const content =
|
|
25208
|
-
const name =
|
|
26049
|
+
for (const ruleFile of ts(path30.join(sourceRulesDir, "*.md")).sort()) {
|
|
26050
|
+
const content = fs31.readFileSync(ruleFile, "utf8");
|
|
26051
|
+
const name = path30.basename(ruleFile, ".md");
|
|
25209
26052
|
let frontmatterData = {};
|
|
25210
26053
|
let body = content;
|
|
25211
26054
|
if (content.startsWith("---\n")) {
|
|
@@ -25213,7 +26056,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
|
|
|
25213
26056
|
if (endIndex !== -1) {
|
|
25214
26057
|
const frontmatterStr = content.slice(4, endIndex);
|
|
25215
26058
|
try {
|
|
25216
|
-
frontmatterData = (0,
|
|
26059
|
+
frontmatterData = (0, import_yaml9.parse)(frontmatterStr) ?? {};
|
|
25217
26060
|
} catch {
|
|
25218
26061
|
frontmatterData = {};
|
|
25219
26062
|
}
|
|
@@ -25222,13 +26065,13 @@ function compileClineRules(sourceRulesDir, lossReport) {
|
|
|
25222
26065
|
}
|
|
25223
26066
|
const marker = formatProvenanceMarker(
|
|
25224
26067
|
"markdown",
|
|
25225
|
-
`rules/${
|
|
26068
|
+
`rules/${path30.basename(ruleFile)}`,
|
|
25226
26069
|
computeSourceHash(ruleFile),
|
|
25227
26070
|
"cline"
|
|
25228
26071
|
);
|
|
25229
26072
|
if (frontmatterData.mode === "exec-policy") {
|
|
25230
26073
|
addLoss(lossReport, "cline", "rules", {
|
|
25231
|
-
source: `rules/${
|
|
26074
|
+
source: `rules/${path30.basename(ruleFile)}`,
|
|
25232
26075
|
fields: [
|
|
25233
26076
|
{
|
|
25234
26077
|
field: "mode",
|
|
@@ -25238,7 +26081,7 @@ function compileClineRules(sourceRulesDir, lossReport) {
|
|
|
25238
26081
|
"mode",
|
|
25239
26082
|
"rule-mode-downgrade"
|
|
25240
26083
|
),
|
|
25241
|
-
detail: `${
|
|
26084
|
+
detail: `${path30.basename(ruleFile)}: Cline rules have no exec-policy mode; rule emitted as guidance.`
|
|
25242
26085
|
}
|
|
25243
26086
|
]
|
|
25244
26087
|
});
|
|
@@ -25283,7 +26126,7 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
25283
26126
|
rules: profile.rules
|
|
25284
26127
|
};
|
|
25285
26128
|
const rules = compileRules(
|
|
25286
|
-
|
|
26129
|
+
path31.join(sourceRoot, config.source.rules),
|
|
25287
26130
|
"codex",
|
|
25288
26131
|
mappings,
|
|
25289
26132
|
lossReport
|
|
@@ -25428,9 +26271,9 @@ function syncCodex(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
25428
26271
|
function buildProviderTomlSection(config, sourceRoot, mappings, scope, lossReport) {
|
|
25429
26272
|
const cp = mappings.modelTiers.custom_provider;
|
|
25430
26273
|
if (!cp) return "";
|
|
25431
|
-
const agentsDir =
|
|
25432
|
-
if (!
|
|
25433
|
-
const agentFiles = ts(
|
|
26274
|
+
const agentsDir = path31.join(sourceRoot, config.source.agents);
|
|
26275
|
+
if (!fs32.existsSync(agentsDir)) return "";
|
|
26276
|
+
const agentFiles = ts(path31.join(agentsDir, "*.md")).sort();
|
|
25434
26277
|
const hasProviderAgent = agentFiles.some((agentFile) => {
|
|
25435
26278
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
25436
26279
|
return typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
@@ -25495,7 +26338,7 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
|
|
|
25495
26338
|
}
|
|
25496
26339
|
];
|
|
25497
26340
|
for (const ruleFile of rules.dotRulesFiles) {
|
|
25498
|
-
const destination =
|
|
26341
|
+
const destination = path31.join(rulesRoot, ruleFile.name);
|
|
25499
26342
|
if (options.dryRun) {
|
|
25500
26343
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
25501
26344
|
outcomes.push({
|
|
@@ -25523,15 +26366,15 @@ function syncRules(config, sourceRoot, paths, rules, options, logger, manifest,
|
|
|
25523
26366
|
return outcomes;
|
|
25524
26367
|
}
|
|
25525
26368
|
function syncInstructions(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
|
|
25526
|
-
const source =
|
|
26369
|
+
const source = path31.join(sourceRoot, config.source.instructions);
|
|
25527
26370
|
const destination = resolveTargetPath(paths.instructions);
|
|
25528
|
-
const composed = `${
|
|
26371
|
+
const composed = `${fs32.readFileSync(source, "utf8").trim()}
|
|
25529
26372
|
|
|
25530
26373
|
--- tangyr managed rules ---
|
|
25531
26374
|
${agentsAppendix}`.trim();
|
|
25532
26375
|
const marker = formatProvenanceMarker(
|
|
25533
26376
|
"markdown",
|
|
25534
|
-
|
|
26377
|
+
path31.basename(config.source.instructions),
|
|
25535
26378
|
hashString(composed),
|
|
25536
26379
|
"codex"
|
|
25537
26380
|
);
|
|
@@ -25558,9 +26401,9 @@ ${composed}
|
|
|
25558
26401
|
);
|
|
25559
26402
|
}
|
|
25560
26403
|
function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
25561
|
-
const source =
|
|
26404
|
+
const source = path31.resolve(sourceRoot, config.source.skills);
|
|
25562
26405
|
const destination = resolveTargetPath(paths.skills);
|
|
25563
|
-
if (!
|
|
26406
|
+
if (!fs32.existsSync(source)) {
|
|
25564
26407
|
return skippedMissingSource("skills", source);
|
|
25565
26408
|
}
|
|
25566
26409
|
if (options.dryRun) {
|
|
@@ -25576,29 +26419,29 @@ function syncSkills(config, sourceRoot, paths, options, logger, manifest, scopeP
|
|
|
25576
26419
|
};
|
|
25577
26420
|
}
|
|
25578
26421
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
25579
|
-
|
|
26422
|
+
fs32.unlinkSync(destination);
|
|
25580
26423
|
logger.verbose(`Skills: created skills path ${destination}`);
|
|
25581
26424
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict(destination, config, options, logger, manifest, scopePath)) {
|
|
25582
26425
|
return { component: "skills", status: "conflict", path: destination };
|
|
25583
26426
|
} else if (artifactClass === "managed-symlink") {
|
|
25584
|
-
|
|
26427
|
+
fs32.unlinkSync(destination);
|
|
25585
26428
|
}
|
|
25586
|
-
ensureDir(
|
|
26429
|
+
ensureDir(path31.dirname(destination));
|
|
25587
26430
|
createRelativeSymlink(source, destination, "dir");
|
|
25588
26431
|
logger.verbose(`Skills: created skills path ${destination}`);
|
|
25589
26432
|
return { component: "skills", status: "success", path: destination };
|
|
25590
26433
|
}
|
|
25591
26434
|
function syncAgents(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
25592
|
-
const sourceAgentsRoot =
|
|
25593
|
-
if (!
|
|
26435
|
+
const sourceAgentsRoot = path31.join(sourceRoot, config.source.agents);
|
|
26436
|
+
if (!fs32.existsSync(sourceAgentsRoot)) {
|
|
25594
26437
|
return [skippedMissingSource("agents", sourceAgentsRoot)];
|
|
25595
26438
|
}
|
|
25596
|
-
const sourceAgents = ts(
|
|
26439
|
+
const sourceAgents = ts(path31.join(sourceAgentsRoot, "*.md")).sort();
|
|
25597
26440
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
25598
26441
|
return sourceAgents.map((agentFile) => {
|
|
25599
|
-
const destination =
|
|
26442
|
+
const destination = path31.join(
|
|
25600
26443
|
agentsRoot,
|
|
25601
|
-
`${
|
|
26444
|
+
`${path31.basename(agentFile, ".md")}.toml`
|
|
25602
26445
|
);
|
|
25603
26446
|
const compiled = compileAgent(
|
|
25604
26447
|
agentFile,
|
|
@@ -25634,10 +26477,10 @@ function syncHooks(config, sourceRoot, paths, mappings, options, lossReport, log
|
|
|
25634
26477
|
}
|
|
25635
26478
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
25636
26479
|
const sourceLabel = hooksSourceLabel(config);
|
|
25637
|
-
if (!
|
|
26480
|
+
if (!fs32.existsSync(source)) {
|
|
25638
26481
|
return skippedMissingSource("hooks", source);
|
|
25639
26482
|
}
|
|
25640
|
-
const sourceHooksJson = JSON.parse(
|
|
26483
|
+
const sourceHooksJson = JSON.parse(fs32.readFileSync(source, "utf8"));
|
|
25641
26484
|
const compiled = compileHooks(
|
|
25642
26485
|
sourceHooksJson,
|
|
25643
26486
|
"codex",
|
|
@@ -25659,7 +26502,7 @@ function syncHooks(config, sourceRoot, paths, mappings, options, lossReport, log
|
|
|
25659
26502
|
destination,
|
|
25660
26503
|
hostHooks,
|
|
25661
26504
|
stringifyJson2,
|
|
25662
|
-
!
|
|
26505
|
+
!fs32.existsSync(destination),
|
|
25663
26506
|
logger
|
|
25664
26507
|
);
|
|
25665
26508
|
return {
|
|
@@ -25672,7 +26515,7 @@ function syncMcp(config, sourceRoot, paths, options, lossReport, logger, provide
|
|
|
25672
26515
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
25673
26516
|
const sourceLabel = mcpSourceLabel(config);
|
|
25674
26517
|
const destination = resolveTargetPath(paths.mcp_shared_file);
|
|
25675
|
-
if (!
|
|
26518
|
+
if (!fs32.existsSync(source)) {
|
|
25676
26519
|
if (providerToml && !options.dryRun) {
|
|
25677
26520
|
const changed2 = writeTomlManagedSection(
|
|
25678
26521
|
destination,
|
|
@@ -25687,7 +26530,7 @@ function syncMcp(config, sourceRoot, paths, options, lossReport, logger, provide
|
|
|
25687
26530
|
}
|
|
25688
26531
|
return skippedMissingSource("mcp", source);
|
|
25689
26532
|
}
|
|
25690
|
-
const sourceMcpJson = JSON.parse(
|
|
26533
|
+
const sourceMcpJson = JSON.parse(fs32.readFileSync(source, "utf8"));
|
|
25691
26534
|
const compiled = compileMcp(sourceMcpJson, "codex", lossReport, sourceLabel);
|
|
25692
26535
|
const managedContent = providerToml ? `${compiled.trimEnd()}${providerToml}` : compiled;
|
|
25693
26536
|
if (options.dryRun) {
|
|
@@ -25709,12 +26552,12 @@ function writeCompiledArtifact(component, destination, content, expectedHash, co
|
|
|
25709
26552
|
if (artifactClass === "unmanaged-conflict" && !handleConflict(destination, config, options, logger, manifest, scopePath)) {
|
|
25710
26553
|
return { component, status: "conflict", path: destination };
|
|
25711
26554
|
}
|
|
25712
|
-
ensureDir(
|
|
25713
|
-
|
|
26555
|
+
ensureDir(path31.dirname(destination));
|
|
26556
|
+
fs32.writeFileSync(destination, content);
|
|
25714
26557
|
return { component, status: "success", path: destination };
|
|
25715
26558
|
}
|
|
25716
26559
|
function writeTomlManagedSection(destination, managedContent, logger) {
|
|
25717
|
-
const current =
|
|
26560
|
+
const current = fs32.existsSync(destination) ? fs32.readFileSync(destination, "utf8") : "";
|
|
25718
26561
|
const isFirstWrite = current.length > 0 && !current.includes(managedMcpStart);
|
|
25719
26562
|
if (isFirstWrite) {
|
|
25720
26563
|
logger.warn(
|
|
@@ -25730,8 +26573,8 @@ ${managedMcpEnd}
|
|
|
25730
26573
|
if (current === next.trimStart()) {
|
|
25731
26574
|
return false;
|
|
25732
26575
|
}
|
|
25733
|
-
ensureDir(
|
|
25734
|
-
|
|
26576
|
+
ensureDir(path31.dirname(destination));
|
|
26577
|
+
fs32.writeFileSync(destination, next.trimStart());
|
|
25735
26578
|
return true;
|
|
25736
26579
|
}
|
|
25737
26580
|
function removeManagedTomlSection(content) {
|
|
@@ -25758,16 +26601,16 @@ function handleConflict(destination, config, options, logger, manifest, scopePat
|
|
|
25758
26601
|
backupFile(destination, manifest);
|
|
25759
26602
|
writeManifest(scopePath, manifest);
|
|
25760
26603
|
} else {
|
|
25761
|
-
|
|
26604
|
+
fs32.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
25762
26605
|
}
|
|
25763
26606
|
return true;
|
|
25764
26607
|
}
|
|
25765
|
-
|
|
26608
|
+
fs32.rmSync(destination, { recursive: true, force: true });
|
|
25766
26609
|
return true;
|
|
25767
26610
|
}
|
|
25768
26611
|
function isCompiledCurrent(destination, expectedContent, expectedHash) {
|
|
25769
26612
|
try {
|
|
25770
|
-
const current =
|
|
26613
|
+
const current = fs32.readFileSync(destination, "utf8");
|
|
25771
26614
|
const marker = extractProvenanceMarker(current);
|
|
25772
26615
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "codex" && current === expectedContent : current === expectedContent;
|
|
25773
26616
|
} catch {
|
|
@@ -25786,16 +26629,16 @@ function shouldSkipComponent(options, component) {
|
|
|
25786
26629
|
}
|
|
25787
26630
|
function isSymlinkTo(linkPath, source) {
|
|
25788
26631
|
try {
|
|
25789
|
-
return
|
|
26632
|
+
return fs32.realpathSync(linkPath) === fs32.realpathSync(source);
|
|
25790
26633
|
} catch {
|
|
25791
26634
|
return false;
|
|
25792
26635
|
}
|
|
25793
26636
|
}
|
|
25794
26637
|
function readJsonObject3(filePath) {
|
|
25795
|
-
if (!
|
|
26638
|
+
if (!fs32.existsSync(filePath)) {
|
|
25796
26639
|
return {};
|
|
25797
26640
|
}
|
|
25798
|
-
const parsed = JSON.parse(
|
|
26641
|
+
const parsed = JSON.parse(fs32.readFileSync(filePath, "utf8"));
|
|
25799
26642
|
return isRecord4(parsed) ? parsed : {};
|
|
25800
26643
|
}
|
|
25801
26644
|
function stringifyJson2(value) {
|
|
@@ -25811,16 +26654,16 @@ function hashString(value) {
|
|
|
25811
26654
|
|
|
25812
26655
|
// src/adapters/copilot.ts
|
|
25813
26656
|
import crypto6 from "crypto";
|
|
25814
|
-
import
|
|
25815
|
-
import
|
|
26657
|
+
import fs33 from "fs";
|
|
26658
|
+
import path33 from "path";
|
|
25816
26659
|
|
|
25817
26660
|
// src/compiler/commands.ts
|
|
25818
|
-
var
|
|
25819
|
-
import
|
|
26661
|
+
var import_yaml10 = __toESM(require_dist(), 1);
|
|
26662
|
+
import path32 from "path";
|
|
25820
26663
|
function compileCommandPrompt(sourceFile) {
|
|
25821
26664
|
const { data, body } = parseMarkdownFrontmatter(sourceFile);
|
|
25822
|
-
const relativeSource = `commands/${
|
|
25823
|
-
const fields = promptFrontmatter(data,
|
|
26665
|
+
const relativeSource = `commands/${path32.basename(sourceFile)}`;
|
|
26666
|
+
const fields = promptFrontmatter(data, path32.basename(sourceFile, ".md"));
|
|
25824
26667
|
const marker = formatProvenanceMarker(
|
|
25825
26668
|
"markdown",
|
|
25826
26669
|
relativeSource,
|
|
@@ -25829,7 +26672,7 @@ function compileCommandPrompt(sourceFile) {
|
|
|
25829
26672
|
);
|
|
25830
26673
|
return `${marker}
|
|
25831
26674
|
---
|
|
25832
|
-
${(0,
|
|
26675
|
+
${(0, import_yaml10.stringify)(fields).trim()}
|
|
25833
26676
|
---
|
|
25834
26677
|
|
|
25835
26678
|
${body.trimEnd()}
|
|
@@ -25995,13 +26838,13 @@ function syncCopilot(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
25995
26838
|
}
|
|
25996
26839
|
function syncProviderLoss(config, sourceRoot, mappings, lossReport) {
|
|
25997
26840
|
if (!mappings.modelTiers.custom_provider) return;
|
|
25998
|
-
const agentsDir =
|
|
25999
|
-
if (!
|
|
26000
|
-
for (const agentFile of ts(
|
|
26841
|
+
const agentsDir = path33.join(sourceRoot, config.source.agents);
|
|
26842
|
+
if (!fs33.existsSync(agentsDir)) return;
|
|
26843
|
+
for (const agentFile of ts(path33.join(agentsDir, "*.md")).sort()) {
|
|
26001
26844
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
26002
26845
|
const hasProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
26003
26846
|
if (hasProvider) {
|
|
26004
|
-
const basename =
|
|
26847
|
+
const basename = path33.basename(agentFile);
|
|
26005
26848
|
addLoss(lossReport, "copilot", "agents", {
|
|
26006
26849
|
source: `agents/${basename}`,
|
|
26007
26850
|
fields: [
|
|
@@ -26026,23 +26869,23 @@ function syncCopilotInstructions(config, sourceRoot, options, lossReport, logger
|
|
|
26026
26869
|
logger.verbose(message);
|
|
26027
26870
|
return [{ component: "instructions", status: "skipped", path: message }];
|
|
26028
26871
|
}
|
|
26029
|
-
const source =
|
|
26030
|
-
if (!
|
|
26872
|
+
const source = path33.resolve(sourceRoot, config.source.instructions);
|
|
26873
|
+
if (!fs33.existsSync(source)) {
|
|
26031
26874
|
return [skippedMissingSource2("instructions", source)];
|
|
26032
26875
|
}
|
|
26033
|
-
const rawContent =
|
|
26876
|
+
const rawContent = fs33.readFileSync(source, "utf8");
|
|
26034
26877
|
const contentHash = hashString2(rawContent);
|
|
26035
26878
|
const marker = formatProvenanceMarker(
|
|
26036
26879
|
"markdown",
|
|
26037
|
-
|
|
26880
|
+
path33.basename(config.source.instructions),
|
|
26038
26881
|
contentHash,
|
|
26039
26882
|
"copilot"
|
|
26040
26883
|
);
|
|
26041
26884
|
const composedContent = `${marker}
|
|
26042
26885
|
${rawContent}`;
|
|
26043
26886
|
const projectRoot = options.projectRoot ?? process.cwd();
|
|
26044
|
-
const agentsMdDest =
|
|
26045
|
-
const mirrorDest =
|
|
26887
|
+
const agentsMdDest = path33.resolve(projectRoot, "AGENTS.md");
|
|
26888
|
+
const mirrorDest = path33.resolve(
|
|
26046
26889
|
projectRoot,
|
|
26047
26890
|
".github",
|
|
26048
26891
|
"copilot-instructions.md"
|
|
@@ -26096,17 +26939,17 @@ function writeInstructionsFile(component, destination, content, contentHash, con
|
|
|
26096
26939
|
if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
|
|
26097
26940
|
return { component, status: "conflict", path: destination };
|
|
26098
26941
|
}
|
|
26099
|
-
ensureDir(
|
|
26100
|
-
|
|
26942
|
+
ensureDir(path33.dirname(destination));
|
|
26943
|
+
fs33.writeFileSync(destination, content);
|
|
26101
26944
|
return { component, status: "success", path: destination };
|
|
26102
26945
|
}
|
|
26103
26946
|
function hashString2(value) {
|
|
26104
26947
|
return `sha256:${crypto6.createHash("sha256").update(value).digest("hex")}`;
|
|
26105
26948
|
}
|
|
26106
26949
|
function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
26107
|
-
const source =
|
|
26950
|
+
const source = path33.resolve(sourceRoot, config.source.skills);
|
|
26108
26951
|
const destination = resolveTargetPath(paths.skills);
|
|
26109
|
-
if (!
|
|
26952
|
+
if (!fs33.existsSync(source)) {
|
|
26110
26953
|
return skippedMissingSource2("skills", source);
|
|
26111
26954
|
}
|
|
26112
26955
|
if (options.dryRun) {
|
|
@@ -26122,27 +26965,27 @@ function syncSkills2(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
26122
26965
|
};
|
|
26123
26966
|
}
|
|
26124
26967
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
26125
|
-
|
|
26968
|
+
fs33.unlinkSync(destination);
|
|
26126
26969
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
|
|
26127
26970
|
return { component: "skills", status: "conflict", path: destination };
|
|
26128
26971
|
} else if (artifactClass === "managed-symlink") {
|
|
26129
|
-
|
|
26972
|
+
fs33.unlinkSync(destination);
|
|
26130
26973
|
}
|
|
26131
|
-
ensureDir(
|
|
26974
|
+
ensureDir(path33.dirname(destination));
|
|
26132
26975
|
createRelativeSymlink(source, destination, "dir");
|
|
26133
26976
|
return { component: "skills", status: "success", path: destination };
|
|
26134
26977
|
}
|
|
26135
26978
|
function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
26136
|
-
const sourceAgentsRoot =
|
|
26137
|
-
if (!
|
|
26979
|
+
const sourceAgentsRoot = path33.join(sourceRoot, config.source.agents);
|
|
26980
|
+
if (!fs33.existsSync(sourceAgentsRoot)) {
|
|
26138
26981
|
return [skippedMissingSource2("agents", sourceAgentsRoot)];
|
|
26139
26982
|
}
|
|
26140
|
-
const sourceAgents = ts(
|
|
26983
|
+
const sourceAgents = ts(path33.join(sourceAgentsRoot, "*.md")).sort();
|
|
26141
26984
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
26142
26985
|
return sourceAgents.map((agentFile) => {
|
|
26143
|
-
const destination =
|
|
26986
|
+
const destination = path33.join(
|
|
26144
26987
|
agentsRoot,
|
|
26145
|
-
`${
|
|
26988
|
+
`${path33.basename(agentFile, ".md")}.agent.md`
|
|
26146
26989
|
);
|
|
26147
26990
|
const compiled = compileAgent(
|
|
26148
26991
|
agentFile,
|
|
@@ -26170,16 +27013,16 @@ function syncAgents2(config, sourceRoot, paths, mappings, extensions, options, l
|
|
|
26170
27013
|
});
|
|
26171
27014
|
}
|
|
26172
27015
|
function syncCommands(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
26173
|
-
const sourceCommandsRoot =
|
|
26174
|
-
if (!
|
|
27016
|
+
const sourceCommandsRoot = path33.join(sourceRoot, config.source.commands);
|
|
27017
|
+
if (!fs33.existsSync(sourceCommandsRoot)) {
|
|
26175
27018
|
return [skippedMissingSource2("commands", sourceCommandsRoot)];
|
|
26176
27019
|
}
|
|
26177
|
-
const sourceCommands = ts(
|
|
27020
|
+
const sourceCommands = ts(path33.join(sourceCommandsRoot, "*.md")).sort();
|
|
26178
27021
|
const promptsRoot = resolveTargetPath(paths.prompts);
|
|
26179
27022
|
return sourceCommands.map((commandFile) => {
|
|
26180
|
-
const destination =
|
|
27023
|
+
const destination = path33.join(
|
|
26181
27024
|
promptsRoot,
|
|
26182
|
-
`${
|
|
27025
|
+
`${path33.basename(commandFile, ".md")}.prompt.md`
|
|
26183
27026
|
);
|
|
26184
27027
|
const compiled = compileCommandPrompt(commandFile);
|
|
26185
27028
|
if (options.dryRun) {
|
|
@@ -26205,14 +27048,14 @@ function syncCommands(config, sourceRoot, paths, options, logger, manifest, scop
|
|
|
26205
27048
|
function syncHooks2(config, sourceRoot, paths, mappings, options, lossReport, logger) {
|
|
26206
27049
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
26207
27050
|
const sourceLabel = hooksSourceLabel(config);
|
|
26208
|
-
const destination =
|
|
27051
|
+
const destination = path33.join(
|
|
26209
27052
|
resolveTargetPath(paths.hooks),
|
|
26210
27053
|
"tangyr-managed.json"
|
|
26211
27054
|
);
|
|
26212
|
-
if (!
|
|
27055
|
+
if (!fs33.existsSync(source)) {
|
|
26213
27056
|
return skippedMissingSource2("hooks", source);
|
|
26214
27057
|
}
|
|
26215
|
-
const sourceHooksJson = JSON.parse(
|
|
27058
|
+
const sourceHooksJson = JSON.parse(fs33.readFileSync(source, "utf8"));
|
|
26216
27059
|
const compiled = compileHooks(
|
|
26217
27060
|
sourceHooksJson,
|
|
26218
27061
|
"copilot",
|
|
@@ -26249,10 +27092,10 @@ function syncMcp2(config, sourceRoot, paths, options, lossReport, logger) {
|
|
|
26249
27092
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
26250
27093
|
const sourceLabel = mcpSourceLabel(config);
|
|
26251
27094
|
const destination = resolveTargetPath(paths.mcp_shared_file);
|
|
26252
|
-
if (!
|
|
27095
|
+
if (!fs33.existsSync(source)) {
|
|
26253
27096
|
return skippedMissingSource2("mcp", source);
|
|
26254
27097
|
}
|
|
26255
|
-
const sourceMcpJson = JSON.parse(
|
|
27098
|
+
const sourceMcpJson = JSON.parse(fs33.readFileSync(source, "utf8"));
|
|
26256
27099
|
const compiled = compileMcp(
|
|
26257
27100
|
sourceMcpJson,
|
|
26258
27101
|
"copilot",
|
|
@@ -26282,13 +27125,13 @@ function writeCompiledArtifact2(component, destination, content, expectedHash, c
|
|
|
26282
27125
|
if (artifactClass === "unmanaged-conflict" && !handleConflict2(destination, config, options, logger, manifest, scopePath)) {
|
|
26283
27126
|
return { component, status: "conflict", path: destination };
|
|
26284
27127
|
}
|
|
26285
|
-
ensureDir(
|
|
26286
|
-
|
|
27128
|
+
ensureDir(path33.dirname(destination));
|
|
27129
|
+
fs33.writeFileSync(destination, content);
|
|
26287
27130
|
return { component, status: "success", path: destination };
|
|
26288
27131
|
}
|
|
26289
27132
|
function isCompiledCurrent2(destination, expectedContent, expectedHash) {
|
|
26290
27133
|
try {
|
|
26291
|
-
const current =
|
|
27134
|
+
const current = fs33.readFileSync(destination, "utf8");
|
|
26292
27135
|
const marker = extractProvenanceMarker(current);
|
|
26293
27136
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "copilot" && current === expectedContent : current === expectedContent;
|
|
26294
27137
|
} catch {
|
|
@@ -26311,11 +27154,11 @@ function handleConflict2(destination, config, options, logger, manifest, scopePa
|
|
|
26311
27154
|
backupFile(destination, manifest);
|
|
26312
27155
|
writeManifest(scopePath, manifest);
|
|
26313
27156
|
} else {
|
|
26314
|
-
|
|
27157
|
+
fs33.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
26315
27158
|
}
|
|
26316
27159
|
return true;
|
|
26317
27160
|
}
|
|
26318
|
-
|
|
27161
|
+
fs33.rmSync(destination, { recursive: true, force: true });
|
|
26319
27162
|
return true;
|
|
26320
27163
|
}
|
|
26321
27164
|
function shouldSkipComponent2(options, component) {
|
|
@@ -26324,12 +27167,12 @@ function shouldSkipComponent2(options, component) {
|
|
|
26324
27167
|
function cleanupLegacyAgents(paths, options, logger) {
|
|
26325
27168
|
const currentAgentsRoot = resolveTargetPath(paths.agents);
|
|
26326
27169
|
const legacyAgentsRoot = resolveTargetPath(legacyCopilotAgentsPath);
|
|
26327
|
-
if (
|
|
27170
|
+
if (path33.resolve(currentAgentsRoot) === path33.resolve(legacyAgentsRoot)) {
|
|
26328
27171
|
return [];
|
|
26329
27172
|
}
|
|
26330
27173
|
const outcomes = [];
|
|
26331
27174
|
for (const filePath of ts(
|
|
26332
|
-
|
|
27175
|
+
path33.join(legacyAgentsRoot, "*.agent.md")
|
|
26333
27176
|
).sort()) {
|
|
26334
27177
|
if (!isCopilotManagedCompiledFile(filePath)) {
|
|
26335
27178
|
continue;
|
|
@@ -26339,14 +27182,14 @@ function cleanupLegacyAgents(paths, options, logger) {
|
|
|
26339
27182
|
outcomes.push({ component: "agents", status: "dry-run", path: filePath });
|
|
26340
27183
|
continue;
|
|
26341
27184
|
}
|
|
26342
|
-
|
|
27185
|
+
fs33.rmSync(filePath, { force: true });
|
|
26343
27186
|
outcomes.push({ component: "agents", status: "success", path: filePath });
|
|
26344
27187
|
}
|
|
26345
27188
|
return outcomes;
|
|
26346
27189
|
}
|
|
26347
27190
|
function isCopilotManagedCompiledFile(filePath) {
|
|
26348
27191
|
try {
|
|
26349
|
-
return extractProvenanceMarker(
|
|
27192
|
+
return extractProvenanceMarker(fs33.readFileSync(filePath, "utf8"))?.target === "copilot";
|
|
26350
27193
|
} catch {
|
|
26351
27194
|
return false;
|
|
26352
27195
|
}
|
|
@@ -26360,7 +27203,7 @@ function skippedMissingSource2(component, source) {
|
|
|
26360
27203
|
}
|
|
26361
27204
|
function isSymlinkTo2(linkPath, source) {
|
|
26362
27205
|
try {
|
|
26363
|
-
return
|
|
27206
|
+
return fs33.realpathSync(linkPath) === fs33.realpathSync(source);
|
|
26364
27207
|
} catch {
|
|
26365
27208
|
return false;
|
|
26366
27209
|
}
|
|
@@ -26368,8 +27211,8 @@ function isSymlinkTo2(linkPath, source) {
|
|
|
26368
27211
|
|
|
26369
27212
|
// src/adapters/cursor.ts
|
|
26370
27213
|
import crypto7 from "crypto";
|
|
26371
|
-
import
|
|
26372
|
-
import
|
|
27214
|
+
import fs34 from "fs";
|
|
27215
|
+
import path34 from "path";
|
|
26373
27216
|
function syncCursor(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
26374
27217
|
const scope = options.scope ?? "global";
|
|
26375
27218
|
const profile = resolveTargetPaths({
|
|
@@ -26520,9 +27363,9 @@ function syncCursor(config, sourceRoot, mappings, extensions, options, lossRepor
|
|
|
26520
27363
|
return { target: "cursor", outcomes };
|
|
26521
27364
|
}
|
|
26522
27365
|
function syncInstructions2(config, sourceRoot, paths, options, lossReport, logger, manifest, scopePath) {
|
|
26523
|
-
const source =
|
|
27366
|
+
const source = path34.join(sourceRoot, config.source.instructions);
|
|
26524
27367
|
const destination = resolveTargetPath(paths.instructions);
|
|
26525
|
-
const baseContent =
|
|
27368
|
+
const baseContent = fs34.existsSync(source) ? fs34.readFileSync(source, "utf8").trim() : "";
|
|
26526
27369
|
const personaContent = extractPrimaryPersonaContent(
|
|
26527
27370
|
config,
|
|
26528
27371
|
sourceRoot,
|
|
@@ -26535,7 +27378,7 @@ function syncInstructions2(config, sourceRoot, paths, options, lossReport, logge
|
|
|
26535
27378
|
${personaContent}`.trim() : baseContent;
|
|
26536
27379
|
const marker = formatProvenanceMarker(
|
|
26537
27380
|
"markdown",
|
|
26538
|
-
|
|
27381
|
+
path34.basename(config.source.instructions),
|
|
26539
27382
|
hashString3(composed),
|
|
26540
27383
|
"cursor"
|
|
26541
27384
|
);
|
|
@@ -26560,11 +27403,11 @@ ${composed}
|
|
|
26560
27403
|
);
|
|
26561
27404
|
}
|
|
26562
27405
|
function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
26563
|
-
const agentsDir =
|
|
26564
|
-
if (!
|
|
27406
|
+
const agentsDir = path34.join(sourceRoot, config.source.agents);
|
|
27407
|
+
if (!fs34.existsSync(agentsDir)) {
|
|
26565
27408
|
return null;
|
|
26566
27409
|
}
|
|
26567
|
-
const agentFiles = ts(
|
|
27410
|
+
const agentFiles = ts(path34.join(agentsDir, "*.md")).sort();
|
|
26568
27411
|
if (agentFiles.length === 0) {
|
|
26569
27412
|
return null;
|
|
26570
27413
|
}
|
|
@@ -26587,7 +27430,7 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
|
26587
27430
|
return null;
|
|
26588
27431
|
}
|
|
26589
27432
|
addLoss(lossReport, "cursor", "instructions", {
|
|
26590
|
-
source: `agents/${
|
|
27433
|
+
source: `agents/${path34.basename(primaryFile)}`,
|
|
26591
27434
|
fields: [
|
|
26592
27435
|
{
|
|
26593
27436
|
field: "persona",
|
|
@@ -26597,23 +27440,23 @@ function extractPrimaryPersonaContent(config, sourceRoot, lossReport) {
|
|
|
26597
27440
|
"persona",
|
|
26598
27441
|
"instructions-shim"
|
|
26599
27442
|
),
|
|
26600
|
-
detail: `Primary persona from ${
|
|
27443
|
+
detail: `Primary persona from ${path34.basename(primaryFile)} folded into AGENTS.md (Cursor has no custom modes surface)`
|
|
26601
27444
|
}
|
|
26602
27445
|
]
|
|
26603
27446
|
});
|
|
26604
27447
|
return body.trim();
|
|
26605
27448
|
}
|
|
26606
27449
|
function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
26607
|
-
const sourceAgentsRoot =
|
|
26608
|
-
if (!
|
|
27450
|
+
const sourceAgentsRoot = path34.join(sourceRoot, config.source.agents);
|
|
27451
|
+
if (!fs34.existsSync(sourceAgentsRoot)) {
|
|
26609
27452
|
return [skippedMissingSource3("agents", sourceAgentsRoot)];
|
|
26610
27453
|
}
|
|
26611
|
-
const sourceAgents = ts(
|
|
27454
|
+
const sourceAgents = ts(path34.join(sourceAgentsRoot, "*.md")).sort();
|
|
26612
27455
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
26613
27456
|
return sourceAgents.map((agentFile) => {
|
|
26614
|
-
const destination =
|
|
27457
|
+
const destination = path34.join(
|
|
26615
27458
|
agentsRoot,
|
|
26616
|
-
`${
|
|
27459
|
+
`${path34.basename(agentFile, ".md")}.md`
|
|
26617
27460
|
);
|
|
26618
27461
|
let compiled;
|
|
26619
27462
|
try {
|
|
@@ -26654,14 +27497,14 @@ function syncAgents3(config, sourceRoot, paths, mappings, extensions, options, l
|
|
|
26654
27497
|
});
|
|
26655
27498
|
}
|
|
26656
27499
|
function syncRules2(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
|
|
26657
|
-
const sourceRulesDir =
|
|
26658
|
-
if (!
|
|
27500
|
+
const sourceRulesDir = path34.join(sourceRoot, config.source.rules);
|
|
27501
|
+
if (!fs34.existsSync(sourceRulesDir)) {
|
|
26659
27502
|
return [skippedMissingSource3("rules", sourceRulesDir)];
|
|
26660
27503
|
}
|
|
26661
27504
|
const compiled = compileRules(sourceRulesDir, "cursor", mappings, lossReport);
|
|
26662
27505
|
const rulesDir = resolveTargetPath(paths.rules);
|
|
26663
27506
|
return compiled.dotRulesFiles.map(({ name, content }) => {
|
|
26664
|
-
const destination =
|
|
27507
|
+
const destination = path34.join(rulesDir, name);
|
|
26665
27508
|
if (options.dryRun) {
|
|
26666
27509
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
26667
27510
|
return {
|
|
@@ -26685,17 +27528,17 @@ function syncRules2(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
26685
27528
|
});
|
|
26686
27529
|
}
|
|
26687
27530
|
function syncCommands2(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
26688
|
-
const sourceCommandsRoot =
|
|
26689
|
-
if (!
|
|
27531
|
+
const sourceCommandsRoot = path34.join(sourceRoot, config.source.commands);
|
|
27532
|
+
if (!fs34.existsSync(sourceCommandsRoot)) {
|
|
26690
27533
|
return [skippedMissingSource3("commands", sourceCommandsRoot)];
|
|
26691
27534
|
}
|
|
26692
|
-
const sourceCommands = ts(
|
|
27535
|
+
const sourceCommands = ts(path34.join(sourceCommandsRoot, "*.md")).sort();
|
|
26693
27536
|
const skillsRoot = resolveTargetPath(paths.skills);
|
|
26694
27537
|
return sourceCommands.map((commandFile) => {
|
|
26695
|
-
const baseName =
|
|
26696
|
-
const destination =
|
|
26697
|
-
const commandContent =
|
|
26698
|
-
const relativeSource = `commands/${
|
|
27538
|
+
const baseName = path34.basename(commandFile, ".md");
|
|
27539
|
+
const destination = path34.join(skillsRoot, baseName, "SKILL.md");
|
|
27540
|
+
const commandContent = fs34.readFileSync(commandFile, "utf8");
|
|
27541
|
+
const relativeSource = `commands/${path34.basename(commandFile)}`;
|
|
26699
27542
|
const marker = formatProvenanceMarker(
|
|
26700
27543
|
"markdown",
|
|
26701
27544
|
relativeSource,
|
|
@@ -26733,9 +27576,9 @@ ${commandContent.trim()}
|
|
|
26733
27576
|
);
|
|
26734
27577
|
});
|
|
26735
27578
|
}
|
|
26736
|
-
function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, component = "skills", destination = "", asSymlink = false) {
|
|
26737
|
-
const source =
|
|
26738
|
-
if (!
|
|
27579
|
+
function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, component = "skills", destination = "", asSymlink = false) {
|
|
27580
|
+
const source = path34.resolve(sourceRoot, config.source.skills);
|
|
27581
|
+
if (!fs34.existsSync(source)) {
|
|
26739
27582
|
return skippedMissingSource3(component, source);
|
|
26740
27583
|
}
|
|
26741
27584
|
if (options.dryRun) {
|
|
@@ -26749,18 +27592,18 @@ function syncSkills3(config, sourceRoot, options, logger, manifest, scopePath, c
|
|
|
26749
27592
|
return { component, status: "skipped-current", path: destination };
|
|
26750
27593
|
}
|
|
26751
27594
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
26752
|
-
|
|
27595
|
+
fs34.unlinkSync(destination);
|
|
26753
27596
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
|
|
26754
27597
|
return { component, status: "conflict", path: destination };
|
|
26755
27598
|
} else if (artifactClass === "managed-symlink") {
|
|
26756
|
-
|
|
27599
|
+
fs34.unlinkSync(destination);
|
|
26757
27600
|
}
|
|
26758
|
-
ensureDir(
|
|
27601
|
+
ensureDir(path34.dirname(destination));
|
|
26759
27602
|
createRelativeSymlink(source, destination, "dir");
|
|
26760
27603
|
logger.verbose(`Skills: created shared skills symlink ${destination}`);
|
|
26761
27604
|
return { component, status: "success", path: destination };
|
|
26762
27605
|
}
|
|
26763
|
-
if (
|
|
27606
|
+
if (fs34.existsSync(destination)) {
|
|
26764
27607
|
return { component, status: "skipped-current", path: destination };
|
|
26765
27608
|
}
|
|
26766
27609
|
ensureDir(destination);
|
|
@@ -26771,7 +27614,7 @@ function syncHooks3(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
26771
27614
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
26772
27615
|
const sourceLabel = hooksSourceLabel(config);
|
|
26773
27616
|
const destination = resolveTargetPath(paths.hooks_file);
|
|
26774
|
-
const sourceHooksJson =
|
|
27617
|
+
const sourceHooksJson = fs34.existsSync(source) ? JSON.parse(fs34.readFileSync(source, "utf8")) : { hooks: {} };
|
|
26775
27618
|
const compiled = compileHooks(
|
|
26776
27619
|
sourceHooksJson,
|
|
26777
27620
|
"cursor",
|
|
@@ -26785,18 +27628,18 @@ function syncHooks3(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
26785
27628
|
}
|
|
26786
27629
|
const hooksFileContent = `${JSON.stringify({ version: 1, hooks: compiled.payload }, null, 2)}
|
|
26787
27630
|
`;
|
|
26788
|
-
ensureDir(
|
|
26789
|
-
|
|
27631
|
+
ensureDir(path34.dirname(destination));
|
|
27632
|
+
fs34.writeFileSync(destination, hooksFileContent);
|
|
26790
27633
|
return { component: "hooks", status: "success", path: destination };
|
|
26791
27634
|
}
|
|
26792
27635
|
function syncMcp3(config, sourceRoot, paths, options, lossReport, logger, manifest, scopePath) {
|
|
26793
27636
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
26794
27637
|
const sourceLabel = mcpSourceLabel(config);
|
|
26795
27638
|
const destination = resolveTargetPath(paths.mcp_file);
|
|
26796
|
-
if (!
|
|
27639
|
+
if (!fs34.existsSync(source)) {
|
|
26797
27640
|
return skippedMissingSource3("mcp", source);
|
|
26798
27641
|
}
|
|
26799
|
-
const sourceMcpJson = JSON.parse(
|
|
27642
|
+
const sourceMcpJson = JSON.parse(fs34.readFileSync(source, "utf8"));
|
|
26800
27643
|
const mcpJson = compileMcp(sourceMcpJson, "cursor", lossReport, sourceLabel);
|
|
26801
27644
|
if (options.dryRun) {
|
|
26802
27645
|
logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
|
|
@@ -26847,13 +27690,13 @@ function syncPermissions(config, paths, options, _lossReport, logger, manifest,
|
|
|
26847
27690
|
);
|
|
26848
27691
|
}
|
|
26849
27692
|
function syncProviderPin(config, sourceRoot, lossReport) {
|
|
26850
|
-
const agentsDir =
|
|
26851
|
-
if (!
|
|
26852
|
-
for (const agentFile of ts(
|
|
27693
|
+
const agentsDir = path34.join(sourceRoot, config.source.agents);
|
|
27694
|
+
if (!fs34.existsSync(agentsDir)) return;
|
|
27695
|
+
for (const agentFile of ts(path34.join(agentsDir, "*.md")).sort()) {
|
|
26853
27696
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
26854
27697
|
const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
26855
27698
|
if (hasCustomProvider) {
|
|
26856
|
-
const relativeSource = `agents/${
|
|
27699
|
+
const relativeSource = `agents/${path34.basename(agentFile)}`;
|
|
26857
27700
|
addLoss(lossReport, "cursor", "agents", {
|
|
26858
27701
|
source: relativeSource,
|
|
26859
27702
|
fields: [
|
|
@@ -26865,7 +27708,7 @@ function syncProviderPin(config, sourceRoot, lossReport) {
|
|
|
26865
27708
|
"provider",
|
|
26866
27709
|
"provider-not-representable"
|
|
26867
27710
|
),
|
|
26868
|
-
detail: `${
|
|
27711
|
+
detail: `${path34.basename(agentFile)}: custom provider cannot be expressed in Cursor subagent frontmatter \u2014 configure manually via Cursor settings`
|
|
26869
27712
|
}
|
|
26870
27713
|
]
|
|
26871
27714
|
});
|
|
@@ -26880,8 +27723,8 @@ function writeCompiledArtifact3(component, destination, content, expectedHash, c
|
|
|
26880
27723
|
if (artifactClass === "unmanaged-conflict" && !handleConflict3(destination, config, options, logger, manifest, scopePath)) {
|
|
26881
27724
|
return { component, status: "conflict", path: destination };
|
|
26882
27725
|
}
|
|
26883
|
-
ensureDir(
|
|
26884
|
-
|
|
27726
|
+
ensureDir(path34.dirname(destination));
|
|
27727
|
+
fs34.writeFileSync(destination, content);
|
|
26885
27728
|
return { component, status: "success", path: destination };
|
|
26886
27729
|
}
|
|
26887
27730
|
function handleConflict3(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -26900,16 +27743,16 @@ function handleConflict3(destination, config, options, logger, manifest, scopePa
|
|
|
26900
27743
|
backupFile(destination, manifest);
|
|
26901
27744
|
writeManifest(scopePath, manifest);
|
|
26902
27745
|
} else {
|
|
26903
|
-
|
|
27746
|
+
fs34.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
26904
27747
|
}
|
|
26905
27748
|
return true;
|
|
26906
27749
|
}
|
|
26907
|
-
|
|
27750
|
+
fs34.rmSync(destination, { recursive: true, force: true });
|
|
26908
27751
|
return true;
|
|
26909
27752
|
}
|
|
26910
27753
|
function isCompiledCurrent3(destination, expectedContent, expectedHash) {
|
|
26911
27754
|
try {
|
|
26912
|
-
const current =
|
|
27755
|
+
const current = fs34.readFileSync(destination, "utf8");
|
|
26913
27756
|
const marker = extractProvenanceMarker(current);
|
|
26914
27757
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "cursor" && current === expectedContent : current === expectedContent;
|
|
26915
27758
|
} catch {
|
|
@@ -26928,7 +27771,7 @@ function shouldSkipComponent3(options, component) {
|
|
|
26928
27771
|
}
|
|
26929
27772
|
function isSymlinkTo3(linkPath, source) {
|
|
26930
27773
|
try {
|
|
26931
|
-
return
|
|
27774
|
+
return fs34.realpathSync(linkPath) === fs34.realpathSync(source);
|
|
26932
27775
|
} catch {
|
|
26933
27776
|
return false;
|
|
26934
27777
|
}
|
|
@@ -26939,8 +27782,8 @@ function hashString3(value) {
|
|
|
26939
27782
|
|
|
26940
27783
|
// src/adapters/cline.ts
|
|
26941
27784
|
import crypto8 from "crypto";
|
|
26942
|
-
import
|
|
26943
|
-
import
|
|
27785
|
+
import fs35 from "fs";
|
|
27786
|
+
import path35 from "path";
|
|
26944
27787
|
function syncCline(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
26945
27788
|
const scope = options.scope ?? "global";
|
|
26946
27789
|
const profile = resolveTargetPaths({
|
|
@@ -27053,7 +27896,7 @@ function syncCline(config, sourceRoot, mappings, extensions, options, lossReport
|
|
|
27053
27896
|
function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport, logger, manifest, scopePath) {
|
|
27054
27897
|
if (scope === "global" || paths.instructions === null) {
|
|
27055
27898
|
addLoss(lossReport, "cline", "instructions", {
|
|
27056
|
-
source:
|
|
27899
|
+
source: path35.basename(config.source.instructions),
|
|
27057
27900
|
fields: [
|
|
27058
27901
|
{
|
|
27059
27902
|
field: "instructions",
|
|
@@ -27073,12 +27916,12 @@ function syncInstructions3(config, sourceRoot, paths, scope, options, lossReport
|
|
|
27073
27916
|
path: "cline/global/instructions: no committable global path"
|
|
27074
27917
|
};
|
|
27075
27918
|
}
|
|
27076
|
-
const source =
|
|
27919
|
+
const source = path35.join(sourceRoot, config.source.instructions);
|
|
27077
27920
|
const destination = resolveTargetPath(paths.instructions);
|
|
27078
|
-
const baseContent =
|
|
27921
|
+
const baseContent = fs35.existsSync(source) ? fs35.readFileSync(source, "utf8").trim() : "";
|
|
27079
27922
|
const marker = formatProvenanceMarker(
|
|
27080
27923
|
"markdown",
|
|
27081
|
-
|
|
27924
|
+
path35.basename(config.source.instructions),
|
|
27082
27925
|
hashString4(baseContent),
|
|
27083
27926
|
"cline"
|
|
27084
27927
|
);
|
|
@@ -27103,11 +27946,11 @@ ${baseContent}
|
|
|
27103
27946
|
);
|
|
27104
27947
|
}
|
|
27105
27948
|
function syncAgents4(config, sourceRoot, mappings, extensions, options, lossReport, logger) {
|
|
27106
|
-
const sourceAgentsRoot =
|
|
27107
|
-
if (!
|
|
27949
|
+
const sourceAgentsRoot = path35.join(sourceRoot, config.source.agents);
|
|
27950
|
+
if (!fs35.existsSync(sourceAgentsRoot)) {
|
|
27108
27951
|
return [skippedMissingSource4("agents", sourceAgentsRoot)];
|
|
27109
27952
|
}
|
|
27110
|
-
const sourceAgents = ts(
|
|
27953
|
+
const sourceAgents = ts(path35.join(sourceAgentsRoot, "*.md")).sort();
|
|
27111
27954
|
return sourceAgents.map((agentFile) => {
|
|
27112
27955
|
compileAgent(agentFile, "cline", mappings, extensions, lossReport);
|
|
27113
27956
|
if (options.dryRun) {
|
|
@@ -27123,14 +27966,14 @@ function syncAgents4(config, sourceRoot, mappings, extensions, options, lossRepo
|
|
|
27123
27966
|
});
|
|
27124
27967
|
}
|
|
27125
27968
|
function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, logger, manifest, scopePath) {
|
|
27126
|
-
const sourceRulesDir =
|
|
27127
|
-
if (!
|
|
27969
|
+
const sourceRulesDir = path35.join(sourceRoot, config.source.rules);
|
|
27970
|
+
if (!fs35.existsSync(sourceRulesDir)) {
|
|
27128
27971
|
return [skippedMissingSource4("rules", sourceRulesDir)];
|
|
27129
27972
|
}
|
|
27130
27973
|
const compiled = compileRules(sourceRulesDir, "cline", mappings, lossReport);
|
|
27131
27974
|
const rulesDir = resolveTargetPath(paths.rules);
|
|
27132
27975
|
return compiled.dotRulesFiles.map(({ name, content }) => {
|
|
27133
|
-
const destination =
|
|
27976
|
+
const destination = path35.join(rulesDir, name);
|
|
27134
27977
|
if (options.dryRun) {
|
|
27135
27978
|
logger.info(`[dry-run] rules: write ${destination}`);
|
|
27136
27979
|
return {
|
|
@@ -27154,17 +27997,17 @@ function syncRules3(config, sourceRoot, paths, mappings, options, lossReport, lo
|
|
|
27154
27997
|
});
|
|
27155
27998
|
}
|
|
27156
27999
|
function syncCommands3(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
27157
|
-
const sourceCommandsRoot =
|
|
27158
|
-
if (!
|
|
28000
|
+
const sourceCommandsRoot = path35.join(sourceRoot, config.source.commands);
|
|
28001
|
+
if (!fs35.existsSync(sourceCommandsRoot)) {
|
|
27159
28002
|
return [skippedMissingSource4("commands", sourceCommandsRoot)];
|
|
27160
28003
|
}
|
|
27161
|
-
const sourceCommands = ts(
|
|
28004
|
+
const sourceCommands = ts(path35.join(sourceCommandsRoot, "*.md")).sort();
|
|
27162
28005
|
const workflowsRoot = resolveTargetPath(paths.workflows);
|
|
27163
28006
|
return sourceCommands.map((commandFile) => {
|
|
27164
|
-
const baseName =
|
|
27165
|
-
const destination =
|
|
27166
|
-
const commandContent =
|
|
27167
|
-
const relativeSource = `commands/${
|
|
28007
|
+
const baseName = path35.basename(commandFile);
|
|
28008
|
+
const destination = path35.join(workflowsRoot, baseName);
|
|
28009
|
+
const commandContent = fs35.readFileSync(commandFile, "utf8");
|
|
28010
|
+
const relativeSource = `commands/${path35.basename(commandFile)}`;
|
|
27168
28011
|
const marker = formatProvenanceMarker(
|
|
27169
28012
|
"markdown",
|
|
27170
28013
|
relativeSource,
|
|
@@ -27199,9 +28042,9 @@ ${commandContent.trim()}
|
|
|
27199
28042
|
});
|
|
27200
28043
|
}
|
|
27201
28044
|
function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
27202
|
-
const source =
|
|
28045
|
+
const source = path35.resolve(sourceRoot, config.source.skills);
|
|
27203
28046
|
const destination = resolveTargetPath(paths.skills);
|
|
27204
|
-
if (!
|
|
28047
|
+
if (!fs35.existsSync(source)) {
|
|
27205
28048
|
return skippedMissingSource4("skills", source);
|
|
27206
28049
|
}
|
|
27207
28050
|
if (options.dryRun) {
|
|
@@ -27221,9 +28064,9 @@ function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
27221
28064
|
return { component: "skills", status: "conflict", path: destination };
|
|
27222
28065
|
}
|
|
27223
28066
|
} else if (artifactClass === "managed-symlink") {
|
|
27224
|
-
|
|
28067
|
+
fs35.unlinkSync(destination);
|
|
27225
28068
|
}
|
|
27226
|
-
ensureDir(
|
|
28069
|
+
ensureDir(path35.dirname(destination));
|
|
27227
28070
|
createRelativeSymlink(source, destination, "dir");
|
|
27228
28071
|
logger.verbose(`Skills: created Cline skills symlink ${destination}`);
|
|
27229
28072
|
return { component: "skills", status: "success", path: destination };
|
|
@@ -27231,7 +28074,7 @@ function syncSkills4(config, sourceRoot, paths, options, logger, manifest, scope
|
|
|
27231
28074
|
function syncHooks4(config, sourceRoot, mappings, options, lossReport, logger) {
|
|
27232
28075
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
27233
28076
|
const sourceLabel = hooksSourceLabel(config);
|
|
27234
|
-
const sourceHooksJson =
|
|
28077
|
+
const sourceHooksJson = fs35.existsSync(source) ? JSON.parse(fs35.readFileSync(source, "utf8")) : { hooks: {} };
|
|
27235
28078
|
compileHooks(sourceHooksJson, "cline", mappings, lossReport, sourceLabel);
|
|
27236
28079
|
if (options.dryRun) {
|
|
27237
28080
|
logger.info(`[dry-run] hooks: record hook-as-plugin loss for ${source}`);
|
|
@@ -27246,10 +28089,10 @@ function syncMcp4(config, sourceRoot, paths, options, lossReport, logger, manife
|
|
|
27246
28089
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
27247
28090
|
const sourceLabel = mcpSourceLabel(config);
|
|
27248
28091
|
const destination = resolveTargetPath(paths.mcp_file);
|
|
27249
|
-
if (!
|
|
28092
|
+
if (!fs35.existsSync(source)) {
|
|
27250
28093
|
return skippedMissingSource4("mcp", source);
|
|
27251
28094
|
}
|
|
27252
|
-
const sourceMcpJson = JSON.parse(
|
|
28095
|
+
const sourceMcpJson = JSON.parse(fs35.readFileSync(source, "utf8"));
|
|
27253
28096
|
const mcpJson = compileMcp(sourceMcpJson, "cline", lossReport, sourceLabel);
|
|
27254
28097
|
if (options.dryRun) {
|
|
27255
28098
|
logger.info(`[dry-run] mcp: compile ${source} -> ${destination}`);
|
|
@@ -27292,11 +28135,11 @@ function syncSettings(lossReport) {
|
|
|
27292
28135
|
};
|
|
27293
28136
|
}
|
|
27294
28137
|
function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
27295
|
-
const agentsDir =
|
|
27296
|
-
if (!
|
|
27297
|
-
for (const agentFile of ts(
|
|
28138
|
+
const agentsDir = path35.join(sourceRoot, config.source.agents);
|
|
28139
|
+
if (!fs35.existsSync(agentsDir)) return;
|
|
28140
|
+
for (const agentFile of ts(path35.join(agentsDir, "*.md")).sort()) {
|
|
27298
28141
|
const { data } = parseMarkdownFrontmatter(agentFile);
|
|
27299
|
-
const relativeSource = `agents/${
|
|
28142
|
+
const relativeSource = `agents/${path35.basename(agentFile)}`;
|
|
27300
28143
|
const hasCustomProvider = typeof data.provider === "string" || typeof data.provider === "object" && data.provider !== null && Object.keys(data.provider).length > 0;
|
|
27301
28144
|
if (hasCustomProvider) {
|
|
27302
28145
|
addLoss(lossReport, "cline", "agents", {
|
|
@@ -27310,7 +28153,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
|
27310
28153
|
"provider",
|
|
27311
28154
|
"provider-not-representable"
|
|
27312
28155
|
),
|
|
27313
|
-
detail: `${
|
|
28156
|
+
detail: `${path35.basename(agentFile)}: Cline provider is interface-only (Settings \u2192 API Provider); configure manually.`
|
|
27314
28157
|
}
|
|
27315
28158
|
]
|
|
27316
28159
|
});
|
|
@@ -27328,7 +28171,7 @@ function syncProviderAndModel(config, sourceRoot, lossReport) {
|
|
|
27328
28171
|
"model",
|
|
27329
28172
|
"model-not-representable"
|
|
27330
28173
|
),
|
|
27331
|
-
detail: `${
|
|
28174
|
+
detail: `${path35.basename(agentFile)}: Cline model pin is interface-only (Settings \u2192 Model); configure manually.`
|
|
27332
28175
|
}
|
|
27333
28176
|
]
|
|
27334
28177
|
});
|
|
@@ -27343,8 +28186,8 @@ function writeCompiledArtifact4(component, destination, content, expectedHash, c
|
|
|
27343
28186
|
if (artifactClass === "unmanaged-conflict" && !handleConflict4(destination, config, options, logger, manifest, scopePath)) {
|
|
27344
28187
|
return { component, status: "conflict", path: destination };
|
|
27345
28188
|
}
|
|
27346
|
-
ensureDir(
|
|
27347
|
-
|
|
28189
|
+
ensureDir(path35.dirname(destination));
|
|
28190
|
+
fs35.writeFileSync(destination, content);
|
|
27348
28191
|
return { component, status: "success", path: destination };
|
|
27349
28192
|
}
|
|
27350
28193
|
function handleConflict4(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -27363,16 +28206,16 @@ function handleConflict4(destination, config, options, logger, manifest, scopePa
|
|
|
27363
28206
|
backupFile(destination, manifest);
|
|
27364
28207
|
writeManifest(scopePath, manifest);
|
|
27365
28208
|
} else {
|
|
27366
|
-
|
|
28209
|
+
fs35.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
27367
28210
|
}
|
|
27368
28211
|
return true;
|
|
27369
28212
|
}
|
|
27370
|
-
|
|
28213
|
+
fs35.rmSync(destination, { recursive: true, force: true });
|
|
27371
28214
|
return true;
|
|
27372
28215
|
}
|
|
27373
28216
|
function isCompiledCurrent4(destination, expectedContent, expectedHash) {
|
|
27374
28217
|
try {
|
|
27375
|
-
const current =
|
|
28218
|
+
const current = fs35.readFileSync(destination, "utf8");
|
|
27376
28219
|
const marker = extractProvenanceMarker(current);
|
|
27377
28220
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "cline" && current === expectedContent : current === expectedContent;
|
|
27378
28221
|
} catch {
|
|
@@ -27391,7 +28234,7 @@ function shouldSkipComponent4(options, component) {
|
|
|
27391
28234
|
}
|
|
27392
28235
|
function isSymlinkTo4(linkPath, source) {
|
|
27393
28236
|
try {
|
|
27394
|
-
return
|
|
28237
|
+
return fs35.realpathSync(linkPath) === fs35.realpathSync(source);
|
|
27395
28238
|
} catch {
|
|
27396
28239
|
return false;
|
|
27397
28240
|
}
|
|
@@ -27402,10 +28245,10 @@ function hashString4(value) {
|
|
|
27402
28245
|
|
|
27403
28246
|
// src/adapters/opencode.ts
|
|
27404
28247
|
import crypto9 from "crypto";
|
|
27405
|
-
import
|
|
28248
|
+
import fs36 from "fs";
|
|
27406
28249
|
import os6 from "os";
|
|
27407
|
-
import
|
|
27408
|
-
var
|
|
28250
|
+
import path36 from "path";
|
|
28251
|
+
var import_yaml11 = __toESM(require_dist(), 1);
|
|
27409
28252
|
function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
27410
28253
|
const scope = options.scope ?? "global";
|
|
27411
28254
|
const profile = resolveTargetPaths({
|
|
@@ -27422,7 +28265,7 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
|
|
|
27422
28265
|
config_doc: profile.config_doc
|
|
27423
28266
|
};
|
|
27424
28267
|
const rules = compileRules(
|
|
27425
|
-
|
|
28268
|
+
path36.join(sourceRoot, config.source.rules),
|
|
27426
28269
|
"opencode",
|
|
27427
28270
|
mappings,
|
|
27428
28271
|
lossReport
|
|
@@ -27524,16 +28367,16 @@ function syncOpenCode(config, sourceRoot, mappings, extensions, options, lossRep
|
|
|
27524
28367
|
return { target: "opencode", outcomes };
|
|
27525
28368
|
}
|
|
27526
28369
|
function syncInstructions4(config, sourceRoot, paths, agentsAppendix, options, logger, manifest, scopePath) {
|
|
27527
|
-
const source =
|
|
28370
|
+
const source = path36.join(sourceRoot, config.source.instructions);
|
|
27528
28371
|
const destination = resolveTargetPath(paths.instructions);
|
|
27529
|
-
const baseContent =
|
|
28372
|
+
const baseContent = fs36.existsSync(source) ? fs36.readFileSync(source, "utf8").trim() : "";
|
|
27530
28373
|
const composed = agentsAppendix ? `${baseContent}
|
|
27531
28374
|
|
|
27532
28375
|
--- tangyr managed rules ---
|
|
27533
28376
|
${agentsAppendix}`.trim() : baseContent;
|
|
27534
28377
|
const marker = formatProvenanceMarker(
|
|
27535
28378
|
"markdown",
|
|
27536
|
-
|
|
28379
|
+
path36.basename(config.source.instructions),
|
|
27537
28380
|
hashString5(composed),
|
|
27538
28381
|
"opencode"
|
|
27539
28382
|
);
|
|
@@ -27560,16 +28403,16 @@ ${composed}
|
|
|
27560
28403
|
);
|
|
27561
28404
|
}
|
|
27562
28405
|
function syncAgents5(config, sourceRoot, paths, mappings, extensions, options, lossReport, logger, manifest, scopePath) {
|
|
27563
|
-
const sourceAgentsRoot =
|
|
27564
|
-
if (!
|
|
28406
|
+
const sourceAgentsRoot = path36.join(sourceRoot, config.source.agents);
|
|
28407
|
+
if (!fs36.existsSync(sourceAgentsRoot)) {
|
|
27565
28408
|
return [skippedMissingSource5("agents", sourceAgentsRoot)];
|
|
27566
28409
|
}
|
|
27567
|
-
const sourceAgents = ts(
|
|
28410
|
+
const sourceAgents = ts(path36.join(sourceAgentsRoot, "*.md")).sort();
|
|
27568
28411
|
const agentsRoot = resolveTargetPath(paths.agents);
|
|
27569
28412
|
return sourceAgents.map((agentFile) => {
|
|
27570
|
-
const destination =
|
|
28413
|
+
const destination = path36.join(
|
|
27571
28414
|
agentsRoot,
|
|
27572
|
-
`${
|
|
28415
|
+
`${path36.basename(agentFile, ".md")}.md`
|
|
27573
28416
|
);
|
|
27574
28417
|
let compiled;
|
|
27575
28418
|
try {
|
|
@@ -27625,19 +28468,19 @@ function applyProviderModelBinding(compiled, mappings) {
|
|
|
27625
28468
|
const after = compiled.slice(fmEnd);
|
|
27626
28469
|
let fields;
|
|
27627
28470
|
try {
|
|
27628
|
-
fields = (0,
|
|
28471
|
+
fields = (0, import_yaml11.parse)(yamlBlock) ?? {};
|
|
27629
28472
|
} catch {
|
|
27630
28473
|
return compiled;
|
|
27631
28474
|
}
|
|
27632
28475
|
fields.model = modelValue;
|
|
27633
|
-
return `${before}${(0,
|
|
28476
|
+
return `${before}${(0, import_yaml11.stringify)(fields).trim()}${after}`;
|
|
27634
28477
|
}
|
|
27635
28478
|
function syncCommands4(config, sourceRoot, paths, options, logger, manifest, scopePath) {
|
|
27636
|
-
const sourceCommandsRoot =
|
|
27637
|
-
if (!
|
|
28479
|
+
const sourceCommandsRoot = path36.join(sourceRoot, config.source.commands);
|
|
28480
|
+
if (!fs36.existsSync(sourceCommandsRoot)) {
|
|
27638
28481
|
return [skippedMissingSource5("commands", sourceCommandsRoot)];
|
|
27639
28482
|
}
|
|
27640
|
-
const sourceCommands = ts(
|
|
28483
|
+
const sourceCommands = ts(path36.join(sourceCommandsRoot, "*.md")).sort();
|
|
27641
28484
|
const commandsRoot = resolveTargetPath(paths.commands);
|
|
27642
28485
|
return sourceCommands.map((commandFile) => {
|
|
27643
28486
|
const { data, body } = parseCommandFile(commandFile);
|
|
@@ -27651,7 +28494,7 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
|
|
|
27651
28494
|
if (typeof data.model === "string") {
|
|
27652
28495
|
frontmatter.model = data.model;
|
|
27653
28496
|
}
|
|
27654
|
-
const relativeSource = `commands/${
|
|
28497
|
+
const relativeSource = `commands/${path36.basename(commandFile)}`;
|
|
27655
28498
|
const marker = formatProvenanceMarker(
|
|
27656
28499
|
"markdown",
|
|
27657
28500
|
relativeSource,
|
|
@@ -27660,16 +28503,16 @@ function syncCommands4(config, sourceRoot, paths, options, logger, manifest, sco
|
|
|
27660
28503
|
);
|
|
27661
28504
|
const content = Object.keys(frontmatter).length > 0 ? `${marker}
|
|
27662
28505
|
---
|
|
27663
|
-
${(0,
|
|
28506
|
+
${(0, import_yaml11.stringify)(frontmatter).trim()}
|
|
27664
28507
|
---
|
|
27665
28508
|
|
|
27666
28509
|
${body.trimEnd()}
|
|
27667
28510
|
` : `${marker}
|
|
27668
28511
|
${body.trimEnd()}
|
|
27669
28512
|
`;
|
|
27670
|
-
const destination =
|
|
28513
|
+
const destination = path36.join(
|
|
27671
28514
|
commandsRoot,
|
|
27672
|
-
`${
|
|
28515
|
+
`${path36.basename(commandFile, ".md")}.md`
|
|
27673
28516
|
);
|
|
27674
28517
|
if (options.dryRun) {
|
|
27675
28518
|
logger.info(
|
|
@@ -27696,8 +28539,8 @@ ${body.trimEnd()}
|
|
|
27696
28539
|
});
|
|
27697
28540
|
}
|
|
27698
28541
|
function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scopePath, component = "skills", destination = "") {
|
|
27699
|
-
const source =
|
|
27700
|
-
if (!
|
|
28542
|
+
const source = path36.resolve(sourceRoot, config.source.skills);
|
|
28543
|
+
if (!fs36.existsSync(source)) {
|
|
27701
28544
|
return skippedMissingSource5(component, source);
|
|
27702
28545
|
}
|
|
27703
28546
|
if (options.dryRun) {
|
|
@@ -27709,13 +28552,13 @@ function syncSkills5(config, sourceRoot, _paths, options, logger, manifest, scop
|
|
|
27709
28552
|
return { component, status: "skipped-current", path: destination };
|
|
27710
28553
|
}
|
|
27711
28554
|
if (artifactClass === "managed-stale" && isOurStaleSymlink(destination, /* @__PURE__ */ new Set([destination]), config)) {
|
|
27712
|
-
|
|
28555
|
+
fs36.unlinkSync(destination);
|
|
27713
28556
|
} else if (artifactClass === "unmanaged-conflict" && !handleConflict5(destination, config, options, logger, manifest, scopePath)) {
|
|
27714
28557
|
return { component, status: "conflict", path: destination };
|
|
27715
28558
|
} else if (artifactClass === "managed-symlink") {
|
|
27716
|
-
|
|
28559
|
+
fs36.unlinkSync(destination);
|
|
27717
28560
|
}
|
|
27718
|
-
ensureDir(
|
|
28561
|
+
ensureDir(path36.dirname(destination));
|
|
27719
28562
|
createRelativeSymlink(source, destination, "dir");
|
|
27720
28563
|
logger.verbose(`Skills: created skills path ${destination}`);
|
|
27721
28564
|
return { component, status: "success", path: destination };
|
|
@@ -27724,13 +28567,13 @@ function syncMcp5(config, sourceRoot, paths, mappings, options, lossReport, logg
|
|
|
27724
28567
|
const source = resolveMcpSourceFile(sourceRoot, config);
|
|
27725
28568
|
const sourceLabel = mcpSourceLabel(config);
|
|
27726
28569
|
const destination = resolveTargetPath(paths.config_doc);
|
|
27727
|
-
if (!
|
|
28570
|
+
if (!fs36.existsSync(source)) {
|
|
27728
28571
|
if (!options.dryRun) {
|
|
27729
28572
|
syncConfigDoc(paths, {}, lossReport, {}, mappings);
|
|
27730
28573
|
}
|
|
27731
28574
|
return skippedMissingSource5("mcp", source);
|
|
27732
28575
|
}
|
|
27733
|
-
const sourceMcpJson = JSON.parse(
|
|
28576
|
+
const sourceMcpJson = JSON.parse(fs36.readFileSync(source, "utf8"));
|
|
27734
28577
|
const mcpJson = compileMcp(
|
|
27735
28578
|
sourceMcpJson,
|
|
27736
28579
|
"opencode",
|
|
@@ -27761,7 +28604,7 @@ function syncPermissions2(config, _sourceRoot, paths, options, lossReport, logge
|
|
|
27761
28604
|
function syncHooks5(config, sourceRoot, mappings, options, lossReport) {
|
|
27762
28605
|
const source = resolveHooksSourceFile(sourceRoot, config);
|
|
27763
28606
|
const sourceLabel = hooksSourceLabel(config);
|
|
27764
|
-
const sourceHooksJson =
|
|
28607
|
+
const sourceHooksJson = fs36.existsSync(source) ? JSON.parse(fs36.readFileSync(source, "utf8")) : { hooks: {} };
|
|
27765
28608
|
compileHooks(sourceHooksJson, "opencode", mappings, lossReport, sourceLabel);
|
|
27766
28609
|
const message = "hooks: Skip \u2014 OpenCode exposes hooks only as plugin code (hook-as-plugin loss recorded)";
|
|
27767
28610
|
return { component: "hooks", status: "skipped", path: message };
|
|
@@ -27795,9 +28638,9 @@ function syncProviderBlock(mappings) {
|
|
|
27795
28638
|
function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings) {
|
|
27796
28639
|
const destination = resolveTargetPath(paths.config_doc);
|
|
27797
28640
|
let existing = {};
|
|
27798
|
-
if (
|
|
28641
|
+
if (fs36.existsSync(destination)) {
|
|
27799
28642
|
try {
|
|
27800
|
-
existing = JSON.parse(
|
|
28643
|
+
existing = JSON.parse(fs36.readFileSync(destination, "utf8"));
|
|
27801
28644
|
} catch {
|
|
27802
28645
|
existing = {};
|
|
27803
28646
|
}
|
|
@@ -27822,8 +28665,8 @@ function syncConfigDoc(paths, mcpEntries, _lossReport, permissionMap, mappings)
|
|
|
27822
28665
|
};
|
|
27823
28666
|
}
|
|
27824
28667
|
}
|
|
27825
|
-
ensureDir(
|
|
27826
|
-
|
|
28668
|
+
ensureDir(path36.dirname(destination));
|
|
28669
|
+
fs36.writeFileSync(destination, `${JSON.stringify(config, null, 2)}
|
|
27827
28670
|
`);
|
|
27828
28671
|
}
|
|
27829
28672
|
function writeCompiledArtifact5(component, destination, content, expectedHash, config, sourceRoot, options, logger, manifest, scopePath) {
|
|
@@ -27834,8 +28677,8 @@ function writeCompiledArtifact5(component, destination, content, expectedHash, c
|
|
|
27834
28677
|
if (artifactClass === "unmanaged-conflict" && !handleConflict5(destination, config, options, logger, manifest, scopePath)) {
|
|
27835
28678
|
return { component, status: "conflict", path: destination };
|
|
27836
28679
|
}
|
|
27837
|
-
ensureDir(
|
|
27838
|
-
|
|
28680
|
+
ensureDir(path36.dirname(destination));
|
|
28681
|
+
fs36.writeFileSync(destination, content);
|
|
27839
28682
|
return { component, status: "success", path: destination };
|
|
27840
28683
|
}
|
|
27841
28684
|
function handleConflict5(destination, config, options, logger, manifest, scopePath) {
|
|
@@ -27854,16 +28697,16 @@ function handleConflict5(destination, config, options, logger, manifest, scopePa
|
|
|
27854
28697
|
backupFile(destination, manifest);
|
|
27855
28698
|
writeManifest(scopePath, manifest);
|
|
27856
28699
|
} else {
|
|
27857
|
-
|
|
28700
|
+
fs36.renameSync(destination, `${destination}.bak.${Date.now()}`);
|
|
27858
28701
|
}
|
|
27859
28702
|
return true;
|
|
27860
28703
|
}
|
|
27861
|
-
|
|
28704
|
+
fs36.rmSync(destination, { recursive: true, force: true });
|
|
27862
28705
|
return true;
|
|
27863
28706
|
}
|
|
27864
28707
|
function isCompiledCurrent5(destination, expectedContent, expectedHash) {
|
|
27865
28708
|
try {
|
|
27866
|
-
const current =
|
|
28709
|
+
const current = fs36.readFileSync(destination, "utf8");
|
|
27867
28710
|
const marker = extractProvenanceMarker(current);
|
|
27868
28711
|
return expectedHash ? marker?.hash === expectedHash && marker.target === "opencode" && current === expectedContent : current === expectedContent;
|
|
27869
28712
|
} catch {
|
|
@@ -27882,7 +28725,7 @@ function shouldSkipComponent5(options, component) {
|
|
|
27882
28725
|
}
|
|
27883
28726
|
function isSymlinkTo5(linkPath, source) {
|
|
27884
28727
|
try {
|
|
27885
|
-
return
|
|
28728
|
+
return fs36.realpathSync(linkPath) === fs36.realpathSync(source);
|
|
27886
28729
|
} catch {
|
|
27887
28730
|
return false;
|
|
27888
28731
|
}
|
|
@@ -27891,7 +28734,7 @@ function hashString5(value) {
|
|
|
27891
28734
|
return `sha256:${crypto9.createHash("sha256").update(value).digest("hex")}`;
|
|
27892
28735
|
}
|
|
27893
28736
|
function parseCommandFile(commandFile) {
|
|
27894
|
-
const content =
|
|
28737
|
+
const content = fs36.readFileSync(commandFile, "utf8");
|
|
27895
28738
|
if (!content.startsWith("---\n")) {
|
|
27896
28739
|
return { data: {}, body: content };
|
|
27897
28740
|
}
|
|
@@ -27900,7 +28743,7 @@ function parseCommandFile(commandFile) {
|
|
|
27900
28743
|
return { data: {}, body: content };
|
|
27901
28744
|
}
|
|
27902
28745
|
try {
|
|
27903
|
-
const data = (0,
|
|
28746
|
+
const data = (0, import_yaml11.parse)(content.slice(4, endIndex)) ?? {};
|
|
27904
28747
|
const body = content.slice(endIndex + "\n---".length).replace(/^\n/u, "");
|
|
27905
28748
|
return { data, body };
|
|
27906
28749
|
} catch {
|
|
@@ -27911,10 +28754,10 @@ function parseCommandFile(commandFile) {
|
|
|
27911
28754
|
// src/commands/install.ts
|
|
27912
28755
|
function isBackupableFile(targetPath) {
|
|
27913
28756
|
try {
|
|
27914
|
-
const lstat =
|
|
28757
|
+
const lstat = fs37.lstatSync(targetPath);
|
|
27915
28758
|
if (lstat.isDirectory()) return false;
|
|
27916
28759
|
if (lstat.isSymbolicLink()) {
|
|
27917
|
-
const stat =
|
|
28760
|
+
const stat = fs37.statSync(targetPath);
|
|
27918
28761
|
return stat.isFile();
|
|
27919
28762
|
}
|
|
27920
28763
|
return lstat.isFile();
|
|
@@ -27924,10 +28767,10 @@ function isBackupableFile(targetPath) {
|
|
|
27924
28767
|
}
|
|
27925
28768
|
function backupConflictingTarget(targetPath, scopePath) {
|
|
27926
28769
|
const ts2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/gu, "").replace("T", "T").replace(/\.\d+Z$/u, "Z");
|
|
27927
|
-
const relativeToRoot =
|
|
27928
|
-
const backupPath =
|
|
27929
|
-
|
|
27930
|
-
|
|
28770
|
+
const relativeToRoot = path37.relative("/", targetPath).replace(/^\.\.\/+/gu, "");
|
|
28771
|
+
const backupPath = path37.join(scopePath, "backups", ts2, relativeToRoot);
|
|
28772
|
+
fs37.mkdirSync(path37.dirname(backupPath), { recursive: true });
|
|
28773
|
+
fs37.copyFileSync(targetPath, backupPath);
|
|
27931
28774
|
return backupPath;
|
|
27932
28775
|
}
|
|
27933
28776
|
async function runInstallCommand(options, logger) {
|
|
@@ -27956,7 +28799,7 @@ async function runInstallCommand(options, logger) {
|
|
|
27956
28799
|
);
|
|
27957
28800
|
}
|
|
27958
28801
|
const kitName = resolvedKitName ?? config.kit;
|
|
27959
|
-
const kitPath = kitPathOverride ?? (options.kitPath ?
|
|
28802
|
+
const kitPath = kitPathOverride ?? (options.kitPath ? path37.resolve(options.kitPath) : config.kitPath);
|
|
27960
28803
|
if (!kitName && !kitPath) {
|
|
27961
28804
|
logger.error(
|
|
27962
28805
|
"No kit specified. Use --kit <name>, --kit-path <path>, or set 'kit'/'kitPath' in tangyr.config.yaml."
|
|
@@ -28097,7 +28940,7 @@ ACCEPTED CONFLICTS (backup-and-replace applied to ${conflictingFindings.length}
|
|
|
28097
28940
|
logger.info(` source: ${finding.tool}`);
|
|
28098
28941
|
logger.info(` action: backup-and-replace`);
|
|
28099
28942
|
logger.info(` backup: ${backupLocation}`);
|
|
28100
|
-
} else if (
|
|
28943
|
+
} else if (fs37.existsSync(finding.path)) {
|
|
28101
28944
|
logger.info(` - ${finding.path}`);
|
|
28102
28945
|
logger.info(` source: ${finding.tool}`);
|
|
28103
28946
|
logger.info(
|
|
@@ -28208,7 +29051,7 @@ SKIPPED CONFLICTS (${skippedTargetPaths.size} target(s) left unchanged):`
|
|
|
28208
29051
|
writeManifest(scopePath, manifest);
|
|
28209
29052
|
logger.info(`
|
|
28210
29053
|
Installation complete: ${installedCount} files installed.`);
|
|
28211
|
-
logger.info(`Manifest written to ${
|
|
29054
|
+
logger.info(`Manifest written to ${path37.join(scopePath, "manifest.json")}`);
|
|
28212
29055
|
logger.info(`Kit: ${kitInfo.name} (archetype: ${kitInfo.archetype})`);
|
|
28213
29056
|
logger.info(`Scope: ${scope}`);
|
|
28214
29057
|
logger.info(`Tools: ${tools.join(", ")}`);
|
|
@@ -28350,13 +29193,13 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
|
|
|
28350
29193
|
logger.verbose(` skipped (operator choice): ${placement.destination}`);
|
|
28351
29194
|
continue;
|
|
28352
29195
|
}
|
|
28353
|
-
const destDir =
|
|
28354
|
-
|
|
29196
|
+
const destDir = path37.dirname(placement.destination);
|
|
29197
|
+
fs37.mkdirSync(destDir, { recursive: true });
|
|
28355
29198
|
if (placement.type === "symlink") {
|
|
28356
|
-
if (
|
|
29199
|
+
if (fs37.existsSync(placement.destination) || isSymlink2(placement.destination)) {
|
|
28357
29200
|
removeManagedPath(placement.destination);
|
|
28358
29201
|
}
|
|
28359
|
-
|
|
29202
|
+
fs37.symlinkSync(
|
|
28360
29203
|
placement.source,
|
|
28361
29204
|
placement.destination,
|
|
28362
29205
|
placement.isDir ? "dir" : "file"
|
|
@@ -28365,12 +29208,12 @@ function applyClaudeCodePlacements(placements, manifest, skippedTargetPaths, log
|
|
|
28365
29208
|
` symlink: ${placement.source} \u2192 ${placement.destination}`
|
|
28366
29209
|
);
|
|
28367
29210
|
} else {
|
|
28368
|
-
|
|
29211
|
+
fs37.copyFileSync(placement.source, placement.destination);
|
|
28369
29212
|
logger.verbose(` copy: ${placement.source} \u2192 ${placement.destination}`);
|
|
28370
29213
|
}
|
|
28371
29214
|
addArtifactToManifest(manifest, {
|
|
28372
29215
|
relativePath: placement.manifestKey,
|
|
28373
|
-
hash:
|
|
29216
|
+
hash: fs37.statSync(placement.source).isDirectory() ? `dir:${placement.source}` : computeSourceHash(placement.source),
|
|
28374
29217
|
origin: "tangyr-managed"
|
|
28375
29218
|
});
|
|
28376
29219
|
count++;
|
|
@@ -28617,11 +29460,11 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28617
29460
|
if (outcome.path === mcpFile2) {
|
|
28618
29461
|
return "cline/mcp.json";
|
|
28619
29462
|
}
|
|
28620
|
-
if (outcome.path.startsWith(`${workflowsRoot}${
|
|
28621
|
-
return `cline/workflows/${
|
|
29463
|
+
if (outcome.path.startsWith(`${workflowsRoot}${path37.sep}`)) {
|
|
29464
|
+
return `cline/workflows/${path37.basename(outcome.path)}`;
|
|
28622
29465
|
}
|
|
28623
|
-
if (outcome.path.startsWith(`${rulesRoot2}${
|
|
28624
|
-
return `cline/rules/${
|
|
29466
|
+
if (outcome.path.startsWith(`${rulesRoot2}${path37.sep}`)) {
|
|
29467
|
+
return `cline/rules/${path37.basename(outcome.path)}`;
|
|
28625
29468
|
}
|
|
28626
29469
|
return null;
|
|
28627
29470
|
}
|
|
@@ -28657,14 +29500,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28657
29500
|
if (outcome.path === permissionsFile) {
|
|
28658
29501
|
return "cursor/permissions.json";
|
|
28659
29502
|
}
|
|
28660
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
28661
|
-
return `cursor/agents/${
|
|
29503
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path37.sep}`)) {
|
|
29504
|
+
return `cursor/agents/${path37.basename(outcome.path)}`;
|
|
28662
29505
|
}
|
|
28663
|
-
if (outcome.path.startsWith(`${rulesRoot2}${
|
|
28664
|
-
return `cursor/rules/${
|
|
29506
|
+
if (outcome.path.startsWith(`${rulesRoot2}${path37.sep}`)) {
|
|
29507
|
+
return `cursor/rules/${path37.basename(outcome.path)}`;
|
|
28665
29508
|
}
|
|
28666
|
-
if (outcome.path.startsWith(`${skillsRoot2}${
|
|
28667
|
-
const rel =
|
|
29509
|
+
if (outcome.path.startsWith(`${skillsRoot2}${path37.sep}`)) {
|
|
29510
|
+
const rel = path37.relative(skillsRoot2, outcome.path);
|
|
28668
29511
|
return `cursor/skills/${rel}`;
|
|
28669
29512
|
}
|
|
28670
29513
|
return null;
|
|
@@ -28690,14 +29533,14 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28690
29533
|
if (outcome.path === skillsSharedRoot) {
|
|
28691
29534
|
return "opencode/skills_shared";
|
|
28692
29535
|
}
|
|
28693
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
28694
|
-
return `opencode/agents/${
|
|
29536
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path37.sep}`)) {
|
|
29537
|
+
return `opencode/agents/${path37.basename(outcome.path)}`;
|
|
28695
29538
|
}
|
|
28696
|
-
if (outcome.path.startsWith(`${commandsRoot}${
|
|
28697
|
-
return `opencode/commands/${
|
|
29539
|
+
if (outcome.path.startsWith(`${commandsRoot}${path37.sep}`)) {
|
|
29540
|
+
return `opencode/commands/${path37.basename(outcome.path)}`;
|
|
28698
29541
|
}
|
|
28699
29542
|
if (outcome.path === configDocFile) {
|
|
28700
|
-
return `opencode/${
|
|
29543
|
+
return `opencode/${path37.basename(outcome.path)}`;
|
|
28701
29544
|
}
|
|
28702
29545
|
return null;
|
|
28703
29546
|
}
|
|
@@ -28711,17 +29554,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28711
29554
|
if (outcome.path === skillsRoot2) {
|
|
28712
29555
|
return "copilot/skills";
|
|
28713
29556
|
}
|
|
28714
|
-
if (outcome.path.startsWith(`${agentsRoot2}${
|
|
28715
|
-
return `copilot/agents/${
|
|
29557
|
+
if (outcome.path.startsWith(`${agentsRoot2}${path37.sep}`)) {
|
|
29558
|
+
return `copilot/agents/${path37.basename(outcome.path)}`;
|
|
28716
29559
|
}
|
|
28717
|
-
if (outcome.path.startsWith(`${promptsRoot}${
|
|
28718
|
-
return `copilot/prompts/${
|
|
29560
|
+
if (outcome.path.startsWith(`${promptsRoot}${path37.sep}`)) {
|
|
29561
|
+
return `copilot/prompts/${path37.basename(outcome.path)}`;
|
|
28719
29562
|
}
|
|
28720
|
-
if (outcome.path.startsWith(`${hooksRoot}${
|
|
28721
|
-
return `copilot/hooks/${
|
|
29563
|
+
if (outcome.path.startsWith(`${hooksRoot}${path37.sep}`)) {
|
|
29564
|
+
return `copilot/hooks/${path37.basename(outcome.path)}`;
|
|
28722
29565
|
}
|
|
28723
29566
|
if (outcome.path === mcpFile2) {
|
|
28724
|
-
return `copilot/${
|
|
29567
|
+
return `copilot/${path37.basename(outcome.path)}`;
|
|
28725
29568
|
}
|
|
28726
29569
|
return null;
|
|
28727
29570
|
}
|
|
@@ -28737,17 +29580,17 @@ function syncOutcomeToManifestKey(tool, outcome, mappings, scope = "global", pro
|
|
|
28737
29580
|
if (outcome.path === skillsRoot) {
|
|
28738
29581
|
return "codex/skills";
|
|
28739
29582
|
}
|
|
28740
|
-
if (outcome.path.startsWith(`${agentsRoot}${
|
|
28741
|
-
return `codex/agents/${
|
|
29583
|
+
if (outcome.path.startsWith(`${agentsRoot}${path37.sep}`)) {
|
|
29584
|
+
return `codex/agents/${path37.basename(outcome.path)}`;
|
|
28742
29585
|
}
|
|
28743
|
-
if (outcome.path.startsWith(`${rulesRoot}${
|
|
28744
|
-
return `codex/rules/${
|
|
29586
|
+
if (outcome.path.startsWith(`${rulesRoot}${path37.sep}`)) {
|
|
29587
|
+
return `codex/rules/${path37.basename(outcome.path)}`;
|
|
28745
29588
|
}
|
|
28746
29589
|
if (outcome.path === hooksFile) {
|
|
28747
|
-
return `codex/${
|
|
29590
|
+
return `codex/${path37.basename(outcome.path)}`;
|
|
28748
29591
|
}
|
|
28749
29592
|
if (outcome.path === mcpFile) {
|
|
28750
|
-
return `codex/${
|
|
29593
|
+
return `codex/${path37.basename(outcome.path)}`;
|
|
28751
29594
|
}
|
|
28752
29595
|
return null;
|
|
28753
29596
|
}
|
|
@@ -28782,8 +29625,8 @@ function getClaudeCodePlacements(kitInfo, scope = "global", projectRoot, mapping
|
|
|
28782
29625
|
};
|
|
28783
29626
|
}
|
|
28784
29627
|
const placements = [];
|
|
28785
|
-
const claudeMd =
|
|
28786
|
-
if (
|
|
29628
|
+
const claudeMd = path37.join(kitInfo.path, "CLAUDE.md");
|
|
29629
|
+
if (fs37.existsSync(claudeMd)) {
|
|
28787
29630
|
placements.push({
|
|
28788
29631
|
source: claudeMd,
|
|
28789
29632
|
destination: resolvedPaths.instructions,
|
|
@@ -28799,8 +29642,8 @@ function getClaudeCodePlacements(kitInfo, scope = "global", projectRoot, mapping
|
|
|
28799
29642
|
rules: resolvedPaths.rules
|
|
28800
29643
|
};
|
|
28801
29644
|
for (const [component, targetPath] of Object.entries(componentDirMap)) {
|
|
28802
|
-
const componentDir =
|
|
28803
|
-
if (
|
|
29645
|
+
const componentDir = path37.join(kitInfo.path, component);
|
|
29646
|
+
if (fs37.existsSync(componentDir) && fs37.statSync(componentDir).isDirectory()) {
|
|
28804
29647
|
placements.push({
|
|
28805
29648
|
source: componentDir,
|
|
28806
29649
|
destination: targetPath,
|
|
@@ -28814,8 +29657,8 @@ function getClaudeCodePlacements(kitInfo, scope = "global", projectRoot, mapping
|
|
|
28814
29657
|
}
|
|
28815
29658
|
function getClaudeCodePlacementsFromProfile(kitInfo, profile) {
|
|
28816
29659
|
const placements = [];
|
|
28817
|
-
const claudeMd =
|
|
28818
|
-
if (
|
|
29660
|
+
const claudeMd = path37.join(kitInfo.path, "CLAUDE.md");
|
|
29661
|
+
if (fs37.existsSync(claudeMd)) {
|
|
28819
29662
|
placements.push({
|
|
28820
29663
|
source: claudeMd,
|
|
28821
29664
|
destination: profile.instructions,
|
|
@@ -28831,8 +29674,8 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile) {
|
|
|
28831
29674
|
rules: profile.rules
|
|
28832
29675
|
};
|
|
28833
29676
|
for (const [component, targetPath] of Object.entries(componentDirMap)) {
|
|
28834
|
-
const componentDir =
|
|
28835
|
-
if (
|
|
29677
|
+
const componentDir = path37.join(kitInfo.path, component);
|
|
29678
|
+
if (fs37.existsSync(componentDir) && fs37.statSync(componentDir).isDirectory()) {
|
|
28836
29679
|
placements.push({
|
|
28837
29680
|
source: componentDir,
|
|
28838
29681
|
destination: targetPath,
|
|
@@ -28846,8 +29689,8 @@ function getClaudeCodePlacementsFromProfile(kitInfo, profile) {
|
|
|
28846
29689
|
}
|
|
28847
29690
|
function collectAllFiles(kitInfo) {
|
|
28848
29691
|
const files = /* @__PURE__ */ new Map();
|
|
28849
|
-
const claudeMd =
|
|
28850
|
-
if (
|
|
29692
|
+
const claudeMd = path37.join(kitInfo.path, "CLAUDE.md");
|
|
29693
|
+
if (fs37.existsSync(claudeMd)) {
|
|
28851
29694
|
files.set("CLAUDE.md", claudeMd);
|
|
28852
29695
|
}
|
|
28853
29696
|
for (const [component, reconciliation] of Object.entries(
|
|
@@ -28857,15 +29700,15 @@ function collectAllFiles(kitInfo) {
|
|
|
28857
29700
|
const missingSet = new Set(reconciliation.missing);
|
|
28858
29701
|
for (const entry of reconciliation.declared) {
|
|
28859
29702
|
if (missingSet.has(entry)) continue;
|
|
28860
|
-
const relPath = isSkills ?
|
|
28861
|
-
files.set(relPath,
|
|
29703
|
+
const relPath = isSkills ? path37.join(component, entry) : path37.join(component, `${entry}.md`);
|
|
29704
|
+
files.set(relPath, path37.join(kitInfo.path, relPath));
|
|
28862
29705
|
}
|
|
28863
29706
|
}
|
|
28864
29707
|
return files;
|
|
28865
29708
|
}
|
|
28866
29709
|
function isSymlink2(p) {
|
|
28867
29710
|
try {
|
|
28868
|
-
return
|
|
29711
|
+
return fs37.lstatSync(p).isSymbolicLink();
|
|
28869
29712
|
} catch {
|
|
28870
29713
|
return false;
|
|
28871
29714
|
}
|
|
@@ -28910,14 +29753,14 @@ async function runKitUpdateCommand(options, logger) {
|
|
|
28910
29753
|
}
|
|
28911
29754
|
|
|
28912
29755
|
// src/commands/list.ts
|
|
28913
|
-
import
|
|
29756
|
+
import path38 from "path";
|
|
28914
29757
|
function runListCommand(options, logger) {
|
|
28915
29758
|
let searchPaths = [];
|
|
28916
|
-
let directKitPath = options.kitPath ?
|
|
29759
|
+
let directKitPath = options.kitPath ? path38.resolve(options.kitPath) : void 0;
|
|
28917
29760
|
try {
|
|
28918
29761
|
const { config, configDir } = resolveConfig(options.config);
|
|
28919
29762
|
searchPaths = config.kitSearchPaths ?? [
|
|
28920
|
-
|
|
29763
|
+
path38.join(configDir, "operating-kits")
|
|
28921
29764
|
];
|
|
28922
29765
|
directKitPath = directKitPath ?? config.kitPath;
|
|
28923
29766
|
} catch (err) {
|
|
@@ -28992,7 +29835,7 @@ function withDirectKit(kits, directKitPath) {
|
|
|
28992
29835
|
return kits;
|
|
28993
29836
|
}
|
|
28994
29837
|
const directKit = loadKit(directKitPath);
|
|
28995
|
-
if (kits.some((kit) =>
|
|
29838
|
+
if (kits.some((kit) => path38.resolve(kit.path) === directKit.path)) {
|
|
28996
29839
|
return kits;
|
|
28997
29840
|
}
|
|
28998
29841
|
return [...kits, directKit];
|
|
@@ -29000,12 +29843,12 @@ function withDirectKit(kits, directKitPath) {
|
|
|
29000
29843
|
|
|
29001
29844
|
// src/commands/probe.ts
|
|
29002
29845
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
29003
|
-
import
|
|
29004
|
-
import
|
|
29846
|
+
import fs38 from "fs";
|
|
29847
|
+
import path39 from "path";
|
|
29005
29848
|
function runProbeCommand(options, logger) {
|
|
29006
29849
|
const { config, configDir, sourceRoot } = resolveRuntime(options, import.meta.url);
|
|
29007
29850
|
const platformPaths = readYamlObject(
|
|
29008
|
-
|
|
29851
|
+
path39.join(
|
|
29009
29852
|
resolveConfiguredPath(config.mappings, configDir, sourceRoot, "mappings"),
|
|
29010
29853
|
"platform-paths.yaml"
|
|
29011
29854
|
)
|
|
@@ -29039,12 +29882,12 @@ function toProbeRow(target, key, rawPath) {
|
|
|
29039
29882
|
const resolved = resolveTargetPath(rawPath);
|
|
29040
29883
|
let accessible = false;
|
|
29041
29884
|
try {
|
|
29042
|
-
|
|
29885
|
+
fs38.accessSync(resolved);
|
|
29043
29886
|
accessible = true;
|
|
29044
29887
|
} catch {
|
|
29045
29888
|
accessible = false;
|
|
29046
29889
|
}
|
|
29047
|
-
return { target, key, path: resolved, exists:
|
|
29890
|
+
return { target, key, path: resolved, exists: fs38.existsSync(resolved), accessible };
|
|
29048
29891
|
}
|
|
29049
29892
|
function codexRuntimeProbeRows() {
|
|
29050
29893
|
const rows = commandProbeRows("codex", "binary", process.platform === "win32" ? "where.exe" : "which", ["codex"]);
|
|
@@ -29055,7 +29898,7 @@ function codexRuntimeProbeRows() {
|
|
|
29055
29898
|
["binary_snap", "/snap/bin/codex"],
|
|
29056
29899
|
["binary_flatpak", "/var/lib/flatpak/exports/bin/codex"]
|
|
29057
29900
|
]) {
|
|
29058
|
-
if (
|
|
29901
|
+
if (fs38.existsSync(candidatePath)) {
|
|
29059
29902
|
rows.push(toProbeRow("codex", key, candidatePath));
|
|
29060
29903
|
}
|
|
29061
29904
|
}
|
|
@@ -29071,8 +29914,8 @@ function commandProbeRows(target, key, command, args) {
|
|
|
29071
29914
|
|
|
29072
29915
|
// src/commands/status.ts
|
|
29073
29916
|
import crypto10 from "crypto";
|
|
29074
|
-
import
|
|
29075
|
-
import
|
|
29917
|
+
import fs39 from "fs";
|
|
29918
|
+
import path40 from "path";
|
|
29076
29919
|
function runStatusCommand(options, logger) {
|
|
29077
29920
|
const { config, configDir, sourceRoot } = resolveRuntime(
|
|
29078
29921
|
options,
|
|
@@ -29151,21 +29994,21 @@ function classifyCodexFiles(config, sourceRoot, configDir) {
|
|
|
29151
29994
|
rules: paths.rules
|
|
29152
29995
|
};
|
|
29153
29996
|
const rules = compileRules(
|
|
29154
|
-
|
|
29997
|
+
path40.join(sourceRoot, config.source.rules),
|
|
29155
29998
|
"codex",
|
|
29156
29999
|
mappings,
|
|
29157
30000
|
createLossReport()
|
|
29158
30001
|
);
|
|
29159
|
-
const instructionsSource =
|
|
30002
|
+
const instructionsSource = fs39.readFileSync(path40.join(sourceRoot, config.source.instructions), "utf8").trim();
|
|
29160
30003
|
const composedInstructions = `${instructionsSource}
|
|
29161
30004
|
|
|
29162
30005
|
--- tangyr managed rules ---
|
|
29163
30006
|
${rules.agentsAppendix}`.trim();
|
|
29164
30007
|
const agentFiles = ts(
|
|
29165
|
-
|
|
30008
|
+
path40.join(sourceRoot, config.source.agents, "*.md")
|
|
29166
30009
|
).sort();
|
|
29167
|
-
const hooksSource =
|
|
29168
|
-
const mcpSource =
|
|
30010
|
+
const hooksSource = path40.join(sourceRoot, config.source.hooks, "hooks.json");
|
|
30011
|
+
const mcpSource = path40.join(sourceRoot, config.source.mcp);
|
|
29169
30012
|
const ruleRows = rules.dotRulesFiles.length === 0 ? [
|
|
29170
30013
|
{
|
|
29171
30014
|
component: "rules",
|
|
@@ -29176,7 +30019,7 @@ ${rules.agentsAppendix}`.trim();
|
|
|
29176
30019
|
] : rules.dotRulesFiles.map(
|
|
29177
30020
|
(ruleFile) => classifyCompiledFile(
|
|
29178
30021
|
`rules/${ruleFile.name}`,
|
|
29179
|
-
|
|
30022
|
+
path40.join(resolveTargetPath(codexPaths.rules), ruleFile.name),
|
|
29180
30023
|
"codex",
|
|
29181
30024
|
void 0,
|
|
29182
30025
|
config,
|
|
@@ -29194,10 +30037,10 @@ ${rules.agentsAppendix}`.trim();
|
|
|
29194
30037
|
),
|
|
29195
30038
|
...agentFiles.map(
|
|
29196
30039
|
(agentFile) => classifyCompiledFile(
|
|
29197
|
-
`agents/${
|
|
29198
|
-
|
|
30040
|
+
`agents/${path40.basename(agentFile, ".md")}`,
|
|
30041
|
+
path40.join(
|
|
29199
30042
|
resolveTargetPath(codexPaths.agents),
|
|
29200
|
-
`${
|
|
30043
|
+
`${path40.basename(agentFile, ".md")}.toml`
|
|
29201
30044
|
),
|
|
29202
30045
|
"codex",
|
|
29203
30046
|
computeSourceHash(agentFile),
|
|
@@ -29221,11 +30064,11 @@ ${rules.agentsAppendix}`.trim();
|
|
|
29221
30064
|
config,
|
|
29222
30065
|
sourceRoot
|
|
29223
30066
|
),
|
|
29224
|
-
|
|
30067
|
+
fs39.existsSync(hooksSource) ? classifyCodexHooksFile(resolveTargetPath(codexPaths.hooksSharedFile)) : notConfiguredRow(
|
|
29225
30068
|
"hooks",
|
|
29226
30069
|
resolveTargetPath(codexPaths.hooksSharedFile)
|
|
29227
30070
|
),
|
|
29228
|
-
|
|
30071
|
+
fs39.existsSync(mcpSource) ? classifyCompiledFile(
|
|
29229
30072
|
"mcp",
|
|
29230
30073
|
resolveTargetPath(codexPaths.mcpSharedFile),
|
|
29231
30074
|
"codex",
|
|
@@ -29245,7 +30088,7 @@ function classifyCodexHooksFile(filePath) {
|
|
|
29245
30088
|
conformant: true
|
|
29246
30089
|
};
|
|
29247
30090
|
}
|
|
29248
|
-
if (!
|
|
30091
|
+
if (!fs39.existsSync(filePath)) {
|
|
29249
30092
|
return {
|
|
29250
30093
|
component: "hooks",
|
|
29251
30094
|
className: "missing",
|
|
@@ -29277,20 +30120,20 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29277
30120
|
mcpSharedFile: paths.mcp_shared_file
|
|
29278
30121
|
};
|
|
29279
30122
|
const agentFiles = ts(
|
|
29280
|
-
|
|
30123
|
+
path40.join(sourceRoot, config.source.agents, "*.md")
|
|
29281
30124
|
).sort();
|
|
29282
30125
|
const commandFiles = ts(
|
|
29283
|
-
|
|
30126
|
+
path40.join(sourceRoot, config.source.commands, "*.md")
|
|
29284
30127
|
).sort();
|
|
29285
|
-
const hooksSource =
|
|
29286
|
-
const mcpSource =
|
|
30128
|
+
const hooksSource = path40.join(sourceRoot, config.source.hooks, "hooks.json");
|
|
30129
|
+
const mcpSource = path40.join(sourceRoot, config.source.mcp);
|
|
29287
30130
|
return [
|
|
29288
30131
|
...agentFiles.map(
|
|
29289
30132
|
(agentFile) => classifyCompiledFile(
|
|
29290
|
-
`agents/${
|
|
29291
|
-
|
|
30133
|
+
`agents/${path40.basename(agentFile, ".md")}`,
|
|
30134
|
+
path40.join(
|
|
29292
30135
|
resolveTargetPath(copilotPaths.agents),
|
|
29293
|
-
`${
|
|
30136
|
+
`${path40.basename(agentFile, ".md")}.agent.md`
|
|
29294
30137
|
),
|
|
29295
30138
|
"copilot",
|
|
29296
30139
|
computeSourceHash(agentFile),
|
|
@@ -29307,10 +30150,10 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29307
30150
|
),
|
|
29308
30151
|
...commandFiles.map(
|
|
29309
30152
|
(commandFile) => classifyCompiledFile(
|
|
29310
|
-
`commands/${
|
|
29311
|
-
|
|
30153
|
+
`commands/${path40.basename(commandFile, ".md")}`,
|
|
30154
|
+
path40.join(
|
|
29312
30155
|
resolveTargetPath(copilotPaths.prompts),
|
|
29313
|
-
`${
|
|
30156
|
+
`${path40.basename(commandFile, ".md")}.prompt.md`
|
|
29314
30157
|
),
|
|
29315
30158
|
"copilot",
|
|
29316
30159
|
computeSourceHash(commandFile),
|
|
@@ -29328,9 +30171,9 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29328
30171
|
config,
|
|
29329
30172
|
sourceRoot
|
|
29330
30173
|
),
|
|
29331
|
-
|
|
30174
|
+
fs39.existsSync(hooksSource) ? classifyCompiledFile(
|
|
29332
30175
|
"hooks",
|
|
29333
|
-
|
|
30176
|
+
path40.join(
|
|
29334
30177
|
resolveTargetPath(copilotPaths.hooks),
|
|
29335
30178
|
"tangyr-managed.json"
|
|
29336
30179
|
),
|
|
@@ -29340,12 +30183,12 @@ function classifyCopilotFiles(config, sourceRoot, configDir) {
|
|
|
29340
30183
|
sourceRoot
|
|
29341
30184
|
) : notConfiguredRow(
|
|
29342
30185
|
"hooks",
|
|
29343
|
-
|
|
30186
|
+
path40.join(
|
|
29344
30187
|
resolveTargetPath(copilotPaths.hooks),
|
|
29345
30188
|
"tangyr-managed.json"
|
|
29346
30189
|
)
|
|
29347
30190
|
),
|
|
29348
|
-
|
|
30191
|
+
fs39.existsSync(mcpSource) ? classifyCompiledFile(
|
|
29349
30192
|
"mcp",
|
|
29350
30193
|
resolveTargetPath(copilotPaths.mcpSharedFile),
|
|
29351
30194
|
"copilot",
|
|
@@ -29365,7 +30208,7 @@ function notConfiguredRow(component, filePath) {
|
|
|
29365
30208
|
}
|
|
29366
30209
|
function classifyDirectArtifact(artifact, config, sourceRoot) {
|
|
29367
30210
|
const artifactClass = classifyArtifact(artifact.path, config, sourceRoot);
|
|
29368
|
-
const sourcePath = artifact.sourceKey ?
|
|
30211
|
+
const sourcePath = artifact.sourceKey ? path40.resolve(sourceRoot, config.source[artifact.sourceKey]) : void 0;
|
|
29369
30212
|
if (artifactClass === "managed-symlink" && sourcePath && !isSymlinkCurrent(artifact.path, sourcePath)) {
|
|
29370
30213
|
return {
|
|
29371
30214
|
component: artifact.component,
|
|
@@ -29454,9 +30297,9 @@ function classifyClaudeSharedFiles(config, sourceRoot) {
|
|
|
29454
30297
|
classifyHooks(settingsPath),
|
|
29455
30298
|
classifySettings(
|
|
29456
30299
|
settingsPath,
|
|
29457
|
-
|
|
30300
|
+
path40.resolve(sourceRoot, config.source.settings)
|
|
29458
30301
|
),
|
|
29459
|
-
classifyMcp(claudeJsonPath,
|
|
30302
|
+
classifyMcp(claudeJsonPath, path40.resolve(sourceRoot, config.source.mcp))
|
|
29460
30303
|
];
|
|
29461
30304
|
}
|
|
29462
30305
|
function classifyHooks(filePath) {
|
|
@@ -29520,14 +30363,14 @@ function classifyMcp(filePath, sourcePath) {
|
|
|
29520
30363
|
}
|
|
29521
30364
|
function isSymlinkCurrent(linkPath, sourcePath) {
|
|
29522
30365
|
try {
|
|
29523
|
-
return
|
|
30366
|
+
return fs39.realpathSync(linkPath) === fs39.realpathSync(sourcePath);
|
|
29524
30367
|
} catch {
|
|
29525
30368
|
return false;
|
|
29526
30369
|
}
|
|
29527
30370
|
}
|
|
29528
30371
|
function isCompiledCurrent6(filePath, sourcePath) {
|
|
29529
30372
|
try {
|
|
29530
|
-
const marker = extractProvenanceMarker(
|
|
30373
|
+
const marker = extractProvenanceMarker(fs39.readFileSync(filePath, "utf8"));
|
|
29531
30374
|
return marker?.hash === computeSourceHash(sourcePath) && marker.target === "claude-code";
|
|
29532
30375
|
} catch {
|
|
29533
30376
|
return false;
|
|
@@ -29557,7 +30400,7 @@ function classifyCompiledFile(component, filePath, target, expectedHash, config,
|
|
|
29557
30400
|
}
|
|
29558
30401
|
function readCompiledContent(filePath) {
|
|
29559
30402
|
try {
|
|
29560
|
-
return
|
|
30403
|
+
return fs39.readFileSync(filePath, "utf8");
|
|
29561
30404
|
} catch {
|
|
29562
30405
|
return null;
|
|
29563
30406
|
}
|
|
@@ -30103,145 +30946,6 @@ function buildAgentsMdShim(shimPath, _agentsMdPath, target) {
|
|
|
30103
30946
|
${SHIM_BODY}`;
|
|
30104
30947
|
}
|
|
30105
30948
|
|
|
30106
|
-
// src/compiler/hook-components.ts
|
|
30107
|
-
var import_yaml11 = __toESM(require_dist(), 1);
|
|
30108
|
-
import fs39 from "fs";
|
|
30109
|
-
import path40 from "path";
|
|
30110
|
-
function parseHookDeclaration(filePath) {
|
|
30111
|
-
let raw;
|
|
30112
|
-
try {
|
|
30113
|
-
raw = fs39.readFileSync(filePath, "utf8");
|
|
30114
|
-
} catch {
|
|
30115
|
-
return null;
|
|
30116
|
-
}
|
|
30117
|
-
const fm = extractFrontmatter(raw);
|
|
30118
|
-
if (!fm) {
|
|
30119
|
-
return null;
|
|
30120
|
-
}
|
|
30121
|
-
const { name, description, events } = fm;
|
|
30122
|
-
if (typeof name !== "string" || !name.trim()) {
|
|
30123
|
-
return null;
|
|
30124
|
-
}
|
|
30125
|
-
if (typeof description !== "string" || !description.trim()) {
|
|
30126
|
-
return null;
|
|
30127
|
-
}
|
|
30128
|
-
if (!Array.isArray(events) || events.length === 0) {
|
|
30129
|
-
return null;
|
|
30130
|
-
}
|
|
30131
|
-
const parsedEvents = [];
|
|
30132
|
-
for (const entry of events) {
|
|
30133
|
-
if (!entry || typeof entry !== "object") {
|
|
30134
|
-
return null;
|
|
30135
|
-
}
|
|
30136
|
-
const ev = entry;
|
|
30137
|
-
if (typeof ev.event !== "string" || !ev.event.trim()) {
|
|
30138
|
-
return null;
|
|
30139
|
-
}
|
|
30140
|
-
if (typeof ev.timeout !== "number") {
|
|
30141
|
-
return null;
|
|
30142
|
-
}
|
|
30143
|
-
if (typeof ev.statusMessage !== "string" || !ev.statusMessage.trim()) {
|
|
30144
|
-
return null;
|
|
30145
|
-
}
|
|
30146
|
-
const parsed = {
|
|
30147
|
-
event: ev.event,
|
|
30148
|
-
timeout: ev.timeout,
|
|
30149
|
-
statusMessage: ev.statusMessage
|
|
30150
|
-
};
|
|
30151
|
-
if (typeof ev.matcher === "string" && ev.matcher.trim()) {
|
|
30152
|
-
parsed.matcher = ev.matcher;
|
|
30153
|
-
}
|
|
30154
|
-
parsedEvents.push(parsed);
|
|
30155
|
-
}
|
|
30156
|
-
return {
|
|
30157
|
-
name: name.trim(),
|
|
30158
|
-
description: description.trim(),
|
|
30159
|
-
events: parsedEvents
|
|
30160
|
-
};
|
|
30161
|
-
}
|
|
30162
|
-
function hookCommand(name) {
|
|
30163
|
-
return `npx tsx ~/.agents/hooks/scripts/${name}.ts`;
|
|
30164
|
-
}
|
|
30165
|
-
function synthesizeHooksJson(declarations) {
|
|
30166
|
-
const hooks = {};
|
|
30167
|
-
for (const decl of declarations) {
|
|
30168
|
-
for (const ev of decl.events) {
|
|
30169
|
-
if (!hooks[ev.event]) {
|
|
30170
|
-
hooks[ev.event] = [];
|
|
30171
|
-
}
|
|
30172
|
-
const entry = {
|
|
30173
|
-
hooks: [
|
|
30174
|
-
{
|
|
30175
|
-
type: "command",
|
|
30176
|
-
command: hookCommand(decl.name),
|
|
30177
|
-
timeout: ev.timeout,
|
|
30178
|
-
statusMessage: ev.statusMessage
|
|
30179
|
-
}
|
|
30180
|
-
]
|
|
30181
|
-
};
|
|
30182
|
-
if (ev.matcher !== void 0) {
|
|
30183
|
-
const ordered = {
|
|
30184
|
-
matcher: ev.matcher,
|
|
30185
|
-
hooks: entry.hooks
|
|
30186
|
-
};
|
|
30187
|
-
hooks[ev.event].push(ordered);
|
|
30188
|
-
} else {
|
|
30189
|
-
hooks[ev.event].push(entry);
|
|
30190
|
-
}
|
|
30191
|
-
}
|
|
30192
|
-
}
|
|
30193
|
-
return { hooks };
|
|
30194
|
-
}
|
|
30195
|
-
function loadSourceHooks(hooksDir, hookNames) {
|
|
30196
|
-
const hooksJsonPath = path40.join(hooksDir, "hooks.json");
|
|
30197
|
-
if (fs39.existsSync(hooksJsonPath)) {
|
|
30198
|
-
const raw = fs39.readFileSync(hooksJsonPath, "utf8");
|
|
30199
|
-
return JSON.parse(raw);
|
|
30200
|
-
}
|
|
30201
|
-
const declarations = loadHookDeclarations(hooksDir, hookNames);
|
|
30202
|
-
return synthesizeHooksJson(declarations);
|
|
30203
|
-
}
|
|
30204
|
-
function loadHookDeclarations(hooksDir, hookNames) {
|
|
30205
|
-
let names;
|
|
30206
|
-
if (hookNames && hookNames.length > 0) {
|
|
30207
|
-
names = hookNames;
|
|
30208
|
-
} else {
|
|
30209
|
-
if (!fs39.existsSync(hooksDir) || !fs39.statSync(hooksDir).isDirectory()) {
|
|
30210
|
-
return [];
|
|
30211
|
-
}
|
|
30212
|
-
names = fs39.readdirSync(hooksDir).filter((f) => f.endsWith(".md") && !f.startsWith(".")).map((f) => f.slice(0, -3)).sort();
|
|
30213
|
-
}
|
|
30214
|
-
const declarations = [];
|
|
30215
|
-
for (const name of names) {
|
|
30216
|
-
const filePath = path40.join(hooksDir, `${name}.md`);
|
|
30217
|
-
const decl = parseHookDeclaration(filePath);
|
|
30218
|
-
if (decl) {
|
|
30219
|
-
declarations.push(decl);
|
|
30220
|
-
}
|
|
30221
|
-
}
|
|
30222
|
-
return declarations;
|
|
30223
|
-
}
|
|
30224
|
-
function extractFrontmatter(content) {
|
|
30225
|
-
if (!content.startsWith("---\n")) {
|
|
30226
|
-
return null;
|
|
30227
|
-
}
|
|
30228
|
-
const endIndex = content.indexOf("\n---", 4);
|
|
30229
|
-
if (endIndex === -1) {
|
|
30230
|
-
return null;
|
|
30231
|
-
}
|
|
30232
|
-
const rawFm = content.slice(4, endIndex);
|
|
30233
|
-
let parsed;
|
|
30234
|
-
try {
|
|
30235
|
-
parsed = (0, import_yaml11.parse)(rawFm);
|
|
30236
|
-
} catch {
|
|
30237
|
-
return null;
|
|
30238
|
-
}
|
|
30239
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
30240
|
-
return null;
|
|
30241
|
-
}
|
|
30242
|
-
return parsed;
|
|
30243
|
-
}
|
|
30244
|
-
|
|
30245
30949
|
// src/adapters/claude-code.ts
|
|
30246
30950
|
function buildDirectComponents(profile) {
|
|
30247
30951
|
return [
|