skema-core 2.1.0 → 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 +8 -5
package/dist/index.js
CHANGED
|
@@ -323,8 +323,7 @@ function useDaemon(options = {}) {
|
|
|
323
323
|
pending.resolve(msg);
|
|
324
324
|
}
|
|
325
325
|
}
|
|
326
|
-
} catch
|
|
327
|
-
console.error("[useDaemon] Failed to parse message:", e);
|
|
326
|
+
} catch {
|
|
328
327
|
}
|
|
329
328
|
}, []);
|
|
330
329
|
const connect = react.useCallback(() => {
|
|
@@ -336,27 +335,20 @@ function useDaemon(options = {}) {
|
|
|
336
335
|
try {
|
|
337
336
|
const ws = new WebSocket(url);
|
|
338
337
|
ws.onopen = () => {
|
|
339
|
-
console.log("[useDaemon] Connected to daemon");
|
|
340
338
|
};
|
|
341
339
|
ws.onmessage = handleMessage;
|
|
342
340
|
ws.onclose = () => {
|
|
343
|
-
console.log("[useDaemon] Disconnected from daemon");
|
|
344
341
|
setState((prev) => ({ ...prev, connected: false }));
|
|
345
342
|
wsRef.current = null;
|
|
346
343
|
if (autoReconnect) {
|
|
347
|
-
reconnectTimeoutRef.current = setTimeout(
|
|
348
|
-
console.log("[useDaemon] Attempting to reconnect...");
|
|
349
|
-
connect();
|
|
350
|
-
}, reconnectDelay);
|
|
344
|
+
reconnectTimeoutRef.current = setTimeout(connect, reconnectDelay);
|
|
351
345
|
}
|
|
352
346
|
};
|
|
353
|
-
ws.onerror = (
|
|
354
|
-
console.error("[useDaemon] WebSocket error:", e);
|
|
347
|
+
ws.onerror = () => {
|
|
355
348
|
setError("Failed to connect to Skema daemon. Is it running?");
|
|
356
349
|
};
|
|
357
350
|
wsRef.current = ws;
|
|
358
|
-
} catch
|
|
359
|
-
console.error("[useDaemon] Failed to create WebSocket:", e);
|
|
351
|
+
} catch {
|
|
360
352
|
setError("Failed to connect to Skema daemon");
|
|
361
353
|
}
|
|
362
354
|
}, [url, autoReconnect, reconnectDelay, handleMessage]);
|
|
@@ -375,8 +367,7 @@ function useDaemon(options = {}) {
|
|
|
375
367
|
try {
|
|
376
368
|
const response = await sendRequest("set-provider", { provider });
|
|
377
369
|
return response.type === "provider-changed";
|
|
378
|
-
} catch
|
|
379
|
-
console.error("[useDaemon] Failed to set provider:", e);
|
|
370
|
+
} catch {
|
|
380
371
|
return false;
|
|
381
372
|
}
|
|
382
373
|
}, [sendRequest]);
|
|
@@ -384,16 +375,14 @@ function useDaemon(options = {}) {
|
|
|
384
375
|
try {
|
|
385
376
|
const response = await sendRequest("set-mode", { mode });
|
|
386
377
|
return response.type === "mode-changed";
|
|
387
|
-
} catch
|
|
388
|
-
console.error("[useDaemon] Failed to set mode:", e);
|
|
378
|
+
} catch {
|
|
389
379
|
return false;
|
|
390
380
|
}
|
|
391
381
|
}, [sendRequest]);
|
|
392
382
|
const refreshProviderStatus = react.useCallback(async () => {
|
|
393
383
|
try {
|
|
394
384
|
await sendRequest("check-providers", {});
|
|
395
|
-
} catch
|
|
396
|
-
console.error("[useDaemon] Failed to refresh provider status:", e);
|
|
385
|
+
} catch {
|
|
397
386
|
}
|
|
398
387
|
}, [sendRequest]);
|
|
399
388
|
const generate = react.useCallback(async (annotation, onEvent, options2) => {
|
|
@@ -415,7 +404,10 @@ function useDaemon(options = {}) {
|
|
|
415
404
|
annotation,
|
|
416
405
|
// Include optional overrides
|
|
417
406
|
...options2?.mode && { mode: options2.mode },
|
|
418
|
-
...options2?.provider && { provider: options2.provider }
|
|
407
|
+
...options2?.provider && { provider: options2.provider },
|
|
408
|
+
...options2?.visionApiKey != null && options2.visionApiKey !== "" && { visionApiKey: options2.visionApiKey },
|
|
409
|
+
...options2?.visionProvider && { visionProvider: options2.visionProvider },
|
|
410
|
+
...options2?.visionModel && { visionModel: options2.visionModel }
|
|
419
411
|
}));
|
|
420
412
|
});
|
|
421
413
|
}, [nextId]);
|
|
@@ -957,6 +949,76 @@ function extractTextFromShapes(shapes) {
|
|
|
957
949
|
}
|
|
958
950
|
return textContent.filter(Boolean).join("\n");
|
|
959
951
|
}
|
|
952
|
+
|
|
953
|
+
// src/lib/settingsStorage.ts
|
|
954
|
+
var VISION_API_KEY_PREFIX = "skema-vision-api-key-";
|
|
955
|
+
var VISION_PROVIDER_KEY = "skema-vision-provider";
|
|
956
|
+
var VISION_MODEL_KEY = "skema-vision-model";
|
|
957
|
+
var OLD_GEMINI_KEY = "skema-gemini-api-key";
|
|
958
|
+
function getStoredVisionApiKey(provider) {
|
|
959
|
+
if (typeof window === "undefined" || !window.localStorage) return null;
|
|
960
|
+
try {
|
|
961
|
+
let value = localStorage.getItem(VISION_API_KEY_PREFIX + provider);
|
|
962
|
+
if (!value && provider === "gemini") {
|
|
963
|
+
value = localStorage.getItem(OLD_GEMINI_KEY);
|
|
964
|
+
if (value) {
|
|
965
|
+
localStorage.setItem(VISION_API_KEY_PREFIX + "gemini", value);
|
|
966
|
+
localStorage.removeItem(OLD_GEMINI_KEY);
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
return value && value.trim() ? value.trim() : null;
|
|
970
|
+
} catch {
|
|
971
|
+
return null;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
function setStoredVisionApiKey(provider, value) {
|
|
975
|
+
if (typeof window === "undefined" || !window.localStorage) return;
|
|
976
|
+
try {
|
|
977
|
+
const trimmed = value.trim();
|
|
978
|
+
if (trimmed) {
|
|
979
|
+
localStorage.setItem(VISION_API_KEY_PREFIX + provider, trimmed);
|
|
980
|
+
} else {
|
|
981
|
+
localStorage.removeItem(VISION_API_KEY_PREFIX + provider);
|
|
982
|
+
}
|
|
983
|
+
} catch {
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
function getStoredVisionProvider() {
|
|
987
|
+
if (typeof window === "undefined" || !window.localStorage) return "gemini";
|
|
988
|
+
try {
|
|
989
|
+
const value = localStorage.getItem(VISION_PROVIDER_KEY);
|
|
990
|
+
if (value === "gemini" || value === "claude" || value === "openai") return value;
|
|
991
|
+
return "gemini";
|
|
992
|
+
} catch {
|
|
993
|
+
return "gemini";
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
function setStoredVisionProvider(provider) {
|
|
997
|
+
if (typeof window === "undefined" || !window.localStorage) return;
|
|
998
|
+
try {
|
|
999
|
+
localStorage.setItem(VISION_PROVIDER_KEY, provider);
|
|
1000
|
+
} catch {
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
function getStoredVisionModel() {
|
|
1004
|
+
if (typeof window === "undefined" || !window.localStorage) return null;
|
|
1005
|
+
try {
|
|
1006
|
+
return localStorage.getItem(VISION_MODEL_KEY);
|
|
1007
|
+
} catch {
|
|
1008
|
+
return null;
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
function setStoredVisionModel(model) {
|
|
1012
|
+
if (typeof window === "undefined" || !window.localStorage) return;
|
|
1013
|
+
try {
|
|
1014
|
+
if (model) {
|
|
1015
|
+
localStorage.setItem(VISION_MODEL_KEY, model);
|
|
1016
|
+
} else {
|
|
1017
|
+
localStorage.removeItem(VISION_MODEL_KEY);
|
|
1018
|
+
}
|
|
1019
|
+
} catch {
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
960
1022
|
var SLogoIcon = ({ size = 32 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: size, height: size, viewBox: "0 0 166 161", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
961
1023
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
962
1024
|
"path",
|
|
@@ -2532,6 +2594,40 @@ var svg2 = `<svg width="560" height="132" viewBox="378 168 560 132" fill="none"
|
|
|
2532
2594
|
</svg>`;
|
|
2533
2595
|
var logo_light_default = "data:image/svg+xml," + encodeURIComponent(svg2);
|
|
2534
2596
|
var SKEMA_VERSION = "0.2.0";
|
|
2597
|
+
var VISION_PROVIDERS = [
|
|
2598
|
+
{ value: "gemini", label: "Gemini" },
|
|
2599
|
+
{ value: "claude", label: "Claude" },
|
|
2600
|
+
{ value: "openai", label: "OpenAI" }
|
|
2601
|
+
];
|
|
2602
|
+
var VISION_PROVIDER_MODELS = {
|
|
2603
|
+
gemini: [
|
|
2604
|
+
{ value: "gemini-2.5-flash", label: "2.5 Flash" },
|
|
2605
|
+
{ value: "gemini-2.5-pro", label: "2.5 Pro" },
|
|
2606
|
+
{ value: "gemini-3-flash-preview", label: "3 Flash" },
|
|
2607
|
+
{ value: "gemini-3-pro-preview", label: "3 Pro" }
|
|
2608
|
+
],
|
|
2609
|
+
claude: [
|
|
2610
|
+
{ value: "claude-haiku-4-5-20251001", label: "Haiku 4.5" },
|
|
2611
|
+
{ value: "claude-sonnet-4-5-20250929", label: "Sonnet 4.5" },
|
|
2612
|
+
{ value: "claude-opus-4-6", label: "Opus 4.6" }
|
|
2613
|
+
],
|
|
2614
|
+
openai: [
|
|
2615
|
+
{ value: "gpt-4o-mini", label: "GPT-4o Mini" },
|
|
2616
|
+
{ value: "gpt-4o", label: "GPT-4o" },
|
|
2617
|
+
{ value: "gpt-4.1", label: "GPT-4.1" },
|
|
2618
|
+
{ value: "gpt-5.2", label: "GPT-5.2" }
|
|
2619
|
+
]
|
|
2620
|
+
};
|
|
2621
|
+
var VISION_PROVIDER_DEFAULT_MODEL = {
|
|
2622
|
+
gemini: "gemini-2.5-flash",
|
|
2623
|
+
claude: "claude-haiku-4-5-20251001",
|
|
2624
|
+
openai: "gpt-4o-mini"
|
|
2625
|
+
};
|
|
2626
|
+
var VISION_PROVIDER_KEY_LINKS = {
|
|
2627
|
+
gemini: { label: "Google AI Studio", url: "https://aistudio.google.com/apikey" },
|
|
2628
|
+
claude: { label: "Anthropic Console", url: "https://console.anthropic.com/settings/keys" },
|
|
2629
|
+
openai: { label: "OpenAI Platform", url: "https://platform.openai.com/api-keys" }
|
|
2630
|
+
};
|
|
2535
2631
|
var SettingsPanel = ({
|
|
2536
2632
|
isOpen,
|
|
2537
2633
|
onClose,
|
|
@@ -2549,6 +2645,40 @@ var SettingsPanel = ({
|
|
|
2549
2645
|
theme,
|
|
2550
2646
|
onThemeChange
|
|
2551
2647
|
}) => {
|
|
2648
|
+
const [visionProvider, setVisionProvider] = react.useState("gemini");
|
|
2649
|
+
const [visionModel, setVisionModel] = react.useState("");
|
|
2650
|
+
const [visionApiKey, setVisionApiKey] = react.useState("");
|
|
2651
|
+
const [showApiKey, setShowApiKey] = react.useState(false);
|
|
2652
|
+
react.useEffect(() => {
|
|
2653
|
+
if (isOpen) {
|
|
2654
|
+
const storedProvider = getStoredVisionProvider();
|
|
2655
|
+
setVisionProvider(storedProvider);
|
|
2656
|
+
setVisionModel(getStoredVisionModel() || VISION_PROVIDER_DEFAULT_MODEL[storedProvider]);
|
|
2657
|
+
const storedKey = getStoredVisionApiKey(storedProvider);
|
|
2658
|
+
setVisionApiKey(storedKey ?? "");
|
|
2659
|
+
}
|
|
2660
|
+
}, [isOpen]);
|
|
2661
|
+
const handleVisionProviderChange = (e) => {
|
|
2662
|
+
const newProvider = e.target.value;
|
|
2663
|
+
setVisionProvider(newProvider);
|
|
2664
|
+
setStoredVisionProvider(newProvider);
|
|
2665
|
+
const storedKey = getStoredVisionApiKey(newProvider);
|
|
2666
|
+
setVisionApiKey(storedKey ?? "");
|
|
2667
|
+
setShowApiKey(false);
|
|
2668
|
+
const defaultModel = VISION_PROVIDER_DEFAULT_MODEL[newProvider];
|
|
2669
|
+
setVisionModel(defaultModel);
|
|
2670
|
+
setStoredVisionModel(defaultModel);
|
|
2671
|
+
};
|
|
2672
|
+
const handleVisionModelChange = (e) => {
|
|
2673
|
+
const newModel = e.target.value;
|
|
2674
|
+
setVisionModel(newModel);
|
|
2675
|
+
setStoredVisionModel(newModel);
|
|
2676
|
+
};
|
|
2677
|
+
const handleVisionApiKeyChange = (e) => {
|
|
2678
|
+
const v = e.target.value;
|
|
2679
|
+
setVisionApiKey(v);
|
|
2680
|
+
setStoredVisionApiKey(visionProvider, v || "");
|
|
2681
|
+
};
|
|
2552
2682
|
if (!isOpen) return null;
|
|
2553
2683
|
const isDark = theme === "dark";
|
|
2554
2684
|
const bgColor = isDark ? "#1a1a1a" : "#ffffff";
|
|
@@ -2608,6 +2738,130 @@ var SettingsPanel = ({
|
|
|
2608
2738
|
),
|
|
2609
2739
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "16px 20px" }, children: [
|
|
2610
2740
|
/* @__PURE__ */ jsxRuntime.jsx(SettingRow, { label: "Theme", isDark, textColor, mutedColor, children: /* @__PURE__ */ jsxRuntime.jsx(ThemeIconToggle, { isDark, onToggle: () => onThemeChange(isDark ? "light" : "dark") }) }),
|
|
2741
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: 12 }, children: [
|
|
2742
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 14, color: textColor, marginBottom: 6, display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
2743
|
+
"Vision API key",
|
|
2744
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2745
|
+
InfoTooltip,
|
|
2746
|
+
{
|
|
2747
|
+
text: "Used to analyze drawing annotations so the AI understands what you've sketched.",
|
|
2748
|
+
isDark,
|
|
2749
|
+
mutedColor
|
|
2750
|
+
}
|
|
2751
|
+
)
|
|
2752
|
+
] }),
|
|
2753
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative" }, children: [
|
|
2754
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2755
|
+
"input",
|
|
2756
|
+
{
|
|
2757
|
+
type: showApiKey ? "text" : "password",
|
|
2758
|
+
placeholder: "",
|
|
2759
|
+
value: visionApiKey,
|
|
2760
|
+
onChange: handleVisionApiKeyChange,
|
|
2761
|
+
autoComplete: "off",
|
|
2762
|
+
style: {
|
|
2763
|
+
width: "100%",
|
|
2764
|
+
boxSizing: "border-box",
|
|
2765
|
+
padding: "8px 32px 8px 10px",
|
|
2766
|
+
fontSize: 12,
|
|
2767
|
+
fontFamily: "monospace",
|
|
2768
|
+
border: `1px solid ${borderColor}`,
|
|
2769
|
+
borderRadius: 8,
|
|
2770
|
+
backgroundColor: isDark ? "#2a2a2a" : "#f5f5f5",
|
|
2771
|
+
color: textColor,
|
|
2772
|
+
outline: "none"
|
|
2773
|
+
}
|
|
2774
|
+
}
|
|
2775
|
+
),
|
|
2776
|
+
visionApiKey && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2777
|
+
"button",
|
|
2778
|
+
{
|
|
2779
|
+
type: "button",
|
|
2780
|
+
onClick: () => setShowApiKey(!showApiKey),
|
|
2781
|
+
title: showApiKey ? "Hide API key" : "Show API key",
|
|
2782
|
+
style: {
|
|
2783
|
+
position: "absolute",
|
|
2784
|
+
right: 6,
|
|
2785
|
+
top: "50%",
|
|
2786
|
+
transform: "translateY(-50%)",
|
|
2787
|
+
display: "flex",
|
|
2788
|
+
alignItems: "center",
|
|
2789
|
+
justifyContent: "center",
|
|
2790
|
+
width: 24,
|
|
2791
|
+
height: 24,
|
|
2792
|
+
border: "none",
|
|
2793
|
+
borderRadius: 4,
|
|
2794
|
+
backgroundColor: "transparent",
|
|
2795
|
+
cursor: "pointer",
|
|
2796
|
+
padding: 0,
|
|
2797
|
+
color: mutedColor
|
|
2798
|
+
},
|
|
2799
|
+
children: showApiKey ? /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2800
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94" }),
|
|
2801
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19" }),
|
|
2802
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "1", y1: "1", x2: "23", y2: "23" })
|
|
2803
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2804
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }),
|
|
2805
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "3" })
|
|
2806
|
+
] })
|
|
2807
|
+
}
|
|
2808
|
+
)
|
|
2809
|
+
] }),
|
|
2810
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { fontSize: 10, color: mutedColor, marginTop: 4, lineHeight: 1.3 }, children: [
|
|
2811
|
+
"Stored in this browser only. Get a key at",
|
|
2812
|
+
" ",
|
|
2813
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2814
|
+
"a",
|
|
2815
|
+
{
|
|
2816
|
+
href: VISION_PROVIDER_KEY_LINKS[visionProvider].url,
|
|
2817
|
+
target: "_blank",
|
|
2818
|
+
rel: "noopener noreferrer",
|
|
2819
|
+
style: { color: isDark ? "#93c5fd" : "#2563eb" },
|
|
2820
|
+
children: VISION_PROVIDER_KEY_LINKS[visionProvider].label
|
|
2821
|
+
}
|
|
2822
|
+
)
|
|
2823
|
+
] }),
|
|
2824
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: 8, marginTop: 8 }, children: [
|
|
2825
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2826
|
+
"select",
|
|
2827
|
+
{
|
|
2828
|
+
value: visionProvider,
|
|
2829
|
+
onChange: handleVisionProviderChange,
|
|
2830
|
+
style: {
|
|
2831
|
+
flex: 1,
|
|
2832
|
+
padding: "6px 8px",
|
|
2833
|
+
fontSize: 12,
|
|
2834
|
+
border: `1px solid ${borderColor}`,
|
|
2835
|
+
borderRadius: 6,
|
|
2836
|
+
backgroundColor: isDark ? "#2a2a2a" : "#f5f5f5",
|
|
2837
|
+
color: textColor,
|
|
2838
|
+
outline: "none",
|
|
2839
|
+
cursor: "pointer"
|
|
2840
|
+
},
|
|
2841
|
+
children: VISION_PROVIDERS.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.value, children: p.label }, p.value))
|
|
2842
|
+
}
|
|
2843
|
+
),
|
|
2844
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2845
|
+
"select",
|
|
2846
|
+
{
|
|
2847
|
+
value: visionModel,
|
|
2848
|
+
onChange: handleVisionModelChange,
|
|
2849
|
+
style: {
|
|
2850
|
+
flex: 1.5,
|
|
2851
|
+
padding: "6px 8px",
|
|
2852
|
+
fontSize: 11,
|
|
2853
|
+
border: `1px solid ${borderColor}`,
|
|
2854
|
+
borderRadius: 6,
|
|
2855
|
+
backgroundColor: isDark ? "#2a2a2a" : "#f5f5f5",
|
|
2856
|
+
color: textColor,
|
|
2857
|
+
outline: "none",
|
|
2858
|
+
cursor: "pointer"
|
|
2859
|
+
},
|
|
2860
|
+
children: VISION_PROVIDER_MODELS[visionProvider].map((m) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: m.value, children: m.label }, m.value))
|
|
2861
|
+
}
|
|
2862
|
+
)
|
|
2863
|
+
] })
|
|
2864
|
+
] }),
|
|
2611
2865
|
!connected && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2612
2866
|
"div",
|
|
2613
2867
|
{
|
|
@@ -2693,6 +2947,70 @@ var SettingsPanel = ({
|
|
|
2693
2947
|
}
|
|
2694
2948
|
);
|
|
2695
2949
|
};
|
|
2950
|
+
var InfoTooltip = ({ text, isDark, mutedColor }) => {
|
|
2951
|
+
const [show, setShow] = react.useState(false);
|
|
2952
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2953
|
+
"span",
|
|
2954
|
+
{
|
|
2955
|
+
style: { position: "relative", display: "inline-flex" },
|
|
2956
|
+
onMouseEnter: () => setShow(true),
|
|
2957
|
+
onMouseLeave: () => setShow(false),
|
|
2958
|
+
children: [
|
|
2959
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2960
|
+
"svg",
|
|
2961
|
+
{
|
|
2962
|
+
width: "16",
|
|
2963
|
+
height: "16",
|
|
2964
|
+
viewBox: "0 0 16 16",
|
|
2965
|
+
fill: "none",
|
|
2966
|
+
style: { cursor: "help", flexShrink: 0 },
|
|
2967
|
+
children: [
|
|
2968
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8", cy: "8", r: "7", stroke: mutedColor, strokeWidth: "1.5" }),
|
|
2969
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2970
|
+
"text",
|
|
2971
|
+
{
|
|
2972
|
+
x: "8",
|
|
2973
|
+
y: "12",
|
|
2974
|
+
textAnchor: "middle",
|
|
2975
|
+
fill: mutedColor,
|
|
2976
|
+
fontSize: "11",
|
|
2977
|
+
fontWeight: "600",
|
|
2978
|
+
fontStyle: "italic",
|
|
2979
|
+
fontFamily: 'Georgia, "Times New Roman", serif',
|
|
2980
|
+
children: "i"
|
|
2981
|
+
}
|
|
2982
|
+
)
|
|
2983
|
+
]
|
|
2984
|
+
}
|
|
2985
|
+
),
|
|
2986
|
+
show && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2987
|
+
"div",
|
|
2988
|
+
{
|
|
2989
|
+
style: {
|
|
2990
|
+
position: "absolute",
|
|
2991
|
+
bottom: "100%",
|
|
2992
|
+
left: "50%",
|
|
2993
|
+
transform: "translateX(-50%)",
|
|
2994
|
+
marginBottom: 8,
|
|
2995
|
+
width: 240,
|
|
2996
|
+
padding: "10px 12px",
|
|
2997
|
+
borderRadius: 10,
|
|
2998
|
+
backgroundColor: isDark ? "#2a2a2a" : "#ffffff",
|
|
2999
|
+
border: `1px solid ${isDark ? "#444" : "#e0e0e0"}`,
|
|
3000
|
+
boxShadow: "0 4px 16px rgba(0,0,0,0.15)",
|
|
3001
|
+
fontSize: 11,
|
|
3002
|
+
lineHeight: 1.5,
|
|
3003
|
+
color: isDark ? "#ccc" : "#444",
|
|
3004
|
+
zIndex: 10,
|
|
3005
|
+
pointerEvents: "none"
|
|
3006
|
+
},
|
|
3007
|
+
children: text
|
|
3008
|
+
}
|
|
3009
|
+
)
|
|
3010
|
+
]
|
|
3011
|
+
}
|
|
3012
|
+
);
|
|
3013
|
+
};
|
|
2696
3014
|
var SettingRow = ({ label, textColor, disabled, children }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2697
3015
|
"div",
|
|
2698
3016
|
{
|
|
@@ -3444,26 +3762,24 @@ var Skema = ({
|
|
|
3444
3762
|
const isProcessing = externalIsProcessing !== void 0 ? externalIsProcessing : internalIsProcessing || isGenerating;
|
|
3445
3763
|
const internalOnAnnotationSubmit = react.useCallback(async (annotation, comment) => {
|
|
3446
3764
|
if (!daemonState.connected) {
|
|
3447
|
-
console.warn("[Skema] Not connected to daemon. Run: npx skema-serve");
|
|
3448
3765
|
return;
|
|
3449
3766
|
}
|
|
3450
3767
|
setInternalIsProcessing(true);
|
|
3451
3768
|
try {
|
|
3452
3769
|
const result = await generate(
|
|
3453
3770
|
{ ...annotation, comment },
|
|
3454
|
-
(
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3771
|
+
() => {
|
|
3772
|
+
},
|
|
3773
|
+
{
|
|
3774
|
+
visionApiKey: getStoredVisionApiKey(getStoredVisionProvider()),
|
|
3775
|
+
visionProvider: getStoredVisionProvider(),
|
|
3776
|
+
visionModel: getStoredVisionModel() || void 0
|
|
3460
3777
|
}
|
|
3461
3778
|
);
|
|
3462
3779
|
if (result.annotationId) {
|
|
3463
3780
|
annotationChangesRef.current.set(annotation.id, result.annotationId);
|
|
3464
3781
|
}
|
|
3465
|
-
} catch
|
|
3466
|
-
console.error("[Skema] Failed to generate:", error);
|
|
3782
|
+
} catch {
|
|
3467
3783
|
} finally {
|
|
3468
3784
|
setInternalIsProcessing(false);
|
|
3469
3785
|
}
|
|
@@ -3476,8 +3792,7 @@ var Skema = ({
|
|
|
3476
3792
|
try {
|
|
3477
3793
|
await revert(trackedId);
|
|
3478
3794
|
annotationChangesRef.current.delete(annotationId);
|
|
3479
|
-
} catch
|
|
3480
|
-
console.error("[Skema] Failed to revert:", error);
|
|
3795
|
+
} catch {
|
|
3481
3796
|
}
|
|
3482
3797
|
}, [revert]);
|
|
3483
3798
|
const internalOnProcessingCancel = react.useCallback(() => {
|
|
@@ -3813,22 +4128,19 @@ var Skema = ({
|
|
|
3813
4128
|
if (svgResult?.svg) {
|
|
3814
4129
|
drawingSvg = addGridToSvg(svgResult.svg, gridConfig);
|
|
3815
4130
|
}
|
|
3816
|
-
} catch
|
|
3817
|
-
console.warn("[Skema] Failed to export drawing SVG:", e);
|
|
4131
|
+
} catch {
|
|
3818
4132
|
}
|
|
3819
4133
|
try {
|
|
3820
4134
|
const imageResult = await editor.toImage(shapeIds, { format: "png", padding: 20, background: true });
|
|
3821
4135
|
if (imageResult?.blob) {
|
|
3822
4136
|
drawingImage = await blobToBase64(imageResult.blob);
|
|
3823
4137
|
}
|
|
3824
|
-
} catch
|
|
3825
|
-
console.warn("[Skema] Failed to export drawing image:", e);
|
|
4138
|
+
} catch {
|
|
3826
4139
|
}
|
|
3827
4140
|
try {
|
|
3828
4141
|
const shapes = shapeIds.map((id) => editor.getShape(id)).filter(Boolean);
|
|
3829
4142
|
extractedText = extractTextFromShapes(shapes);
|
|
3830
|
-
} catch
|
|
3831
|
-
console.warn("[Skema] Failed to extract text from shapes:", e);
|
|
4143
|
+
} catch {
|
|
3832
4144
|
}
|
|
3833
4145
|
}
|
|
3834
4146
|
const nearbyElements = pendingAnnotation.boundingBox ? findNearbyElementsWithStyles(pendingAnnotation.boundingBox, 5) : [];
|
|
@@ -3908,7 +4220,6 @@ var Skema = ({
|
|
|
3908
4220
|
annotations
|
|
3909
4221
|
};
|
|
3910
4222
|
navigator.clipboard.writeText(JSON.stringify(exportData, null, 2));
|
|
3911
|
-
console.log("[Skema] Exported annotations:", exportData);
|
|
3912
4223
|
alert("Annotations copied to clipboard!");
|
|
3913
4224
|
}, [annotations]);
|
|
3914
4225
|
const handleBrushSelection = react.useCallback((brushBounds) => {
|
|
@@ -4035,8 +4346,7 @@ var Skema = ({
|
|
|
4035
4346
|
}
|
|
4036
4347
|
};
|
|
4037
4348
|
}
|
|
4038
|
-
} catch
|
|
4039
|
-
console.warn("Failed to override double click behavior", e);
|
|
4349
|
+
} catch {
|
|
4040
4350
|
}
|
|
4041
4351
|
editor.setCamera({ x: -window.scrollX, y: -window.scrollY, z: 1 });
|
|
4042
4352
|
editor.sideEffects.registerAfterChangeHandler("camera", () => {
|
|
@@ -4115,11 +4425,21 @@ var Skema = ({
|
|
|
4115
4425
|
${isToolbarExpanded && (currentToolId === "draw" || currentToolId === "geo") ? "" : "display: none !important;"}
|
|
4116
4426
|
}
|
|
4117
4427
|
` }),
|
|
4118
|
-
|
|
4428
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
4429
|
+
@keyframes skema-pulse {
|
|
4430
|
+
0%, 100% { transform: scale(1); opacity: 1; }
|
|
4431
|
+
50% { transform: scale(1.15); opacity: 0.8; }
|
|
4432
|
+
}
|
|
4433
|
+
@keyframes skema-glow {
|
|
4434
|
+
0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4); }
|
|
4435
|
+
50% { box-shadow: 0 0 0 8px rgba(239, 68, 68, 0); }
|
|
4436
|
+
}
|
|
4437
|
+
` }),
|
|
4438
|
+
isToolbarExpanded && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4119
4439
|
"button",
|
|
4120
4440
|
{
|
|
4121
4441
|
onClick: () => setIsStylePanelOpen((prev) => !prev),
|
|
4122
|
-
title: isStylePanelOpen ? "Hide style settings" : "Show style settings",
|
|
4442
|
+
title: isStylePanelOpen ? "Hide style settings" : !daemonState.connected ? "Daemon not connected - click to configure" : "Show style settings",
|
|
4123
4443
|
style: {
|
|
4124
4444
|
position: "fixed",
|
|
4125
4445
|
bottom: 16,
|
|
@@ -4130,36 +4450,68 @@ var Skema = ({
|
|
|
4130
4450
|
alignItems: "center",
|
|
4131
4451
|
justifyContent: "center",
|
|
4132
4452
|
backgroundColor: isStylePanelOpen ? "#FF6800" : isDark ? "#2a2a2a" : "white",
|
|
4133
|
-
border: "none",
|
|
4453
|
+
border: !daemonState.connected && !isStylePanelOpen ? "2px solid #ef4444" : "none",
|
|
4134
4454
|
borderRadius: 12,
|
|
4135
4455
|
boxShadow: "0 2px 10px rgba(0,0,0,0.15)",
|
|
4136
4456
|
cursor: "pointer",
|
|
4137
4457
|
pointerEvents: "auto",
|
|
4138
4458
|
zIndex: zIndex + 5,
|
|
4139
|
-
transition: "all 0.2s ease"
|
|
4459
|
+
transition: "all 0.2s ease",
|
|
4460
|
+
animation: !daemonState.connected && !isStylePanelOpen ? "skema-glow 2s ease-in-out infinite" : "none"
|
|
4140
4461
|
},
|
|
4141
|
-
children:
|
|
4142
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4462
|
+
children: [
|
|
4463
|
+
/* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
4464
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4465
|
+
"path",
|
|
4466
|
+
{
|
|
4467
|
+
d: "M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z",
|
|
4468
|
+
stroke: isStylePanelOpen ? "white" : isDark ? "#9CA3AF" : "#6B7280",
|
|
4469
|
+
strokeWidth: "2",
|
|
4470
|
+
strokeLinecap: "round",
|
|
4471
|
+
strokeLinejoin: "round"
|
|
4472
|
+
}
|
|
4473
|
+
),
|
|
4474
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4475
|
+
"path",
|
|
4476
|
+
{
|
|
4477
|
+
d: "M19.4 15C19.2669 15.3016 19.2272 15.6362 19.286 15.9606C19.3448 16.285 19.4995 16.5843 19.73 16.82L19.79 16.88C19.976 17.0657 20.1235 17.2863 20.2241 17.5291C20.3248 17.7719 20.3766 18.0322 20.3766 18.295C20.3766 18.5578 20.3248 18.8181 20.2241 19.0609C20.1235 19.3037 19.976 19.5243 19.79 19.71C19.6043 19.896 19.3837 20.0435 19.1409 20.1441C18.8981 20.2448 18.6378 20.2966 18.375 20.2966C18.1122 20.2966 17.8519 20.2448 17.6091 20.1441C17.3663 20.0435 17.1457 19.896 16.96 19.71L16.9 19.65C16.6643 19.4195 16.365 19.2648 16.0406 19.206C15.7162 19.1472 15.3816 19.1869 15.08 19.32C14.7842 19.4468 14.532 19.6572 14.3543 19.9255C14.1766 20.1938 14.0813 20.5082 14.08 20.83V21C14.08 21.5304 13.8693 22.0391 13.4942 22.4142C13.1191 22.7893 12.6104 23 12.08 23C11.5496 23 11.0409 22.7893 10.6658 22.4142C10.2907 22.0391 10.08 21.5304 10.08 21V20.91C10.0723 20.579 9.96512 20.258 9.77251 19.9887C9.5799 19.7194 9.31074 19.5143 9 19.4C8.69838 19.2669 8.36381 19.2272 8.03941 19.286C7.71502 19.3448 7.41568 19.4995 7.18 19.73L7.12 19.79C6.93425 19.976 6.71368 20.1235 6.47088 20.2241C6.22808 20.3248 5.96783 20.3766 5.705 20.3766C5.44217 20.3766 5.18192 20.3248 4.93912 20.2241C4.69632 20.1235 4.47575 19.976 4.29 19.79C4.10405 19.6043 3.95653 19.3837 3.85588 19.1409C3.75523 18.8981 3.70343 18.6378 3.70343 18.375C3.70343 18.1122 3.75523 17.8519 3.85588 17.6091C3.95653 17.3663 4.10405 17.1457 4.29 16.96L4.35 16.9C4.58054 16.6643 4.73519 16.365 4.794 16.0406C4.85282 15.7162 4.81312 15.3816 4.68 15.08C4.55324 14.7842 4.34276 14.532 4.07447 14.3543C3.80618 14.1766 3.49179 14.0813 3.17 14.08H3C2.46957 14.08 1.96086 13.8693 1.58579 13.4942C1.21071 13.1191 1 12.6104 1 12.08C1 11.5496 1.21071 11.0409 1.58579 10.6658C1.96086 10.2907 2.46957 10.08 3 10.08H3.09C3.42099 10.0723 3.742 9.96512 4.0113 9.77251C4.28059 9.5799 4.48572 9.31074 4.6 9C4.73312 8.69838 4.77282 8.36381 4.714 8.03941C4.65519 7.71502 4.50054 7.41568 4.27 7.18L4.21 7.12C4.02405 6.93425 3.87653 6.71368 3.77588 6.47088C3.67523 6.22808 3.62343 5.96783 3.62343 5.705C3.62343 5.44217 3.67523 5.18192 3.77588 4.93912C3.87653 4.69632 4.02405 4.47575 4.21 4.29C4.39575 4.10405 4.61632 3.95653 4.85912 3.85588C5.10192 3.75523 5.36217 3.70343 5.625 3.70343C5.88783 3.70343 6.14808 3.75523 6.39088 3.85588C6.63368 3.95653 6.85425 4.10405 7.04 4.29L7.1 4.35C7.33568 4.58054 7.63502 4.73519 7.95941 4.794C8.28381 4.85282 8.61838 4.81312 8.92 4.68H9C9.29577 4.55324 9.54802 4.34276 9.72569 4.07447C9.90337 3.80618 9.99872 3.49179 10 3.17V3C10 2.46957 10.2107 1.96086 10.5858 1.58579C10.9609 1.21071 11.4696 1 12 1C12.5304 1 13.0391 1.21071 13.4142 1.58579C13.7893 1.96086 14 2.46957 14 3V3.09C14.0013 3.41179 14.0966 3.72618 14.2743 3.99447C14.452 4.26276 14.7042 4.47324 15 4.6C15.3016 4.73312 15.6362 4.77282 15.9606 4.714C16.285 4.65519 16.5843 4.50054 16.82 4.27L16.88 4.21C17.0657 4.02405 17.2863 3.87653 17.5291 3.77588C17.7719 3.67523 18.0322 3.62343 18.295 3.62343C18.5578 3.62343 18.8181 3.67523 19.0609 3.77588C19.3037 3.87653 19.5243 4.02405 19.71 4.21C19.896 4.39575 20.0435 4.61632 20.1441 4.85912C20.2448 5.10192 20.2966 5.36217 20.2966 5.625C20.2966 5.88783 20.2448 6.14808 20.1441 6.39088C20.0435 6.63368 19.896 6.85425 19.71 7.04L19.65 7.1C19.4195 7.33568 19.2648 7.63502 19.206 7.95941C19.1472 8.28381 19.1869 8.61838 19.32 8.92V9C19.4468 9.29577 19.6572 9.54802 19.9255 9.72569C20.1938 9.90337 20.5082 9.99872 20.83 10H21C21.5304 10 22.0391 10.2107 22.4142 10.5858C22.7893 10.9609 23 11.4696 23 12C23 12.5304 22.7893 13.0391 22.4142 13.4142C22.0391 13.7893 21.5304 14 21 14H20.91C20.5882 14.0013 20.2738 14.0966 20.0055 14.2743C19.7372 14.452 19.5268 14.7042 19.4 15Z",
|
|
4478
|
+
stroke: isStylePanelOpen ? "white" : isDark ? "#9CA3AF" : "#6B7280",
|
|
4479
|
+
strokeWidth: "2",
|
|
4480
|
+
strokeLinecap: "round",
|
|
4481
|
+
strokeLinejoin: "round"
|
|
4482
|
+
}
|
|
4483
|
+
)
|
|
4484
|
+
] }),
|
|
4485
|
+
!daemonState.connected && !isStylePanelOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4486
|
+
"div",
|
|
4154
4487
|
{
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4488
|
+
style: {
|
|
4489
|
+
position: "absolute",
|
|
4490
|
+
top: -4,
|
|
4491
|
+
right: -4,
|
|
4492
|
+
width: 20,
|
|
4493
|
+
height: 20,
|
|
4494
|
+
backgroundColor: "#ef4444",
|
|
4495
|
+
borderRadius: "50%",
|
|
4496
|
+
display: "flex",
|
|
4497
|
+
alignItems: "center",
|
|
4498
|
+
justifyContent: "center",
|
|
4499
|
+
animation: "skema-pulse 2s ease-in-out infinite",
|
|
4500
|
+
boxShadow: "0 2px 4px rgba(239, 68, 68, 0.4)"
|
|
4501
|
+
},
|
|
4502
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4503
|
+
"path",
|
|
4504
|
+
{
|
|
4505
|
+
d: "M12 9V13M12 17H12.01M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z",
|
|
4506
|
+
stroke: "white",
|
|
4507
|
+
strokeWidth: "2.5",
|
|
4508
|
+
strokeLinecap: "round",
|
|
4509
|
+
strokeLinejoin: "round"
|
|
4510
|
+
}
|
|
4511
|
+
) })
|
|
4160
4512
|
}
|
|
4161
4513
|
)
|
|
4162
|
-
]
|
|
4514
|
+
]
|
|
4163
4515
|
}
|
|
4164
4516
|
),
|
|
4165
4517
|
/* @__PURE__ */ jsxRuntime.jsx(
|