@synapsync/cli 0.1.4 → 0.1.6
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 +1847 -1597
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28,7 +28,7 @@ var init_version = __esm({
|
|
|
28
28
|
"src/version.ts"() {
|
|
29
29
|
"use strict";
|
|
30
30
|
init_esm_shims();
|
|
31
|
-
version = "0.1.
|
|
31
|
+
version = "0.1.6";
|
|
32
32
|
}
|
|
33
33
|
});
|
|
34
34
|
|
|
@@ -70,6 +70,7 @@ var COGNITIVE_FILE_NAMES = {
|
|
|
70
70
|
};
|
|
71
71
|
var DEFAULT_SYNAPSYNC_DIR = process.env["SYNAPSYNC_DIR"] ?? ".synapsync";
|
|
72
72
|
var CONFIG_FILE_NAME = "synapsync.config.yaml";
|
|
73
|
+
var AGENTS_MD_FILE_NAME = "AGENTS.md";
|
|
73
74
|
var DEFAULT_AGENTS_DIR = process.env["SYNAPSYNC_AGENTS_DIR"] ?? ".agents";
|
|
74
75
|
var DEFAULT_SKILLS_SUBDIR = process.env["SYNAPSYNC_SKILLS_SUBDIR"] ?? "skills";
|
|
75
76
|
var CATEGORIES = [
|
|
@@ -718,8 +719,8 @@ function registerInfoCommand(program) {
|
|
|
718
719
|
|
|
719
720
|
// src/commands/init.ts
|
|
720
721
|
init_esm_shims();
|
|
721
|
-
import * as
|
|
722
|
-
import * as
|
|
722
|
+
import * as fs5 from "fs";
|
|
723
|
+
import * as path6 from "path";
|
|
723
724
|
import * as p from "@clack/prompts";
|
|
724
725
|
import pc4 from "picocolors";
|
|
725
726
|
|
|
@@ -822,8 +823,8 @@ function validateConfig(config) {
|
|
|
822
823
|
}
|
|
823
824
|
return errors;
|
|
824
825
|
}
|
|
825
|
-
function getNestedValue(obj,
|
|
826
|
-
const parts =
|
|
826
|
+
function getNestedValue(obj, path18) {
|
|
827
|
+
const parts = path18.split(".");
|
|
827
828
|
let current = obj;
|
|
828
829
|
for (const part of parts) {
|
|
829
830
|
if (current === null || current === void 0) {
|
|
@@ -836,8 +837,8 @@ function getNestedValue(obj, path17) {
|
|
|
836
837
|
}
|
|
837
838
|
return current;
|
|
838
839
|
}
|
|
839
|
-
function setNestedValue(obj,
|
|
840
|
-
const parts =
|
|
840
|
+
function setNestedValue(obj, path18, value) {
|
|
841
|
+
const parts = path18.split(".");
|
|
841
842
|
let current = obj;
|
|
842
843
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
843
844
|
const part = parts[i];
|
|
@@ -1018,1630 +1019,1861 @@ ${messages}`);
|
|
|
1018
1019
|
}
|
|
1019
1020
|
};
|
|
1020
1021
|
|
|
1021
|
-
// src/
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1022
|
+
// src/services/agents-md/generator.ts
|
|
1023
|
+
init_esm_shims();
|
|
1024
|
+
import * as fs4 from "fs";
|
|
1025
|
+
import * as path5 from "path";
|
|
1026
|
+
|
|
1027
|
+
// src/services/manifest/manager.ts
|
|
1028
|
+
init_esm_shims();
|
|
1029
|
+
import * as fs2 from "fs";
|
|
1030
|
+
import * as path3 from "path";
|
|
1031
|
+
|
|
1032
|
+
// src/services/manifest/types.ts
|
|
1033
|
+
init_esm_shims();
|
|
1034
|
+
var DEFAULT_MANIFEST = {
|
|
1035
|
+
version: "1.0.0",
|
|
1036
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1037
|
+
cognitives: {},
|
|
1038
|
+
syncs: {}
|
|
1039
|
+
};
|
|
1040
|
+
|
|
1041
|
+
// src/services/manifest/manager.ts
|
|
1042
|
+
var ManifestManager = class {
|
|
1043
|
+
manifestPath;
|
|
1044
|
+
manifest;
|
|
1045
|
+
constructor(synapSyncDir) {
|
|
1046
|
+
this.manifestPath = path3.join(synapSyncDir, "manifest.json");
|
|
1047
|
+
this.manifest = this.load();
|
|
1034
1048
|
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1049
|
+
/**
|
|
1050
|
+
* Load manifest from disk
|
|
1051
|
+
*/
|
|
1052
|
+
load() {
|
|
1053
|
+
if (!fs2.existsSync(this.manifestPath)) {
|
|
1054
|
+
return { ...DEFAULT_MANIFEST };
|
|
1055
|
+
}
|
|
1056
|
+
try {
|
|
1057
|
+
const content = fs2.readFileSync(this.manifestPath, "utf-8");
|
|
1058
|
+
const parsed = JSON.parse(content);
|
|
1059
|
+
return {
|
|
1060
|
+
version: parsed.version ?? DEFAULT_MANIFEST.version,
|
|
1061
|
+
lastUpdated: parsed.lastUpdated ?? DEFAULT_MANIFEST.lastUpdated,
|
|
1062
|
+
cognitives: parsed.cognitives ?? {},
|
|
1063
|
+
syncs: parsed.syncs ?? {}
|
|
1064
|
+
};
|
|
1065
|
+
} catch {
|
|
1066
|
+
return { ...DEFAULT_MANIFEST };
|
|
1067
|
+
}
|
|
1041
1068
|
}
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1069
|
+
/**
|
|
1070
|
+
* Save manifest to disk
|
|
1071
|
+
*/
|
|
1072
|
+
save() {
|
|
1073
|
+
this.manifest.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
1074
|
+
const content = JSON.stringify(this.manifest, null, 2);
|
|
1075
|
+
fs2.writeFileSync(this.manifestPath, content, "utf-8");
|
|
1076
|
+
}
|
|
1077
|
+
/**
|
|
1078
|
+
* Get the current manifest
|
|
1079
|
+
*/
|
|
1080
|
+
getManifest() {
|
|
1081
|
+
return this.manifest;
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Get all cognitives from manifest
|
|
1085
|
+
*/
|
|
1086
|
+
getCognitives() {
|
|
1087
|
+
return Object.values(this.manifest.cognitives);
|
|
1088
|
+
}
|
|
1089
|
+
/**
|
|
1090
|
+
* Get a specific cognitive by name
|
|
1091
|
+
*/
|
|
1092
|
+
getCognitive(name) {
|
|
1093
|
+
return this.manifest.cognitives[name];
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Check if a cognitive exists in manifest
|
|
1097
|
+
*/
|
|
1098
|
+
hasCognitive(name) {
|
|
1099
|
+
return this.manifest.cognitives[name] !== void 0;
|
|
1100
|
+
}
|
|
1101
|
+
/**
|
|
1102
|
+
* Add a cognitive to manifest
|
|
1103
|
+
*/
|
|
1104
|
+
addCognitive(cognitive) {
|
|
1105
|
+
this.manifest.cognitives[cognitive.name] = cognitive;
|
|
1106
|
+
}
|
|
1107
|
+
/**
|
|
1108
|
+
* Update a cognitive in manifest
|
|
1109
|
+
*/
|
|
1110
|
+
updateCognitive(name, updates) {
|
|
1111
|
+
const existing = this.manifest.cognitives[name];
|
|
1112
|
+
if (existing !== void 0) {
|
|
1113
|
+
this.manifest.cognitives[name] = { ...existing, ...updates };
|
|
1081
1114
|
}
|
|
1082
|
-
);
|
|
1083
|
-
if (p.isCancel(result)) {
|
|
1084
|
-
return null;
|
|
1085
1115
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
const projectRoot = process.cwd();
|
|
1094
|
-
const configPath = path3.join(projectRoot, CONFIG_FILE_NAME);
|
|
1095
|
-
const storagePath = path3.join(projectRoot, DEFAULT_SYNAPSYNC_DIR);
|
|
1096
|
-
const s = p.spinner();
|
|
1097
|
-
s.start("Creating project structure...");
|
|
1098
|
-
try {
|
|
1099
|
-
createStorageStructure(storagePath);
|
|
1100
|
-
const configManager = new ConfigManager(projectRoot);
|
|
1101
|
-
configManager.create(setup.name, setup.description);
|
|
1102
|
-
for (const provider of setup.providers) {
|
|
1103
|
-
configManager.set(`sync.providers.${provider}.enabled`, true);
|
|
1116
|
+
/**
|
|
1117
|
+
* Remove a cognitive from manifest
|
|
1118
|
+
*/
|
|
1119
|
+
removeCognitive(name) {
|
|
1120
|
+
if (this.manifest.cognitives[name] !== void 0) {
|
|
1121
|
+
delete this.manifest.cognitives[name];
|
|
1122
|
+
return true;
|
|
1104
1123
|
}
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1124
|
+
return false;
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* Reconcile manifest with scanned cognitives
|
|
1128
|
+
* Returns what was added, removed, and updated
|
|
1129
|
+
*/
|
|
1130
|
+
reconcile(scannedCognitives) {
|
|
1131
|
+
const result = {
|
|
1132
|
+
added: [],
|
|
1133
|
+
removed: [],
|
|
1134
|
+
updated: [],
|
|
1135
|
+
unchanged: 0
|
|
1115
1136
|
};
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
if (error instanceof Error) {
|
|
1120
|
-
logger.error(error.message);
|
|
1137
|
+
const scannedMap = /* @__PURE__ */ new Map();
|
|
1138
|
+
for (const cognitive of scannedCognitives) {
|
|
1139
|
+
scannedMap.set(cognitive.name, cognitive);
|
|
1121
1140
|
}
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
fs2.mkdirSync(storagePath, { recursive: true });
|
|
1127
|
-
for (const cognitiveType of COGNITIVE_TYPES) {
|
|
1128
|
-
const typePath = path3.join(storagePath, `${cognitiveType}s`);
|
|
1129
|
-
fs2.mkdirSync(typePath, { recursive: true });
|
|
1130
|
-
const gitkeepPath = path3.join(typePath, ".gitkeep");
|
|
1131
|
-
fs2.writeFileSync(gitkeepPath, "");
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
function createManifest(storagePath) {
|
|
1135
|
-
const manifestPath = path3.join(storagePath, "manifest.json");
|
|
1136
|
-
const manifest = {
|
|
1137
|
-
version: "1.0.0",
|
|
1138
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1139
|
-
cognitives: {},
|
|
1140
|
-
syncs: {}
|
|
1141
|
-
};
|
|
1142
|
-
fs2.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
1143
|
-
}
|
|
1144
|
-
function updateGitignore(projectRoot) {
|
|
1145
|
-
const gitignorePath = path3.join(projectRoot, ".gitignore");
|
|
1146
|
-
const synapsyncEntries = `
|
|
1147
|
-
# SynapSync
|
|
1148
|
-
.synapsync/manifest.json
|
|
1149
|
-
*.local.yaml
|
|
1150
|
-
`;
|
|
1151
|
-
if (fs2.existsSync(gitignorePath)) {
|
|
1152
|
-
const content = fs2.readFileSync(gitignorePath, "utf-8");
|
|
1153
|
-
if (!content.includes("# SynapSync")) {
|
|
1154
|
-
fs2.appendFileSync(gitignorePath, synapsyncEntries);
|
|
1141
|
+
for (const name of Object.keys(this.manifest.cognitives)) {
|
|
1142
|
+
if (!scannedMap.has(name)) {
|
|
1143
|
+
result.removed.push(name);
|
|
1144
|
+
}
|
|
1155
1145
|
}
|
|
1156
|
-
|
|
1157
|
-
|
|
1146
|
+
for (const scanned of scannedCognitives) {
|
|
1147
|
+
const existing = this.manifest.cognitives[scanned.name];
|
|
1148
|
+
if (existing === void 0) {
|
|
1149
|
+
result.added.push(scanned);
|
|
1150
|
+
} else if (scanned.hash !== void 0 && existing.hash !== scanned.hash) {
|
|
1151
|
+
result.updated.push(scanned);
|
|
1152
|
+
} else {
|
|
1153
|
+
result.unchanged++;
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
return result;
|
|
1158
1157
|
}
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
}
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
[
|
|
1186
|
-
`${pc4.dim("Config:")} ${pc4.cyan(configPath)}`,
|
|
1187
|
-
`${pc4.dim("Storage:")} ${pc4.cyan(storagePath)}`,
|
|
1188
|
-
"",
|
|
1189
|
-
`${pc4.dim("Providers:")} ${setup.providers.map((p2) => pc4.green(p2)).join(", ") || pc4.dim("none")}`
|
|
1190
|
-
].join("\n"),
|
|
1191
|
-
`Project "${setup.name}" initialized!`
|
|
1192
|
-
);
|
|
1193
|
-
logger.line();
|
|
1194
|
-
logger.bold(" Next Steps:");
|
|
1195
|
-
logger.line();
|
|
1196
|
-
logger.log(` ${pc4.cyan("1.")} Connect to providers:`);
|
|
1197
|
-
logger.log(` ${pc4.dim("$")} synapsync connect claude`);
|
|
1198
|
-
logger.line();
|
|
1199
|
-
logger.log(` ${pc4.cyan("2.")} Add cognitives:`);
|
|
1200
|
-
logger.log(` ${pc4.dim("$")} synapsync add code-reviewer`);
|
|
1201
|
-
logger.log(` ${pc4.dim("$")} synapsync add github:user/my-skill`);
|
|
1202
|
-
logger.line();
|
|
1203
|
-
logger.log(` ${pc4.cyan("3.")} Sync to providers:`);
|
|
1204
|
-
logger.log(` ${pc4.dim("$")} synapsync sync`);
|
|
1205
|
-
logger.line();
|
|
1206
|
-
p.outro(pc4.green("Happy syncing!"));
|
|
1207
|
-
}
|
|
1208
|
-
function registerInitCommand(program) {
|
|
1209
|
-
program.command("init").description("Initialize a new SynapSync project").option("-n, --name <name>", "Project name").option("-d, --description <desc>", "Project description").option("-p, --provider <providers...>", "Enable providers (claude, openai, etc.)").option("-y, --yes", "Skip prompts and use defaults").action(async (options) => {
|
|
1210
|
-
await executeInitCommand({
|
|
1211
|
-
...options.name !== void 0 && { name: options.name },
|
|
1212
|
-
...options.description !== void 0 && { description: options.description },
|
|
1213
|
-
...options.provider !== void 0 && { providers: options.provider },
|
|
1214
|
-
...options.yes !== void 0 && { yes: options.yes }
|
|
1215
|
-
});
|
|
1216
|
-
});
|
|
1217
|
-
}
|
|
1218
|
-
|
|
1219
|
-
// src/commands/config.ts
|
|
1220
|
-
init_esm_shims();
|
|
1221
|
-
import pc5 from "picocolors";
|
|
1222
|
-
function executeConfigCommand(args) {
|
|
1223
|
-
const options = parseConfigArgs(args);
|
|
1224
|
-
const configManager = ConfigManager.findConfig();
|
|
1225
|
-
if (configManager === null) {
|
|
1226
|
-
logger.line();
|
|
1227
|
-
logger.error("No SynapSync project found.");
|
|
1228
|
-
logger.hint("Run /init to initialize a project.");
|
|
1229
|
-
return;
|
|
1158
|
+
/**
|
|
1159
|
+
* Apply reconciliation result to manifest
|
|
1160
|
+
*/
|
|
1161
|
+
applyReconciliation(result) {
|
|
1162
|
+
for (const name of result.removed) {
|
|
1163
|
+
delete this.manifest.cognitives[name];
|
|
1164
|
+
}
|
|
1165
|
+
for (const cognitive of result.added) {
|
|
1166
|
+
this.manifest.cognitives[cognitive.name] = cognitive;
|
|
1167
|
+
}
|
|
1168
|
+
for (const cognitive of result.updated) {
|
|
1169
|
+
const existing = this.manifest.cognitives[cognitive.name];
|
|
1170
|
+
if (existing !== void 0) {
|
|
1171
|
+
const updated = {
|
|
1172
|
+
...existing,
|
|
1173
|
+
...cognitive,
|
|
1174
|
+
// Keep original installation info
|
|
1175
|
+
installedAt: existing.installedAt,
|
|
1176
|
+
source: existing.source
|
|
1177
|
+
};
|
|
1178
|
+
if (existing.sourceUrl !== void 0) {
|
|
1179
|
+
updated.sourceUrl = existing.sourceUrl;
|
|
1180
|
+
}
|
|
1181
|
+
this.manifest.cognitives[cognitive.name] = updated;
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1230
1184
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
showConfigValue(configManager, options.key ?? "");
|
|
1237
|
-
break;
|
|
1238
|
-
case "set":
|
|
1239
|
-
setConfigValue(configManager, options.key ?? "", options.value ?? "");
|
|
1240
|
-
break;
|
|
1185
|
+
/**
|
|
1186
|
+
* Get provider sync state
|
|
1187
|
+
*/
|
|
1188
|
+
getProviderSync(provider) {
|
|
1189
|
+
return this.manifest.syncs[provider];
|
|
1241
1190
|
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
logger.line();
|
|
1248
|
-
const groups = {};
|
|
1249
|
-
for (const [key, value] of Object.entries(flatConfig)) {
|
|
1250
|
-
const parts = key.split(".");
|
|
1251
|
-
const group2 = parts[0] ?? "other";
|
|
1252
|
-
groups[group2] ??= {};
|
|
1253
|
-
groups[group2][key] = value;
|
|
1191
|
+
/**
|
|
1192
|
+
* Update provider sync state
|
|
1193
|
+
*/
|
|
1194
|
+
setProviderSync(provider, state) {
|
|
1195
|
+
this.manifest.syncs[provider] = state;
|
|
1254
1196
|
}
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
logger.log(` ${pc5.dim(displayKey.padEnd(30))} ${displayValue}`);
|
|
1261
|
-
}
|
|
1262
|
-
logger.line();
|
|
1197
|
+
/**
|
|
1198
|
+
* Get all synced cognitives for a provider
|
|
1199
|
+
*/
|
|
1200
|
+
getSyncedCognitives(provider) {
|
|
1201
|
+
return this.manifest.syncs[provider]?.cognitives ?? [];
|
|
1263
1202
|
}
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
logger.error("Key is required.");
|
|
1270
|
-
logger.hint("Usage: /config get <key>");
|
|
1271
|
-
logger.hint("Example: /config get cli.theme");
|
|
1272
|
-
return;
|
|
1203
|
+
/**
|
|
1204
|
+
* Get cognitive count
|
|
1205
|
+
*/
|
|
1206
|
+
getCognitiveCount() {
|
|
1207
|
+
return Object.keys(this.manifest.cognitives).length;
|
|
1273
1208
|
}
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
logger.hint("Use /config list to see all available keys.");
|
|
1280
|
-
} else {
|
|
1281
|
-
logger.log(` ${pc5.cyan(key)} = ${formatValue(value)}`);
|
|
1209
|
+
/**
|
|
1210
|
+
* Get cognitives by type
|
|
1211
|
+
*/
|
|
1212
|
+
getCognitivesByType(type) {
|
|
1213
|
+
return Object.values(this.manifest.cognitives).filter((c) => c.type === type);
|
|
1282
1214
|
}
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
logger.hint("Usage: /config set <key> <value>");
|
|
1289
|
-
logger.hint("Example: /config set cli.theme dark");
|
|
1290
|
-
return;
|
|
1215
|
+
/**
|
|
1216
|
+
* Get cognitives by source
|
|
1217
|
+
*/
|
|
1218
|
+
getCognitivesBySource(source) {
|
|
1219
|
+
return Object.values(this.manifest.cognitives).filter((c) => c.source === source);
|
|
1291
1220
|
}
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1221
|
+
};
|
|
1222
|
+
|
|
1223
|
+
// src/services/scanner/scanner.ts
|
|
1224
|
+
init_esm_shims();
|
|
1225
|
+
import * as fs3 from "fs";
|
|
1226
|
+
import * as path4 from "path";
|
|
1227
|
+
import * as crypto from "crypto";
|
|
1228
|
+
|
|
1229
|
+
// src/services/scanner/parser.ts
|
|
1230
|
+
init_esm_shims();
|
|
1231
|
+
function parseFrontmatter(content) {
|
|
1232
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
1233
|
+
if (match?.[1] === void 0) {
|
|
1234
|
+
return {};
|
|
1297
1235
|
}
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
configManager.save();
|
|
1303
|
-
logger.line();
|
|
1304
|
-
if (isNewKey) {
|
|
1305
|
-
logger.warning(`Created new key: ${pc5.cyan(key)}`);
|
|
1236
|
+
try {
|
|
1237
|
+
return parseYaml(match[1]);
|
|
1238
|
+
} catch {
|
|
1239
|
+
return {};
|
|
1306
1240
|
}
|
|
1307
|
-
logger.success(`${pc5.cyan(key)} = ${formatValue(parsedValue)}`);
|
|
1308
1241
|
}
|
|
1309
|
-
function
|
|
1310
|
-
const
|
|
1311
|
-
const
|
|
1312
|
-
|
|
1313
|
-
|
|
1242
|
+
function parseYaml(yaml2) {
|
|
1243
|
+
const result = {};
|
|
1244
|
+
const lines = yaml2.split("\n");
|
|
1245
|
+
let currentKey = null;
|
|
1246
|
+
let currentArray = null;
|
|
1247
|
+
for (const line of lines) {
|
|
1248
|
+
if (line.trim() === "" || line.trim().startsWith("#")) {
|
|
1249
|
+
continue;
|
|
1250
|
+
}
|
|
1251
|
+
if (line.match(/^\s+-\s+/)) {
|
|
1252
|
+
const value = line.replace(/^\s+-\s+/, "").trim();
|
|
1253
|
+
if (currentArray !== null) {
|
|
1254
|
+
currentArray.push(cleanValue(value));
|
|
1255
|
+
}
|
|
1256
|
+
continue;
|
|
1257
|
+
}
|
|
1258
|
+
const colonIndex = line.indexOf(":");
|
|
1259
|
+
if (colonIndex > 0) {
|
|
1260
|
+
const key = line.slice(0, colonIndex).trim();
|
|
1261
|
+
const rawValue = line.slice(colonIndex + 1).trim();
|
|
1262
|
+
if (currentKey !== null && currentArray !== null) {
|
|
1263
|
+
setNestedValue2(result, currentKey, currentArray);
|
|
1264
|
+
currentArray = null;
|
|
1265
|
+
}
|
|
1266
|
+
currentKey = key;
|
|
1267
|
+
if (rawValue === "" || rawValue === "|" || rawValue === ">") {
|
|
1268
|
+
currentArray = [];
|
|
1269
|
+
} else if (rawValue.startsWith("[") && rawValue.endsWith("]")) {
|
|
1270
|
+
const arrayContent = rawValue.slice(1, -1);
|
|
1271
|
+
const items = arrayContent.split(",").map((item) => cleanValue(item.trim()));
|
|
1272
|
+
setNestedValue2(result, key, items);
|
|
1273
|
+
currentKey = null;
|
|
1274
|
+
} else {
|
|
1275
|
+
setNestedValue2(result, key, cleanValue(rawValue));
|
|
1276
|
+
currentKey = null;
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1314
1279
|
}
|
|
1315
|
-
if (
|
|
1316
|
-
|
|
1317
|
-
action: "get",
|
|
1318
|
-
key: parts[1] ?? ""
|
|
1319
|
-
};
|
|
1280
|
+
if (currentKey !== null && currentArray !== null) {
|
|
1281
|
+
setNestedValue2(result, currentKey, currentArray);
|
|
1320
1282
|
}
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
};
|
|
1283
|
+
return result;
|
|
1284
|
+
}
|
|
1285
|
+
function cleanValue(value) {
|
|
1286
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
1287
|
+
return value.slice(1, -1);
|
|
1327
1288
|
}
|
|
1328
|
-
return
|
|
1329
|
-
action: "get",
|
|
1330
|
-
key: action
|
|
1331
|
-
};
|
|
1289
|
+
return value;
|
|
1332
1290
|
}
|
|
1333
|
-
function
|
|
1334
|
-
|
|
1335
|
-
return pc5.dim("(not set)");
|
|
1336
|
-
}
|
|
1337
|
-
if (typeof value === "boolean") {
|
|
1338
|
-
return value ? pc5.green("true") : pc5.red("false");
|
|
1339
|
-
}
|
|
1340
|
-
if (typeof value === "number") {
|
|
1341
|
-
return pc5.yellow(String(value));
|
|
1342
|
-
}
|
|
1343
|
-
if (typeof value === "string") {
|
|
1344
|
-
return pc5.white(`"${value}"`);
|
|
1345
|
-
}
|
|
1346
|
-
if (Array.isArray(value)) {
|
|
1347
|
-
return pc5.dim(`[${value.join(", ")}]`);
|
|
1348
|
-
}
|
|
1349
|
-
return pc5.dim(JSON.stringify(value));
|
|
1350
|
-
}
|
|
1351
|
-
function parseValue(value) {
|
|
1352
|
-
if (value.toLowerCase() === "true") return true;
|
|
1353
|
-
if (value.toLowerCase() === "false") return false;
|
|
1354
|
-
const num = Number(value);
|
|
1355
|
-
if (!isNaN(num) && value.trim() !== "") return num;
|
|
1356
|
-
return value;
|
|
1357
|
-
}
|
|
1358
|
-
function registerConfigCommand(program) {
|
|
1359
|
-
const configCmd = program.command("config").description("Manage project configuration");
|
|
1360
|
-
configCmd.command("list").description("Show all configuration values").action(() => {
|
|
1361
|
-
executeConfigCommand("list");
|
|
1362
|
-
});
|
|
1363
|
-
configCmd.command("get <key>").description("Get a configuration value").action((key) => {
|
|
1364
|
-
executeConfigCommand(`get ${key}`);
|
|
1365
|
-
});
|
|
1366
|
-
configCmd.command("set <key> <value>").description("Set a configuration value").action((key, value) => {
|
|
1367
|
-
executeConfigCommand(`set ${key} ${value}`);
|
|
1368
|
-
});
|
|
1369
|
-
configCmd.action(() => {
|
|
1370
|
-
executeConfigCommand("list");
|
|
1371
|
-
});
|
|
1291
|
+
function setNestedValue2(obj, key, value) {
|
|
1292
|
+
obj[key] = value;
|
|
1372
1293
|
}
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
import * as fs3 from "fs";
|
|
1377
|
-
import * as path4 from "path";
|
|
1378
|
-
import pc6 from "picocolors";
|
|
1379
|
-
function executeStatusCommand(_args = "") {
|
|
1380
|
-
const status = getProjectStatus();
|
|
1381
|
-
logger.line();
|
|
1382
|
-
if (!status.initialized) {
|
|
1383
|
-
showNotInitialized();
|
|
1384
|
-
return;
|
|
1294
|
+
function extractVersion(metadata, content) {
|
|
1295
|
+
if (metadata.version !== void 0) {
|
|
1296
|
+
return metadata.version;
|
|
1385
1297
|
}
|
|
1386
|
-
|
|
1298
|
+
const versionMatch = content.match(/version:\s*['"]?([0-9]+\.[0-9]+\.[0-9]+)['"]?/i);
|
|
1299
|
+
if (versionMatch?.[1] !== void 0) {
|
|
1300
|
+
return versionMatch[1];
|
|
1301
|
+
}
|
|
1302
|
+
return "1.0.0";
|
|
1387
1303
|
}
|
|
1388
|
-
function
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
return {
|
|
1392
|
-
initialized: false,
|
|
1393
|
-
cognitives: createEmptyCognitiveCount(),
|
|
1394
|
-
providers: []
|
|
1395
|
-
};
|
|
1304
|
+
function extractName(metadata, dirName, content) {
|
|
1305
|
+
if (metadata.name !== void 0) {
|
|
1306
|
+
return metadata.name;
|
|
1396
1307
|
}
|
|
1397
|
-
const
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
const cognitives = countCognitives(storagePath);
|
|
1401
|
-
const providers = getProviderStatuses(config, projectRoot);
|
|
1402
|
-
const lastSync = getLastSyncTime(storagePath);
|
|
1403
|
-
const status = {
|
|
1404
|
-
initialized: true,
|
|
1405
|
-
projectName: config.name,
|
|
1406
|
-
projectRoot,
|
|
1407
|
-
configPath: path4.join(projectRoot, "synapsync.config.yaml"),
|
|
1408
|
-
storagePath,
|
|
1409
|
-
cognitives,
|
|
1410
|
-
providers
|
|
1411
|
-
};
|
|
1412
|
-
if (lastSync !== void 0) {
|
|
1413
|
-
status.lastSync = lastSync;
|
|
1308
|
+
const titleMatch = content.match(/^#\s+(.+)$/m);
|
|
1309
|
+
if (titleMatch?.[1] !== void 0) {
|
|
1310
|
+
return titleMatch[1].toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
1414
1311
|
}
|
|
1415
|
-
return
|
|
1312
|
+
return dirName;
|
|
1416
1313
|
}
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1314
|
+
|
|
1315
|
+
// src/services/scanner/scanner.ts
|
|
1316
|
+
var CognitiveScanner = class {
|
|
1317
|
+
synapSyncDir;
|
|
1318
|
+
constructor(synapSyncDir) {
|
|
1319
|
+
this.synapSyncDir = synapSyncDir;
|
|
1421
1320
|
}
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
const
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
).length;
|
|
1434
|
-
} catch {
|
|
1435
|
-
counts[type] = 0;
|
|
1321
|
+
/**
|
|
1322
|
+
* Scan the filesystem for cognitives
|
|
1323
|
+
*/
|
|
1324
|
+
scan(options = {}) {
|
|
1325
|
+
const cognitives = [];
|
|
1326
|
+
const errors = [];
|
|
1327
|
+
const typesToScan = options.types ?? COGNITIVE_TYPES;
|
|
1328
|
+
for (const type of typesToScan) {
|
|
1329
|
+
const typeDir = path4.join(this.synapSyncDir, `${type}s`);
|
|
1330
|
+
if (!fs3.existsSync(typeDir)) {
|
|
1331
|
+
continue;
|
|
1436
1332
|
}
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1333
|
+
const categories = this.listDirectories(typeDir);
|
|
1334
|
+
for (const category of categories) {
|
|
1335
|
+
if (options.categories !== void 0 && !options.categories.includes(category)) {
|
|
1336
|
+
continue;
|
|
1337
|
+
}
|
|
1338
|
+
const categoryDir = path4.join(typeDir, category);
|
|
1339
|
+
const cognitiveDirs = this.listDirectories(categoryDir);
|
|
1340
|
+
for (const cognitiveDir of cognitiveDirs) {
|
|
1341
|
+
try {
|
|
1342
|
+
const cognitive = this.scanCognitive(
|
|
1343
|
+
path4.join(categoryDir, cognitiveDir),
|
|
1344
|
+
type,
|
|
1345
|
+
category
|
|
1346
|
+
);
|
|
1347
|
+
if (cognitive !== null) {
|
|
1348
|
+
cognitives.push(cognitive);
|
|
1349
|
+
}
|
|
1350
|
+
} catch (error) {
|
|
1351
|
+
errors.push({
|
|
1352
|
+
path: path4.join(categoryDir, cognitiveDir),
|
|
1353
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
1354
|
+
});
|
|
1456
1355
|
}
|
|
1457
1356
|
}
|
|
1458
|
-
} catch {
|
|
1459
1357
|
}
|
|
1460
1358
|
}
|
|
1461
|
-
|
|
1462
|
-
name: provider,
|
|
1463
|
-
enabled,
|
|
1464
|
-
connected: false,
|
|
1465
|
-
// TODO: Check actual connection status
|
|
1466
|
-
cognitivesCount
|
|
1467
|
-
});
|
|
1468
|
-
}
|
|
1469
|
-
return statuses;
|
|
1470
|
-
}
|
|
1471
|
-
function getLastSyncTime(storagePath) {
|
|
1472
|
-
const manifestPath = path4.join(storagePath, "manifest.json");
|
|
1473
|
-
if (!fs3.existsSync(manifestPath)) {
|
|
1474
|
-
return void 0;
|
|
1359
|
+
return cognitives;
|
|
1475
1360
|
}
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1361
|
+
/**
|
|
1362
|
+
* Scan a single cognitive directory
|
|
1363
|
+
*/
|
|
1364
|
+
scanCognitive(cognitiveDir, type, category) {
|
|
1365
|
+
const filePath = this.findCognitiveFile(cognitiveDir, type);
|
|
1366
|
+
if (filePath === null) {
|
|
1367
|
+
return null;
|
|
1368
|
+
}
|
|
1369
|
+
const content = fs3.readFileSync(filePath, "utf-8");
|
|
1370
|
+
const metadata = parseFrontmatter(content);
|
|
1371
|
+
const dirName = path4.basename(cognitiveDir);
|
|
1372
|
+
const fileName = path4.basename(filePath);
|
|
1373
|
+
const name = extractName(metadata, dirName, content);
|
|
1374
|
+
const version2 = extractVersion(metadata, content);
|
|
1375
|
+
const hash = this.computeHash(content);
|
|
1376
|
+
return {
|
|
1377
|
+
name,
|
|
1378
|
+
type,
|
|
1379
|
+
category: metadata.category ?? category,
|
|
1380
|
+
path: cognitiveDir,
|
|
1381
|
+
filePath,
|
|
1382
|
+
fileName,
|
|
1383
|
+
// Add original filename
|
|
1384
|
+
hash,
|
|
1385
|
+
metadata: {
|
|
1386
|
+
...metadata,
|
|
1387
|
+
name,
|
|
1388
|
+
version: version2
|
|
1389
|
+
}
|
|
1390
|
+
};
|
|
1482
1391
|
}
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
const icon = getCognitiveIcon(type);
|
|
1506
|
-
logger.log(` ${icon} ${pc6.white(count.toString().padStart(3))} ${type}s`);
|
|
1392
|
+
/**
|
|
1393
|
+
* Find the cognitive file in a directory
|
|
1394
|
+
* Checks for legacy fixed filename first, then any file with matching extension
|
|
1395
|
+
*/
|
|
1396
|
+
findCognitiveFile(cognitiveDir, type) {
|
|
1397
|
+
const legacyFileName = COGNITIVE_FILE_NAMES[type];
|
|
1398
|
+
const legacyPath = path4.join(cognitiveDir, legacyFileName);
|
|
1399
|
+
if (fs3.existsSync(legacyPath)) {
|
|
1400
|
+
return legacyPath;
|
|
1401
|
+
}
|
|
1402
|
+
const extension = COGNITIVE_FILE_EXTENSIONS[type];
|
|
1403
|
+
if (!fs3.existsSync(cognitiveDir)) {
|
|
1404
|
+
return null;
|
|
1405
|
+
}
|
|
1406
|
+
const files = fs3.readdirSync(cognitiveDir);
|
|
1407
|
+
for (const file of files) {
|
|
1408
|
+
if (file.endsWith(extension) && !file.startsWith(".")) {
|
|
1409
|
+
const fullPath = path4.join(cognitiveDir, file);
|
|
1410
|
+
const stat = fs3.statSync(fullPath);
|
|
1411
|
+
if (stat.isFile()) {
|
|
1412
|
+
return fullPath;
|
|
1413
|
+
}
|
|
1507
1414
|
}
|
|
1508
1415
|
}
|
|
1509
|
-
|
|
1510
|
-
logger.log(` ${pc6.bold(totalCognitives.toString().padStart(5))} total`);
|
|
1416
|
+
return null;
|
|
1511
1417
|
}
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1418
|
+
/**
|
|
1419
|
+
* Compare scanned cognitives with manifest and return differences
|
|
1420
|
+
*/
|
|
1421
|
+
compare(scanned, manifestCognitives) {
|
|
1422
|
+
const result = {
|
|
1423
|
+
found: scanned,
|
|
1424
|
+
new: [],
|
|
1425
|
+
removed: [],
|
|
1426
|
+
modified: [],
|
|
1427
|
+
unchanged: 0,
|
|
1428
|
+
errors: []
|
|
1429
|
+
};
|
|
1430
|
+
const manifestMap = /* @__PURE__ */ new Map();
|
|
1431
|
+
for (const cognitive of manifestCognitives) {
|
|
1432
|
+
manifestMap.set(cognitive.name, cognitive);
|
|
1522
1433
|
}
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
const
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
function getCognitiveIcon(type) {
|
|
1534
|
-
const icons = {
|
|
1535
|
-
skill: pc6.blue("\u25C6"),
|
|
1536
|
-
agent: pc6.magenta("\u25C6"),
|
|
1537
|
-
prompt: pc6.yellow("\u25C6"),
|
|
1538
|
-
workflow: pc6.cyan("\u25C6"),
|
|
1539
|
-
tool: pc6.green("\u25C6")
|
|
1540
|
-
};
|
|
1541
|
-
return icons[type];
|
|
1542
|
-
}
|
|
1543
|
-
function getRelativeTime(date) {
|
|
1544
|
-
const now = /* @__PURE__ */ new Date();
|
|
1545
|
-
const diffMs = now.getTime() - date.getTime();
|
|
1546
|
-
const diffMins = Math.floor(diffMs / 6e4);
|
|
1547
|
-
const diffHours = Math.floor(diffMins / 60);
|
|
1548
|
-
const diffDays = Math.floor(diffHours / 24);
|
|
1549
|
-
if (diffMins < 1) return "just now";
|
|
1550
|
-
if (diffMins < 60) return `${diffMins} minute${diffMins === 1 ? "" : "s"} ago`;
|
|
1551
|
-
if (diffHours < 24) return `${diffHours} hour${diffHours === 1 ? "" : "s"} ago`;
|
|
1552
|
-
if (diffDays < 7) return `${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
|
|
1553
|
-
return date.toLocaleDateString();
|
|
1554
|
-
}
|
|
1555
|
-
function registerStatusCommand(program) {
|
|
1556
|
-
program.command("status").description("Show project status").action(() => {
|
|
1557
|
-
executeStatusCommand();
|
|
1558
|
-
});
|
|
1559
|
-
}
|
|
1560
|
-
|
|
1561
|
-
// src/commands/providers.ts
|
|
1562
|
-
init_esm_shims();
|
|
1563
|
-
import * as fs4 from "fs";
|
|
1564
|
-
import * as path5 from "path";
|
|
1565
|
-
import pc7 from "picocolors";
|
|
1566
|
-
function executeProvidersCommand(args) {
|
|
1567
|
-
const parts = args.trim().split(/\s+/);
|
|
1568
|
-
const subcommand = parts[0]?.toLowerCase() ?? "";
|
|
1569
|
-
const configManager = ConfigManager.findConfig();
|
|
1570
|
-
if (configManager === null) {
|
|
1571
|
-
logger.line();
|
|
1572
|
-
logger.error("No SynapSync project found.");
|
|
1573
|
-
logger.hint("Run /init to initialize a project.");
|
|
1574
|
-
return;
|
|
1575
|
-
}
|
|
1576
|
-
switch (subcommand) {
|
|
1577
|
-
case "":
|
|
1578
|
-
case "list":
|
|
1579
|
-
listProviders(configManager);
|
|
1580
|
-
break;
|
|
1581
|
-
case "enable":
|
|
1582
|
-
enableProvider(configManager, parts[1]);
|
|
1583
|
-
break;
|
|
1584
|
-
case "disable":
|
|
1585
|
-
disableProvider(configManager, parts[1]);
|
|
1586
|
-
break;
|
|
1587
|
-
case "path":
|
|
1588
|
-
setProviderPath(configManager, parts[1], parts[2]);
|
|
1589
|
-
break;
|
|
1590
|
-
default:
|
|
1591
|
-
if (SUPPORTED_PROVIDERS.includes(subcommand)) {
|
|
1592
|
-
showProviderInfo(configManager, subcommand);
|
|
1434
|
+
const scannedMap = /* @__PURE__ */ new Map();
|
|
1435
|
+
for (const cognitive of scanned) {
|
|
1436
|
+
scannedMap.set(cognitive.name, cognitive);
|
|
1437
|
+
}
|
|
1438
|
+
for (const scannedCognitive of scanned) {
|
|
1439
|
+
const manifestCognitive = manifestMap.get(scannedCognitive.name);
|
|
1440
|
+
if (manifestCognitive === void 0) {
|
|
1441
|
+
result.new.push(scannedCognitive);
|
|
1442
|
+
} else if (manifestCognitive.hash !== void 0 && manifestCognitive.hash !== scannedCognitive.hash) {
|
|
1443
|
+
result.modified.push(scannedCognitive);
|
|
1593
1444
|
} else {
|
|
1594
|
-
|
|
1595
|
-
logger.error(`Unknown subcommand: ${subcommand}`);
|
|
1596
|
-
logger.hint("Usage: /providers [list|enable|disable|path]");
|
|
1445
|
+
result.unchanged++;
|
|
1597
1446
|
}
|
|
1447
|
+
}
|
|
1448
|
+
for (const manifestCognitive of manifestCognitives) {
|
|
1449
|
+
if (!scannedMap.has(manifestCognitive.name)) {
|
|
1450
|
+
result.removed.push(manifestCognitive.name);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
return result;
|
|
1598
1454
|
}
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
const pathText = pc7.cyan(provider.path);
|
|
1613
|
-
const existsText = provider.exists ? pc7.green("\u2713 exists") : pc7.dim("\u2717 missing");
|
|
1614
|
-
logger.log(
|
|
1615
|
-
` ${statusIcon} ${pc7.white(provider.name.padEnd(10))} ${statusText.padEnd(19)} ${pathText.padEnd(29)} ${existsText}`
|
|
1616
|
-
);
|
|
1617
|
-
}
|
|
1618
|
-
logger.line();
|
|
1619
|
-
const enabledCount = providers.filter((p2) => p2.enabled).length;
|
|
1620
|
-
logger.log(` ${pc7.dim("Enabled:")} ${enabledCount} of ${providers.length} providers`);
|
|
1621
|
-
logger.line();
|
|
1622
|
-
logger.hint("Use /providers enable <name> or /providers disable <name>");
|
|
1623
|
-
}
|
|
1624
|
-
function enableProvider(configManager, providerName) {
|
|
1625
|
-
if (providerName === void 0 || providerName === "") {
|
|
1626
|
-
logger.line();
|
|
1627
|
-
logger.error("Provider name is required.");
|
|
1628
|
-
logger.hint("Usage: /providers enable <provider>");
|
|
1629
|
-
logger.hint(`Available: ${SUPPORTED_PROVIDERS.join(", ")}`);
|
|
1630
|
-
return;
|
|
1455
|
+
/**
|
|
1456
|
+
* Convert a scanned cognitive to a manifest cognitive
|
|
1457
|
+
*/
|
|
1458
|
+
toManifestCognitive(scanned) {
|
|
1459
|
+
return {
|
|
1460
|
+
name: scanned.name,
|
|
1461
|
+
type: scanned.type,
|
|
1462
|
+
category: scanned.category,
|
|
1463
|
+
version: scanned.metadata.version ?? "1.0.0",
|
|
1464
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1465
|
+
source: "local",
|
|
1466
|
+
hash: scanned.hash
|
|
1467
|
+
};
|
|
1631
1468
|
}
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
return;
|
|
1469
|
+
/**
|
|
1470
|
+
* Compute content hash for change detection
|
|
1471
|
+
*/
|
|
1472
|
+
computeHash(content) {
|
|
1473
|
+
return crypto.createHash("sha256").update(content).digest("hex").slice(0, 16);
|
|
1638
1474
|
}
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1475
|
+
/**
|
|
1476
|
+
* List directories in a path
|
|
1477
|
+
*/
|
|
1478
|
+
listDirectories(dirPath) {
|
|
1479
|
+
if (!fs3.existsSync(dirPath)) {
|
|
1480
|
+
return [];
|
|
1481
|
+
}
|
|
1482
|
+
return fs3.readdirSync(dirPath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).filter((dirent) => !dirent.name.startsWith(".")).map((dirent) => dirent.name);
|
|
1644
1483
|
}
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1484
|
+
/**
|
|
1485
|
+
* Detect cognitive type from directory contents
|
|
1486
|
+
*/
|
|
1487
|
+
detectType(cognitiveDir) {
|
|
1488
|
+
for (const type of COGNITIVE_TYPES) {
|
|
1489
|
+
const fileName = COGNITIVE_FILE_NAMES[type];
|
|
1490
|
+
const filePath = path4.join(cognitiveDir, fileName);
|
|
1491
|
+
if (fs3.existsSync(filePath)) {
|
|
1492
|
+
return type;
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
return null;
|
|
1650
1496
|
}
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1497
|
+
/**
|
|
1498
|
+
* Get cognitive count by type
|
|
1499
|
+
*/
|
|
1500
|
+
countByType(cognitives) {
|
|
1501
|
+
const counts = {
|
|
1502
|
+
skill: 0,
|
|
1503
|
+
agent: 0,
|
|
1504
|
+
prompt: 0,
|
|
1505
|
+
workflow: 0,
|
|
1506
|
+
tool: 0
|
|
1507
|
+
};
|
|
1508
|
+
for (const cognitive of cognitives) {
|
|
1509
|
+
counts[cognitive.type]++;
|
|
1510
|
+
}
|
|
1511
|
+
return counts;
|
|
1664
1512
|
}
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1513
|
+
};
|
|
1514
|
+
|
|
1515
|
+
// src/services/agents-md/generator.ts
|
|
1516
|
+
var START_MARKER = "<!-- synapsync:start -->";
|
|
1517
|
+
var END_MARKER = "<!-- synapsync:end -->";
|
|
1518
|
+
var TYPE_ICONS = {
|
|
1519
|
+
skill: "\u{1F527}",
|
|
1520
|
+
agent: "\u{1F916}",
|
|
1521
|
+
prompt: "\u{1F4AC}",
|
|
1522
|
+
workflow: "\u{1F504}",
|
|
1523
|
+
tool: "\u{1F9F0}"
|
|
1524
|
+
};
|
|
1525
|
+
var TYPE_LABELS = {
|
|
1526
|
+
skill: "Skills",
|
|
1527
|
+
agent: "Agents",
|
|
1528
|
+
prompt: "Prompts",
|
|
1529
|
+
workflow: "Workflows",
|
|
1530
|
+
tool: "Tools"
|
|
1531
|
+
};
|
|
1532
|
+
var MAX_DESCRIPTION_LENGTH = 80;
|
|
1533
|
+
var AgentsMdGenerator = class {
|
|
1534
|
+
projectRoot;
|
|
1535
|
+
synapSyncDir;
|
|
1536
|
+
scanner;
|
|
1537
|
+
constructor(projectRoot, synapSyncDir) {
|
|
1538
|
+
this.projectRoot = projectRoot;
|
|
1539
|
+
this.synapSyncDir = synapSyncDir;
|
|
1540
|
+
this.scanner = new CognitiveScanner(this.synapSyncDir);
|
|
1671
1541
|
}
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1542
|
+
/**
|
|
1543
|
+
* Generate and write the AGENTS.md file from manifest cognitives.
|
|
1544
|
+
*/
|
|
1545
|
+
generate(cognitives) {
|
|
1546
|
+
const outputPath = path5.join(this.projectRoot, AGENTS_MD_FILE_NAME);
|
|
1547
|
+
try {
|
|
1548
|
+
const entries = this.buildEntries(cognitives);
|
|
1549
|
+
const managedContent = this.renderManagedSection(entries);
|
|
1550
|
+
this.writeWithMarkers(outputPath, managedContent);
|
|
1551
|
+
return {
|
|
1552
|
+
success: true,
|
|
1553
|
+
filePath: outputPath,
|
|
1554
|
+
cognitiveCount: entries.length
|
|
1555
|
+
};
|
|
1556
|
+
} catch (error) {
|
|
1557
|
+
return {
|
|
1558
|
+
success: false,
|
|
1559
|
+
filePath: outputPath,
|
|
1560
|
+
cognitiveCount: 0,
|
|
1561
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
1562
|
+
};
|
|
1563
|
+
}
|
|
1677
1564
|
}
|
|
1678
|
-
configManager.set(`sync.providers.${provider}.enabled`, false);
|
|
1679
|
-
configManager.save();
|
|
1680
|
-
logger.line();
|
|
1681
|
-
logger.success(`Provider '${pc7.cyan(provider)}' disabled`);
|
|
1682
|
-
}
|
|
1683
|
-
function setProviderPath(configManager, providerName, newPath) {
|
|
1684
|
-
if (providerName === void 0 || providerName === "") {
|
|
1685
|
-
logger.line();
|
|
1686
|
-
logger.error("Provider name is required.");
|
|
1687
|
-
logger.hint("Usage: /providers path <provider> <path>");
|
|
1688
|
-
return;
|
|
1689
|
-
}
|
|
1690
|
-
if (newPath === void 0 || newPath === "") {
|
|
1691
|
-
logger.line();
|
|
1692
|
-
logger.error("Path is required.");
|
|
1693
|
-
logger.hint("Usage: /providers path <provider> <path>");
|
|
1694
|
-
logger.hint("Example: /providers path claude .claude-code/");
|
|
1695
|
-
return;
|
|
1696
|
-
}
|
|
1697
|
-
const provider = providerName.toLowerCase();
|
|
1698
|
-
if (!SUPPORTED_PROVIDERS.includes(provider)) {
|
|
1699
|
-
logger.line();
|
|
1700
|
-
logger.error(`Unknown provider: ${provider}`);
|
|
1701
|
-
logger.hint(`Available: ${SUPPORTED_PROVIDERS.join(", ")}`);
|
|
1702
|
-
return;
|
|
1703
|
-
}
|
|
1704
|
-
const normalizedPath = newPath.endsWith("/") ? newPath : `${newPath}/`;
|
|
1705
|
-
const cognitiveTypes = ["skill", "agent", "prompt", "workflow", "tool"];
|
|
1706
|
-
for (const type of cognitiveTypes) {
|
|
1707
|
-
configManager.set(`sync.providers.${provider}.paths.${type}`, `${normalizedPath}${type}s`);
|
|
1708
|
-
}
|
|
1709
|
-
configManager.save();
|
|
1710
|
-
logger.line();
|
|
1711
|
-
logger.success(`Updated paths for '${pc7.cyan(provider)}'`);
|
|
1712
|
-
logger.log(` ${pc7.dim("Base path:")} ${pc7.cyan(normalizedPath)}`);
|
|
1713
|
-
logger.line();
|
|
1714
|
-
}
|
|
1715
|
-
function showProviderInfo(configManager, provider) {
|
|
1716
|
-
const config = configManager.getConfig();
|
|
1717
|
-
const projectRoot = configManager.getProjectRoot();
|
|
1718
|
-
const providerConfig = config.sync?.providers?.[provider];
|
|
1719
|
-
const enabled = providerConfig?.enabled ?? false;
|
|
1720
|
-
const paths = providerConfig?.paths ?? PROVIDER_PATHS[provider];
|
|
1721
|
-
logger.line();
|
|
1722
|
-
logger.bold(` ${getProviderDisplayName(provider)}`);
|
|
1723
|
-
logger.line();
|
|
1724
|
-
const statusIcon = enabled ? pc7.green("\u25CF") : pc7.dim("\u25CB");
|
|
1725
|
-
const statusText = enabled ? pc7.green("Enabled") : pc7.dim("Disabled");
|
|
1726
|
-
logger.log(` ${pc7.dim("Status:")} ${statusIcon} ${statusText}`);
|
|
1727
|
-
logger.line();
|
|
1728
|
-
logger.log(` ${pc7.dim("Paths:")}`);
|
|
1729
|
-
const cognitiveTypes = ["skill", "agent", "prompt", "workflow", "tool"];
|
|
1730
|
-
for (const type of cognitiveTypes) {
|
|
1731
|
-
const typePath = paths[type] ?? "";
|
|
1732
|
-
const fullPath = path5.join(projectRoot, typePath);
|
|
1733
|
-
const exists = fs4.existsSync(fullPath);
|
|
1734
|
-
const existsIcon = exists ? pc7.green("\u2713") : pc7.dim("\u2717");
|
|
1735
|
-
logger.log(` ${pc7.dim(type.padEnd(10))} ${pc7.cyan(typePath)} ${existsIcon}`);
|
|
1736
|
-
}
|
|
1737
|
-
logger.line();
|
|
1738
|
-
}
|
|
1739
|
-
function getProvidersInfo(configManager) {
|
|
1740
|
-
const config = configManager.getConfig();
|
|
1741
|
-
const projectRoot = configManager.getProjectRoot();
|
|
1742
|
-
const providers = [];
|
|
1743
|
-
for (const provider of SUPPORTED_PROVIDERS) {
|
|
1744
|
-
const providerConfig = config.sync?.providers?.[provider];
|
|
1745
|
-
const enabled = providerConfig?.enabled ?? false;
|
|
1746
|
-
const basePath = providerConfig?.paths?.skill?.split("/")[0] ?? `.${provider}`;
|
|
1747
|
-
const fullPath = path5.join(projectRoot, basePath);
|
|
1748
|
-
const exists = fs4.existsSync(fullPath);
|
|
1749
|
-
providers.push({
|
|
1750
|
-
name: provider,
|
|
1751
|
-
enabled,
|
|
1752
|
-
path: `${basePath}/`,
|
|
1753
|
-
exists
|
|
1754
|
-
});
|
|
1755
|
-
}
|
|
1756
|
-
return providers;
|
|
1757
|
-
}
|
|
1758
|
-
function getProviderDisplayName(provider) {
|
|
1759
|
-
const names = {
|
|
1760
|
-
claude: "Claude (Anthropic)",
|
|
1761
|
-
openai: "OpenAI (GPT)",
|
|
1762
|
-
gemini: "Gemini (Google)",
|
|
1763
|
-
cursor: "Cursor IDE",
|
|
1764
|
-
windsurf: "Windsurf IDE",
|
|
1765
|
-
copilot: "GitHub Copilot"
|
|
1766
|
-
};
|
|
1767
|
-
return names[provider];
|
|
1768
|
-
}
|
|
1769
|
-
function registerProvidersCommand(program) {
|
|
1770
|
-
const providersCmd = program.command("providers").description("Manage provider configuration");
|
|
1771
|
-
providersCmd.command("list", { isDefault: true }).description("List all providers and their status").action(() => {
|
|
1772
|
-
executeProvidersCommand("list");
|
|
1773
|
-
});
|
|
1774
|
-
providersCmd.command("enable <provider>").description("Enable a provider").action((provider) => {
|
|
1775
|
-
executeProvidersCommand(`enable ${provider}`);
|
|
1776
|
-
});
|
|
1777
|
-
providersCmd.command("disable <provider>").description("Disable a provider").action((provider) => {
|
|
1778
|
-
executeProvidersCommand(`disable ${provider}`);
|
|
1779
|
-
});
|
|
1780
|
-
providersCmd.command("path <provider> <path>").description("Set custom sync path for a provider").action((provider, newPath) => {
|
|
1781
|
-
executeProvidersCommand(`path ${provider} ${newPath}`);
|
|
1782
|
-
});
|
|
1783
|
-
providersCmd.action(() => {
|
|
1784
|
-
executeProvidersCommand("list");
|
|
1785
|
-
});
|
|
1786
|
-
}
|
|
1787
|
-
|
|
1788
|
-
// src/commands/search.ts
|
|
1789
|
-
init_esm_shims();
|
|
1790
|
-
import pc8 from "picocolors";
|
|
1791
|
-
|
|
1792
|
-
// src/services/registry/client.ts
|
|
1793
|
-
init_esm_shims();
|
|
1794
|
-
var RegistryClient = class {
|
|
1795
|
-
baseUrl;
|
|
1796
|
-
indexCache = null;
|
|
1797
|
-
indexCacheTime = 0;
|
|
1798
|
-
cacheTtl;
|
|
1799
|
-
constructor(options = {}) {
|
|
1800
|
-
this.baseUrl = options.baseUrl ?? REGISTRY_BASE_URL;
|
|
1801
|
-
this.cacheTtl = options.cacheTtl ?? 5 * 60 * 1e3;
|
|
1802
|
-
}
|
|
1803
|
-
// ============================================
|
|
1804
|
-
// Index Operations
|
|
1805
|
-
// ============================================
|
|
1806
1565
|
/**
|
|
1807
|
-
*
|
|
1566
|
+
* Generate an empty managed section (used by init).
|
|
1808
1567
|
*/
|
|
1809
|
-
|
|
1810
|
-
const
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1568
|
+
generateEmpty() {
|
|
1569
|
+
const outputPath = path5.join(this.projectRoot, AGENTS_MD_FILE_NAME);
|
|
1570
|
+
try {
|
|
1571
|
+
const managedContent = this.renderEmptySection();
|
|
1572
|
+
this.writeWithMarkers(outputPath, managedContent);
|
|
1573
|
+
return {
|
|
1574
|
+
success: true,
|
|
1575
|
+
filePath: outputPath,
|
|
1576
|
+
cognitiveCount: 0
|
|
1577
|
+
};
|
|
1578
|
+
} catch (error) {
|
|
1579
|
+
return {
|
|
1580
|
+
success: false,
|
|
1581
|
+
filePath: outputPath,
|
|
1582
|
+
cognitiveCount: 0,
|
|
1583
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
1584
|
+
};
|
|
1818
1585
|
}
|
|
1819
|
-
const index = await response.json();
|
|
1820
|
-
this.indexCache = index;
|
|
1821
|
-
this.indexCacheTime = now;
|
|
1822
|
-
return index;
|
|
1823
1586
|
}
|
|
1824
1587
|
/**
|
|
1825
|
-
*
|
|
1588
|
+
* Remove the AGENTS.md file entirely (used by purge).
|
|
1826
1589
|
*/
|
|
1827
|
-
|
|
1828
|
-
const
|
|
1829
|
-
|
|
1590
|
+
remove() {
|
|
1591
|
+
const outputPath = path5.join(this.projectRoot, AGENTS_MD_FILE_NAME);
|
|
1592
|
+
if (fs4.existsSync(outputPath)) {
|
|
1593
|
+
fs4.unlinkSync(outputPath);
|
|
1594
|
+
return true;
|
|
1595
|
+
}
|
|
1596
|
+
return false;
|
|
1830
1597
|
}
|
|
1831
|
-
// ============================================
|
|
1832
|
-
// Search Operations
|
|
1833
|
-
// ============================================
|
|
1834
1598
|
/**
|
|
1835
|
-
*
|
|
1599
|
+
* Build enriched entries from manifest cognitives.
|
|
1600
|
+
* Scans filesystem for descriptions from frontmatter.
|
|
1836
1601
|
*/
|
|
1837
|
-
|
|
1838
|
-
const
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1602
|
+
buildEntries(cognitives) {
|
|
1603
|
+
const scanned = this.scanner.scan();
|
|
1604
|
+
const scannedMap = new Map(scanned.map((s) => [s.name, s]));
|
|
1605
|
+
const entries = [];
|
|
1606
|
+
for (const cognitive of cognitives) {
|
|
1607
|
+
const scannedCognitive = scannedMap.get(cognitive.name);
|
|
1608
|
+
let description = "No description available";
|
|
1609
|
+
let relativePath = "";
|
|
1610
|
+
let fileName = "";
|
|
1611
|
+
if (scannedCognitive !== void 0) {
|
|
1612
|
+
const rawDesc = scannedCognitive.metadata.description;
|
|
1613
|
+
if (typeof rawDesc === "string" && rawDesc.length > 0) {
|
|
1614
|
+
description = rawDesc;
|
|
1615
|
+
} else if (Array.isArray(rawDesc) && rawDesc.length > 0) {
|
|
1616
|
+
description = rawDesc.join(" ");
|
|
1617
|
+
}
|
|
1618
|
+
relativePath = path5.relative(this.projectRoot, scannedCognitive.filePath);
|
|
1619
|
+
fileName = scannedCognitive.fileName ?? path5.basename(scannedCognitive.filePath);
|
|
1620
|
+
} else {
|
|
1621
|
+
const typeDir = `${cognitive.type}s`;
|
|
1622
|
+
const expectedDir = path5.join(this.synapSyncDir, typeDir, cognitive.category, cognitive.name);
|
|
1623
|
+
relativePath = path5.relative(this.projectRoot, expectedDir);
|
|
1624
|
+
fileName = cognitive.name;
|
|
1625
|
+
}
|
|
1626
|
+
entries.push({
|
|
1627
|
+
name: cognitive.name,
|
|
1628
|
+
type: cognitive.type,
|
|
1629
|
+
category: cognitive.category,
|
|
1630
|
+
description: truncateDescription(description),
|
|
1631
|
+
version: cognitive.version,
|
|
1632
|
+
relativePath,
|
|
1633
|
+
fileName
|
|
1634
|
+
});
|
|
1859
1635
|
}
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
if (options.category !== void 0) filters.category = options.category;
|
|
1863
|
-
if (options.tag !== void 0) filters.tag = options.tag;
|
|
1864
|
-
return {
|
|
1865
|
-
cognitives: results,
|
|
1866
|
-
total,
|
|
1867
|
-
...query !== void 0 ? { query } : {},
|
|
1868
|
-
filters
|
|
1869
|
-
};
|
|
1636
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
1637
|
+
return entries;
|
|
1870
1638
|
}
|
|
1871
1639
|
/**
|
|
1872
|
-
*
|
|
1640
|
+
* Render the full managed section (between markers).
|
|
1873
1641
|
*/
|
|
1874
|
-
|
|
1875
|
-
const
|
|
1876
|
-
|
|
1642
|
+
renderManagedSection(entries) {
|
|
1643
|
+
const lines = [
|
|
1644
|
+
START_MARKER,
|
|
1645
|
+
"# SynapSync Project Cognitives",
|
|
1646
|
+
"",
|
|
1647
|
+
"> Auto-generated by [SynapSync](https://synapsync.github.io/synapsync-cli/). Do not edit this section manually.",
|
|
1648
|
+
""
|
|
1649
|
+
];
|
|
1650
|
+
if (entries.length === 0) {
|
|
1651
|
+
lines.push("*No cognitives installed yet. Run `synapsync add <name>` to get started.*");
|
|
1652
|
+
} else {
|
|
1653
|
+
lines.push("## Available Cognitives");
|
|
1654
|
+
lines.push("");
|
|
1655
|
+
for (const type of COGNITIVE_TYPES) {
|
|
1656
|
+
const typeEntries = entries.filter((e) => e.type === type);
|
|
1657
|
+
if (typeEntries.length === 0) continue;
|
|
1658
|
+
lines.push(`### ${TYPE_ICONS[type]} ${TYPE_LABELS[type]}`);
|
|
1659
|
+
lines.push("");
|
|
1660
|
+
lines.push(...this.renderTypeTable(typeEntries));
|
|
1661
|
+
lines.push("");
|
|
1662
|
+
}
|
|
1663
|
+
lines.push("---");
|
|
1664
|
+
lines.push("");
|
|
1665
|
+
lines.push(`*Last updated: ${(/* @__PURE__ */ new Date()).toISOString()} \xB7 ${entries.length} cognitive${entries.length !== 1 ? "s" : ""} installed*`);
|
|
1666
|
+
}
|
|
1667
|
+
lines.push(END_MARKER);
|
|
1668
|
+
return lines.join("\n");
|
|
1877
1669
|
}
|
|
1878
1670
|
/**
|
|
1879
|
-
*
|
|
1671
|
+
* Render the empty managed section.
|
|
1880
1672
|
*/
|
|
1881
|
-
|
|
1882
|
-
const
|
|
1883
|
-
|
|
1673
|
+
renderEmptySection() {
|
|
1674
|
+
const lines = [
|
|
1675
|
+
START_MARKER,
|
|
1676
|
+
"# SynapSync Project Cognitives",
|
|
1677
|
+
"",
|
|
1678
|
+
"> Auto-generated by [SynapSync](https://synapsync.github.io/synapsync-cli/). Do not edit this section manually.",
|
|
1679
|
+
"",
|
|
1680
|
+
"*No cognitives installed yet. Run `synapsync add <name>` to get started.*",
|
|
1681
|
+
END_MARKER
|
|
1682
|
+
];
|
|
1683
|
+
return lines.join("\n");
|
|
1884
1684
|
}
|
|
1885
|
-
// ============================================
|
|
1886
|
-
// Download Operations
|
|
1887
|
-
// ============================================
|
|
1888
1685
|
/**
|
|
1889
|
-
*
|
|
1686
|
+
* Render a markdown table for a group of entries.
|
|
1890
1687
|
*/
|
|
1891
|
-
|
|
1892
|
-
const
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
);
|
|
1688
|
+
renderTypeTable(entries) {
|
|
1689
|
+
const lines = [
|
|
1690
|
+
"| Name | Category | Description | Version | Path |",
|
|
1691
|
+
"|------|----------|-------------|---------|------|"
|
|
1692
|
+
];
|
|
1693
|
+
for (const entry of entries) {
|
|
1694
|
+
const name = `\`${escapeTableCell(entry.name)}\``;
|
|
1695
|
+
const category = escapeTableCell(entry.category);
|
|
1696
|
+
const description = escapeTableCell(entry.description);
|
|
1697
|
+
const version2 = escapeTableCell(entry.version);
|
|
1698
|
+
const pathLink = `[${escapeTableCell(entry.fileName)}](${entry.relativePath})`;
|
|
1699
|
+
lines.push(`| ${name} | ${category} | ${description} | ${version2} | ${pathLink} |`);
|
|
1899
1700
|
}
|
|
1900
|
-
return
|
|
1701
|
+
return lines;
|
|
1901
1702
|
}
|
|
1902
1703
|
/**
|
|
1903
|
-
*
|
|
1704
|
+
* Write content within markers, preserving user content outside.
|
|
1904
1705
|
*/
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
throw new RegistryError(
|
|
1910
|
-
`Failed to fetch content for ${cognitiveEntry.name}: ${response.status} ${response.statusText}`,
|
|
1911
|
-
url
|
|
1912
|
-
);
|
|
1706
|
+
writeWithMarkers(filePath, managedContent) {
|
|
1707
|
+
if (!fs4.existsSync(filePath)) {
|
|
1708
|
+
fs4.writeFileSync(filePath, managedContent + "\n", "utf-8");
|
|
1709
|
+
return;
|
|
1913
1710
|
}
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
if (
|
|
1922
|
-
|
|
1711
|
+
const existing = fs4.readFileSync(filePath, "utf-8");
|
|
1712
|
+
const startIdx = existing.indexOf(START_MARKER);
|
|
1713
|
+
const endIdx = existing.indexOf(END_MARKER);
|
|
1714
|
+
if (startIdx !== -1 && endIdx !== -1) {
|
|
1715
|
+
const before = existing.slice(0, startIdx);
|
|
1716
|
+
const after = existing.slice(endIdx + END_MARKER.length);
|
|
1717
|
+
fs4.writeFileSync(filePath, before + managedContent + after, "utf-8");
|
|
1718
|
+
} else if (startIdx !== -1 && endIdx === -1) {
|
|
1719
|
+
const before = existing.slice(0, startIdx);
|
|
1720
|
+
fs4.writeFileSync(filePath, before + managedContent + "\n", "utf-8");
|
|
1721
|
+
} else {
|
|
1722
|
+
const separator = existing.endsWith("\n") ? "\n" : "\n\n";
|
|
1723
|
+
fs4.writeFileSync(filePath, existing + separator + managedContent + "\n", "utf-8");
|
|
1923
1724
|
}
|
|
1924
|
-
const manifest = await this.getManifest(entry);
|
|
1925
|
-
const content = await this.getContent(entry, manifest);
|
|
1926
|
-
return {
|
|
1927
|
-
manifest,
|
|
1928
|
-
content,
|
|
1929
|
-
path: entry.path
|
|
1930
|
-
};
|
|
1931
1725
|
}
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
const response = await this.fetch(url);
|
|
1938
|
-
if (!response.ok) {
|
|
1939
|
-
throw new RegistryError(
|
|
1940
|
-
`Failed to fetch asset ${assetPath} for ${cognitiveEntry.name}: ${response.status} ${response.statusText}`,
|
|
1941
|
-
url
|
|
1942
|
-
);
|
|
1943
|
-
}
|
|
1944
|
-
return response.text();
|
|
1945
|
-
}
|
|
1946
|
-
// ============================================
|
|
1947
|
-
// Utility Methods
|
|
1948
|
-
// ============================================
|
|
1949
|
-
/**
|
|
1950
|
-
* Check if registry is reachable
|
|
1951
|
-
*/
|
|
1952
|
-
async ping() {
|
|
1953
|
-
try {
|
|
1954
|
-
const url = `${this.baseUrl}/${REGISTRY_INDEX_FILE}`;
|
|
1955
|
-
const response = await this.fetch(url, { method: "HEAD" });
|
|
1956
|
-
return response.ok;
|
|
1957
|
-
} catch {
|
|
1958
|
-
return false;
|
|
1959
|
-
}
|
|
1726
|
+
};
|
|
1727
|
+
function truncateDescription(description) {
|
|
1728
|
+
const text2 = String(description ?? "");
|
|
1729
|
+
if (text2.length <= MAX_DESCRIPTION_LENGTH) {
|
|
1730
|
+
return text2;
|
|
1960
1731
|
}
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1732
|
+
return text2.slice(0, MAX_DESCRIPTION_LENGTH - 3) + "...";
|
|
1733
|
+
}
|
|
1734
|
+
function escapeTableCell(value) {
|
|
1735
|
+
return String(value ?? "").replace(/\|/g, "\\|");
|
|
1736
|
+
}
|
|
1737
|
+
function regenerateAgentsMd(projectRoot, synapSyncDir) {
|
|
1738
|
+
const manifest = new ManifestManager(synapSyncDir);
|
|
1739
|
+
const generator = new AgentsMdGenerator(projectRoot, synapSyncDir);
|
|
1740
|
+
return generator.generate(manifest.getCognitives());
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
// src/commands/init.ts
|
|
1744
|
+
async function executeInitCommand(options = {}) {
|
|
1745
|
+
const projectRoot = process.cwd();
|
|
1746
|
+
const configPath = path6.join(projectRoot, CONFIG_FILE_NAME);
|
|
1747
|
+
const storagePath = path6.join(projectRoot, DEFAULT_SYNAPSYNC_DIR);
|
|
1748
|
+
if (ConfigManager.isProjectInitialized(projectRoot)) {
|
|
1749
|
+
logger.line();
|
|
1750
|
+
logger.warning("Project already initialized.");
|
|
1751
|
+
logger.log(` ${pc4.dim("Config:")} ${configPath}`);
|
|
1752
|
+
logger.log(` ${pc4.dim("Storage:")} ${storagePath}`);
|
|
1753
|
+
logger.line();
|
|
1754
|
+
logger.hint("Use /config to view or modify settings.");
|
|
1755
|
+
return null;
|
|
1967
1756
|
}
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1757
|
+
if (options.yes === true) {
|
|
1758
|
+
return initializeProject({
|
|
1759
|
+
name: options.name ?? path6.basename(projectRoot),
|
|
1760
|
+
...options.description !== void 0 && { description: options.description },
|
|
1761
|
+
providers: options.providers ?? ["claude"]
|
|
1762
|
+
});
|
|
1973
1763
|
}
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1764
|
+
logger.line();
|
|
1765
|
+
p.intro(pc4.bgCyan(pc4.black(" Initialize SynapSync Project ")));
|
|
1766
|
+
const result = await p.group(
|
|
1767
|
+
{
|
|
1768
|
+
name: () => {
|
|
1769
|
+
const defaultName = path6.basename(projectRoot);
|
|
1770
|
+
return p.text({
|
|
1771
|
+
message: "Project name",
|
|
1772
|
+
placeholder: defaultName,
|
|
1773
|
+
defaultValue: defaultName,
|
|
1774
|
+
validate: (value) => {
|
|
1775
|
+
const finalValue = value.trim() === "" ? defaultName : value;
|
|
1776
|
+
if (!/^[a-z0-9-_]+$/i.test(finalValue)) {
|
|
1777
|
+
return "Project name can only contain letters, numbers, hyphens, and underscores";
|
|
1778
|
+
}
|
|
1779
|
+
return void 0;
|
|
1780
|
+
}
|
|
1781
|
+
});
|
|
1782
|
+
},
|
|
1783
|
+
description: () => p.text({
|
|
1784
|
+
message: "Description (optional)",
|
|
1785
|
+
placeholder: "A brief description of your project"
|
|
1786
|
+
}),
|
|
1787
|
+
providers: () => p.multiselect({
|
|
1788
|
+
message: "Select AI providers to enable",
|
|
1789
|
+
options: SUPPORTED_PROVIDERS.map((provider) => ({
|
|
1790
|
+
value: provider,
|
|
1791
|
+
label: getProviderLabel(provider),
|
|
1792
|
+
hint: getProviderHint(provider)
|
|
1793
|
+
})),
|
|
1794
|
+
initialValues: ["claude"],
|
|
1795
|
+
required: false
|
|
1796
|
+
})
|
|
1797
|
+
},
|
|
1798
|
+
{
|
|
1799
|
+
onCancel: () => {
|
|
1800
|
+
p.cancel("Project initialization cancelled.");
|
|
1801
|
+
return process.exit(0);
|
|
1989
1802
|
}
|
|
1990
|
-
throw new RegistryError("Network error", url);
|
|
1991
1803
|
}
|
|
1804
|
+
);
|
|
1805
|
+
if (p.isCancel(result)) {
|
|
1806
|
+
return null;
|
|
1992
1807
|
}
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
this.name = "CognitiveNotFoundError";
|
|
2006
|
-
}
|
|
2007
|
-
};
|
|
2008
|
-
|
|
2009
|
-
// src/commands/search.ts
|
|
2010
|
-
async function executeSearchCommand(query, options) {
|
|
2011
|
-
logger.line();
|
|
2012
|
-
const validatedOptions = validateOptions(options);
|
|
2013
|
-
if (validatedOptions === null) {
|
|
2014
|
-
return;
|
|
2015
|
-
}
|
|
2016
|
-
const searchingText = query !== void 0 && query.trim() !== "" ? `Searching for "${query}"...` : "Fetching cognitives from registry...";
|
|
2017
|
-
logger.log(` ${pc8.dim(searchingText)}`);
|
|
1808
|
+
return initializeProject({
|
|
1809
|
+
name: result.name,
|
|
1810
|
+
description: result.description,
|
|
1811
|
+
providers: result.providers
|
|
1812
|
+
});
|
|
1813
|
+
}
|
|
1814
|
+
function initializeProject(setup) {
|
|
1815
|
+
const projectRoot = process.cwd();
|
|
1816
|
+
const configPath = path6.join(projectRoot, CONFIG_FILE_NAME);
|
|
1817
|
+
const storagePath = path6.join(projectRoot, DEFAULT_SYNAPSYNC_DIR);
|
|
1818
|
+
const s = p.spinner();
|
|
1819
|
+
s.start("Creating project structure...");
|
|
2018
1820
|
try {
|
|
2019
|
-
|
|
2020
|
-
const
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
return;
|
|
2025
|
-
}
|
|
2026
|
-
const searchOpts = {};
|
|
2027
|
-
if (validatedOptions.type !== void 0) searchOpts.type = validatedOptions.type;
|
|
2028
|
-
if (validatedOptions.category !== void 0) searchOpts.category = validatedOptions.category;
|
|
2029
|
-
if (validatedOptions.tag !== void 0) searchOpts.tag = validatedOptions.tag;
|
|
2030
|
-
if (validatedOptions.limit !== void 0) searchOpts.limit = validatedOptions.limit;
|
|
2031
|
-
const result = await client.search(query, searchOpts);
|
|
2032
|
-
process.stdout.write("\x1B[1A\x1B[2K");
|
|
2033
|
-
if (options.json === true) {
|
|
2034
|
-
console.log(JSON.stringify(result, null, 2));
|
|
2035
|
-
return;
|
|
1821
|
+
createStorageStructure(storagePath);
|
|
1822
|
+
const configManager = new ConfigManager(projectRoot);
|
|
1823
|
+
configManager.create(setup.name, setup.description);
|
|
1824
|
+
for (const provider of setup.providers) {
|
|
1825
|
+
configManager.set(`sync.providers.${provider}.enabled`, true);
|
|
2036
1826
|
}
|
|
2037
|
-
|
|
1827
|
+
configManager.save();
|
|
1828
|
+
createManifest(storagePath);
|
|
1829
|
+
new AgentsMdGenerator(projectRoot, storagePath).generateEmpty();
|
|
1830
|
+
updateGitignore(projectRoot);
|
|
1831
|
+
s.stop("Project structure created!");
|
|
1832
|
+
showSuccessMessage(setup, configPath, storagePath);
|
|
1833
|
+
return {
|
|
1834
|
+
success: true,
|
|
1835
|
+
projectPath: projectRoot,
|
|
1836
|
+
configPath,
|
|
1837
|
+
storagePath
|
|
1838
|
+
};
|
|
2038
1839
|
} catch (error) {
|
|
1840
|
+
s.stop("Failed to create project.");
|
|
2039
1841
|
logger.line();
|
|
2040
|
-
if (error instanceof
|
|
2041
|
-
logger.error(
|
|
2042
|
-
} else if (error instanceof Error) {
|
|
2043
|
-
logger.error(`Search failed: ${error.message}`);
|
|
2044
|
-
} else {
|
|
2045
|
-
logger.error("Search failed with unknown error");
|
|
1842
|
+
if (error instanceof Error) {
|
|
1843
|
+
logger.error(error.message);
|
|
2046
1844
|
}
|
|
1845
|
+
throw error;
|
|
2047
1846
|
}
|
|
2048
1847
|
}
|
|
2049
|
-
function
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
}
|
|
2057
|
-
validated.type = options.type;
|
|
2058
|
-
}
|
|
2059
|
-
if (options.category !== void 0) {
|
|
2060
|
-
if (!CATEGORIES.includes(options.category)) {
|
|
2061
|
-
logger.error(`Invalid category: ${options.category}`);
|
|
2062
|
-
logger.hint(`Valid categories: ${CATEGORIES.join(", ")}`);
|
|
2063
|
-
return null;
|
|
2064
|
-
}
|
|
2065
|
-
validated.category = options.category;
|
|
2066
|
-
}
|
|
2067
|
-
if (options.tag !== void 0) {
|
|
2068
|
-
validated.tag = options.tag;
|
|
2069
|
-
}
|
|
2070
|
-
if (options.limit !== void 0) {
|
|
2071
|
-
const limit = parseInt(options.limit, 10);
|
|
2072
|
-
if (isNaN(limit) || limit < 1) {
|
|
2073
|
-
logger.error("Limit must be a positive number");
|
|
2074
|
-
return null;
|
|
2075
|
-
}
|
|
2076
|
-
validated.limit = limit;
|
|
1848
|
+
function createStorageStructure(storagePath) {
|
|
1849
|
+
fs5.mkdirSync(storagePath, { recursive: true });
|
|
1850
|
+
for (const cognitiveType of COGNITIVE_TYPES) {
|
|
1851
|
+
const typePath = path6.join(storagePath, `${cognitiveType}s`);
|
|
1852
|
+
fs5.mkdirSync(typePath, { recursive: true });
|
|
1853
|
+
const gitkeepPath = path6.join(typePath, ".gitkeep");
|
|
1854
|
+
fs5.writeFileSync(gitkeepPath, "");
|
|
2077
1855
|
}
|
|
2078
|
-
return validated;
|
|
2079
1856
|
}
|
|
2080
|
-
function
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
1857
|
+
function createManifest(storagePath) {
|
|
1858
|
+
const manifestPath = path6.join(storagePath, "manifest.json");
|
|
1859
|
+
const manifest = {
|
|
1860
|
+
version: "1.0.0",
|
|
1861
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1862
|
+
cognitives: {},
|
|
1863
|
+
syncs: {}
|
|
1864
|
+
};
|
|
1865
|
+
fs5.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
1866
|
+
}
|
|
1867
|
+
function updateGitignore(projectRoot) {
|
|
1868
|
+
const gitignorePath = path6.join(projectRoot, ".gitignore");
|
|
1869
|
+
const synapsyncEntries = `
|
|
1870
|
+
# SynapSync
|
|
1871
|
+
.synapsync/manifest.json
|
|
1872
|
+
*.local.yaml
|
|
1873
|
+
`;
|
|
1874
|
+
if (fs5.existsSync(gitignorePath)) {
|
|
1875
|
+
const content = fs5.readFileSync(gitignorePath, "utf-8");
|
|
1876
|
+
if (!content.includes("# SynapSync")) {
|
|
1877
|
+
fs5.appendFileSync(gitignorePath, synapsyncEntries);
|
|
1878
|
+
}
|
|
2095
1879
|
} else {
|
|
2096
|
-
|
|
1880
|
+
fs5.writeFileSync(gitignorePath, synapsyncEntries.trim() + "\n");
|
|
2097
1881
|
}
|
|
2098
|
-
logger.line();
|
|
2099
|
-
for (const cognitive of cognitives) {
|
|
2100
|
-
displayCognitive(cognitive);
|
|
2101
|
-
}
|
|
2102
|
-
logger.line();
|
|
2103
|
-
logger.hint("Run synapsync add <name> to add a cognitive.");
|
|
2104
1882
|
}
|
|
2105
|
-
function
|
|
2106
|
-
const
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
}
|
|
2116
|
-
logger.log(` ${meta.join(" \xB7 ")}`);
|
|
2117
|
-
if (cognitive.tags.length > 0) {
|
|
2118
|
-
const tags = cognitive.tags.slice(0, 5).map((t) => pc8.cyan(t)).join(" ");
|
|
2119
|
-
logger.log(` ${tags}`);
|
|
2120
|
-
}
|
|
2121
|
-
logger.line();
|
|
1883
|
+
function getProviderLabel(provider) {
|
|
1884
|
+
const labels = {
|
|
1885
|
+
claude: "Claude (Anthropic)",
|
|
1886
|
+
openai: "OpenAI (GPT)",
|
|
1887
|
+
gemini: "Gemini (Google)",
|
|
1888
|
+
cursor: "Cursor IDE",
|
|
1889
|
+
windsurf: "Windsurf IDE",
|
|
1890
|
+
copilot: "GitHub Copilot"
|
|
1891
|
+
};
|
|
1892
|
+
return labels[provider];
|
|
2122
1893
|
}
|
|
2123
|
-
function
|
|
2124
|
-
const
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
1894
|
+
function getProviderHint(provider) {
|
|
1895
|
+
const hints = {
|
|
1896
|
+
claude: "Claude Code, Claude Desktop",
|
|
1897
|
+
openai: "ChatGPT, API",
|
|
1898
|
+
gemini: "Google AI Studio",
|
|
1899
|
+
cursor: "AI-first code editor",
|
|
1900
|
+
windsurf: "AI-powered IDE",
|
|
1901
|
+
copilot: "VS Code integration"
|
|
2130
1902
|
};
|
|
2131
|
-
return
|
|
1903
|
+
return hints[provider];
|
|
2132
1904
|
}
|
|
2133
|
-
function
|
|
2134
|
-
|
|
2135
|
-
|
|
1905
|
+
function showSuccessMessage(setup, configPath, storagePath) {
|
|
1906
|
+
logger.line();
|
|
1907
|
+
p.note(
|
|
1908
|
+
[
|
|
1909
|
+
`${pc4.dim("Config:")} ${pc4.cyan(configPath)}`,
|
|
1910
|
+
`${pc4.dim("Storage:")} ${pc4.cyan(storagePath)}`,
|
|
1911
|
+
"",
|
|
1912
|
+
`${pc4.dim("Providers:")} ${setup.providers.map((p2) => pc4.green(p2)).join(", ") || pc4.dim("none")}`
|
|
1913
|
+
].join("\n"),
|
|
1914
|
+
`Project "${setup.name}" initialized!`
|
|
1915
|
+
);
|
|
1916
|
+
logger.line();
|
|
1917
|
+
logger.bold(" Next Steps:");
|
|
1918
|
+
logger.line();
|
|
1919
|
+
logger.log(` ${pc4.cyan("1.")} Browse available cognitives:`);
|
|
1920
|
+
logger.log(` ${pc4.dim("$")} synapsync list --remote`);
|
|
1921
|
+
logger.line();
|
|
1922
|
+
logger.log(` ${pc4.cyan("2.")} Add cognitives:`);
|
|
1923
|
+
logger.log(` ${pc4.dim("$")} synapsync add code-reviewer`);
|
|
1924
|
+
logger.log(` ${pc4.dim("$")} synapsync add github:user/my-skill`);
|
|
1925
|
+
logger.line();
|
|
1926
|
+
p.outro(pc4.green("Happy syncing!"));
|
|
2136
1927
|
}
|
|
2137
|
-
function
|
|
2138
|
-
program.command("
|
|
2139
|
-
await
|
|
1928
|
+
function registerInitCommand(program) {
|
|
1929
|
+
program.command("init").description("Initialize a new SynapSync project").option("-n, --name <name>", "Project name").option("-d, --description <desc>", "Project description").option("-p, --provider <providers...>", "Enable providers (claude, openai, etc.)").option("-y, --yes", "Skip prompts and use defaults").action(async (options) => {
|
|
1930
|
+
await executeInitCommand({
|
|
1931
|
+
...options.name !== void 0 && { name: options.name },
|
|
1932
|
+
...options.description !== void 0 && { description: options.description },
|
|
1933
|
+
...options.provider !== void 0 && { providers: options.provider },
|
|
1934
|
+
...options.yes !== void 0 && { yes: options.yes }
|
|
1935
|
+
});
|
|
2140
1936
|
});
|
|
2141
1937
|
}
|
|
2142
1938
|
|
|
2143
|
-
// src/commands/
|
|
2144
|
-
init_esm_shims();
|
|
2145
|
-
import * as fs8 from "fs";
|
|
2146
|
-
import * as path10 from "path";
|
|
2147
|
-
import pc9 from "picocolors";
|
|
2148
|
-
|
|
2149
|
-
// src/services/sync/engine.ts
|
|
2150
|
-
init_esm_shims();
|
|
2151
|
-
import * as path9 from "path";
|
|
2152
|
-
|
|
2153
|
-
// src/services/scanner/scanner.ts
|
|
2154
|
-
init_esm_shims();
|
|
2155
|
-
import * as fs5 from "fs";
|
|
2156
|
-
import * as path6 from "path";
|
|
2157
|
-
import * as crypto from "crypto";
|
|
2158
|
-
|
|
2159
|
-
// src/services/scanner/parser.ts
|
|
1939
|
+
// src/commands/config.ts
|
|
2160
1940
|
init_esm_shims();
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
1941
|
+
import pc5 from "picocolors";
|
|
1942
|
+
function executeConfigCommand(args) {
|
|
1943
|
+
const options = parseConfigArgs(args);
|
|
1944
|
+
const configManager = ConfigManager.findConfig();
|
|
1945
|
+
if (configManager === null) {
|
|
1946
|
+
logger.line();
|
|
1947
|
+
logger.error("No SynapSync project found.");
|
|
1948
|
+
logger.hint("Run /init to initialize a project.");
|
|
1949
|
+
return;
|
|
2165
1950
|
}
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
1951
|
+
switch (options.action) {
|
|
1952
|
+
case "list":
|
|
1953
|
+
showConfigList(configManager);
|
|
1954
|
+
break;
|
|
1955
|
+
case "get":
|
|
1956
|
+
showConfigValue(configManager, options.key ?? "");
|
|
1957
|
+
break;
|
|
1958
|
+
case "set":
|
|
1959
|
+
setConfigValue(configManager, options.key ?? "", options.value ?? "");
|
|
1960
|
+
break;
|
|
2170
1961
|
}
|
|
2171
1962
|
}
|
|
2172
|
-
function
|
|
2173
|
-
const
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
if (currentArray !== null) {
|
|
2184
|
-
currentArray.push(cleanValue(value));
|
|
2185
|
-
}
|
|
2186
|
-
continue;
|
|
2187
|
-
}
|
|
2188
|
-
const colonIndex = line.indexOf(":");
|
|
2189
|
-
if (colonIndex > 0) {
|
|
2190
|
-
const key = line.slice(0, colonIndex).trim();
|
|
2191
|
-
const rawValue = line.slice(colonIndex + 1).trim();
|
|
2192
|
-
if (currentKey !== null && currentArray !== null) {
|
|
2193
|
-
setNestedValue2(result, currentKey, currentArray);
|
|
2194
|
-
currentArray = null;
|
|
2195
|
-
}
|
|
2196
|
-
currentKey = key;
|
|
2197
|
-
if (rawValue === "" || rawValue === "|" || rawValue === ">") {
|
|
2198
|
-
currentArray = [];
|
|
2199
|
-
} else if (rawValue.startsWith("[") && rawValue.endsWith("]")) {
|
|
2200
|
-
const arrayContent = rawValue.slice(1, -1);
|
|
2201
|
-
const items = arrayContent.split(",").map((item) => cleanValue(item.trim()));
|
|
2202
|
-
setNestedValue2(result, key, items);
|
|
2203
|
-
currentKey = null;
|
|
2204
|
-
} else {
|
|
2205
|
-
setNestedValue2(result, key, cleanValue(rawValue));
|
|
2206
|
-
currentKey = null;
|
|
2207
|
-
}
|
|
2208
|
-
}
|
|
1963
|
+
function showConfigList(configManager) {
|
|
1964
|
+
const flatConfig = configManager.flatten();
|
|
1965
|
+
logger.line();
|
|
1966
|
+
logger.bold(" Configuration");
|
|
1967
|
+
logger.line();
|
|
1968
|
+
const groups = {};
|
|
1969
|
+
for (const [key, value] of Object.entries(flatConfig)) {
|
|
1970
|
+
const parts = key.split(".");
|
|
1971
|
+
const group2 = parts[0] ?? "other";
|
|
1972
|
+
groups[group2] ??= {};
|
|
1973
|
+
groups[group2][key] = value;
|
|
2209
1974
|
}
|
|
2210
|
-
|
|
2211
|
-
|
|
1975
|
+
for (const [group2, values] of Object.entries(groups)) {
|
|
1976
|
+
logger.log(` ${pc5.cyan(group2)}:`);
|
|
1977
|
+
for (const [key, value] of Object.entries(values)) {
|
|
1978
|
+
const displayKey = key.replace(`${group2}.`, "");
|
|
1979
|
+
const displayValue = formatValue(value);
|
|
1980
|
+
logger.log(` ${pc5.dim(displayKey.padEnd(30))} ${displayValue}`);
|
|
1981
|
+
}
|
|
1982
|
+
logger.line();
|
|
2212
1983
|
}
|
|
2213
|
-
|
|
1984
|
+
logger.hint(`Config file: ${configManager.getProjectRoot()}/synapsync.config.yaml`);
|
|
2214
1985
|
}
|
|
2215
|
-
function
|
|
2216
|
-
if (
|
|
2217
|
-
|
|
1986
|
+
function showConfigValue(configManager, key) {
|
|
1987
|
+
if (key === "") {
|
|
1988
|
+
logger.line();
|
|
1989
|
+
logger.error("Key is required.");
|
|
1990
|
+
logger.hint("Usage: /config get <key>");
|
|
1991
|
+
logger.hint("Example: /config get cli.theme");
|
|
1992
|
+
return;
|
|
1993
|
+
}
|
|
1994
|
+
const value = configManager.get(key);
|
|
1995
|
+
logger.line();
|
|
1996
|
+
if (value === void 0) {
|
|
1997
|
+
logger.warning(`Key not found: ${pc5.cyan(key)}`);
|
|
1998
|
+
logger.line();
|
|
1999
|
+
logger.hint("Use /config list to see all available keys.");
|
|
2000
|
+
} else {
|
|
2001
|
+
logger.log(` ${pc5.cyan(key)} = ${formatValue(value)}`);
|
|
2218
2002
|
}
|
|
2219
|
-
return value;
|
|
2220
|
-
}
|
|
2221
|
-
function setNestedValue2(obj, key, value) {
|
|
2222
|
-
obj[key] = value;
|
|
2223
2003
|
}
|
|
2224
|
-
function
|
|
2225
|
-
if (
|
|
2226
|
-
|
|
2004
|
+
function setConfigValue(configManager, key, value) {
|
|
2005
|
+
if (key === "") {
|
|
2006
|
+
logger.line();
|
|
2007
|
+
logger.error("Key is required.");
|
|
2008
|
+
logger.hint("Usage: /config set <key> <value>");
|
|
2009
|
+
logger.hint("Example: /config set cli.theme dark");
|
|
2010
|
+
return;
|
|
2227
2011
|
}
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2012
|
+
if (value === "") {
|
|
2013
|
+
logger.line();
|
|
2014
|
+
logger.error("Value is required.");
|
|
2015
|
+
logger.hint("Usage: /config set <key> <value>");
|
|
2016
|
+
return;
|
|
2231
2017
|
}
|
|
2232
|
-
|
|
2018
|
+
const existingValue = configManager.get(key);
|
|
2019
|
+
const isNewKey = existingValue === void 0;
|
|
2020
|
+
const parsedValue = parseValue(value);
|
|
2021
|
+
configManager.set(key, parsedValue);
|
|
2022
|
+
configManager.save();
|
|
2023
|
+
logger.line();
|
|
2024
|
+
if (isNewKey) {
|
|
2025
|
+
logger.warning(`Created new key: ${pc5.cyan(key)}`);
|
|
2026
|
+
}
|
|
2027
|
+
logger.success(`${pc5.cyan(key)} = ${formatValue(parsedValue)}`);
|
|
2233
2028
|
}
|
|
2234
|
-
function
|
|
2235
|
-
|
|
2236
|
-
|
|
2029
|
+
function parseConfigArgs(args) {
|
|
2030
|
+
const parts = args.trim().split(/\s+/);
|
|
2031
|
+
const action = (parts[0] ?? "list").toLowerCase();
|
|
2032
|
+
if (action === "" || action === "list") {
|
|
2033
|
+
return { action: "list" };
|
|
2237
2034
|
}
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2035
|
+
if (action === "get") {
|
|
2036
|
+
return {
|
|
2037
|
+
action: "get",
|
|
2038
|
+
key: parts[1] ?? ""
|
|
2039
|
+
};
|
|
2241
2040
|
}
|
|
2242
|
-
|
|
2243
|
-
|
|
2041
|
+
if (action === "set") {
|
|
2042
|
+
return {
|
|
2043
|
+
action: "set",
|
|
2044
|
+
key: parts[1] ?? "",
|
|
2045
|
+
value: parts.slice(2).join(" ")
|
|
2046
|
+
};
|
|
2047
|
+
}
|
|
2048
|
+
return {
|
|
2049
|
+
action: "get",
|
|
2050
|
+
key: action
|
|
2051
|
+
};
|
|
2052
|
+
}
|
|
2053
|
+
function formatValue(value) {
|
|
2054
|
+
if (value === null || value === void 0) {
|
|
2055
|
+
return pc5.dim("(not set)");
|
|
2056
|
+
}
|
|
2057
|
+
if (typeof value === "boolean") {
|
|
2058
|
+
return value ? pc5.green("true") : pc5.red("false");
|
|
2059
|
+
}
|
|
2060
|
+
if (typeof value === "number") {
|
|
2061
|
+
return pc5.yellow(String(value));
|
|
2062
|
+
}
|
|
2063
|
+
if (typeof value === "string") {
|
|
2064
|
+
return pc5.white(`"${value}"`);
|
|
2065
|
+
}
|
|
2066
|
+
if (Array.isArray(value)) {
|
|
2067
|
+
return pc5.dim(`[${value.join(", ")}]`);
|
|
2068
|
+
}
|
|
2069
|
+
return pc5.dim(JSON.stringify(value));
|
|
2070
|
+
}
|
|
2071
|
+
function parseValue(value) {
|
|
2072
|
+
if (value.toLowerCase() === "true") return true;
|
|
2073
|
+
if (value.toLowerCase() === "false") return false;
|
|
2074
|
+
const num = Number(value);
|
|
2075
|
+
if (!isNaN(num) && value.trim() !== "") return num;
|
|
2076
|
+
return value;
|
|
2077
|
+
}
|
|
2078
|
+
function registerConfigCommand(program) {
|
|
2079
|
+
const configCmd = program.command("config").description("Manage project configuration");
|
|
2080
|
+
configCmd.command("list").description("Show all configuration values").action(() => {
|
|
2081
|
+
executeConfigCommand("list");
|
|
2082
|
+
});
|
|
2083
|
+
configCmd.command("get <key>").description("Get a configuration value").action((key) => {
|
|
2084
|
+
executeConfigCommand(`get ${key}`);
|
|
2085
|
+
});
|
|
2086
|
+
configCmd.command("set <key> <value>").description("Set a configuration value").action((key, value) => {
|
|
2087
|
+
executeConfigCommand(`set ${key} ${value}`);
|
|
2088
|
+
});
|
|
2089
|
+
configCmd.action(() => {
|
|
2090
|
+
executeConfigCommand("list");
|
|
2091
|
+
});
|
|
2092
|
+
}
|
|
2244
2093
|
|
|
2245
|
-
// src/
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2094
|
+
// src/commands/status.ts
|
|
2095
|
+
init_esm_shims();
|
|
2096
|
+
import * as fs6 from "fs";
|
|
2097
|
+
import * as path7 from "path";
|
|
2098
|
+
import pc6 from "picocolors";
|
|
2099
|
+
function executeStatusCommand(_args = "") {
|
|
2100
|
+
const status = getProjectStatus();
|
|
2101
|
+
logger.line();
|
|
2102
|
+
if (!status.initialized) {
|
|
2103
|
+
showNotInitialized();
|
|
2104
|
+
return;
|
|
2250
2105
|
}
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2106
|
+
showProjectStatus(status);
|
|
2107
|
+
}
|
|
2108
|
+
function getProjectStatus() {
|
|
2109
|
+
const configManager = ConfigManager.findConfig();
|
|
2110
|
+
if (configManager === null) {
|
|
2111
|
+
return {
|
|
2112
|
+
initialized: false,
|
|
2113
|
+
cognitives: createEmptyCognitiveCount(),
|
|
2114
|
+
providers: []
|
|
2115
|
+
};
|
|
2116
|
+
}
|
|
2117
|
+
const config = configManager.getConfig();
|
|
2118
|
+
const projectRoot = configManager.getProjectRoot();
|
|
2119
|
+
const storagePath = configManager.getSynapSyncDir();
|
|
2120
|
+
const cognitives = countCognitives(storagePath);
|
|
2121
|
+
const providers = getProviderStatuses(config, projectRoot);
|
|
2122
|
+
const lastSync = getLastSyncTime(storagePath);
|
|
2123
|
+
const status = {
|
|
2124
|
+
initialized: true,
|
|
2125
|
+
projectName: config.name,
|
|
2126
|
+
projectRoot,
|
|
2127
|
+
configPath: path7.join(projectRoot, "synapsync.config.yaml"),
|
|
2128
|
+
storagePath,
|
|
2129
|
+
cognitives,
|
|
2130
|
+
providers
|
|
2131
|
+
};
|
|
2132
|
+
if (lastSync !== void 0) {
|
|
2133
|
+
status.lastSync = lastSync;
|
|
2134
|
+
}
|
|
2135
|
+
return status;
|
|
2136
|
+
}
|
|
2137
|
+
function createEmptyCognitiveCount() {
|
|
2138
|
+
const counts = {};
|
|
2139
|
+
for (const type of COGNITIVE_TYPES) {
|
|
2140
|
+
counts[type] = 0;
|
|
2141
|
+
}
|
|
2142
|
+
return counts;
|
|
2143
|
+
}
|
|
2144
|
+
function countCognitives(storagePath) {
|
|
2145
|
+
const counts = createEmptyCognitiveCount();
|
|
2146
|
+
for (const type of COGNITIVE_TYPES) {
|
|
2147
|
+
const typePath = path7.join(storagePath, `${type}s`);
|
|
2148
|
+
if (fs6.existsSync(typePath)) {
|
|
2149
|
+
try {
|
|
2150
|
+
const entries = fs6.readdirSync(typePath, { withFileTypes: true });
|
|
2151
|
+
counts[type] = entries.filter(
|
|
2152
|
+
(e) => e.isDirectory() || e.isSymbolicLink() && !e.name.startsWith(".")
|
|
2153
|
+
).length;
|
|
2154
|
+
} catch {
|
|
2155
|
+
counts[type] = 0;
|
|
2262
2156
|
}
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
path: path6.join(categoryDir, cognitiveDir),
|
|
2283
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
2284
|
-
});
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
return counts;
|
|
2160
|
+
}
|
|
2161
|
+
function getProviderStatuses(config, projectRoot) {
|
|
2162
|
+
const statuses = [];
|
|
2163
|
+
for (const provider of SUPPORTED_PROVIDERS) {
|
|
2164
|
+
const providerConfig = config.sync?.providers?.[provider];
|
|
2165
|
+
const enabled = providerConfig?.enabled ?? false;
|
|
2166
|
+
const providerPath = path7.join(projectRoot, `.${provider}`);
|
|
2167
|
+
let cognitivesCount = 0;
|
|
2168
|
+
if (fs6.existsSync(providerPath)) {
|
|
2169
|
+
try {
|
|
2170
|
+
const subdirs = ["skills", "agents", "prompts", "workflows", "tools"];
|
|
2171
|
+
for (const subdir of subdirs) {
|
|
2172
|
+
const subdirPath = path7.join(providerPath, subdir);
|
|
2173
|
+
if (fs6.existsSync(subdirPath)) {
|
|
2174
|
+
const entries = fs6.readdirSync(subdirPath);
|
|
2175
|
+
cognitivesCount += entries.filter((e) => !e.startsWith(".")).length;
|
|
2285
2176
|
}
|
|
2286
2177
|
}
|
|
2178
|
+
} catch {
|
|
2287
2179
|
}
|
|
2288
2180
|
}
|
|
2289
|
-
|
|
2181
|
+
statuses.push({
|
|
2182
|
+
name: provider,
|
|
2183
|
+
enabled,
|
|
2184
|
+
connected: false,
|
|
2185
|
+
// TODO: Check actual connection status
|
|
2186
|
+
cognitivesCount
|
|
2187
|
+
});
|
|
2290
2188
|
}
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
return null;
|
|
2298
|
-
}
|
|
2299
|
-
const content = fs5.readFileSync(filePath, "utf-8");
|
|
2300
|
-
const metadata = parseFrontmatter(content);
|
|
2301
|
-
const dirName = path6.basename(cognitiveDir);
|
|
2302
|
-
const fileName = path6.basename(filePath);
|
|
2303
|
-
const name = extractName(metadata, dirName, content);
|
|
2304
|
-
const version2 = extractVersion(metadata, content);
|
|
2305
|
-
const hash = this.computeHash(content);
|
|
2306
|
-
return {
|
|
2307
|
-
name,
|
|
2308
|
-
type,
|
|
2309
|
-
category: metadata.category ?? category,
|
|
2310
|
-
path: cognitiveDir,
|
|
2311
|
-
filePath,
|
|
2312
|
-
fileName,
|
|
2313
|
-
// Add original filename
|
|
2314
|
-
hash,
|
|
2315
|
-
metadata: {
|
|
2316
|
-
...metadata,
|
|
2317
|
-
name,
|
|
2318
|
-
version: version2
|
|
2319
|
-
}
|
|
2320
|
-
};
|
|
2189
|
+
return statuses;
|
|
2190
|
+
}
|
|
2191
|
+
function getLastSyncTime(storagePath) {
|
|
2192
|
+
const manifestPath = path7.join(storagePath, "manifest.json");
|
|
2193
|
+
if (!fs6.existsSync(manifestPath)) {
|
|
2194
|
+
return void 0;
|
|
2321
2195
|
}
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2196
|
+
try {
|
|
2197
|
+
const content = fs6.readFileSync(manifestPath, "utf-8");
|
|
2198
|
+
const manifest = JSON.parse(content);
|
|
2199
|
+
return manifest.lastUpdated;
|
|
2200
|
+
} catch {
|
|
2201
|
+
return void 0;
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
function showNotInitialized() {
|
|
2205
|
+
logger.bold(" Project Status");
|
|
2206
|
+
logger.line();
|
|
2207
|
+
logger.log(` ${pc6.red("\u25CF")} ${pc6.dim("Not initialized")}`);
|
|
2208
|
+
logger.line();
|
|
2209
|
+
logger.hint("Run /init to initialize a SynapSync project.");
|
|
2210
|
+
}
|
|
2211
|
+
function showProjectStatus(status) {
|
|
2212
|
+
logger.bold(` ${status.projectName ?? "SynapSync Project"}`);
|
|
2213
|
+
logger.line();
|
|
2214
|
+
logger.log(` ${pc6.green("\u25CF")} ${pc6.dim("Initialized")}`);
|
|
2215
|
+
logger.log(` ${pc6.dim("Root:")} ${status.projectRoot}`);
|
|
2216
|
+
logger.line();
|
|
2217
|
+
logger.bold(" Cognitives");
|
|
2218
|
+
const totalCognitives = Object.values(status.cognitives).reduce((a, b) => a + b, 0);
|
|
2219
|
+
if (totalCognitives === 0) {
|
|
2220
|
+
logger.log(` ${pc6.dim("No cognitives installed")}`);
|
|
2221
|
+
} else {
|
|
2222
|
+
for (const type of COGNITIVE_TYPES) {
|
|
2223
|
+
const count = status.cognitives[type];
|
|
2224
|
+
if (count > 0) {
|
|
2225
|
+
const icon = getCognitiveIcon(type);
|
|
2226
|
+
logger.log(` ${icon} ${pc6.white(count.toString().padStart(3))} ${type}s`);
|
|
2344
2227
|
}
|
|
2345
2228
|
}
|
|
2346
|
-
|
|
2229
|
+
logger.log(` ${pc6.dim("\u2500\u2500\u2500")}`);
|
|
2230
|
+
logger.log(` ${pc6.bold(totalCognitives.toString().padStart(5))} total`);
|
|
2347
2231
|
}
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
errors: []
|
|
2359
|
-
};
|
|
2360
|
-
const manifestMap = /* @__PURE__ */ new Map();
|
|
2361
|
-
for (const cognitive of manifestCognitives) {
|
|
2362
|
-
manifestMap.set(cognitive.name, cognitive);
|
|
2363
|
-
}
|
|
2364
|
-
const scannedMap = /* @__PURE__ */ new Map();
|
|
2365
|
-
for (const cognitive of scanned) {
|
|
2366
|
-
scannedMap.set(cognitive.name, cognitive);
|
|
2232
|
+
logger.line();
|
|
2233
|
+
logger.bold(" Providers");
|
|
2234
|
+
const enabledProviders = status.providers.filter((p2) => p2.enabled);
|
|
2235
|
+
if (enabledProviders.length === 0) {
|
|
2236
|
+
logger.log(` ${pc6.dim("No providers enabled")}`);
|
|
2237
|
+
} else {
|
|
2238
|
+
for (const provider of enabledProviders) {
|
|
2239
|
+
const icon = provider.cognitivesCount > 0 ? pc6.green("\u25CF") : pc6.yellow("\u25CB");
|
|
2240
|
+
const syncStatus = provider.cognitivesCount > 0 ? pc6.dim(`(${provider.cognitivesCount} synced)`) : pc6.dim("(not synced)");
|
|
2241
|
+
logger.log(` ${icon} ${pc6.white(provider.name)} ${syncStatus}`);
|
|
2367
2242
|
}
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2243
|
+
}
|
|
2244
|
+
logger.line();
|
|
2245
|
+
if (status.lastSync !== void 0) {
|
|
2246
|
+
const syncDate = new Date(status.lastSync);
|
|
2247
|
+
const relativeTime = getRelativeTime(syncDate);
|
|
2248
|
+
logger.log(` ${pc6.dim("Last updated:")} ${relativeTime}`);
|
|
2249
|
+
logger.line();
|
|
2250
|
+
}
|
|
2251
|
+
logger.hint("Run /help for available commands.");
|
|
2252
|
+
}
|
|
2253
|
+
function getCognitiveIcon(type) {
|
|
2254
|
+
const icons = {
|
|
2255
|
+
skill: pc6.blue("\u25C6"),
|
|
2256
|
+
agent: pc6.magenta("\u25C6"),
|
|
2257
|
+
prompt: pc6.yellow("\u25C6"),
|
|
2258
|
+
workflow: pc6.cyan("\u25C6"),
|
|
2259
|
+
tool: pc6.green("\u25C6")
|
|
2260
|
+
};
|
|
2261
|
+
return icons[type];
|
|
2262
|
+
}
|
|
2263
|
+
function getRelativeTime(date) {
|
|
2264
|
+
const now = /* @__PURE__ */ new Date();
|
|
2265
|
+
const diffMs = now.getTime() - date.getTime();
|
|
2266
|
+
const diffMins = Math.floor(diffMs / 6e4);
|
|
2267
|
+
const diffHours = Math.floor(diffMins / 60);
|
|
2268
|
+
const diffDays = Math.floor(diffHours / 24);
|
|
2269
|
+
if (diffMins < 1) return "just now";
|
|
2270
|
+
if (diffMins < 60) return `${diffMins} minute${diffMins === 1 ? "" : "s"} ago`;
|
|
2271
|
+
if (diffHours < 24) return `${diffHours} hour${diffHours === 1 ? "" : "s"} ago`;
|
|
2272
|
+
if (diffDays < 7) return `${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
|
|
2273
|
+
return date.toLocaleDateString();
|
|
2274
|
+
}
|
|
2275
|
+
function registerStatusCommand(program) {
|
|
2276
|
+
program.command("status").description("Show project status").action(() => {
|
|
2277
|
+
executeStatusCommand();
|
|
2278
|
+
});
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2281
|
+
// src/commands/providers.ts
|
|
2282
|
+
init_esm_shims();
|
|
2283
|
+
import * as fs7 from "fs";
|
|
2284
|
+
import * as path8 from "path";
|
|
2285
|
+
import pc7 from "picocolors";
|
|
2286
|
+
function executeProvidersCommand(args) {
|
|
2287
|
+
const parts = args.trim().split(/\s+/);
|
|
2288
|
+
const subcommand = parts[0]?.toLowerCase() ?? "";
|
|
2289
|
+
const configManager = ConfigManager.findConfig();
|
|
2290
|
+
if (configManager === null) {
|
|
2291
|
+
logger.line();
|
|
2292
|
+
logger.error("No SynapSync project found.");
|
|
2293
|
+
logger.hint("Run /init to initialize a project.");
|
|
2294
|
+
return;
|
|
2295
|
+
}
|
|
2296
|
+
switch (subcommand) {
|
|
2297
|
+
case "":
|
|
2298
|
+
case "list":
|
|
2299
|
+
listProviders(configManager);
|
|
2300
|
+
break;
|
|
2301
|
+
case "enable":
|
|
2302
|
+
enableProvider(configManager, parts[1]);
|
|
2303
|
+
break;
|
|
2304
|
+
case "disable":
|
|
2305
|
+
disableProvider(configManager, parts[1]);
|
|
2306
|
+
break;
|
|
2307
|
+
case "path":
|
|
2308
|
+
setProviderPath(configManager, parts[1], parts[2]);
|
|
2309
|
+
break;
|
|
2310
|
+
default:
|
|
2311
|
+
if (SUPPORTED_PROVIDERS.includes(subcommand)) {
|
|
2312
|
+
showProviderInfo(configManager, subcommand);
|
|
2374
2313
|
} else {
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
for (const manifestCognitive of manifestCognitives) {
|
|
2379
|
-
if (!scannedMap.has(manifestCognitive.name)) {
|
|
2380
|
-
result.removed.push(manifestCognitive.name);
|
|
2314
|
+
logger.line();
|
|
2315
|
+
logger.error(`Unknown subcommand: ${subcommand}`);
|
|
2316
|
+
logger.hint("Usage: /providers [list|enable|disable|path]");
|
|
2381
2317
|
}
|
|
2382
|
-
}
|
|
2383
|
-
return result;
|
|
2384
2318
|
}
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2319
|
+
}
|
|
2320
|
+
function listProviders(configManager) {
|
|
2321
|
+
const providers = getProvidersInfo(configManager);
|
|
2322
|
+
logger.line();
|
|
2323
|
+
logger.bold(" Providers");
|
|
2324
|
+
logger.line();
|
|
2325
|
+
logger.log(
|
|
2326
|
+
` ${pc7.dim("Provider".padEnd(12))} ${pc7.dim("Status".padEnd(10))} ${pc7.dim("Path".padEnd(20))} ${pc7.dim("Directory")}`
|
|
2327
|
+
);
|
|
2328
|
+
logger.log(` ${pc7.dim("\u2500".repeat(60))}`);
|
|
2329
|
+
for (const provider of providers) {
|
|
2330
|
+
const statusIcon = provider.enabled ? pc7.green("\u25CF") : pc7.dim("\u25CB");
|
|
2331
|
+
const statusText = provider.enabled ? pc7.green("enabled") : pc7.dim("disabled");
|
|
2332
|
+
const pathText = pc7.cyan(provider.path);
|
|
2333
|
+
const existsText = provider.exists ? pc7.green("\u2713 exists") : pc7.dim("\u2717 missing");
|
|
2334
|
+
logger.log(
|
|
2335
|
+
` ${statusIcon} ${pc7.white(provider.name.padEnd(10))} ${statusText.padEnd(19)} ${pathText.padEnd(29)} ${existsText}`
|
|
2336
|
+
);
|
|
2398
2337
|
}
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2338
|
+
logger.line();
|
|
2339
|
+
const enabledCount = providers.filter((p2) => p2.enabled).length;
|
|
2340
|
+
logger.log(` ${pc7.dim("Enabled:")} ${enabledCount} of ${providers.length} providers`);
|
|
2341
|
+
logger.line();
|
|
2342
|
+
logger.hint("Use /providers enable <name> or /providers disable <name>");
|
|
2343
|
+
}
|
|
2344
|
+
function enableProvider(configManager, providerName) {
|
|
2345
|
+
if (providerName === void 0 || providerName === "") {
|
|
2346
|
+
logger.line();
|
|
2347
|
+
logger.error("Provider name is required.");
|
|
2348
|
+
logger.hint("Usage: /providers enable <provider>");
|
|
2349
|
+
logger.hint(`Available: ${SUPPORTED_PROVIDERS.join(", ")}`);
|
|
2350
|
+
return;
|
|
2351
|
+
}
|
|
2352
|
+
const provider = providerName.toLowerCase();
|
|
2353
|
+
if (!SUPPORTED_PROVIDERS.includes(provider)) {
|
|
2354
|
+
logger.line();
|
|
2355
|
+
logger.error(`Unknown provider: ${provider}`);
|
|
2356
|
+
logger.hint(`Available: ${SUPPORTED_PROVIDERS.join(", ")}`);
|
|
2357
|
+
return;
|
|
2358
|
+
}
|
|
2359
|
+
const currentValue = configManager.get(`sync.providers.${provider}.enabled`);
|
|
2360
|
+
if (currentValue === true) {
|
|
2361
|
+
logger.line();
|
|
2362
|
+
logger.info(`Provider '${provider}' is already enabled.`);
|
|
2363
|
+
return;
|
|
2364
|
+
}
|
|
2365
|
+
configManager.set(`sync.providers.${provider}.enabled`, true);
|
|
2366
|
+
const defaultPaths = PROVIDER_PATHS[provider];
|
|
2367
|
+
const currentPaths = configManager.get(`sync.providers.${provider}.paths`);
|
|
2368
|
+
if (currentPaths === void 0) {
|
|
2369
|
+
configManager.set(`sync.providers.${provider}.paths`, defaultPaths);
|
|
2370
|
+
}
|
|
2371
|
+
configManager.save();
|
|
2372
|
+
logger.line();
|
|
2373
|
+
logger.success(`Provider '${pc7.cyan(provider)}' enabled`);
|
|
2374
|
+
logger.log(` ${pc7.dim("Path:")} ${defaultPaths.skill.split("/")[0]}/`);
|
|
2375
|
+
logger.line();
|
|
2376
|
+
logger.hint("Run /sync to synchronize cognitives to this provider.");
|
|
2377
|
+
}
|
|
2378
|
+
function disableProvider(configManager, providerName) {
|
|
2379
|
+
if (providerName === void 0 || providerName === "") {
|
|
2380
|
+
logger.line();
|
|
2381
|
+
logger.error("Provider name is required.");
|
|
2382
|
+
logger.hint("Usage: /providers disable <provider>");
|
|
2383
|
+
return;
|
|
2384
|
+
}
|
|
2385
|
+
const provider = providerName.toLowerCase();
|
|
2386
|
+
if (!SUPPORTED_PROVIDERS.includes(provider)) {
|
|
2387
|
+
logger.line();
|
|
2388
|
+
logger.error(`Unknown provider: ${provider}`);
|
|
2389
|
+
logger.hint(`Available: ${SUPPORTED_PROVIDERS.join(", ")}`);
|
|
2390
|
+
return;
|
|
2391
|
+
}
|
|
2392
|
+
const currentValue = configManager.get(`sync.providers.${provider}.enabled`);
|
|
2393
|
+
if (currentValue !== true) {
|
|
2394
|
+
logger.line();
|
|
2395
|
+
logger.info(`Provider '${provider}' is already disabled.`);
|
|
2396
|
+
return;
|
|
2397
|
+
}
|
|
2398
|
+
configManager.set(`sync.providers.${provider}.enabled`, false);
|
|
2399
|
+
configManager.save();
|
|
2400
|
+
logger.line();
|
|
2401
|
+
logger.success(`Provider '${pc7.cyan(provider)}' disabled`);
|
|
2402
|
+
}
|
|
2403
|
+
function setProviderPath(configManager, providerName, newPath) {
|
|
2404
|
+
if (providerName === void 0 || providerName === "") {
|
|
2405
|
+
logger.line();
|
|
2406
|
+
logger.error("Provider name is required.");
|
|
2407
|
+
logger.hint("Usage: /providers path <provider> <path>");
|
|
2408
|
+
return;
|
|
2409
|
+
}
|
|
2410
|
+
if (newPath === void 0 || newPath === "") {
|
|
2411
|
+
logger.line();
|
|
2412
|
+
logger.error("Path is required.");
|
|
2413
|
+
logger.hint("Usage: /providers path <provider> <path>");
|
|
2414
|
+
logger.hint("Example: /providers path claude .claude-code/");
|
|
2415
|
+
return;
|
|
2416
|
+
}
|
|
2417
|
+
const provider = providerName.toLowerCase();
|
|
2418
|
+
if (!SUPPORTED_PROVIDERS.includes(provider)) {
|
|
2419
|
+
logger.line();
|
|
2420
|
+
logger.error(`Unknown provider: ${provider}`);
|
|
2421
|
+
logger.hint(`Available: ${SUPPORTED_PROVIDERS.join(", ")}`);
|
|
2422
|
+
return;
|
|
2423
|
+
}
|
|
2424
|
+
const normalizedPath = newPath.endsWith("/") ? newPath : `${newPath}/`;
|
|
2425
|
+
const cognitiveTypes = ["skill", "agent", "prompt", "workflow", "tool"];
|
|
2426
|
+
for (const type of cognitiveTypes) {
|
|
2427
|
+
configManager.set(`sync.providers.${provider}.paths.${type}`, `${normalizedPath}${type}s`);
|
|
2428
|
+
}
|
|
2429
|
+
configManager.save();
|
|
2430
|
+
logger.line();
|
|
2431
|
+
logger.success(`Updated paths for '${pc7.cyan(provider)}'`);
|
|
2432
|
+
logger.log(` ${pc7.dim("Base path:")} ${pc7.cyan(normalizedPath)}`);
|
|
2433
|
+
logger.line();
|
|
2434
|
+
}
|
|
2435
|
+
function showProviderInfo(configManager, provider) {
|
|
2436
|
+
const config = configManager.getConfig();
|
|
2437
|
+
const projectRoot = configManager.getProjectRoot();
|
|
2438
|
+
const providerConfig = config.sync?.providers?.[provider];
|
|
2439
|
+
const enabled = providerConfig?.enabled ?? false;
|
|
2440
|
+
const paths = providerConfig?.paths ?? PROVIDER_PATHS[provider];
|
|
2441
|
+
logger.line();
|
|
2442
|
+
logger.bold(` ${getProviderDisplayName(provider)}`);
|
|
2443
|
+
logger.line();
|
|
2444
|
+
const statusIcon = enabled ? pc7.green("\u25CF") : pc7.dim("\u25CB");
|
|
2445
|
+
const statusText = enabled ? pc7.green("Enabled") : pc7.dim("Disabled");
|
|
2446
|
+
logger.log(` ${pc7.dim("Status:")} ${statusIcon} ${statusText}`);
|
|
2447
|
+
logger.line();
|
|
2448
|
+
logger.log(` ${pc7.dim("Paths:")}`);
|
|
2449
|
+
const cognitiveTypes = ["skill", "agent", "prompt", "workflow", "tool"];
|
|
2450
|
+
for (const type of cognitiveTypes) {
|
|
2451
|
+
const typePath = paths[type] ?? "";
|
|
2452
|
+
const fullPath = path8.join(projectRoot, typePath);
|
|
2453
|
+
const exists = fs7.existsSync(fullPath);
|
|
2454
|
+
const existsIcon = exists ? pc7.green("\u2713") : pc7.dim("\u2717");
|
|
2455
|
+
logger.log(` ${pc7.dim(type.padEnd(10))} ${pc7.cyan(typePath)} ${existsIcon}`);
|
|
2456
|
+
}
|
|
2457
|
+
logger.line();
|
|
2458
|
+
}
|
|
2459
|
+
function getProvidersInfo(configManager) {
|
|
2460
|
+
const config = configManager.getConfig();
|
|
2461
|
+
const projectRoot = configManager.getProjectRoot();
|
|
2462
|
+
const providers = [];
|
|
2463
|
+
for (const provider of SUPPORTED_PROVIDERS) {
|
|
2464
|
+
const providerConfig = config.sync?.providers?.[provider];
|
|
2465
|
+
const enabled = providerConfig?.enabled ?? false;
|
|
2466
|
+
const basePath = providerConfig?.paths?.skill?.split("/")[0] ?? `.${provider}`;
|
|
2467
|
+
const fullPath = path8.join(projectRoot, basePath);
|
|
2468
|
+
const exists = fs7.existsSync(fullPath);
|
|
2469
|
+
providers.push({
|
|
2470
|
+
name: provider,
|
|
2471
|
+
enabled,
|
|
2472
|
+
path: `${basePath}/`,
|
|
2473
|
+
exists
|
|
2474
|
+
});
|
|
2475
|
+
}
|
|
2476
|
+
return providers;
|
|
2477
|
+
}
|
|
2478
|
+
function getProviderDisplayName(provider) {
|
|
2479
|
+
const names = {
|
|
2480
|
+
claude: "Claude (Anthropic)",
|
|
2481
|
+
openai: "OpenAI (GPT)",
|
|
2482
|
+
gemini: "Gemini (Google)",
|
|
2483
|
+
cursor: "Cursor IDE",
|
|
2484
|
+
windsurf: "Windsurf IDE",
|
|
2485
|
+
copilot: "GitHub Copilot"
|
|
2486
|
+
};
|
|
2487
|
+
return names[provider];
|
|
2488
|
+
}
|
|
2489
|
+
function registerProvidersCommand(program) {
|
|
2490
|
+
const providersCmd = program.command("providers").description("Manage provider configuration");
|
|
2491
|
+
providersCmd.command("list", { isDefault: true }).description("List all providers and their status").action(() => {
|
|
2492
|
+
executeProvidersCommand("list");
|
|
2493
|
+
});
|
|
2494
|
+
providersCmd.command("enable <provider>").description("Enable a provider").action((provider) => {
|
|
2495
|
+
executeProvidersCommand(`enable ${provider}`);
|
|
2496
|
+
});
|
|
2497
|
+
providersCmd.command("disable <provider>").description("Disable a provider").action((provider) => {
|
|
2498
|
+
executeProvidersCommand(`disable ${provider}`);
|
|
2499
|
+
});
|
|
2500
|
+
providersCmd.command("path <provider> <path>").description("Set custom sync path for a provider").action((provider, newPath) => {
|
|
2501
|
+
executeProvidersCommand(`path ${provider} ${newPath}`);
|
|
2502
|
+
});
|
|
2503
|
+
providersCmd.action(() => {
|
|
2504
|
+
executeProvidersCommand("list");
|
|
2505
|
+
});
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
// src/commands/search.ts
|
|
2509
|
+
init_esm_shims();
|
|
2510
|
+
import pc8 from "picocolors";
|
|
2511
|
+
|
|
2512
|
+
// src/services/registry/client.ts
|
|
2513
|
+
init_esm_shims();
|
|
2514
|
+
var RegistryClient = class {
|
|
2515
|
+
baseUrl;
|
|
2516
|
+
indexCache = null;
|
|
2517
|
+
indexCacheTime = 0;
|
|
2518
|
+
cacheTtl;
|
|
2519
|
+
constructor(options = {}) {
|
|
2520
|
+
this.baseUrl = options.baseUrl ?? REGISTRY_BASE_URL;
|
|
2521
|
+
this.cacheTtl = options.cacheTtl ?? 5 * 60 * 1e3;
|
|
2404
2522
|
}
|
|
2523
|
+
// ============================================
|
|
2524
|
+
// Index Operations
|
|
2525
|
+
// ============================================
|
|
2405
2526
|
/**
|
|
2406
|
-
*
|
|
2527
|
+
* Fetch the registry index
|
|
2407
2528
|
*/
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2529
|
+
async getIndex(forceRefresh = false) {
|
|
2530
|
+
const now = Date.now();
|
|
2531
|
+
if (!forceRefresh && this.indexCache !== null && now - this.indexCacheTime < this.cacheTtl) {
|
|
2532
|
+
return this.indexCache;
|
|
2411
2533
|
}
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
*/
|
|
2417
|
-
detectType(cognitiveDir) {
|
|
2418
|
-
for (const type of COGNITIVE_TYPES) {
|
|
2419
|
-
const fileName = COGNITIVE_FILE_NAMES[type];
|
|
2420
|
-
const filePath = path6.join(cognitiveDir, fileName);
|
|
2421
|
-
if (fs5.existsSync(filePath)) {
|
|
2422
|
-
return type;
|
|
2423
|
-
}
|
|
2534
|
+
const url = `${this.baseUrl}/${REGISTRY_INDEX_FILE}`;
|
|
2535
|
+
const response = await this.fetch(url);
|
|
2536
|
+
if (!response.ok) {
|
|
2537
|
+
throw new RegistryError(`Failed to fetch registry index: ${response.status} ${response.statusText}`, url);
|
|
2424
2538
|
}
|
|
2425
|
-
|
|
2539
|
+
const index = await response.json();
|
|
2540
|
+
this.indexCache = index;
|
|
2541
|
+
this.indexCacheTime = now;
|
|
2542
|
+
return index;
|
|
2426
2543
|
}
|
|
2427
2544
|
/**
|
|
2428
|
-
* Get
|
|
2545
|
+
* Get total count of cognitives in registry
|
|
2429
2546
|
*/
|
|
2430
|
-
|
|
2431
|
-
const
|
|
2432
|
-
|
|
2433
|
-
agent: 0,
|
|
2434
|
-
prompt: 0,
|
|
2435
|
-
workflow: 0,
|
|
2436
|
-
tool: 0
|
|
2437
|
-
};
|
|
2438
|
-
for (const cognitive of cognitives) {
|
|
2439
|
-
counts[cognitive.type]++;
|
|
2440
|
-
}
|
|
2441
|
-
return counts;
|
|
2442
|
-
}
|
|
2443
|
-
};
|
|
2444
|
-
|
|
2445
|
-
// src/services/manifest/manager.ts
|
|
2446
|
-
init_esm_shims();
|
|
2447
|
-
import * as fs6 from "fs";
|
|
2448
|
-
import * as path7 from "path";
|
|
2449
|
-
|
|
2450
|
-
// src/services/manifest/types.ts
|
|
2451
|
-
init_esm_shims();
|
|
2452
|
-
var DEFAULT_MANIFEST = {
|
|
2453
|
-
version: "1.0.0",
|
|
2454
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2455
|
-
cognitives: {},
|
|
2456
|
-
syncs: {}
|
|
2457
|
-
};
|
|
2458
|
-
|
|
2459
|
-
// src/services/manifest/manager.ts
|
|
2460
|
-
var ManifestManager = class {
|
|
2461
|
-
manifestPath;
|
|
2462
|
-
manifest;
|
|
2463
|
-
constructor(synapSyncDir) {
|
|
2464
|
-
this.manifestPath = path7.join(synapSyncDir, "manifest.json");
|
|
2465
|
-
this.manifest = this.load();
|
|
2547
|
+
async getCount() {
|
|
2548
|
+
const index = await this.getIndex();
|
|
2549
|
+
return index.totalCognitives;
|
|
2466
2550
|
}
|
|
2551
|
+
// ============================================
|
|
2552
|
+
// Search Operations
|
|
2553
|
+
// ============================================
|
|
2467
2554
|
/**
|
|
2468
|
-
*
|
|
2555
|
+
* Search for cognitives in the registry
|
|
2469
2556
|
*/
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2557
|
+
async search(query, options = {}) {
|
|
2558
|
+
const index = await this.getIndex();
|
|
2559
|
+
let results = [...index.cognitives];
|
|
2560
|
+
if (query !== void 0 && query.trim() !== "") {
|
|
2561
|
+
const q = query.toLowerCase();
|
|
2562
|
+
results = results.filter(
|
|
2563
|
+
(c) => c.name.toLowerCase().includes(q) || c.description.toLowerCase().includes(q) || c.tags.some((t) => t.toLowerCase().includes(q))
|
|
2564
|
+
);
|
|
2473
2565
|
}
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
} catch {
|
|
2484
|
-
return { ...DEFAULT_MANIFEST };
|
|
2566
|
+
if (options.type !== void 0) {
|
|
2567
|
+
results = results.filter((c) => c.type === options.type);
|
|
2568
|
+
}
|
|
2569
|
+
if (options.category !== void 0) {
|
|
2570
|
+
results = results.filter((c) => c.category === options.category);
|
|
2571
|
+
}
|
|
2572
|
+
if (options.tag !== void 0) {
|
|
2573
|
+
const tag = options.tag.toLowerCase();
|
|
2574
|
+
results = results.filter((c) => c.tags.some((t) => t.toLowerCase() === tag));
|
|
2485
2575
|
}
|
|
2576
|
+
const total = results.length;
|
|
2577
|
+
if (options.limit !== void 0 && options.limit > 0) {
|
|
2578
|
+
results = results.slice(0, options.limit);
|
|
2579
|
+
}
|
|
2580
|
+
const filters = {};
|
|
2581
|
+
if (options.type !== void 0) filters.type = options.type;
|
|
2582
|
+
if (options.category !== void 0) filters.category = options.category;
|
|
2583
|
+
if (options.tag !== void 0) filters.tag = options.tag;
|
|
2584
|
+
return {
|
|
2585
|
+
cognitives: results,
|
|
2586
|
+
total,
|
|
2587
|
+
...query !== void 0 ? { query } : {},
|
|
2588
|
+
filters
|
|
2589
|
+
};
|
|
2486
2590
|
}
|
|
2487
2591
|
/**
|
|
2488
|
-
*
|
|
2592
|
+
* Find a cognitive by name
|
|
2489
2593
|
*/
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
fs6.writeFileSync(this.manifestPath, content, "utf-8");
|
|
2594
|
+
async findByName(name) {
|
|
2595
|
+
const index = await this.getIndex();
|
|
2596
|
+
return index.cognitives.find((c) => c.name === name) ?? null;
|
|
2494
2597
|
}
|
|
2495
2598
|
/**
|
|
2496
|
-
*
|
|
2599
|
+
* List all cognitives
|
|
2497
2600
|
*/
|
|
2498
|
-
|
|
2499
|
-
|
|
2601
|
+
async list(options = {}) {
|
|
2602
|
+
const result = await this.search(void 0, options);
|
|
2603
|
+
return result.cognitives;
|
|
2500
2604
|
}
|
|
2605
|
+
// ============================================
|
|
2606
|
+
// Download Operations
|
|
2607
|
+
// ============================================
|
|
2501
2608
|
/**
|
|
2502
|
-
* Get
|
|
2609
|
+
* Get the manifest for a cognitive
|
|
2503
2610
|
*/
|
|
2504
|
-
|
|
2505
|
-
|
|
2611
|
+
async getManifest(cognitiveEntry) {
|
|
2612
|
+
const url = `${this.baseUrl}/${cognitiveEntry.path}/${REGISTRY_MANIFEST_FILE}`;
|
|
2613
|
+
const response = await this.fetch(url);
|
|
2614
|
+
if (!response.ok) {
|
|
2615
|
+
throw new RegistryError(
|
|
2616
|
+
`Failed to fetch manifest for ${cognitiveEntry.name}: ${response.status} ${response.statusText}`,
|
|
2617
|
+
url
|
|
2618
|
+
);
|
|
2619
|
+
}
|
|
2620
|
+
return await response.json();
|
|
2506
2621
|
}
|
|
2507
2622
|
/**
|
|
2508
|
-
* Get
|
|
2623
|
+
* Get the content file for a cognitive
|
|
2509
2624
|
*/
|
|
2510
|
-
|
|
2511
|
-
|
|
2625
|
+
async getContent(cognitiveEntry, manifest) {
|
|
2626
|
+
const url = `${this.baseUrl}/${cognitiveEntry.path}/${manifest.file}`;
|
|
2627
|
+
const response = await this.fetch(url);
|
|
2628
|
+
if (!response.ok) {
|
|
2629
|
+
throw new RegistryError(
|
|
2630
|
+
`Failed to fetch content for ${cognitiveEntry.name}: ${response.status} ${response.statusText}`,
|
|
2631
|
+
url
|
|
2632
|
+
);
|
|
2633
|
+
}
|
|
2634
|
+
return response.text();
|
|
2512
2635
|
}
|
|
2513
2636
|
/**
|
|
2514
|
-
*
|
|
2637
|
+
* Download a cognitive (manifest + content)
|
|
2515
2638
|
*/
|
|
2516
|
-
|
|
2517
|
-
|
|
2639
|
+
async download(name) {
|
|
2640
|
+
const entry = await this.findByName(name);
|
|
2641
|
+
if (entry === null) {
|
|
2642
|
+
throw new CognitiveNotFoundError(name);
|
|
2643
|
+
}
|
|
2644
|
+
const manifest = await this.getManifest(entry);
|
|
2645
|
+
const content = await this.getContent(entry, manifest);
|
|
2646
|
+
return {
|
|
2647
|
+
manifest,
|
|
2648
|
+
content,
|
|
2649
|
+
path: entry.path
|
|
2650
|
+
};
|
|
2518
2651
|
}
|
|
2519
2652
|
/**
|
|
2520
|
-
*
|
|
2653
|
+
* Download additional assets for a cognitive
|
|
2521
2654
|
*/
|
|
2522
|
-
|
|
2523
|
-
this.
|
|
2655
|
+
async downloadAsset(cognitiveEntry, assetPath) {
|
|
2656
|
+
const url = `${this.baseUrl}/${cognitiveEntry.path}/${assetPath}`;
|
|
2657
|
+
const response = await this.fetch(url);
|
|
2658
|
+
if (!response.ok) {
|
|
2659
|
+
throw new RegistryError(
|
|
2660
|
+
`Failed to fetch asset ${assetPath} for ${cognitiveEntry.name}: ${response.status} ${response.statusText}`,
|
|
2661
|
+
url
|
|
2662
|
+
);
|
|
2663
|
+
}
|
|
2664
|
+
return response.text();
|
|
2524
2665
|
}
|
|
2666
|
+
// ============================================
|
|
2667
|
+
// Utility Methods
|
|
2668
|
+
// ============================================
|
|
2525
2669
|
/**
|
|
2526
|
-
*
|
|
2670
|
+
* Check if registry is reachable
|
|
2527
2671
|
*/
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2672
|
+
async ping() {
|
|
2673
|
+
try {
|
|
2674
|
+
const url = `${this.baseUrl}/${REGISTRY_INDEX_FILE}`;
|
|
2675
|
+
const response = await this.fetch(url, { method: "HEAD" });
|
|
2676
|
+
return response.ok;
|
|
2677
|
+
} catch {
|
|
2678
|
+
return false;
|
|
2532
2679
|
}
|
|
2533
2680
|
}
|
|
2534
2681
|
/**
|
|
2535
|
-
*
|
|
2682
|
+
* Clear the cache
|
|
2536
2683
|
*/
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2684
|
+
clearCache() {
|
|
2685
|
+
this.indexCache = null;
|
|
2686
|
+
this.indexCacheTime = 0;
|
|
2687
|
+
}
|
|
2688
|
+
/**
|
|
2689
|
+
* Get the base URL
|
|
2690
|
+
*/
|
|
2691
|
+
getBaseUrl() {
|
|
2692
|
+
return this.baseUrl;
|
|
2693
|
+
}
|
|
2694
|
+
// ============================================
|
|
2695
|
+
// Private Methods
|
|
2696
|
+
// ============================================
|
|
2697
|
+
async fetch(url, options) {
|
|
2698
|
+
try {
|
|
2699
|
+
return await fetch(url, {
|
|
2700
|
+
...options,
|
|
2701
|
+
headers: {
|
|
2702
|
+
"User-Agent": "SynapSync-CLI",
|
|
2703
|
+
...options?.headers
|
|
2704
|
+
}
|
|
2705
|
+
});
|
|
2706
|
+
} catch (error) {
|
|
2707
|
+
if (error instanceof Error) {
|
|
2708
|
+
throw new RegistryError(`Network error: ${error.message}`, url);
|
|
2709
|
+
}
|
|
2710
|
+
throw new RegistryError("Network error", url);
|
|
2541
2711
|
}
|
|
2542
|
-
return false;
|
|
2543
2712
|
}
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
};
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2713
|
+
};
|
|
2714
|
+
var RegistryError = class extends Error {
|
|
2715
|
+
constructor(message, url) {
|
|
2716
|
+
super(message);
|
|
2717
|
+
this.url = url;
|
|
2718
|
+
this.name = "RegistryError";
|
|
2719
|
+
}
|
|
2720
|
+
};
|
|
2721
|
+
var CognitiveNotFoundError = class extends Error {
|
|
2722
|
+
constructor(cognitiveName) {
|
|
2723
|
+
super(`Cognitive '${cognitiveName}' not found in registry`);
|
|
2724
|
+
this.cognitiveName = cognitiveName;
|
|
2725
|
+
this.name = "CognitiveNotFoundError";
|
|
2726
|
+
}
|
|
2727
|
+
};
|
|
2728
|
+
|
|
2729
|
+
// src/commands/search.ts
|
|
2730
|
+
async function executeSearchCommand(query, options) {
|
|
2731
|
+
logger.line();
|
|
2732
|
+
const validatedOptions = validateOptions(options);
|
|
2733
|
+
if (validatedOptions === null) {
|
|
2734
|
+
return;
|
|
2735
|
+
}
|
|
2736
|
+
const searchingText = query !== void 0 && query.trim() !== "" ? `Searching for "${query}"...` : "Fetching cognitives from registry...";
|
|
2737
|
+
logger.log(` ${pc8.dim(searchingText)}`);
|
|
2738
|
+
try {
|
|
2739
|
+
const client = new RegistryClient();
|
|
2740
|
+
const isReachable = await client.ping();
|
|
2741
|
+
if (!isReachable) {
|
|
2742
|
+
logger.line();
|
|
2743
|
+
logger.error("Unable to reach the registry. Check your internet connection.");
|
|
2744
|
+
return;
|
|
2558
2745
|
}
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2746
|
+
const searchOpts = {};
|
|
2747
|
+
if (validatedOptions.type !== void 0) searchOpts.type = validatedOptions.type;
|
|
2748
|
+
if (validatedOptions.category !== void 0) searchOpts.category = validatedOptions.category;
|
|
2749
|
+
if (validatedOptions.tag !== void 0) searchOpts.tag = validatedOptions.tag;
|
|
2750
|
+
if (validatedOptions.limit !== void 0) searchOpts.limit = validatedOptions.limit;
|
|
2751
|
+
const result = await client.search(query, searchOpts);
|
|
2752
|
+
process.stdout.write("\x1B[1A\x1B[2K");
|
|
2753
|
+
if (options.json === true) {
|
|
2754
|
+
console.log(JSON.stringify(result, null, 2));
|
|
2755
|
+
return;
|
|
2563
2756
|
}
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2757
|
+
displaySearchResults(result.cognitives, query, result.total);
|
|
2758
|
+
} catch (error) {
|
|
2759
|
+
logger.line();
|
|
2760
|
+
if (error instanceof RegistryError) {
|
|
2761
|
+
logger.error(`Registry error: ${error.message}`);
|
|
2762
|
+
} else if (error instanceof Error) {
|
|
2763
|
+
logger.error(`Search failed: ${error.message}`);
|
|
2764
|
+
} else {
|
|
2765
|
+
logger.error("Search failed with unknown error");
|
|
2573
2766
|
}
|
|
2574
|
-
return result;
|
|
2575
2767
|
}
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2768
|
+
}
|
|
2769
|
+
function validateOptions(options) {
|
|
2770
|
+
const validated = {};
|
|
2771
|
+
if (options.type !== void 0) {
|
|
2772
|
+
if (!COGNITIVE_TYPES.includes(options.type)) {
|
|
2773
|
+
logger.error(`Invalid type: ${options.type}`);
|
|
2774
|
+
logger.hint(`Valid types: ${COGNITIVE_TYPES.join(", ")}`);
|
|
2775
|
+
return null;
|
|
2582
2776
|
}
|
|
2583
|
-
|
|
2584
|
-
|
|
2777
|
+
validated.type = options.type;
|
|
2778
|
+
}
|
|
2779
|
+
if (options.category !== void 0) {
|
|
2780
|
+
if (!CATEGORIES.includes(options.category)) {
|
|
2781
|
+
logger.error(`Invalid category: ${options.category}`);
|
|
2782
|
+
logger.hint(`Valid categories: ${CATEGORIES.join(", ")}`);
|
|
2783
|
+
return null;
|
|
2585
2784
|
}
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
if (existing.sourceUrl !== void 0) {
|
|
2597
|
-
updated.sourceUrl = existing.sourceUrl;
|
|
2598
|
-
}
|
|
2599
|
-
this.manifest.cognitives[cognitive.name] = updated;
|
|
2600
|
-
}
|
|
2785
|
+
validated.category = options.category;
|
|
2786
|
+
}
|
|
2787
|
+
if (options.tag !== void 0) {
|
|
2788
|
+
validated.tag = options.tag;
|
|
2789
|
+
}
|
|
2790
|
+
if (options.limit !== void 0) {
|
|
2791
|
+
const limit = parseInt(options.limit, 10);
|
|
2792
|
+
if (isNaN(limit) || limit < 1) {
|
|
2793
|
+
logger.error("Limit must be a positive number");
|
|
2794
|
+
return null;
|
|
2601
2795
|
}
|
|
2796
|
+
validated.limit = limit;
|
|
2602
2797
|
}
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2798
|
+
return validated;
|
|
2799
|
+
}
|
|
2800
|
+
function displaySearchResults(cognitives, query, total) {
|
|
2801
|
+
if (query !== void 0 && query.trim() !== "") {
|
|
2802
|
+
logger.bold(` Search Results for "${query}"`);
|
|
2803
|
+
} else {
|
|
2804
|
+
logger.bold(" Registry Cognitives");
|
|
2608
2805
|
}
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2806
|
+
logger.line();
|
|
2807
|
+
if (cognitives.length === 0) {
|
|
2808
|
+
logger.log(` ${pc8.dim("No cognitives found")}`);
|
|
2809
|
+
logger.line();
|
|
2810
|
+
logger.hint("Try a different search query or remove filters.");
|
|
2811
|
+
return;
|
|
2614
2812
|
}
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
return this.manifest.syncs[provider]?.cognitives ?? [];
|
|
2813
|
+
if (cognitives.length < total) {
|
|
2814
|
+
logger.log(` ${pc8.dim(`Showing ${cognitives.length} of ${total} results`)}`);
|
|
2815
|
+
} else {
|
|
2816
|
+
logger.log(` ${pc8.dim(`Found ${total} cognitive${total === 1 ? "" : "s"}`)}`);
|
|
2620
2817
|
}
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
getCognitiveCount() {
|
|
2625
|
-
return Object.keys(this.manifest.cognitives).length;
|
|
2818
|
+
logger.line();
|
|
2819
|
+
for (const cognitive of cognitives) {
|
|
2820
|
+
displayCognitive(cognitive);
|
|
2626
2821
|
}
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2822
|
+
logger.line();
|
|
2823
|
+
logger.hint("Run synapsync add <name> to add a cognitive.");
|
|
2824
|
+
}
|
|
2825
|
+
function displayCognitive(cognitive) {
|
|
2826
|
+
const typeIcon = getCognitiveIcon2(cognitive.type);
|
|
2827
|
+
const typeLabel = pc8.dim(`[${cognitive.type}]`);
|
|
2828
|
+
logger.log(` ${typeIcon} ${pc8.bold(pc8.white(cognitive.name))} ${typeLabel}`);
|
|
2829
|
+
logger.log(` ${pc8.dim(truncate(cognitive.description, 60))}`);
|
|
2830
|
+
const meta = [];
|
|
2831
|
+
meta.push(pc8.dim(`v${cognitive.version}`));
|
|
2832
|
+
meta.push(pc8.dim(cognitive.category));
|
|
2833
|
+
if (cognitive.downloads > 0) {
|
|
2834
|
+
meta.push(pc8.dim(`${cognitive.downloads} downloads`));
|
|
2632
2835
|
}
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
return Object.values(this.manifest.cognitives).filter((c) => c.source === source);
|
|
2836
|
+
logger.log(` ${meta.join(" \xB7 ")}`);
|
|
2837
|
+
if (cognitive.tags.length > 0) {
|
|
2838
|
+
const tags = cognitive.tags.slice(0, 5).map((t) => pc8.cyan(t)).join(" ");
|
|
2839
|
+
logger.log(` ${tags}`);
|
|
2638
2840
|
}
|
|
2639
|
-
|
|
2841
|
+
logger.line();
|
|
2842
|
+
}
|
|
2843
|
+
function getCognitiveIcon2(type) {
|
|
2844
|
+
const icons = {
|
|
2845
|
+
skill: pc8.blue("\u25C6"),
|
|
2846
|
+
agent: pc8.magenta("\u25C6"),
|
|
2847
|
+
prompt: pc8.yellow("\u25C6"),
|
|
2848
|
+
workflow: pc8.cyan("\u25C6"),
|
|
2849
|
+
tool: pc8.green("\u25C6")
|
|
2850
|
+
};
|
|
2851
|
+
return icons[type];
|
|
2852
|
+
}
|
|
2853
|
+
function truncate(text2, maxLength) {
|
|
2854
|
+
if (text2.length <= maxLength) return text2;
|
|
2855
|
+
return text2.slice(0, maxLength - 3) + "...";
|
|
2856
|
+
}
|
|
2857
|
+
function registerSearchCommand(program) {
|
|
2858
|
+
program.command("search [query]").description("Search for cognitives in the registry").option("-t, --type <type>", "Filter by type (skill, agent, prompt, workflow, tool)").option("-c, --category <category>", "Filter by category").option("--tag <tag>", "Filter by tag").option("-l, --limit <number>", "Limit results", "20").option("--json", "Output as JSON").action(async (query, options) => {
|
|
2859
|
+
await executeSearchCommand(query, options);
|
|
2860
|
+
});
|
|
2861
|
+
}
|
|
2862
|
+
|
|
2863
|
+
// src/commands/add.ts
|
|
2864
|
+
init_esm_shims();
|
|
2865
|
+
import * as fs9 from "fs";
|
|
2866
|
+
import * as path11 from "path";
|
|
2867
|
+
import pc9 from "picocolors";
|
|
2868
|
+
|
|
2869
|
+
// src/services/sync/engine.ts
|
|
2870
|
+
init_esm_shims();
|
|
2871
|
+
import * as path10 from "path";
|
|
2640
2872
|
|
|
2641
2873
|
// src/services/symlink/manager.ts
|
|
2642
2874
|
init_esm_shims();
|
|
2643
|
-
import * as
|
|
2644
|
-
import * as
|
|
2875
|
+
import * as fs8 from "fs";
|
|
2876
|
+
import * as path9 from "path";
|
|
2645
2877
|
var SymlinkManager = class {
|
|
2646
2878
|
projectRoot;
|
|
2647
2879
|
synapSyncDir;
|
|
@@ -2659,12 +2891,12 @@ var SymlinkManager = class {
|
|
|
2659
2891
|
}
|
|
2660
2892
|
if (process.platform === "win32") {
|
|
2661
2893
|
try {
|
|
2662
|
-
const testSource =
|
|
2663
|
-
const testTarget =
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2894
|
+
const testSource = path9.join(this.synapSyncDir, ".symlink-test");
|
|
2895
|
+
const testTarget = path9.join(this.synapSyncDir, ".symlink-test-target");
|
|
2896
|
+
fs8.writeFileSync(testTarget, "test", "utf-8");
|
|
2897
|
+
fs8.symlinkSync(testTarget, testSource);
|
|
2898
|
+
fs8.unlinkSync(testSource);
|
|
2899
|
+
fs8.unlinkSync(testTarget);
|
|
2668
2900
|
this.supportsSymlinks = true;
|
|
2669
2901
|
} catch {
|
|
2670
2902
|
this.supportsSymlinks = false;
|
|
@@ -2767,7 +2999,7 @@ var SymlinkManager = class {
|
|
|
2767
2999
|
cognitiveType: cognitive.type,
|
|
2768
3000
|
sourcePath: cognitive.path,
|
|
2769
3001
|
// Directory path
|
|
2770
|
-
targetPath:
|
|
3002
|
+
targetPath: path9.join(this.projectRoot, typeDir, cognitive.name),
|
|
2771
3003
|
isFile: false
|
|
2772
3004
|
});
|
|
2773
3005
|
} else {
|
|
@@ -2777,7 +3009,7 @@ var SymlinkManager = class {
|
|
|
2777
3009
|
cognitiveType: cognitive.type,
|
|
2778
3010
|
sourcePath: cognitive.filePath,
|
|
2779
3011
|
// File path
|
|
2780
|
-
targetPath:
|
|
3012
|
+
targetPath: path9.join(this.projectRoot, typeDir, fileName),
|
|
2781
3013
|
isFile: true
|
|
2782
3014
|
});
|
|
2783
3015
|
}
|
|
@@ -2794,12 +3026,12 @@ var SymlinkManager = class {
|
|
|
2794
3026
|
for (const cognitiveType of COGNITIVE_TYPES) {
|
|
2795
3027
|
const typeDir = providerPaths[cognitiveType];
|
|
2796
3028
|
if (typeDir === void 0) continue;
|
|
2797
|
-
const fullPath =
|
|
2798
|
-
if (!
|
|
2799
|
-
const entries =
|
|
3029
|
+
const fullPath = path9.join(this.projectRoot, typeDir);
|
|
3030
|
+
if (!fs8.existsSync(fullPath)) continue;
|
|
3031
|
+
const entries = fs8.readdirSync(fullPath, { withFileTypes: true });
|
|
2800
3032
|
for (const entry of entries) {
|
|
2801
3033
|
if (entry.name.startsWith(".")) continue;
|
|
2802
|
-
const entryPath =
|
|
3034
|
+
const entryPath = path9.join(fullPath, entry.name);
|
|
2803
3035
|
if (entry.isFile() || entry.isDirectory() || entry.isSymbolicLink()) {
|
|
2804
3036
|
const info = this.getLinkInfo(entryPath, cognitiveType);
|
|
2805
3037
|
if (info !== null) {
|
|
@@ -2815,13 +3047,13 @@ var SymlinkManager = class {
|
|
|
2815
3047
|
*/
|
|
2816
3048
|
getLinkInfo(linkPath, cognitiveType) {
|
|
2817
3049
|
try {
|
|
2818
|
-
const stats =
|
|
3050
|
+
const stats = fs8.lstatSync(linkPath);
|
|
2819
3051
|
const isSymlink = stats.isSymbolicLink();
|
|
2820
|
-
const baseName =
|
|
3052
|
+
const baseName = path9.basename(linkPath);
|
|
2821
3053
|
let isDirectory = stats.isDirectory();
|
|
2822
3054
|
if (isSymlink) {
|
|
2823
3055
|
try {
|
|
2824
|
-
const realStats =
|
|
3056
|
+
const realStats = fs8.statSync(linkPath);
|
|
2825
3057
|
isDirectory = realStats.isDirectory();
|
|
2826
3058
|
} catch {
|
|
2827
3059
|
isDirectory = !baseName.match(/\.(md|yaml)$/i);
|
|
@@ -2831,9 +3063,9 @@ var SymlinkManager = class {
|
|
|
2831
3063
|
let target = "";
|
|
2832
3064
|
let isValid = false;
|
|
2833
3065
|
if (isSymlink) {
|
|
2834
|
-
target =
|
|
2835
|
-
const resolvedTarget =
|
|
2836
|
-
isValid =
|
|
3066
|
+
target = fs8.readlinkSync(linkPath);
|
|
3067
|
+
const resolvedTarget = path9.resolve(path9.dirname(linkPath), target);
|
|
3068
|
+
isValid = fs8.existsSync(resolvedTarget);
|
|
2837
3069
|
} else if (stats.isDirectory()) {
|
|
2838
3070
|
target = linkPath;
|
|
2839
3071
|
isValid = true;
|
|
@@ -2861,11 +3093,11 @@ var SymlinkManager = class {
|
|
|
2861
3093
|
const method = this.getMethod(options);
|
|
2862
3094
|
const isFile = mapping.isFile ?? false;
|
|
2863
3095
|
try {
|
|
2864
|
-
const targetDir =
|
|
2865
|
-
if (!
|
|
2866
|
-
|
|
3096
|
+
const targetDir = path9.dirname(mapping.targetPath);
|
|
3097
|
+
if (!fs8.existsSync(targetDir)) {
|
|
3098
|
+
fs8.mkdirSync(targetDir, { recursive: true });
|
|
2867
3099
|
}
|
|
2868
|
-
if (
|
|
3100
|
+
if (fs8.existsSync(mapping.targetPath)) {
|
|
2869
3101
|
if (options.force === true) {
|
|
2870
3102
|
this.removeLink(mapping.targetPath);
|
|
2871
3103
|
} else {
|
|
@@ -2879,11 +3111,11 @@ var SymlinkManager = class {
|
|
|
2879
3111
|
}
|
|
2880
3112
|
}
|
|
2881
3113
|
if (method === "symlink") {
|
|
2882
|
-
const relativePath =
|
|
2883
|
-
|
|
3114
|
+
const relativePath = path9.relative(targetDir, mapping.sourcePath);
|
|
3115
|
+
fs8.symlinkSync(relativePath, mapping.targetPath, isFile ? "file" : "dir");
|
|
2884
3116
|
} else {
|
|
2885
3117
|
if (isFile) {
|
|
2886
|
-
|
|
3118
|
+
fs8.copyFileSync(mapping.sourcePath, mapping.targetPath);
|
|
2887
3119
|
} else {
|
|
2888
3120
|
this.copyDirectory(mapping.sourcePath, mapping.targetPath);
|
|
2889
3121
|
}
|
|
@@ -2898,7 +3130,7 @@ var SymlinkManager = class {
|
|
|
2898
3130
|
if (method === "symlink" && options.copy !== true) {
|
|
2899
3131
|
try {
|
|
2900
3132
|
if (isFile) {
|
|
2901
|
-
|
|
3133
|
+
fs8.copyFileSync(mapping.sourcePath, mapping.targetPath);
|
|
2902
3134
|
} else {
|
|
2903
3135
|
this.copyDirectory(mapping.sourcePath, mapping.targetPath);
|
|
2904
3136
|
}
|
|
@@ -2931,26 +3163,26 @@ var SymlinkManager = class {
|
|
|
2931
3163
|
* Remove a symlink, file, or directory
|
|
2932
3164
|
*/
|
|
2933
3165
|
removeLink(linkPath) {
|
|
2934
|
-
const stats =
|
|
3166
|
+
const stats = fs8.lstatSync(linkPath);
|
|
2935
3167
|
if (stats.isSymbolicLink() || stats.isFile()) {
|
|
2936
|
-
|
|
3168
|
+
fs8.unlinkSync(linkPath);
|
|
2937
3169
|
} else if (stats.isDirectory()) {
|
|
2938
|
-
|
|
3170
|
+
fs8.rmSync(linkPath, { recursive: true });
|
|
2939
3171
|
}
|
|
2940
3172
|
}
|
|
2941
3173
|
/**
|
|
2942
3174
|
* Copy a directory recursively
|
|
2943
3175
|
*/
|
|
2944
3176
|
copyDirectory(source, target) {
|
|
2945
|
-
|
|
2946
|
-
const entries =
|
|
3177
|
+
fs8.mkdirSync(target, { recursive: true });
|
|
3178
|
+
const entries = fs8.readdirSync(source, { withFileTypes: true });
|
|
2947
3179
|
for (const entry of entries) {
|
|
2948
|
-
const sourcePath =
|
|
2949
|
-
const targetPath =
|
|
3180
|
+
const sourcePath = path9.join(source, entry.name);
|
|
3181
|
+
const targetPath = path9.join(target, entry.name);
|
|
2950
3182
|
if (entry.isDirectory()) {
|
|
2951
3183
|
this.copyDirectory(sourcePath, targetPath);
|
|
2952
3184
|
} else {
|
|
2953
|
-
|
|
3185
|
+
fs8.copyFileSync(sourcePath, targetPath);
|
|
2954
3186
|
}
|
|
2955
3187
|
}
|
|
2956
3188
|
}
|
|
@@ -2979,8 +3211,8 @@ var SymlinkManager = class {
|
|
|
2979
3211
|
broken.push(link);
|
|
2980
3212
|
} else {
|
|
2981
3213
|
if (link.isSymlink) {
|
|
2982
|
-
const resolvedTarget =
|
|
2983
|
-
if (!resolvedTarget.includes(
|
|
3214
|
+
const resolvedTarget = path9.resolve(path9.dirname(link.path), link.target);
|
|
3215
|
+
if (!resolvedTarget.includes(path9.basename(this.synapSyncDir))) {
|
|
2984
3216
|
orphaned.push(link);
|
|
2985
3217
|
} else {
|
|
2986
3218
|
valid.push(link);
|
|
@@ -3021,7 +3253,7 @@ var SyncEngine = class {
|
|
|
3021
3253
|
projectRoot;
|
|
3022
3254
|
config;
|
|
3023
3255
|
constructor(synapSyncDir, projectRoot, config) {
|
|
3024
|
-
this.projectRoot = projectRoot ??
|
|
3256
|
+
this.projectRoot = projectRoot ?? path10.dirname(synapSyncDir);
|
|
3025
3257
|
this.config = config ?? null;
|
|
3026
3258
|
this.scanner = new CognitiveScanner(synapSyncDir);
|
|
3027
3259
|
this.manifest = new ManifestManager(synapSyncDir);
|
|
@@ -3361,6 +3593,7 @@ async function executeAddCommand(source, options) {
|
|
|
3361
3593
|
}
|
|
3362
3594
|
}
|
|
3363
3595
|
}
|
|
3596
|
+
regenerateAgentsMd(projectRoot, synapSyncDir);
|
|
3364
3597
|
logger.line();
|
|
3365
3598
|
}
|
|
3366
3599
|
} catch (error) {
|
|
@@ -3381,7 +3614,7 @@ function parseSource(source) {
|
|
|
3381
3614
|
if (source.startsWith("./") || source.startsWith("/") || source.startsWith("../")) {
|
|
3382
3615
|
return {
|
|
3383
3616
|
type: "local",
|
|
3384
|
-
name:
|
|
3617
|
+
name: path11.basename(source),
|
|
3385
3618
|
path: source
|
|
3386
3619
|
};
|
|
3387
3620
|
}
|
|
@@ -3418,7 +3651,7 @@ async function installFromRegistry(name, options, configManager) {
|
|
|
3418
3651
|
const manifest = downloaded.manifest;
|
|
3419
3652
|
const category = options.category ?? manifest.category;
|
|
3420
3653
|
const targetDir = getTargetDir(configManager, manifest.type, category, manifest.name);
|
|
3421
|
-
if (
|
|
3654
|
+
if (fs9.existsSync(targetDir) && options.force !== true) {
|
|
3422
3655
|
logger.line();
|
|
3423
3656
|
logger.error(`Cognitive '${manifest.name}' is already installed.`);
|
|
3424
3657
|
logger.hint("Use --force to overwrite.");
|
|
@@ -3431,7 +3664,7 @@ async function installFromRegistry(name, options, configManager) {
|
|
|
3431
3664
|
logger.log(` ${pc9.green("\u2713")} Installed ${pc9.bold(manifest.name)} ${pc9.dim(`v${manifest.version}`)}`);
|
|
3432
3665
|
logger.log(` ${pc9.dim("Type:")} ${manifest.type}`);
|
|
3433
3666
|
logger.log(` ${pc9.dim("Category:")} ${category}`);
|
|
3434
|
-
logger.log(` ${pc9.dim("Location:")} ${
|
|
3667
|
+
logger.log(` ${pc9.dim("Location:")} ${path11.relative(process.cwd(), targetDir)}`);
|
|
3435
3668
|
return true;
|
|
3436
3669
|
}
|
|
3437
3670
|
async function downloadAssets(client, name, _manifest) {
|
|
@@ -3452,8 +3685,8 @@ async function downloadAssets(client, name, _manifest) {
|
|
|
3452
3685
|
return assets;
|
|
3453
3686
|
}
|
|
3454
3687
|
function installFromLocal(sourcePath, options, configManager) {
|
|
3455
|
-
const absolutePath =
|
|
3456
|
-
if (!
|
|
3688
|
+
const absolutePath = path11.resolve(process.cwd(), sourcePath);
|
|
3689
|
+
if (!fs9.existsSync(absolutePath)) {
|
|
3457
3690
|
throw new Error(`Path not found: ${absolutePath}`);
|
|
3458
3691
|
}
|
|
3459
3692
|
const detected = detectCognitiveType(absolutePath);
|
|
@@ -3464,13 +3697,13 @@ function installFromLocal(sourcePath, options, configManager) {
|
|
|
3464
3697
|
}
|
|
3465
3698
|
const cognitiveType = options.type ?? detected?.type ?? "skill";
|
|
3466
3699
|
const fileName = detected?.fileName ?? COGNITIVE_FILE_NAMES[cognitiveType];
|
|
3467
|
-
const filePath =
|
|
3468
|
-
if (!
|
|
3700
|
+
const filePath = path11.join(absolutePath, fileName);
|
|
3701
|
+
if (!fs9.existsSync(filePath)) {
|
|
3469
3702
|
throw new Error(`Cognitive file not found: ${filePath}`);
|
|
3470
3703
|
}
|
|
3471
|
-
const content =
|
|
3704
|
+
const content = fs9.readFileSync(filePath, "utf-8");
|
|
3472
3705
|
const metadata = parseMetadata(content);
|
|
3473
|
-
const name = metadata["name"] ??
|
|
3706
|
+
const name = metadata["name"] ?? path11.basename(absolutePath);
|
|
3474
3707
|
const category = options.category ?? metadata["category"] ?? "general";
|
|
3475
3708
|
const manifest = {
|
|
3476
3709
|
name,
|
|
@@ -3488,18 +3721,18 @@ function installFromLocal(sourcePath, options, configManager) {
|
|
|
3488
3721
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3489
3722
|
};
|
|
3490
3723
|
const targetDir = getTargetDir(configManager, cognitiveType, category, name);
|
|
3491
|
-
if (
|
|
3724
|
+
if (fs9.existsSync(targetDir) && options.force !== true) {
|
|
3492
3725
|
logger.line();
|
|
3493
3726
|
logger.error(`Cognitive '${name}' is already installed.`);
|
|
3494
3727
|
logger.hint("Use --force to overwrite.");
|
|
3495
3728
|
return false;
|
|
3496
3729
|
}
|
|
3497
3730
|
const assets = /* @__PURE__ */ new Map();
|
|
3498
|
-
const assetsDir =
|
|
3499
|
-
if (
|
|
3500
|
-
const assetFiles =
|
|
3731
|
+
const assetsDir = path11.join(absolutePath, "assets");
|
|
3732
|
+
if (fs9.existsSync(assetsDir)) {
|
|
3733
|
+
const assetFiles = fs9.readdirSync(assetsDir);
|
|
3501
3734
|
for (const file of assetFiles) {
|
|
3502
|
-
const assetContent =
|
|
3735
|
+
const assetContent = fs9.readFileSync(path11.join(assetsDir, file), "utf-8");
|
|
3503
3736
|
assets.set(`assets/${file}`, assetContent);
|
|
3504
3737
|
}
|
|
3505
3738
|
}
|
|
@@ -3510,18 +3743,18 @@ function installFromLocal(sourcePath, options, configManager) {
|
|
|
3510
3743
|
logger.log(` ${pc9.dim("Type:")} ${cognitiveType}`);
|
|
3511
3744
|
logger.log(` ${pc9.dim("Category:")} ${category}`);
|
|
3512
3745
|
logger.log(` ${pc9.dim("Source:")} local`);
|
|
3513
|
-
logger.log(` ${pc9.dim("Location:")} ${
|
|
3746
|
+
logger.log(` ${pc9.dim("Location:")} ${path11.relative(process.cwd(), targetDir)}`);
|
|
3514
3747
|
return true;
|
|
3515
3748
|
}
|
|
3516
3749
|
function detectCognitiveType(dirPath) {
|
|
3517
3750
|
for (const type of COGNITIVE_TYPES) {
|
|
3518
3751
|
const fileName = COGNITIVE_FILE_NAMES[type];
|
|
3519
|
-
if (
|
|
3752
|
+
if (fs9.existsSync(path11.join(dirPath, fileName))) {
|
|
3520
3753
|
return { type, fileName };
|
|
3521
3754
|
}
|
|
3522
3755
|
}
|
|
3523
|
-
if (!
|
|
3524
|
-
const files =
|
|
3756
|
+
if (!fs9.existsSync(dirPath)) return null;
|
|
3757
|
+
const files = fs9.readdirSync(dirPath);
|
|
3525
3758
|
for (const file of files) {
|
|
3526
3759
|
if (file.endsWith(".yaml") && !file.startsWith(".")) {
|
|
3527
3760
|
return { type: "workflow", fileName: file };
|
|
@@ -3529,7 +3762,7 @@ function detectCognitiveType(dirPath) {
|
|
|
3529
3762
|
}
|
|
3530
3763
|
for (const file of files) {
|
|
3531
3764
|
if (file.endsWith(".md") && !file.startsWith(".")) {
|
|
3532
|
-
const content =
|
|
3765
|
+
const content = fs9.readFileSync(path11.join(dirPath, file), "utf-8");
|
|
3533
3766
|
const metadata = parseMetadata(content);
|
|
3534
3767
|
const detectedType = metadata["type"] ?? "skill";
|
|
3535
3768
|
if (COGNITIVE_TYPES.includes(detectedType)) {
|
|
@@ -3573,25 +3806,25 @@ function installFromGitHub(_source, _options, _configManager) {
|
|
|
3573
3806
|
}
|
|
3574
3807
|
function getTargetDir(configManager, type, category, name) {
|
|
3575
3808
|
const synapSyncDir = configManager.getSynapSyncDir();
|
|
3576
|
-
return
|
|
3809
|
+
return path11.join(synapSyncDir, `${type}s`, category, name);
|
|
3577
3810
|
}
|
|
3578
3811
|
function saveCognitive(targetDir, manifest, content, assets) {
|
|
3579
|
-
|
|
3580
|
-
const mainFilePath =
|
|
3581
|
-
|
|
3812
|
+
fs9.mkdirSync(targetDir, { recursive: true });
|
|
3813
|
+
const mainFilePath = path11.join(targetDir, manifest.file);
|
|
3814
|
+
fs9.writeFileSync(mainFilePath, content, "utf-8");
|
|
3582
3815
|
for (const [assetPath, assetContent] of assets) {
|
|
3583
|
-
const fullPath =
|
|
3584
|
-
const assetDir =
|
|
3585
|
-
|
|
3586
|
-
|
|
3816
|
+
const fullPath = path11.join(targetDir, assetPath);
|
|
3817
|
+
const assetDir = path11.dirname(fullPath);
|
|
3818
|
+
fs9.mkdirSync(assetDir, { recursive: true });
|
|
3819
|
+
fs9.writeFileSync(fullPath, assetContent, "utf-8");
|
|
3587
3820
|
}
|
|
3588
3821
|
}
|
|
3589
3822
|
function updateProjectManifest(configManager, manifest, source) {
|
|
3590
3823
|
const synapSyncDir = configManager.getSynapSyncDir();
|
|
3591
|
-
const manifestPath =
|
|
3824
|
+
const manifestPath = path11.join(synapSyncDir, "manifest.json");
|
|
3592
3825
|
let projectManifest;
|
|
3593
|
-
if (
|
|
3594
|
-
const content =
|
|
3826
|
+
if (fs9.existsSync(manifestPath)) {
|
|
3827
|
+
const content = fs9.readFileSync(manifestPath, "utf-8");
|
|
3595
3828
|
projectManifest = JSON.parse(content);
|
|
3596
3829
|
} else {
|
|
3597
3830
|
projectManifest = {
|
|
@@ -3615,7 +3848,7 @@ function updateProjectManifest(configManager, manifest, source) {
|
|
|
3615
3848
|
}
|
|
3616
3849
|
projectManifest.cognitives[manifest.name] = entry;
|
|
3617
3850
|
projectManifest.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
3618
|
-
|
|
3851
|
+
fs9.writeFileSync(manifestPath, JSON.stringify(projectManifest, null, 2), "utf-8");
|
|
3619
3852
|
}
|
|
3620
3853
|
function registerAddCommand(program) {
|
|
3621
3854
|
program.command("add <source>").description("Add a cognitive from registry, local path, or GitHub").option("-t, --type <type>", "Cognitive type (skill, agent, prompt, workflow, tool)").option("-c, --category <category>", "Category (overrides default)").option("-f, --force", "Overwrite if already installed").action(async (source, options) => {
|
|
@@ -3625,8 +3858,8 @@ function registerAddCommand(program) {
|
|
|
3625
3858
|
|
|
3626
3859
|
// src/commands/list.ts
|
|
3627
3860
|
init_esm_shims();
|
|
3628
|
-
import * as
|
|
3629
|
-
import * as
|
|
3861
|
+
import * as fs10 from "fs";
|
|
3862
|
+
import * as path12 from "path";
|
|
3630
3863
|
import pc10 from "picocolors";
|
|
3631
3864
|
async function executeListCommand(options) {
|
|
3632
3865
|
logger.line();
|
|
@@ -3746,8 +3979,8 @@ function validateOptions2(options) {
|
|
|
3746
3979
|
}
|
|
3747
3980
|
function readManifest(configManager) {
|
|
3748
3981
|
const synapSyncDir = configManager.getSynapSyncDir();
|
|
3749
|
-
const manifestPath =
|
|
3750
|
-
if (!
|
|
3982
|
+
const manifestPath = path12.join(synapSyncDir, "manifest.json");
|
|
3983
|
+
if (!fs10.existsSync(manifestPath)) {
|
|
3751
3984
|
return {
|
|
3752
3985
|
version: "1.0.0",
|
|
3753
3986
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -3756,7 +3989,7 @@ function readManifest(configManager) {
|
|
|
3756
3989
|
};
|
|
3757
3990
|
}
|
|
3758
3991
|
try {
|
|
3759
|
-
const content =
|
|
3992
|
+
const content = fs10.readFileSync(manifestPath, "utf-8");
|
|
3760
3993
|
return JSON.parse(content);
|
|
3761
3994
|
} catch {
|
|
3762
3995
|
return {
|
|
@@ -3865,8 +4098,8 @@ function registerListCommand(program) {
|
|
|
3865
4098
|
|
|
3866
4099
|
// src/commands/uninstall.ts
|
|
3867
4100
|
init_esm_shims();
|
|
3868
|
-
import * as
|
|
3869
|
-
import * as
|
|
4101
|
+
import * as fs11 from "fs";
|
|
4102
|
+
import * as path13 from "path";
|
|
3870
4103
|
import pc11 from "picocolors";
|
|
3871
4104
|
function executeUninstallCommand(name, options) {
|
|
3872
4105
|
logger.line();
|
|
@@ -3896,14 +4129,15 @@ function executeUninstallCommand(name, options) {
|
|
|
3896
4129
|
try {
|
|
3897
4130
|
if (options.keepFiles !== true) {
|
|
3898
4131
|
const cognitiveDir = getCognitiveDir(configManager, cognitive);
|
|
3899
|
-
if (
|
|
3900
|
-
|
|
3901
|
-
logger.log(` ${pc11.dim("Removed files from")} ${
|
|
4132
|
+
if (fs11.existsSync(cognitiveDir)) {
|
|
4133
|
+
fs11.rmSync(cognitiveDir, { recursive: true, force: true });
|
|
4134
|
+
logger.log(` ${pc11.dim("Removed files from")} ${path13.relative(process.cwd(), cognitiveDir)}`);
|
|
3902
4135
|
}
|
|
3903
4136
|
}
|
|
3904
4137
|
delete manifest.cognitives[name];
|
|
3905
4138
|
manifest.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
3906
4139
|
saveManifest(configManager, manifest);
|
|
4140
|
+
regenerateAgentsMd(configManager.getProjectRoot(), configManager.getSynapSyncDir());
|
|
3907
4141
|
logger.line();
|
|
3908
4142
|
logger.log(` ${pc11.green("\u2713")} Uninstalled ${pc11.bold(name)}`);
|
|
3909
4143
|
logger.line();
|
|
@@ -3919,8 +4153,8 @@ function executeUninstallCommand(name, options) {
|
|
|
3919
4153
|
}
|
|
3920
4154
|
function readManifest2(configManager) {
|
|
3921
4155
|
const synapSyncDir = configManager.getSynapSyncDir();
|
|
3922
|
-
const manifestPath =
|
|
3923
|
-
if (!
|
|
4156
|
+
const manifestPath = path13.join(synapSyncDir, "manifest.json");
|
|
4157
|
+
if (!fs11.existsSync(manifestPath)) {
|
|
3924
4158
|
return {
|
|
3925
4159
|
version: "1.0.0",
|
|
3926
4160
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -3929,7 +4163,7 @@ function readManifest2(configManager) {
|
|
|
3929
4163
|
};
|
|
3930
4164
|
}
|
|
3931
4165
|
try {
|
|
3932
|
-
const content =
|
|
4166
|
+
const content = fs11.readFileSync(manifestPath, "utf-8");
|
|
3933
4167
|
return JSON.parse(content);
|
|
3934
4168
|
} catch {
|
|
3935
4169
|
return {
|
|
@@ -3942,12 +4176,12 @@ function readManifest2(configManager) {
|
|
|
3942
4176
|
}
|
|
3943
4177
|
function saveManifest(configManager, manifest) {
|
|
3944
4178
|
const synapSyncDir = configManager.getSynapSyncDir();
|
|
3945
|
-
const manifestPath =
|
|
3946
|
-
|
|
4179
|
+
const manifestPath = path13.join(synapSyncDir, "manifest.json");
|
|
4180
|
+
fs11.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
3947
4181
|
}
|
|
3948
4182
|
function getCognitiveDir(configManager, cognitive) {
|
|
3949
4183
|
const synapSyncDir = configManager.getSynapSyncDir();
|
|
3950
|
-
return
|
|
4184
|
+
return path13.join(synapSyncDir, `${cognitive.type}s`, cognitive.category, cognitive.name);
|
|
3951
4185
|
}
|
|
3952
4186
|
function registerUninstallCommand(program) {
|
|
3953
4187
|
program.command("uninstall <name>").alias("rm").description("Uninstall a cognitive").option("-f, --force", "Skip confirmation").option("--keep-files", "Remove from manifest but keep files").action((name, options) => {
|
|
@@ -3998,6 +4232,11 @@ function executeSyncCommand(options) {
|
|
|
3998
4232
|
}
|
|
3999
4233
|
} : void 0
|
|
4000
4234
|
);
|
|
4235
|
+
if (options.dryRun !== true) {
|
|
4236
|
+
const synapSyncDir2 = configManager.getSynapSyncDir();
|
|
4237
|
+
const projectRoot2 = configManager.getProjectRoot();
|
|
4238
|
+
regenerateAgentsMd(projectRoot2, synapSyncDir2);
|
|
4239
|
+
}
|
|
4001
4240
|
if (options.json === true) {
|
|
4002
4241
|
console.log(JSON.stringify(result, null, 2));
|
|
4003
4242
|
return;
|
|
@@ -4231,8 +4470,8 @@ function registerSyncCommand(program) {
|
|
|
4231
4470
|
|
|
4232
4471
|
// src/commands/update.ts
|
|
4233
4472
|
init_esm_shims();
|
|
4234
|
-
import * as
|
|
4235
|
-
import * as
|
|
4473
|
+
import * as fs12 from "fs";
|
|
4474
|
+
import * as path14 from "path";
|
|
4236
4475
|
import pc13 from "picocolors";
|
|
4237
4476
|
|
|
4238
4477
|
// src/services/maintenance/update-checker.ts
|
|
@@ -4411,18 +4650,18 @@ async function executeUpdateCommand(cognitiveName, options = {}) {
|
|
|
4411
4650
|
const downloaded = await registry.download(update.name);
|
|
4412
4651
|
const manifestEntry = installed.find((c) => c.name === update.name);
|
|
4413
4652
|
if (manifestEntry === void 0) continue;
|
|
4414
|
-
const targetDir =
|
|
4653
|
+
const targetDir = path14.join(
|
|
4415
4654
|
synapSyncDir,
|
|
4416
4655
|
`${update.type}s`,
|
|
4417
4656
|
update.category,
|
|
4418
4657
|
update.name
|
|
4419
4658
|
);
|
|
4420
4659
|
const fileName = COGNITIVE_FILE_NAMES[update.type];
|
|
4421
|
-
const filePath =
|
|
4422
|
-
if (!
|
|
4423
|
-
|
|
4660
|
+
const filePath = path14.join(targetDir, fileName);
|
|
4661
|
+
if (!fs12.existsSync(targetDir)) {
|
|
4662
|
+
fs12.mkdirSync(targetDir, { recursive: true });
|
|
4424
4663
|
}
|
|
4425
|
-
|
|
4664
|
+
fs12.writeFileSync(filePath, downloaded.content, "utf-8");
|
|
4426
4665
|
manifest.updateCognitive(update.name, {
|
|
4427
4666
|
version: update.latestVersion
|
|
4428
4667
|
});
|
|
@@ -4442,6 +4681,7 @@ async function executeUpdateCommand(cognitiveName, options = {}) {
|
|
|
4442
4681
|
const config = configManager.getConfig();
|
|
4443
4682
|
const syncEngine = new SyncEngine(synapSyncDir, projectRoot, config);
|
|
4444
4683
|
syncEngine.sync();
|
|
4684
|
+
regenerateAgentsMd(projectRoot, synapSyncDir);
|
|
4445
4685
|
logger.line();
|
|
4446
4686
|
if (updated.length > 0) {
|
|
4447
4687
|
logger.log(` ${pc13.green("\u2713")} Updated ${updated.length} cognitive(s)`);
|
|
@@ -4485,8 +4725,8 @@ import pc14 from "picocolors";
|
|
|
4485
4725
|
|
|
4486
4726
|
// src/services/maintenance/doctor.ts
|
|
4487
4727
|
init_esm_shims();
|
|
4488
|
-
import * as
|
|
4489
|
-
import * as
|
|
4728
|
+
import * as fs13 from "fs";
|
|
4729
|
+
import * as path15 from "path";
|
|
4490
4730
|
var DoctorService = class {
|
|
4491
4731
|
projectRoot;
|
|
4492
4732
|
synapSyncDir;
|
|
@@ -4581,7 +4821,7 @@ var DoctorService = class {
|
|
|
4581
4821
|
};
|
|
4582
4822
|
}
|
|
4583
4823
|
checkSynapSyncDir() {
|
|
4584
|
-
if (
|
|
4824
|
+
if (fs13.existsSync(this.synapSyncDir)) {
|
|
4585
4825
|
return {
|
|
4586
4826
|
id: "synapsync-dir",
|
|
4587
4827
|
name: ".synapsync Directory",
|
|
@@ -4601,8 +4841,8 @@ var DoctorService = class {
|
|
|
4601
4841
|
};
|
|
4602
4842
|
}
|
|
4603
4843
|
checkConfig() {
|
|
4604
|
-
const configPath =
|
|
4605
|
-
if (
|
|
4844
|
+
const configPath = path15.join(this.projectRoot, "synapsync.config.yaml");
|
|
4845
|
+
if (fs13.existsSync(configPath)) {
|
|
4606
4846
|
if (this.config !== null) {
|
|
4607
4847
|
return {
|
|
4608
4848
|
id: "config-valid",
|
|
@@ -4632,8 +4872,8 @@ var DoctorService = class {
|
|
|
4632
4872
|
};
|
|
4633
4873
|
}
|
|
4634
4874
|
checkManifest() {
|
|
4635
|
-
const manifestPath =
|
|
4636
|
-
if (!
|
|
4875
|
+
const manifestPath = path15.join(this.synapSyncDir, "manifest.json");
|
|
4876
|
+
if (!fs13.existsSync(manifestPath)) {
|
|
4637
4877
|
return {
|
|
4638
4878
|
id: "manifest-exists",
|
|
4639
4879
|
name: "Manifest File",
|
|
@@ -4644,7 +4884,7 @@ var DoctorService = class {
|
|
|
4644
4884
|
};
|
|
4645
4885
|
}
|
|
4646
4886
|
try {
|
|
4647
|
-
const content =
|
|
4887
|
+
const content = fs13.readFileSync(manifestPath, "utf-8");
|
|
4648
4888
|
JSON.parse(content);
|
|
4649
4889
|
return {
|
|
4650
4890
|
id: "manifest-exists",
|
|
@@ -4666,7 +4906,7 @@ var DoctorService = class {
|
|
|
4666
4906
|
}
|
|
4667
4907
|
}
|
|
4668
4908
|
checkManifestConsistency() {
|
|
4669
|
-
if (!
|
|
4909
|
+
if (!fs13.existsSync(this.synapSyncDir)) {
|
|
4670
4910
|
return {
|
|
4671
4911
|
id: "manifest-consistency",
|
|
4672
4912
|
name: "Manifest Consistency",
|
|
@@ -4863,13 +5103,13 @@ var DoctorService = class {
|
|
|
4863
5103
|
}
|
|
4864
5104
|
}
|
|
4865
5105
|
fixSynapSyncDir() {
|
|
4866
|
-
if (!
|
|
4867
|
-
|
|
5106
|
+
if (!fs13.existsSync(this.synapSyncDir)) {
|
|
5107
|
+
fs13.mkdirSync(this.synapSyncDir, { recursive: true });
|
|
4868
5108
|
}
|
|
4869
5109
|
for (const type of COGNITIVE_TYPES) {
|
|
4870
|
-
const typeDir =
|
|
4871
|
-
if (!
|
|
4872
|
-
|
|
5110
|
+
const typeDir = path15.join(this.synapSyncDir, `${type}s`);
|
|
5111
|
+
if (!fs13.existsSync(typeDir)) {
|
|
5112
|
+
fs13.mkdirSync(typeDir, { recursive: true });
|
|
4873
5113
|
}
|
|
4874
5114
|
}
|
|
4875
5115
|
}
|
|
@@ -5045,8 +5285,8 @@ import pc15 from "picocolors";
|
|
|
5045
5285
|
|
|
5046
5286
|
// src/services/maintenance/cleaner.ts
|
|
5047
5287
|
init_esm_shims();
|
|
5048
|
-
import * as
|
|
5049
|
-
import * as
|
|
5288
|
+
import * as fs14 from "fs";
|
|
5289
|
+
import * as path16 from "path";
|
|
5050
5290
|
var CleanerService = class {
|
|
5051
5291
|
projectRoot;
|
|
5052
5292
|
synapSyncDir;
|
|
@@ -5106,8 +5346,8 @@ var CleanerService = class {
|
|
|
5106
5346
|
const cleaned = [];
|
|
5107
5347
|
const errors = [];
|
|
5108
5348
|
let bytes = 0;
|
|
5109
|
-
const cacheDir =
|
|
5110
|
-
if (!
|
|
5349
|
+
const cacheDir = path16.join(this.synapSyncDir, "cache");
|
|
5350
|
+
if (!fs14.existsSync(cacheDir)) {
|
|
5111
5351
|
return { cleaned, bytes, errors };
|
|
5112
5352
|
}
|
|
5113
5353
|
try {
|
|
@@ -5178,14 +5418,14 @@ var CleanerService = class {
|
|
|
5178
5418
|
const errors = [];
|
|
5179
5419
|
let bytes = 0;
|
|
5180
5420
|
const tempPatterns = [
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5421
|
+
path16.join(this.synapSyncDir, ".tmp"),
|
|
5422
|
+
path16.join(this.synapSyncDir, "temp"),
|
|
5423
|
+
path16.join(this.synapSyncDir, "*.tmp"),
|
|
5424
|
+
path16.join(this.synapSyncDir, "*.temp")
|
|
5185
5425
|
];
|
|
5186
5426
|
for (const pattern of tempPatterns) {
|
|
5187
5427
|
if (!pattern.includes("*")) {
|
|
5188
|
-
if (
|
|
5428
|
+
if (fs14.existsSync(pattern)) {
|
|
5189
5429
|
const size = this.getSize(pattern);
|
|
5190
5430
|
cleaned.push({
|
|
5191
5431
|
type: "temp",
|
|
@@ -5205,14 +5445,14 @@ var CleanerService = class {
|
|
|
5205
5445
|
}
|
|
5206
5446
|
}
|
|
5207
5447
|
} else {
|
|
5208
|
-
const dir =
|
|
5209
|
-
const ext =
|
|
5210
|
-
if (
|
|
5448
|
+
const dir = path16.dirname(pattern);
|
|
5449
|
+
const ext = path16.extname(pattern);
|
|
5450
|
+
if (fs14.existsSync(dir)) {
|
|
5211
5451
|
try {
|
|
5212
|
-
const entries =
|
|
5452
|
+
const entries = fs14.readdirSync(dir);
|
|
5213
5453
|
for (const entry of entries) {
|
|
5214
5454
|
if (entry.endsWith(ext.slice(1))) {
|
|
5215
|
-
const fullPath =
|
|
5455
|
+
const fullPath = path16.join(dir, entry);
|
|
5216
5456
|
const size = this.getSize(fullPath);
|
|
5217
5457
|
cleaned.push({
|
|
5218
5458
|
type: "temp",
|
|
@@ -5248,9 +5488,9 @@ var CleanerService = class {
|
|
|
5248
5488
|
*/
|
|
5249
5489
|
listDirectory(dir) {
|
|
5250
5490
|
const items = [];
|
|
5251
|
-
const entries =
|
|
5491
|
+
const entries = fs14.readdirSync(dir, { withFileTypes: true });
|
|
5252
5492
|
for (const entry of entries) {
|
|
5253
|
-
const fullPath =
|
|
5493
|
+
const fullPath = path16.join(dir, entry.name);
|
|
5254
5494
|
items.push(fullPath);
|
|
5255
5495
|
if (entry.isDirectory()) {
|
|
5256
5496
|
items.push(...this.listDirectory(fullPath));
|
|
@@ -5263,15 +5503,15 @@ var CleanerService = class {
|
|
|
5263
5503
|
*/
|
|
5264
5504
|
getSize(itemPath) {
|
|
5265
5505
|
try {
|
|
5266
|
-
const stats =
|
|
5506
|
+
const stats = fs14.statSync(itemPath);
|
|
5267
5507
|
if (stats.isFile()) {
|
|
5268
5508
|
return stats.size;
|
|
5269
5509
|
}
|
|
5270
5510
|
if (stats.isDirectory()) {
|
|
5271
5511
|
let size = 0;
|
|
5272
|
-
const entries =
|
|
5512
|
+
const entries = fs14.readdirSync(itemPath, { withFileTypes: true });
|
|
5273
5513
|
for (const entry of entries) {
|
|
5274
|
-
size += this.getSize(
|
|
5514
|
+
size += this.getSize(path16.join(itemPath, entry.name));
|
|
5275
5515
|
}
|
|
5276
5516
|
return size;
|
|
5277
5517
|
}
|
|
@@ -5284,11 +5524,11 @@ var CleanerService = class {
|
|
|
5284
5524
|
* Remove a file or directory
|
|
5285
5525
|
*/
|
|
5286
5526
|
removeItem(itemPath) {
|
|
5287
|
-
const stats =
|
|
5527
|
+
const stats = fs14.lstatSync(itemPath);
|
|
5288
5528
|
if (stats.isSymbolicLink() || stats.isFile()) {
|
|
5289
|
-
|
|
5529
|
+
fs14.unlinkSync(itemPath);
|
|
5290
5530
|
} else if (stats.isDirectory()) {
|
|
5291
|
-
|
|
5531
|
+
fs14.rmSync(itemPath, { recursive: true });
|
|
5292
5532
|
}
|
|
5293
5533
|
}
|
|
5294
5534
|
/**
|
|
@@ -5421,8 +5661,8 @@ function registerCleanCommand(program) {
|
|
|
5421
5661
|
|
|
5422
5662
|
// src/commands/purge.ts
|
|
5423
5663
|
init_esm_shims();
|
|
5424
|
-
import * as
|
|
5425
|
-
import * as
|
|
5664
|
+
import * as fs15 from "fs";
|
|
5665
|
+
import * as path17 from "path";
|
|
5426
5666
|
import pc16 from "picocolors";
|
|
5427
5667
|
function executePurgeCommand(options) {
|
|
5428
5668
|
logger.line();
|
|
@@ -5448,17 +5688,23 @@ function executePurgeCommand(options) {
|
|
|
5448
5688
|
let removedCount = 0;
|
|
5449
5689
|
try {
|
|
5450
5690
|
removedCount += removeProviderSymlinks(projectRoot, synapSyncDir);
|
|
5451
|
-
if (
|
|
5452
|
-
|
|
5453
|
-
logger.log(` ${pc16.red("\u2717")} Removed ${
|
|
5691
|
+
if (fs15.existsSync(synapSyncDir)) {
|
|
5692
|
+
fs15.rmSync(synapSyncDir, { recursive: true, force: true });
|
|
5693
|
+
logger.log(` ${pc16.red("\u2717")} Removed ${path17.relative(projectRoot, synapSyncDir)}/`);
|
|
5454
5694
|
removedCount++;
|
|
5455
5695
|
}
|
|
5456
|
-
const configPath =
|
|
5457
|
-
if (
|
|
5458
|
-
|
|
5696
|
+
const configPath = path17.join(projectRoot, "synapsync.config.yaml");
|
|
5697
|
+
if (fs15.existsSync(configPath)) {
|
|
5698
|
+
fs15.unlinkSync(configPath);
|
|
5459
5699
|
logger.log(` ${pc16.red("\u2717")} Removed synapsync.config.yaml`);
|
|
5460
5700
|
removedCount++;
|
|
5461
5701
|
}
|
|
5702
|
+
const agentsMdPath = path17.join(projectRoot, AGENTS_MD_FILE_NAME);
|
|
5703
|
+
if (fs15.existsSync(agentsMdPath)) {
|
|
5704
|
+
fs15.unlinkSync(agentsMdPath);
|
|
5705
|
+
logger.log(` ${pc16.red("\u2717")} Removed ${AGENTS_MD_FILE_NAME}`);
|
|
5706
|
+
removedCount++;
|
|
5707
|
+
}
|
|
5462
5708
|
if (cleanGitignore(projectRoot)) {
|
|
5463
5709
|
logger.log(` ${pc16.red("\u2717")} Cleaned SynapSync entries from .gitignore`);
|
|
5464
5710
|
removedCount++;
|
|
@@ -5483,18 +5729,22 @@ function collectItemsToRemove(projectRoot, synapSyncDir) {
|
|
|
5483
5729
|
const items = [];
|
|
5484
5730
|
const symlinks = findSynapSyncSymlinks(projectRoot, synapSyncDir);
|
|
5485
5731
|
for (const link of symlinks) {
|
|
5486
|
-
items.push(`${
|
|
5732
|
+
items.push(`${path17.relative(projectRoot, link)} (symlink)`);
|
|
5487
5733
|
}
|
|
5488
|
-
if (
|
|
5489
|
-
items.push(
|
|
5734
|
+
if (fs15.existsSync(synapSyncDir)) {
|
|
5735
|
+
items.push(path17.relative(projectRoot, synapSyncDir) + "/");
|
|
5490
5736
|
}
|
|
5491
|
-
const configPath =
|
|
5492
|
-
if (
|
|
5737
|
+
const configPath = path17.join(projectRoot, "synapsync.config.yaml");
|
|
5738
|
+
if (fs15.existsSync(configPath)) {
|
|
5493
5739
|
items.push("synapsync.config.yaml");
|
|
5494
5740
|
}
|
|
5495
|
-
const
|
|
5496
|
-
if (
|
|
5497
|
-
|
|
5741
|
+
const agentsMdPath = path17.join(projectRoot, AGENTS_MD_FILE_NAME);
|
|
5742
|
+
if (fs15.existsSync(agentsMdPath)) {
|
|
5743
|
+
items.push(AGENTS_MD_FILE_NAME);
|
|
5744
|
+
}
|
|
5745
|
+
const gitignorePath = path17.join(projectRoot, ".gitignore");
|
|
5746
|
+
if (fs15.existsSync(gitignorePath)) {
|
|
5747
|
+
const content = fs15.readFileSync(gitignorePath, "utf-8");
|
|
5498
5748
|
if (content.includes("# SynapSync")) {
|
|
5499
5749
|
items.push(".gitignore (SynapSync entries)");
|
|
5500
5750
|
}
|
|
@@ -5503,18 +5753,18 @@ function collectItemsToRemove(projectRoot, synapSyncDir) {
|
|
|
5503
5753
|
}
|
|
5504
5754
|
function findSynapSyncSymlinks(projectRoot, synapSyncDir) {
|
|
5505
5755
|
const symlinks = [];
|
|
5506
|
-
const resolvedSynapSync =
|
|
5756
|
+
const resolvedSynapSync = path17.resolve(synapSyncDir);
|
|
5507
5757
|
for (const provider of SUPPORTED_PROVIDERS) {
|
|
5508
5758
|
const providerPaths = PROVIDER_PATHS[provider];
|
|
5509
5759
|
for (const type of COGNITIVE_TYPES) {
|
|
5510
|
-
const typePath =
|
|
5511
|
-
if (!
|
|
5760
|
+
const typePath = path17.join(projectRoot, providerPaths[type]);
|
|
5761
|
+
if (!fs15.existsSync(typePath)) continue;
|
|
5512
5762
|
try {
|
|
5513
|
-
const entries =
|
|
5763
|
+
const entries = fs15.readdirSync(typePath, { withFileTypes: true });
|
|
5514
5764
|
for (const entry of entries) {
|
|
5515
|
-
const fullPath =
|
|
5765
|
+
const fullPath = path17.join(typePath, entry.name);
|
|
5516
5766
|
if (entry.isSymbolicLink()) {
|
|
5517
|
-
const target =
|
|
5767
|
+
const target = path17.resolve(typePath, fs15.readlinkSync(fullPath));
|
|
5518
5768
|
if (target.startsWith(resolvedSynapSync)) {
|
|
5519
5769
|
symlinks.push(fullPath);
|
|
5520
5770
|
}
|
|
@@ -5529,21 +5779,21 @@ function findSynapSyncSymlinks(projectRoot, synapSyncDir) {
|
|
|
5529
5779
|
function removeProviderSymlinks(projectRoot, synapSyncDir) {
|
|
5530
5780
|
const symlinks = findSynapSyncSymlinks(projectRoot, synapSyncDir);
|
|
5531
5781
|
for (const link of symlinks) {
|
|
5532
|
-
|
|
5533
|
-
logger.log(` ${pc16.red("\u2717")} Removed symlink ${
|
|
5782
|
+
fs15.unlinkSync(link);
|
|
5783
|
+
logger.log(` ${pc16.red("\u2717")} Removed symlink ${path17.relative(projectRoot, link)}`);
|
|
5534
5784
|
}
|
|
5535
5785
|
return symlinks.length;
|
|
5536
5786
|
}
|
|
5537
5787
|
function cleanGitignore(projectRoot) {
|
|
5538
|
-
const gitignorePath =
|
|
5539
|
-
if (!
|
|
5540
|
-
const content =
|
|
5788
|
+
const gitignorePath = path17.join(projectRoot, ".gitignore");
|
|
5789
|
+
if (!fs15.existsSync(gitignorePath)) return false;
|
|
5790
|
+
const content = fs15.readFileSync(gitignorePath, "utf-8");
|
|
5541
5791
|
if (!content.includes("# SynapSync")) return false;
|
|
5542
5792
|
const cleaned = content.replace(/\n?# SynapSync\n\.synapsync\/manifest\.json\n\*\.local\.yaml\n?/g, "").replace(/^\s*\n$/gm, "\n");
|
|
5543
5793
|
if (cleaned.trim() === "") {
|
|
5544
|
-
|
|
5794
|
+
fs15.unlinkSync(gitignorePath);
|
|
5545
5795
|
} else {
|
|
5546
|
-
|
|
5796
|
+
fs15.writeFileSync(gitignorePath, cleaned, "utf-8");
|
|
5547
5797
|
}
|
|
5548
5798
|
return true;
|
|
5549
5799
|
}
|