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