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/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 { SkemaWrapper } from "@/components/skema-wrapper" line.
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 import { SkemaWrapper } from "@/components/skema-wrapper" line or the SkemaWrapper component itself
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. Run: ${newProvider === "gemini" ? "npm install -g @anthropic-ai/gemini-cli" : "npm install -g @anthropic-ai/claude-code"}`
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: currentProvider
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: currentProvider
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: currentProvider
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: currentProvider
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: currentProvider,
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: currentProvider
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
- if (!isProviderAvailable(currentProvider)) {
1259
- const available = getAvailableProviders();
1260
- if (available.length > 0) {
1261
- console.log(`[Daemon] ${currentProvider} not found, falling back to ${available[0]}`);
1262
- currentProvider = available[0];
1263
- } else {
1264
- console.warn("[Daemon] Warning: No AI providers found. Install gemini or claude CLI.");
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 \u{1F3A8} Skema Daemon running on ws://localhost:${port} \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