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/README.md +5 -11
- package/dist/cli.js +89 -73
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +414 -62
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +414 -62
- package/dist/index.mjs.map +1 -1
- package/dist/server.d.mts +9 -4
- package/dist/server.d.ts +9 -4
- package/dist/server.js +90 -72
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +90 -73
- package/dist/server.mjs.map +1 -1
- package/package.json +5 -3
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
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
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
|
|
911
|
-
error:
|
|
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
|
|
952
|
+
const model = getProviderModel(provider, apiKey, config.model);
|
|
953
|
+
const result = await generateText({
|
|
921
954
|
model,
|
|
922
|
-
|
|
955
|
+
maxTokens: 1024,
|
|
923
956
|
messages: [
|
|
924
957
|
{
|
|
925
958
|
role: "user",
|
|
926
959
|
content: [
|
|
927
960
|
{
|
|
928
961
|
type: "image",
|
|
929
|
-
|
|
930
|
-
|
|
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
|
|
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(
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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 -
|
|
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
|