skema-core 2.1.1 → 2.1.2

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
@@ -3,6 +3,10 @@ import { GoogleGenerativeAI } from '@google/generative-ai';
3
3
  import { WebSocketServer, WebSocket } from 'ws';
4
4
  import * as fs from 'fs';
5
5
  import * as path from 'path';
6
+ import { generateText } from 'ai';
7
+ import { createGoogleGenerativeAI } from '@ai-sdk/google';
8
+ import { createAnthropic } from '@ai-sdk/anthropic';
9
+ import { createOpenAI } from '@ai-sdk/openai';
6
10
 
7
11
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
12
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
@@ -880,57 +884,83 @@ function getAllProviderStatuses() {
880
884
  claude: getProviderStatus("claude")
881
885
  };
882
886
  }
883
- async function analyzeWithGemini(base64Image, apiKey, model = "gemini-2.5-flash") {
884
- try {
885
- const genAI = new GoogleGenerativeAI(apiKey);
886
- const visionModel = genAI.getGenerativeModel({ model });
887
- const cleanBase64 = base64Image.replace(/^data:image\/\w+;base64,/, "");
888
- const result = await visionModel.generateContent([
889
- IMAGE_ANALYSIS_PROMPT,
890
- {
891
- inlineData: {
892
- data: cleanBase64,
893
- mimeType: "image/png"
894
- }
895
- }
896
- ]);
897
- const response = await result.response;
898
- const text = response.text();
899
- return {
900
- success: true,
901
- description: text,
902
- provider: "gemini"
903
- };
904
- } catch (error) {
905
- const message = error instanceof Error ? error.message : String(error);
906
- console.error("[Vision] Gemini analysis failed:", message);
887
+ var VISION_MODELS = {
888
+ gemini: {
889
+ models: ["gemini-2.5-flash", "gemini-2.5-pro", "gemini-3-flash-preview", "gemini-3-pro-preview"],
890
+ default: "gemini-2.5-flash"
891
+ },
892
+ claude: {
893
+ models: ["claude-haiku-4-5-20251001", "claude-sonnet-4-5-20250929", "claude-opus-4-6"],
894
+ default: "claude-haiku-4-5-20251001"
895
+ },
896
+ openai: {
897
+ models: ["gpt-4o-mini", "gpt-4o", "gpt-4.1", "gpt-5.2"],
898
+ default: "gpt-4o-mini"
899
+ }
900
+ };
901
+ function getProviderModel(provider, apiKey, model) {
902
+ const modelId = model || VISION_MODELS[provider].default;
903
+ switch (provider) {
904
+ case "gemini": {
905
+ const google = createGoogleGenerativeAI({ apiKey });
906
+ return google(modelId);
907
+ }
908
+ case "claude": {
909
+ const anthropic = createAnthropic({ apiKey });
910
+ return anthropic(modelId);
911
+ }
912
+ case "openai": {
913
+ const openai = createOpenAI({ apiKey });
914
+ return openai(modelId);
915
+ }
916
+ }
917
+ }
918
+ function getEnvVarForProvider(provider) {
919
+ switch (provider) {
920
+ case "gemini":
921
+ return process.env.GEMINI_API_KEY;
922
+ case "claude":
923
+ return process.env.ANTHROPIC_API_KEY;
924
+ case "openai":
925
+ return process.env.OPENAI_API_KEY;
926
+ }
927
+ }
928
+ function getEnvVarName(provider) {
929
+ switch (provider) {
930
+ case "gemini":
931
+ return "GEMINI_API_KEY";
932
+ case "claude":
933
+ return "ANTHROPIC_API_KEY";
934
+ case "openai":
935
+ return "OPENAI_API_KEY";
936
+ }
937
+ }
938
+ async function analyzeImage(base64Image, config) {
939
+ const { provider } = config;
940
+ const apiKey = config.apiKey || getEnvVarForProvider(provider);
941
+ if (!apiKey) {
907
942
  return {
908
943
  success: false,
909
944
  description: "",
910
- provider: "gemini",
911
- error: message
945
+ provider,
946
+ error: `No API key found for ${provider} vision. Set ${getEnvVarName(provider)} environment variable.`
912
947
  };
913
948
  }
914
- }
915
- async function analyzeWithClaude(base64Image, apiKey, model = "claude-sonnet-4-20250514") {
949
+ console.log(`[Vision] Analyzing image with ${provider}...`);
916
950
  try {
917
- const Anthropic = (await import('@anthropic-ai/sdk')).default;
918
- const client = new Anthropic({ apiKey });
919
951
  const cleanBase64 = base64Image.replace(/^data:image\/\w+;base64,/, "");
920
- const response = await client.messages.create({
952
+ const model = getProviderModel(provider, apiKey, config.model);
953
+ const result = await generateText({
921
954
  model,
922
- max_tokens: 1024,
955
+ maxTokens: 1024,
923
956
  messages: [
924
957
  {
925
958
  role: "user",
926
959
  content: [
927
960
  {
928
961
  type: "image",
929
- source: {
930
- type: "base64",
931
- media_type: "image/png",
932
- data: cleanBase64
933
- }
962
+ image: Buffer.from(cleanBase64, "base64"),
963
+ mimeType: "image/png"
934
964
  },
935
965
  {
936
966
  type: "text",
@@ -940,51 +970,24 @@ async function analyzeWithClaude(base64Image, apiKey, model = "claude-sonnet-4-2
940
970
  }
941
971
  ]
942
972
  });
943
- const textContent = response.content.find((c) => c.type === "text");
944
- const description = textContent && "text" in textContent ? textContent.text : "";
945
973
  return {
946
974
  success: true,
947
- description,
948
- provider: "claude"
975
+ description: result.text,
976
+ provider
949
977
  };
950
978
  } catch (error) {
951
979
  const message = error instanceof Error ? error.message : String(error);
952
- console.error("[Vision] Claude analysis failed:", message);
953
- return {
954
- success: false,
955
- description: "",
956
- provider: "claude",
957
- error: message
958
- };
959
- }
960
- }
961
- async function analyzeImage(base64Image, config) {
962
- const { provider } = config;
963
- let apiKey = config.apiKey;
964
- if (!apiKey) {
965
- apiKey = provider === "gemini" ? process.env.GEMINI_API_KEY : process.env.ANTHROPIC_API_KEY;
966
- }
967
- if (!apiKey) {
980
+ console.error(`[Vision] ${provider} analysis failed:`, message);
968
981
  return {
969
982
  success: false,
970
983
  description: "",
971
984
  provider,
972
- error: `No API key found for ${provider} vision. Set ${provider === "gemini" ? "GEMINI_API_KEY" : "ANTHROPIC_API_KEY"} environment variable.`
985
+ error: message
973
986
  };
974
987
  }
975
- console.log(`[Vision] Analyzing image with ${provider}...`);
976
- if (provider === "gemini") {
977
- return analyzeWithGemini(base64Image, apiKey, config.model);
978
- } else {
979
- return analyzeWithClaude(base64Image, apiKey, config.model);
980
- }
981
988
  }
982
989
  function isVisionAvailable(provider) {
983
- if (provider === "gemini") {
984
- return !!process.env.GEMINI_API_KEY;
985
- } else {
986
- return !!process.env.ANTHROPIC_API_KEY;
987
- }
990
+ return !!getEnvVarForProvider(provider);
988
991
  }
989
992
 
990
993
  // src/server/annotation-store.ts
@@ -1228,9 +1231,14 @@ var handlers = {
1228
1231
  provider: requestProvider
1229
1232
  }
1230
1233
  });
1231
- if (isVisionAvailable("gemini")) {
1234
+ const visionProvider = msg.visionProvider || "gemini";
1235
+ const visionModel = msg.visionModel;
1236
+ const visionApiKey = msg.visionApiKey || (visionProvider === "gemini" ? process.env.GEMINI_API_KEY : visionProvider === "claude" ? process.env.ANTHROPIC_API_KEY : process.env.OPENAI_API_KEY);
1237
+ if (visionApiKey) {
1232
1238
  const visionResult = await analyzeImage(drawingAnnotation.drawingImage, {
1233
- provider: "gemini"
1239
+ provider: visionProvider,
1240
+ apiKey: visionApiKey,
1241
+ model: visionModel
1234
1242
  });
1235
1243
  if (visionResult.success) {
1236
1244
  visionDescription = visionResult.description;
@@ -1263,7 +1271,7 @@ ${visionDescription}`,
1263
1271
  type: "ai-event",
1264
1272
  event: {
1265
1273
  type: "text",
1266
- content: `[Vision not available - set GEMINI_API_KEY for image analysis]`,
1274
+ content: `[Vision not available - add your API key in Settings (gear icon)]`,
1267
1275
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1268
1276
  provider: requestProvider
1269
1277
  }
@@ -1274,6 +1282,8 @@ ${visionDescription}`,
1274
1282
  fastMode: msg.fastMode === true,
1275
1283
  visionDescription
1276
1284
  });
1285
+ console.log(`[Skema] Prompt:
1286
+ ${prompt}`);
1277
1287
  sendMessage(ws, {
1278
1288
  id: msg.id,
1279
1289
  type: "ai-event",
@@ -1304,7 +1314,14 @@ ${visionDescription}`,
1304
1314
  model: msg.model
1305
1315
  };
1306
1316
  const { process: aiProcess, events } = spawnAICLI(prompt, config);
1317
+ const prefixGreen = "\x1B[32m";
1318
+ const reset = "\x1B[0m";
1307
1319
  for await (const event of events) {
1320
+ if (event.type === "text" && event.content) {
1321
+ console.log(`${prefixGreen}[Skema ${requestProvider}]${reset} ${event.content}`);
1322
+ } else if (event.type === "error" && event.content) {
1323
+ console.error(`${prefixGreen}[Skema ${requestProvider}]${reset} ${event.content}`);
1324
+ }
1308
1325
  sendMessage(ws, {
1309
1326
  id: msg.id,
1310
1327
  type: "ai-event",
@@ -1694,6 +1711,6 @@ function startDaemon(config = {}) {
1694
1711
  };
1695
1712
  }
1696
1713
 
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 };
1714
+ export { DELETE, IMAGE_ANALYSIS_PROMPT, POST, VISION_MODELS, 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 };
1698
1715
  //# sourceMappingURL=server.mjs.map
1699
1716
  //# sourceMappingURL=server.mjs.map