skema-core 0.2.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -3
- package/dist/cli.js +896 -63
- package/dist/index.d.mts +37 -7
- package/dist/index.d.ts +37 -7
- package/dist/index.js +739 -136
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +740 -137
- package/dist/index.mjs.map +1 -1
- package/dist/mcp.js +413 -0
- package/dist/server.d.mts +107 -31
- package/dist/server.d.ts +107 -31
- package/dist/server.js +451 -42
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +430 -32
- package/dist/server.mjs.map +1 -1
- package/package.json +11 -4
package/dist/server.mjs
CHANGED
|
@@ -22,7 +22,7 @@ function getGridCellReference(x, y, gridSize = 100) {
|
|
|
22
22
|
// src/server/prompts.ts
|
|
23
23
|
var CRITICAL_RULES = `CRITICAL RULES:
|
|
24
24
|
- Do NOT create new files. Only edit existing files.
|
|
25
|
-
- Do NOT modify the import
|
|
25
|
+
- Do NOT modify the Skema overlay component import or the SkemaOverlay component itself.
|
|
26
26
|
- Ensure all JSX tags are properly closed - every <tag> needs a matching </tag>.
|
|
27
27
|
- Do NOT run any shell commands. No npm, no git, no lint, no build commands. Just edit files.
|
|
28
28
|
- STOP immediately after making the file changes. Do not verify, do not run tests, do not check status.`;
|
|
@@ -161,7 +161,7 @@ var DRAWING_IMPLEMENTATION_GUIDELINES = `- **CRITICAL: DO NOT CREATE ANY NEW FIL
|
|
|
161
161
|
var DRAWING_ERROR_PREVENTION_RULES = `1. **NEVER CREATE NEW FILES** - Do NOT create new component files, utility files, or any other files. Write everything inline in the existing file
|
|
162
162
|
2. You do not need to update package.json or anything, just add / edit the react component.
|
|
163
163
|
3. Do NOT add import statements in the middle of the file or inside JSX - imports go ONLY at the top
|
|
164
|
-
4. Do NOT modify the
|
|
164
|
+
4. Do NOT modify the Skema overlay component import or the SkemaOverlay component itself
|
|
165
165
|
5. If you need something that requires an import and it's not already imported, either use an alternative that doesn't need an import, or add the import at the very TOP of the file with the other imports
|
|
166
166
|
6. DONT MAKE ANY CHANGES THAT WOULD RESULT IN A Build Error
|
|
167
167
|
7. **JSX SYNTAX VALIDATION** - ALWAYS ensure every JSX tag is properly closed. Every opening tag like <div>, <a>, <span>, <button> MUST have a matching closing tag </div>, </a>, </span>, </button>. Self-closing tags like <img />, <input />, <br /> must end with />. Before finishing, mentally verify all tag pairs are balanced.`;
|
|
@@ -836,6 +836,50 @@ function isProviderAvailable(provider) {
|
|
|
836
836
|
function getAvailableProviders() {
|
|
837
837
|
return ["gemini", "claude"].filter(isProviderAvailable);
|
|
838
838
|
}
|
|
839
|
+
function checkProviderAuthorized(provider) {
|
|
840
|
+
const { execSync: execSync3 } = __require("child_process");
|
|
841
|
+
try {
|
|
842
|
+
if (provider === "gemini") {
|
|
843
|
+
execSync3("gemini --version", { stdio: "ignore", timeout: 5e3 });
|
|
844
|
+
return true;
|
|
845
|
+
} else if (provider === "claude") {
|
|
846
|
+
execSync3("claude --version", { stdio: "ignore", timeout: 5e3 });
|
|
847
|
+
return true;
|
|
848
|
+
}
|
|
849
|
+
return false;
|
|
850
|
+
} catch {
|
|
851
|
+
return false;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
function getProviderStatus(provider) {
|
|
855
|
+
const installed = isProviderAvailable(provider);
|
|
856
|
+
if (!installed) {
|
|
857
|
+
return {
|
|
858
|
+
installed: false,
|
|
859
|
+
authorized: false,
|
|
860
|
+
message: `${provider} CLI not installed`
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
const authorized = checkProviderAuthorized(provider);
|
|
864
|
+
if (!authorized) {
|
|
865
|
+
return {
|
|
866
|
+
installed: true,
|
|
867
|
+
authorized: false,
|
|
868
|
+
message: `${provider} CLI installed but not authorized`
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
return {
|
|
872
|
+
installed: true,
|
|
873
|
+
authorized: true,
|
|
874
|
+
message: "Ready"
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
function getAllProviderStatuses() {
|
|
878
|
+
return {
|
|
879
|
+
gemini: getProviderStatus("gemini"),
|
|
880
|
+
claude: getProviderStatus("claude")
|
|
881
|
+
};
|
|
882
|
+
}
|
|
839
883
|
async function analyzeWithGemini(base64Image, apiKey, model = "gemini-2.5-flash") {
|
|
840
884
|
try {
|
|
841
885
|
const genAI = new GoogleGenerativeAI(apiKey);
|
|
@@ -943,10 +987,108 @@ function isVisionAvailable(provider) {
|
|
|
943
987
|
}
|
|
944
988
|
}
|
|
945
989
|
|
|
990
|
+
// src/server/annotation-store.ts
|
|
991
|
+
var storedAnnotations = /* @__PURE__ */ new Map();
|
|
992
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
993
|
+
function notify(event, annotation) {
|
|
994
|
+
for (const listener of listeners) {
|
|
995
|
+
try {
|
|
996
|
+
listener(event, annotation);
|
|
997
|
+
} catch (e) {
|
|
998
|
+
console.error("[AnnotationStore] Listener error:", e);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
function queueAnnotation(annotation, comment) {
|
|
1003
|
+
const id = annotation.id || `ann-${Date.now()}`;
|
|
1004
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1005
|
+
const stored = {
|
|
1006
|
+
annotation: { ...annotation, id },
|
|
1007
|
+
comment,
|
|
1008
|
+
status: "pending",
|
|
1009
|
+
createdAt: now,
|
|
1010
|
+
updatedAt: now
|
|
1011
|
+
};
|
|
1012
|
+
storedAnnotations.set(id, stored);
|
|
1013
|
+
console.log(`[AnnotationStore] Queued annotation ${id}: "${comment.slice(0, 50)}..."`);
|
|
1014
|
+
notify("annotation.created", stored);
|
|
1015
|
+
return stored;
|
|
1016
|
+
}
|
|
1017
|
+
function getPendingAnnotations() {
|
|
1018
|
+
return Array.from(storedAnnotations.values()).filter((a) => a.status === "pending");
|
|
1019
|
+
}
|
|
1020
|
+
function getAllAnnotations() {
|
|
1021
|
+
return Array.from(storedAnnotations.values());
|
|
1022
|
+
}
|
|
1023
|
+
function getAnnotation(id) {
|
|
1024
|
+
return storedAnnotations.get(id);
|
|
1025
|
+
}
|
|
1026
|
+
function acknowledgeAnnotation(id) {
|
|
1027
|
+
const stored = storedAnnotations.get(id);
|
|
1028
|
+
if (!stored) return void 0;
|
|
1029
|
+
stored.status = "acknowledged";
|
|
1030
|
+
stored.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1031
|
+
notify("annotation.updated", stored);
|
|
1032
|
+
return stored;
|
|
1033
|
+
}
|
|
1034
|
+
function resolveAnnotation(id, summary) {
|
|
1035
|
+
const stored = storedAnnotations.get(id);
|
|
1036
|
+
if (!stored) return void 0;
|
|
1037
|
+
stored.status = "resolved";
|
|
1038
|
+
stored.resolvedBy = "agent";
|
|
1039
|
+
stored.resolutionSummary = summary;
|
|
1040
|
+
stored.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1041
|
+
notify("annotation.updated", stored);
|
|
1042
|
+
return stored;
|
|
1043
|
+
}
|
|
1044
|
+
function dismissAnnotation(id, reason) {
|
|
1045
|
+
const stored = storedAnnotations.get(id);
|
|
1046
|
+
if (!stored) return void 0;
|
|
1047
|
+
stored.status = "dismissed";
|
|
1048
|
+
stored.resolvedBy = "agent";
|
|
1049
|
+
stored.dismissalReason = reason;
|
|
1050
|
+
stored.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1051
|
+
notify("annotation.updated", stored);
|
|
1052
|
+
return stored;
|
|
1053
|
+
}
|
|
1054
|
+
function removeAnnotation(id) {
|
|
1055
|
+
const stored = storedAnnotations.get(id);
|
|
1056
|
+
if (!stored) return void 0;
|
|
1057
|
+
storedAnnotations.delete(id);
|
|
1058
|
+
notify("annotation.deleted", stored);
|
|
1059
|
+
return stored;
|
|
1060
|
+
}
|
|
1061
|
+
function clearAnnotations() {
|
|
1062
|
+
storedAnnotations.clear();
|
|
1063
|
+
}
|
|
1064
|
+
function onStoreEvent(listener) {
|
|
1065
|
+
listeners.add(listener);
|
|
1066
|
+
return () => listeners.delete(listener);
|
|
1067
|
+
}
|
|
1068
|
+
function getPendingCount() {
|
|
1069
|
+
let count = 0;
|
|
1070
|
+
for (const a of storedAnnotations.values()) {
|
|
1071
|
+
if (a.status === "pending") count++;
|
|
1072
|
+
}
|
|
1073
|
+
return count;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
946
1076
|
// src/server/daemon.ts
|
|
947
1077
|
var currentProvider = "gemini";
|
|
948
1078
|
var workingDirectory = process.cwd();
|
|
1079
|
+
var currentMode = "direct-cli";
|
|
949
1080
|
var annotationSnapshots2 = /* @__PURE__ */ new Map();
|
|
1081
|
+
var mcpServerClient = null;
|
|
1082
|
+
var mcpClientName = null;
|
|
1083
|
+
function getAnnotationCounts() {
|
|
1084
|
+
const all = getAllAnnotations();
|
|
1085
|
+
return {
|
|
1086
|
+
pending: all.filter((a) => a.status === "pending").length,
|
|
1087
|
+
acknowledged: all.filter((a) => a.status === "acknowledged").length,
|
|
1088
|
+
resolved: all.filter((a) => a.status === "resolved").length,
|
|
1089
|
+
dismissed: all.filter((a) => a.status === "dismissed").length
|
|
1090
|
+
};
|
|
1091
|
+
}
|
|
950
1092
|
function createSnapshot2(annotationId) {
|
|
951
1093
|
try {
|
|
952
1094
|
const stashRef = execSync("git stash create", { cwd: workingDirectory, encoding: "utf-8" }).trim();
|
|
@@ -1006,17 +1148,45 @@ var handlers = {
|
|
|
1006
1148
|
if (!["gemini", "claude"].includes(newProvider)) {
|
|
1007
1149
|
return { id: msg.id, type: "error", error: `Invalid provider: ${newProvider}` };
|
|
1008
1150
|
}
|
|
1009
|
-
if (!isProviderAvailable(newProvider)) {
|
|
1151
|
+
if (currentMode === "direct-cli" && !isProviderAvailable(newProvider)) {
|
|
1010
1152
|
return {
|
|
1011
1153
|
id: msg.id,
|
|
1012
1154
|
type: "error",
|
|
1013
|
-
error: `Provider "${newProvider}" is not installed
|
|
1155
|
+
error: `Provider "${newProvider}" CLI is not installed.`
|
|
1014
1156
|
};
|
|
1015
1157
|
}
|
|
1016
1158
|
currentProvider = newProvider;
|
|
1017
1159
|
console.log(`[Daemon] Switched to provider: ${currentProvider}`);
|
|
1018
1160
|
return { id: msg.id, type: "provider-changed", provider: currentProvider };
|
|
1019
1161
|
},
|
|
1162
|
+
"check-providers": async (msg) => {
|
|
1163
|
+
const statuses = getAllProviderStatuses();
|
|
1164
|
+
return {
|
|
1165
|
+
id: msg.id,
|
|
1166
|
+
type: "provider-statuses",
|
|
1167
|
+
providerStatus: statuses
|
|
1168
|
+
};
|
|
1169
|
+
},
|
|
1170
|
+
// -------------------------------------------------------------------------
|
|
1171
|
+
// Mode Management
|
|
1172
|
+
// -------------------------------------------------------------------------
|
|
1173
|
+
"get-mode": async (msg) => {
|
|
1174
|
+
return {
|
|
1175
|
+
id: msg.id,
|
|
1176
|
+
type: "mode",
|
|
1177
|
+
mode: currentMode,
|
|
1178
|
+
availableModes: ["direct-cli", "mcp"]
|
|
1179
|
+
};
|
|
1180
|
+
},
|
|
1181
|
+
"set-mode": async (msg) => {
|
|
1182
|
+
const newMode = msg.mode;
|
|
1183
|
+
if (!["direct-cli", "mcp"].includes(newMode)) {
|
|
1184
|
+
return { id: msg.id, type: "error", error: `Invalid mode: ${newMode}` };
|
|
1185
|
+
}
|
|
1186
|
+
currentMode = newMode;
|
|
1187
|
+
console.log(`[Daemon] Switched to mode: ${currentMode}`);
|
|
1188
|
+
return { id: msg.id, type: "mode-changed", mode: currentMode };
|
|
1189
|
+
},
|
|
1020
1190
|
// -------------------------------------------------------------------------
|
|
1021
1191
|
// AI Generation (streaming)
|
|
1022
1192
|
// -------------------------------------------------------------------------
|
|
@@ -1024,21 +1194,41 @@ var handlers = {
|
|
|
1024
1194
|
const annotation = msg.annotation;
|
|
1025
1195
|
const projectContext = msg.projectContext;
|
|
1026
1196
|
const annotationId = annotation.id || `temp-${Date.now()}`;
|
|
1197
|
+
const requestMode = msg.mode || currentMode;
|
|
1198
|
+
const requestProvider = msg.provider || currentProvider;
|
|
1199
|
+
if (requestMode === "mcp") {
|
|
1200
|
+
const comment = annotation.comment || "";
|
|
1201
|
+
const stored = queueAnnotation(annotation, comment);
|
|
1202
|
+
const counts = getAnnotationCounts();
|
|
1203
|
+
sendMessage(ws, {
|
|
1204
|
+
id: msg.id,
|
|
1205
|
+
type: "annotation-queued",
|
|
1206
|
+
success: true,
|
|
1207
|
+
annotationId: stored.annotation.id,
|
|
1208
|
+
pendingCount: getPendingCount(),
|
|
1209
|
+
annotationCounts: counts
|
|
1210
|
+
});
|
|
1211
|
+
broadcastToClients({
|
|
1212
|
+
type: "mcp-annotation-counts",
|
|
1213
|
+
counts
|
|
1214
|
+
});
|
|
1215
|
+
return;
|
|
1216
|
+
}
|
|
1027
1217
|
createSnapshot2(annotationId);
|
|
1028
1218
|
let visionDescription = "";
|
|
1029
1219
|
const drawingAnnotation = annotation;
|
|
1030
1220
|
if (annotation.type === "drawing" && drawingAnnotation.drawingImage) {
|
|
1221
|
+
sendMessage(ws, {
|
|
1222
|
+
id: msg.id,
|
|
1223
|
+
type: "ai-event",
|
|
1224
|
+
event: {
|
|
1225
|
+
type: "text",
|
|
1226
|
+
content: `[Analyzing drawing with vision...]`,
|
|
1227
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1228
|
+
provider: requestProvider
|
|
1229
|
+
}
|
|
1230
|
+
});
|
|
1031
1231
|
if (isVisionAvailable("gemini")) {
|
|
1032
|
-
sendMessage(ws, {
|
|
1033
|
-
id: msg.id,
|
|
1034
|
-
type: "ai-event",
|
|
1035
|
-
event: {
|
|
1036
|
-
type: "text",
|
|
1037
|
-
content: `[Analyzing drawing with Gemini vision...]`,
|
|
1038
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1039
|
-
provider: currentProvider
|
|
1040
|
-
}
|
|
1041
|
-
});
|
|
1042
1232
|
const visionResult = await analyzeImage(drawingAnnotation.drawingImage, {
|
|
1043
1233
|
provider: "gemini"
|
|
1044
1234
|
});
|
|
@@ -1052,7 +1242,7 @@ var handlers = {
|
|
|
1052
1242
|
content: `[Vision analysis complete]
|
|
1053
1243
|
${visionDescription}`,
|
|
1054
1244
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1055
|
-
provider:
|
|
1245
|
+
provider: requestProvider
|
|
1056
1246
|
}
|
|
1057
1247
|
});
|
|
1058
1248
|
} else {
|
|
@@ -1063,7 +1253,7 @@ ${visionDescription}`,
|
|
|
1063
1253
|
type: "error",
|
|
1064
1254
|
content: `Vision analysis failed: ${visionResult.error}`,
|
|
1065
1255
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1066
|
-
provider:
|
|
1256
|
+
provider: requestProvider
|
|
1067
1257
|
}
|
|
1068
1258
|
});
|
|
1069
1259
|
}
|
|
@@ -1075,14 +1265,13 @@ ${visionDescription}`,
|
|
|
1075
1265
|
type: "text",
|
|
1076
1266
|
content: `[Vision not available - set GEMINI_API_KEY for image analysis]`,
|
|
1077
1267
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1078
|
-
provider:
|
|
1268
|
+
provider: requestProvider
|
|
1079
1269
|
}
|
|
1080
1270
|
});
|
|
1081
1271
|
}
|
|
1082
1272
|
}
|
|
1083
1273
|
const prompt = buildPromptFromAnnotation(annotation, projectContext, {
|
|
1084
1274
|
fastMode: msg.fastMode === true,
|
|
1085
|
-
// Default to detailed mode (false) unless explicitly set to true
|
|
1086
1275
|
visionDescription
|
|
1087
1276
|
});
|
|
1088
1277
|
sendMessage(ws, {
|
|
@@ -1092,11 +1281,25 @@ ${visionDescription}`,
|
|
|
1092
1281
|
type: "debug",
|
|
1093
1282
|
content: prompt,
|
|
1094
1283
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1095
|
-
provider:
|
|
1284
|
+
provider: requestProvider
|
|
1096
1285
|
}
|
|
1097
1286
|
});
|
|
1287
|
+
const cliProvider = requestProvider;
|
|
1288
|
+
if (!isProviderAvailable(cliProvider)) {
|
|
1289
|
+
sendMessage(ws, {
|
|
1290
|
+
id: msg.id,
|
|
1291
|
+
type: "ai-event",
|
|
1292
|
+
event: {
|
|
1293
|
+
type: "error",
|
|
1294
|
+
content: `${requestProvider} CLI is not installed. Run: npm install -g @google/gemini-cli`,
|
|
1295
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1296
|
+
provider: requestProvider
|
|
1297
|
+
}
|
|
1298
|
+
});
|
|
1299
|
+
return;
|
|
1300
|
+
}
|
|
1098
1301
|
const config = {
|
|
1099
|
-
provider:
|
|
1302
|
+
provider: cliProvider,
|
|
1100
1303
|
cwd: workingDirectory,
|
|
1101
1304
|
model: msg.model
|
|
1102
1305
|
};
|
|
@@ -1114,7 +1317,8 @@ ${visionDescription}`,
|
|
|
1114
1317
|
type: "generate-complete",
|
|
1115
1318
|
success: true,
|
|
1116
1319
|
annotationId,
|
|
1117
|
-
provider:
|
|
1320
|
+
provider: requestProvider,
|
|
1321
|
+
mode: requestMode
|
|
1118
1322
|
});
|
|
1119
1323
|
break;
|
|
1120
1324
|
}
|
|
@@ -1132,6 +1336,109 @@ ${visionDescription}`,
|
|
|
1132
1336
|
return { id: msg.id, type: "revert-result", ...result };
|
|
1133
1337
|
},
|
|
1134
1338
|
// -------------------------------------------------------------------------
|
|
1339
|
+
// MCP Annotation Queue Management
|
|
1340
|
+
// -------------------------------------------------------------------------
|
|
1341
|
+
"get-pending-annotations": async (msg) => {
|
|
1342
|
+
const pending = getPendingAnnotations();
|
|
1343
|
+
return {
|
|
1344
|
+
id: msg.id,
|
|
1345
|
+
type: "pending-annotations",
|
|
1346
|
+
count: pending.length,
|
|
1347
|
+
annotations: pending.map(serializeStoredAnnotation)
|
|
1348
|
+
};
|
|
1349
|
+
},
|
|
1350
|
+
"get-all-annotations": async (msg) => {
|
|
1351
|
+
const all = getAllAnnotations();
|
|
1352
|
+
return {
|
|
1353
|
+
id: msg.id,
|
|
1354
|
+
type: "all-annotations",
|
|
1355
|
+
count: all.length,
|
|
1356
|
+
annotations: all.map(serializeStoredAnnotation)
|
|
1357
|
+
};
|
|
1358
|
+
},
|
|
1359
|
+
"get-annotation": async (msg) => {
|
|
1360
|
+
const id = msg.annotationId;
|
|
1361
|
+
const stored = getAnnotation(id);
|
|
1362
|
+
if (!stored) {
|
|
1363
|
+
return { id: msg.id, type: "error", error: `Annotation not found: ${id}` };
|
|
1364
|
+
}
|
|
1365
|
+
return {
|
|
1366
|
+
id: msg.id,
|
|
1367
|
+
type: "annotation",
|
|
1368
|
+
annotation: serializeStoredAnnotation(stored)
|
|
1369
|
+
};
|
|
1370
|
+
},
|
|
1371
|
+
"acknowledge-annotation": async (msg) => {
|
|
1372
|
+
const id = msg.annotationId;
|
|
1373
|
+
const stored = acknowledgeAnnotation(id);
|
|
1374
|
+
if (!stored) {
|
|
1375
|
+
return { id: msg.id, type: "error", error: `Annotation not found: ${id}` };
|
|
1376
|
+
}
|
|
1377
|
+
const counts = getAnnotationCounts();
|
|
1378
|
+
broadcastToClients({
|
|
1379
|
+
type: "annotation-status-changed",
|
|
1380
|
+
annotationId: id,
|
|
1381
|
+
status: "acknowledged"
|
|
1382
|
+
});
|
|
1383
|
+
broadcastToClients({ type: "mcp-annotation-counts", counts });
|
|
1384
|
+
return {
|
|
1385
|
+
id: msg.id,
|
|
1386
|
+
type: "annotation-acknowledged",
|
|
1387
|
+
annotationId: id
|
|
1388
|
+
};
|
|
1389
|
+
},
|
|
1390
|
+
"resolve-annotation": async (msg) => {
|
|
1391
|
+
const id = msg.annotationId;
|
|
1392
|
+
const summary = msg.summary;
|
|
1393
|
+
const stored = resolveAnnotation(id, summary);
|
|
1394
|
+
if (!stored) {
|
|
1395
|
+
return { id: msg.id, type: "error", error: `Annotation not found: ${id}` };
|
|
1396
|
+
}
|
|
1397
|
+
const counts = getAnnotationCounts();
|
|
1398
|
+
broadcastToClients({
|
|
1399
|
+
type: "annotation-status-changed",
|
|
1400
|
+
annotationId: id,
|
|
1401
|
+
status: "resolved",
|
|
1402
|
+
summary
|
|
1403
|
+
});
|
|
1404
|
+
broadcastToClients({ type: "mcp-annotation-counts", counts });
|
|
1405
|
+
return {
|
|
1406
|
+
id: msg.id,
|
|
1407
|
+
type: "annotation-resolved",
|
|
1408
|
+
annotationId: id,
|
|
1409
|
+
summary
|
|
1410
|
+
};
|
|
1411
|
+
},
|
|
1412
|
+
"dismiss-annotation": async (msg) => {
|
|
1413
|
+
const id = msg.annotationId;
|
|
1414
|
+
const reason = msg.reason;
|
|
1415
|
+
const stored = dismissAnnotation(id, reason);
|
|
1416
|
+
if (!stored) {
|
|
1417
|
+
return { id: msg.id, type: "error", error: `Annotation not found: ${id}` };
|
|
1418
|
+
}
|
|
1419
|
+
const counts = getAnnotationCounts();
|
|
1420
|
+
broadcastToClients({
|
|
1421
|
+
type: "annotation-status-changed",
|
|
1422
|
+
annotationId: id,
|
|
1423
|
+
status: "dismissed",
|
|
1424
|
+
reason
|
|
1425
|
+
});
|
|
1426
|
+
broadcastToClients({ type: "mcp-annotation-counts", counts });
|
|
1427
|
+
return {
|
|
1428
|
+
id: msg.id,
|
|
1429
|
+
type: "annotation-dismissed",
|
|
1430
|
+
annotationId: id,
|
|
1431
|
+
reason
|
|
1432
|
+
};
|
|
1433
|
+
},
|
|
1434
|
+
"clear-queued-annotations": async (msg) => {
|
|
1435
|
+
clearAnnotations();
|
|
1436
|
+
return {
|
|
1437
|
+
id: msg.id,
|
|
1438
|
+
type: "annotations-cleared"
|
|
1439
|
+
};
|
|
1440
|
+
},
|
|
1441
|
+
// -------------------------------------------------------------------------
|
|
1135
1442
|
// File Operations
|
|
1136
1443
|
// -------------------------------------------------------------------------
|
|
1137
1444
|
"read-file": async (msg) => {
|
|
@@ -1193,6 +1500,33 @@ ${visionDescription}`,
|
|
|
1193
1500
|
});
|
|
1194
1501
|
},
|
|
1195
1502
|
// -------------------------------------------------------------------------
|
|
1503
|
+
// MCP Server Identification
|
|
1504
|
+
// -------------------------------------------------------------------------
|
|
1505
|
+
identify: async (msg, ws) => {
|
|
1506
|
+
if (msg.client === "mcp-server") {
|
|
1507
|
+
mcpServerClient = ws;
|
|
1508
|
+
mcpClientName = null;
|
|
1509
|
+
console.log("[Daemon] MCP server identified and connected");
|
|
1510
|
+
broadcastToClients({
|
|
1511
|
+
type: "mcp-server-status",
|
|
1512
|
+
connected: true,
|
|
1513
|
+
clientName: null
|
|
1514
|
+
});
|
|
1515
|
+
return { id: msg.id, type: "identified", client: "mcp-server" };
|
|
1516
|
+
}
|
|
1517
|
+
return { id: msg.id, type: "identified", client: "unknown" };
|
|
1518
|
+
},
|
|
1519
|
+
"mcp-client-info": async (msg) => {
|
|
1520
|
+
mcpClientName = msg.clientName || null;
|
|
1521
|
+
console.log("[Daemon] MCP client identified:", mcpClientName, msg.clientVersion || "");
|
|
1522
|
+
broadcastToClients({
|
|
1523
|
+
type: "mcp-server-status",
|
|
1524
|
+
connected: true,
|
|
1525
|
+
clientName: mcpClientName
|
|
1526
|
+
});
|
|
1527
|
+
return { id: msg.id, type: "ok" };
|
|
1528
|
+
},
|
|
1529
|
+
// -------------------------------------------------------------------------
|
|
1196
1530
|
// Status
|
|
1197
1531
|
// -------------------------------------------------------------------------
|
|
1198
1532
|
ping: async (msg) => {
|
|
@@ -1200,11 +1534,51 @@ ${visionDescription}`,
|
|
|
1200
1534
|
id: msg.id,
|
|
1201
1535
|
type: "pong",
|
|
1202
1536
|
provider: currentProvider,
|
|
1537
|
+
mode: currentMode,
|
|
1203
1538
|
cwd: workingDirectory,
|
|
1204
|
-
availableProviders: getAvailableProviders()
|
|
1539
|
+
availableProviders: getAvailableProviders(),
|
|
1540
|
+
availableModes: ["direct-cli", "mcp"],
|
|
1541
|
+
mcpServerConnected: mcpServerClient?.readyState === WebSocket.OPEN,
|
|
1542
|
+
mcpClientName
|
|
1205
1543
|
};
|
|
1206
1544
|
}
|
|
1207
1545
|
};
|
|
1546
|
+
var connectedClients = /* @__PURE__ */ new Set();
|
|
1547
|
+
function broadcastToClients(message) {
|
|
1548
|
+
for (const client of connectedClients) {
|
|
1549
|
+
sendMessage(client, message);
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
function serializeStoredAnnotation(stored) {
|
|
1553
|
+
return {
|
|
1554
|
+
id: stored.annotation.id,
|
|
1555
|
+
type: stored.annotation.type,
|
|
1556
|
+
comment: stored.comment,
|
|
1557
|
+
status: stored.status,
|
|
1558
|
+
createdAt: stored.createdAt,
|
|
1559
|
+
updatedAt: stored.updatedAt,
|
|
1560
|
+
resolvedBy: stored.resolvedBy,
|
|
1561
|
+
resolutionSummary: stored.resolutionSummary,
|
|
1562
|
+
dismissalReason: stored.dismissalReason,
|
|
1563
|
+
// Include key annotation data the agent needs
|
|
1564
|
+
annotation: {
|
|
1565
|
+
type: stored.annotation.type,
|
|
1566
|
+
selector: stored.annotation.selector,
|
|
1567
|
+
tagName: stored.annotation.tagName,
|
|
1568
|
+
text: stored.annotation.text,
|
|
1569
|
+
elementPath: stored.annotation.elementPath,
|
|
1570
|
+
boundingBox: stored.annotation.boundingBox,
|
|
1571
|
+
drawingSvg: stored.annotation.drawingSvg,
|
|
1572
|
+
drawingImage: stored.annotation.drawingImage,
|
|
1573
|
+
extractedText: stored.annotation.extractedText,
|
|
1574
|
+
nearbyElements: stored.annotation.nearbyElements,
|
|
1575
|
+
viewport: stored.annotation.viewport,
|
|
1576
|
+
projectStyles: stored.annotation.projectStyles,
|
|
1577
|
+
isMultiSelect: stored.annotation.isMultiSelect,
|
|
1578
|
+
elements: stored.annotation.elements
|
|
1579
|
+
}
|
|
1580
|
+
};
|
|
1581
|
+
}
|
|
1208
1582
|
function sendMessage(ws, message) {
|
|
1209
1583
|
if (ws.readyState === WebSocket.OPEN) {
|
|
1210
1584
|
ws.send(JSON.stringify(message));
|
|
@@ -1212,11 +1586,18 @@ function sendMessage(ws, message) {
|
|
|
1212
1586
|
}
|
|
1213
1587
|
function handleConnection(ws) {
|
|
1214
1588
|
console.log("[Daemon] Client connected");
|
|
1589
|
+
connectedClients.add(ws);
|
|
1215
1590
|
sendMessage(ws, {
|
|
1216
1591
|
type: "connected",
|
|
1217
1592
|
provider: currentProvider,
|
|
1593
|
+
mode: currentMode,
|
|
1218
1594
|
cwd: workingDirectory,
|
|
1219
|
-
availableProviders: getAvailableProviders()
|
|
1595
|
+
availableProviders: getAvailableProviders(),
|
|
1596
|
+
availableModes: ["direct-cli", "mcp"],
|
|
1597
|
+
pendingAnnotations: currentMode === "mcp" ? getPendingCount() : 0,
|
|
1598
|
+
providerStatus: getAllProviderStatuses(),
|
|
1599
|
+
mcpServerConnected: mcpServerClient?.readyState === WebSocket.OPEN,
|
|
1600
|
+
mcpClientName
|
|
1220
1601
|
});
|
|
1221
1602
|
ws.on("message", async (data) => {
|
|
1222
1603
|
let msg;
|
|
@@ -1246,6 +1627,17 @@ function handleConnection(ws) {
|
|
|
1246
1627
|
});
|
|
1247
1628
|
ws.on("close", () => {
|
|
1248
1629
|
console.log("[Daemon] Client disconnected");
|
|
1630
|
+
connectedClients.delete(ws);
|
|
1631
|
+
if (ws === mcpServerClient) {
|
|
1632
|
+
mcpServerClient = null;
|
|
1633
|
+
mcpClientName = null;
|
|
1634
|
+
console.log("[Daemon] MCP server disconnected");
|
|
1635
|
+
broadcastToClients({
|
|
1636
|
+
type: "mcp-server-status",
|
|
1637
|
+
connected: false,
|
|
1638
|
+
clientName: null
|
|
1639
|
+
});
|
|
1640
|
+
}
|
|
1249
1641
|
});
|
|
1250
1642
|
ws.on("error", (error) => {
|
|
1251
1643
|
console.error("[Daemon] WebSocket error:", error);
|
|
@@ -1255,25 +1647,31 @@ function startDaemon(config = {}) {
|
|
|
1255
1647
|
const port = config.port ?? 9999;
|
|
1256
1648
|
workingDirectory = config.cwd ?? process.cwd();
|
|
1257
1649
|
currentProvider = config.defaultProvider ?? "gemini";
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
if (
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1650
|
+
currentMode = config.defaultMode ?? "direct-cli";
|
|
1651
|
+
if (currentMode === "direct-cli") {
|
|
1652
|
+
if (!isProviderAvailable(currentProvider)) {
|
|
1653
|
+
const available = getAvailableProviders();
|
|
1654
|
+
if (available.length > 0) {
|
|
1655
|
+
console.log(`[Daemon] ${currentProvider} CLI not found, falling back to ${available[0]}`);
|
|
1656
|
+
currentProvider = available[0];
|
|
1657
|
+
} else {
|
|
1658
|
+
console.warn("[Daemon] Warning: No CLI providers found. Install gemini or claude CLI.");
|
|
1659
|
+
}
|
|
1265
1660
|
}
|
|
1266
1661
|
}
|
|
1267
1662
|
const wss = new WebSocketServer({ port });
|
|
1268
1663
|
wss.on("connection", handleConnection);
|
|
1269
1664
|
wss.on("listening", () => {
|
|
1665
|
+
const cliProviders = getAvailableProviders();
|
|
1270
1666
|
console.log("");
|
|
1271
1667
|
console.log(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
|
|
1272
1668
|
console.log(" \u2502 \u2502");
|
|
1273
|
-
console.log(` \u2502
|
|
1669
|
+
console.log(` \u2502 Skema Daemon running on ws://localhost:${port} \u2502`);
|
|
1274
1670
|
console.log(" \u2502 \u2502");
|
|
1671
|
+
console.log(` \u2502 Mode: ${currentMode.padEnd(39)}\u2502`);
|
|
1275
1672
|
console.log(` \u2502 Provider: ${currentProvider.padEnd(35)}\u2502`);
|
|
1276
1673
|
console.log(` \u2502 Directory: ${workingDirectory.slice(-33).padEnd(34)}\u2502`);
|
|
1674
|
+
console.log(` \u2502 CLI Providers: ${(cliProviders.join(", ") || "none").padEnd(29)}\u2502`);
|
|
1277
1675
|
console.log(" \u2502 \u2502");
|
|
1278
1676
|
console.log(" \u2502 Waiting for browser connections... \u2502");
|
|
1279
1677
|
console.log(" \u2502 \u2502");
|
|
@@ -1296,6 +1694,6 @@ function startDaemon(config = {}) {
|
|
|
1296
1694
|
};
|
|
1297
1695
|
}
|
|
1298
1696
|
|
|
1299
|
-
export { DELETE, IMAGE_ANALYSIS_PROMPT, POST, analyzeImage, buildDetailedDomSelectionPrompt, buildDrawingToCodePrompt, buildFastDomSelectionPrompt, buildGesturePrompt, buildPromptFromAnnotation, createGeminiCLIStream, createGeminiRouteHandler, createRevertRouteHandler, getAvailableProviders, getTrackedAnnotations, isProviderAvailable, isVisionAvailable, revertAnnotation, runAICLI, runGeminiCLI, spawnAICLI, spawnGeminiCLI, startDaemon };
|
|
1697
|
+
export { DELETE, IMAGE_ANALYSIS_PROMPT, POST, acknowledgeAnnotation, analyzeImage, buildDetailedDomSelectionPrompt, buildDrawingToCodePrompt, buildFastDomSelectionPrompt, buildGesturePrompt, buildPromptFromAnnotation, clearAnnotations, createGeminiCLIStream, createGeminiRouteHandler, createRevertRouteHandler, dismissAnnotation, getAllAnnotations, getAnnotation, getAvailableProviders as getCLIProviders, getPendingAnnotations, getPendingCount, getTrackedAnnotations, isProviderAvailable, isVisionAvailable, onStoreEvent, queueAnnotation, removeAnnotation, resolveAnnotation, revertAnnotation, runAICLI, runGeminiCLI, spawnAICLI, spawnGeminiCLI, startDaemon };
|
|
1300
1698
|
//# sourceMappingURL=server.mjs.map
|
|
1301
1699
|
//# sourceMappingURL=server.mjs.map
|