@tomehq/theme 0.6.4 → 0.7.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/ai-api-6KVITVN6.js +14 -0
- package/dist/{chunk-XTCRYWCB.js → chunk-6AD5TJ6F.js} +426 -87
- package/dist/chunk-LNWYFDZ4.js +73 -0
- package/dist/entry.js +2 -1
- package/dist/index.d.ts +250 -4
- package/dist/index.js +2 -1
- package/package.json +3 -3
- package/src/AiChat.tsx +11 -74
- package/src/Shell.tsx +168 -15
- package/src/__tests__/ai-api.test.ts +42 -0
- package/src/__tests__/ai-search.test.tsx +205 -0
- package/src/__tests__/feedback-widget.test.tsx +132 -0
- package/src/ai-api.ts +110 -0
- package/src/entry-helpers.ts +8 -3
- package/src/entry.test.tsx +6 -0
- package/src/entry.tsx +3 -0
- package/src/presets.ts +93 -3
- package/src/routing.test.ts +2 -3
- package/src/routing.ts +12 -4
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// src/ai-api.ts
|
|
2
|
+
function buildSystemPrompt(context, instruction) {
|
|
3
|
+
const base = instruction || "You are a helpful documentation assistant. Answer questions accurately based on the documentation provided below. If the answer isn't in the documentation, say so clearly. Keep answers concise and reference specific sections when possible.";
|
|
4
|
+
if (!context) return base;
|
|
5
|
+
const trimmed = context.length > 1e5 ? context.slice(0, 1e5) + "\n\n[Documentation truncated...]" : context;
|
|
6
|
+
return `${base}
|
|
7
|
+
|
|
8
|
+
Documentation:
|
|
9
|
+
${trimmed}`;
|
|
10
|
+
}
|
|
11
|
+
async function callOpenAI(messages, apiKey, model, systemPrompt) {
|
|
12
|
+
const res = await fetch("https://api.openai.com/v1/chat/completions", {
|
|
13
|
+
method: "POST",
|
|
14
|
+
headers: {
|
|
15
|
+
"Content-Type": "application/json",
|
|
16
|
+
"Authorization": `Bearer ${apiKey}`
|
|
17
|
+
},
|
|
18
|
+
body: JSON.stringify({
|
|
19
|
+
model,
|
|
20
|
+
messages: [
|
|
21
|
+
{ role: "system", content: systemPrompt },
|
|
22
|
+
...messages.map((m) => ({ role: m.role, content: m.content }))
|
|
23
|
+
]
|
|
24
|
+
})
|
|
25
|
+
});
|
|
26
|
+
if (!res.ok) {
|
|
27
|
+
const err = await res.text();
|
|
28
|
+
throw new Error(`OpenAI API error (${res.status}): ${err}`);
|
|
29
|
+
}
|
|
30
|
+
const data = await res.json();
|
|
31
|
+
return data.choices?.[0]?.message?.content || "No response.";
|
|
32
|
+
}
|
|
33
|
+
async function callAnthropic(messages, apiKey, model, systemPrompt) {
|
|
34
|
+
const res = await fetch("https://api.anthropic.com/v1/messages", {
|
|
35
|
+
method: "POST",
|
|
36
|
+
headers: {
|
|
37
|
+
"Content-Type": "application/json",
|
|
38
|
+
"x-api-key": apiKey,
|
|
39
|
+
"anthropic-version": "2023-06-01",
|
|
40
|
+
"anthropic-dangerous-direct-browser-access": "true"
|
|
41
|
+
},
|
|
42
|
+
body: JSON.stringify({
|
|
43
|
+
model,
|
|
44
|
+
max_tokens: 1024,
|
|
45
|
+
system: systemPrompt,
|
|
46
|
+
messages: messages.map((m) => ({ role: m.role, content: m.content }))
|
|
47
|
+
})
|
|
48
|
+
});
|
|
49
|
+
if (!res.ok) {
|
|
50
|
+
const err = await res.text();
|
|
51
|
+
throw new Error(`Anthropic API error (${res.status}): ${err}`);
|
|
52
|
+
}
|
|
53
|
+
const data = await res.json();
|
|
54
|
+
return data.content?.[0]?.text || "No response.";
|
|
55
|
+
}
|
|
56
|
+
function getDefaultModel(provider) {
|
|
57
|
+
if (provider === "openai") return "gpt-4o-mini";
|
|
58
|
+
return "claude-sonnet-4-20250514";
|
|
59
|
+
}
|
|
60
|
+
async function callAiProvider(provider, messages, apiKey, model, systemPrompt) {
|
|
61
|
+
if (provider === "openai") {
|
|
62
|
+
return callOpenAI(messages, apiKey, model, systemPrompt);
|
|
63
|
+
}
|
|
64
|
+
return callAnthropic(messages, apiKey, model, systemPrompt);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export {
|
|
68
|
+
buildSystemPrompt,
|
|
69
|
+
callOpenAI,
|
|
70
|
+
callAnthropic,
|
|
71
|
+
getDefaultModel,
|
|
72
|
+
callAiProvider
|
|
73
|
+
};
|
package/dist/entry.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ interface ShellProps {
|
|
|
27
27
|
};
|
|
28
28
|
search?: {
|
|
29
29
|
provider?: string;
|
|
30
|
+
ai?: boolean;
|
|
30
31
|
appId?: string;
|
|
31
32
|
apiKey?: string;
|
|
32
33
|
indexName?: string;
|
|
@@ -50,6 +51,13 @@ interface ShellProps {
|
|
|
50
51
|
link?: string;
|
|
51
52
|
dismissible?: boolean;
|
|
52
53
|
};
|
|
54
|
+
branding?: {
|
|
55
|
+
powered?: boolean;
|
|
56
|
+
};
|
|
57
|
+
feedback?: {
|
|
58
|
+
enabled?: boolean;
|
|
59
|
+
textInput?: boolean;
|
|
60
|
+
};
|
|
53
61
|
socialLinks?: Array<{
|
|
54
62
|
platform: string;
|
|
55
63
|
url: string;
|
|
@@ -97,6 +105,7 @@ interface ShellProps {
|
|
|
97
105
|
}>;
|
|
98
106
|
}>;
|
|
99
107
|
apiManifest?: any;
|
|
108
|
+
asyncApiManifest?: any;
|
|
100
109
|
apiBaseUrl?: string;
|
|
101
110
|
apiPlayground?: boolean;
|
|
102
111
|
apiAuth?: {
|
|
@@ -112,6 +121,9 @@ interface ShellProps {
|
|
|
112
121
|
header?: string;
|
|
113
122
|
};
|
|
114
123
|
}>;
|
|
124
|
+
AsyncApiReferenceComponent?: React.ComponentType<{
|
|
125
|
+
manifest: any;
|
|
126
|
+
}>;
|
|
115
127
|
onNavigate: (id: string) => void;
|
|
116
128
|
allPages: Array<{
|
|
117
129
|
id: string;
|
|
@@ -138,7 +150,7 @@ interface ShellProps {
|
|
|
138
150
|
PageFooter?: React.ComponentType<any>;
|
|
139
151
|
};
|
|
140
152
|
}
|
|
141
|
-
declare function Shell({ config, navigation, currentPageId, pageHtml, pageComponent, mdxComponents, pageTitle, pageDescription, headings, tocEnabled, editUrl, lastUpdated, changelogEntries, apiManifest, apiBaseUrl, apiPlayground, apiAuth, ApiReferenceComponent, onNavigate, allPages, versioning, currentVersion, i18n, currentLocale, docContext, basePath, isDraft, dir: dirProp, overrides, }: ShellProps): react_jsx_runtime.JSX.Element;
|
|
153
|
+
declare function Shell({ config, navigation, currentPageId, pageHtml, pageComponent, mdxComponents, pageTitle, pageDescription, headings, tocEnabled, editUrl, lastUpdated, changelogEntries, apiManifest, asyncApiManifest, apiBaseUrl, apiPlayground, apiAuth, ApiReferenceComponent, AsyncApiReferenceComponent, onNavigate, allPages, versioning, currentVersion, i18n, currentLocale, docContext, basePath, isDraft, dir: dirProp, overrides, }: ShellProps): react_jsx_runtime.JSX.Element;
|
|
142
154
|
|
|
143
155
|
interface AiChatProps {
|
|
144
156
|
provider: "openai" | "anthropic" | "custom";
|
|
@@ -260,7 +272,7 @@ declare const THEME_PRESETS: {
|
|
|
260
272
|
readonly bd: "#1a1a25";
|
|
261
273
|
readonly tx: "#d4ff00";
|
|
262
274
|
readonly tx2: "#8a90a0";
|
|
263
|
-
readonly txM: "#
|
|
275
|
+
readonly txM: "#7e8494";
|
|
264
276
|
readonly ac: "#6666ff";
|
|
265
277
|
readonly acD: "rgba(102,102,255,0.10)";
|
|
266
278
|
readonly acT: "#8080ff";
|
|
@@ -276,7 +288,7 @@ declare const THEME_PRESETS: {
|
|
|
276
288
|
readonly bd: "#d0d4db";
|
|
277
289
|
readonly tx: "#0f1219";
|
|
278
290
|
readonly tx2: "#4a5060";
|
|
279
|
-
readonly txM: "#
|
|
291
|
+
readonly txM: "#5c6272";
|
|
280
292
|
readonly ac: "#2020cc";
|
|
281
293
|
readonly acD: "rgba(32,32,204,0.08)";
|
|
282
294
|
readonly acT: "#1a1aa8";
|
|
@@ -299,7 +311,7 @@ declare const THEME_PRESETS: {
|
|
|
299
311
|
readonly bd: "#21262d";
|
|
300
312
|
readonly tx: "#e6edf3";
|
|
301
313
|
readonly tx2: "#8b949e";
|
|
302
|
-
readonly txM: "#
|
|
314
|
+
readonly txM: "#7d858f";
|
|
303
315
|
readonly ac: "#0ea371";
|
|
304
316
|
readonly acD: "rgba(14,163,113,0.10)";
|
|
305
317
|
readonly acT: "#2dd4a0";
|
|
@@ -330,6 +342,240 @@ declare const THEME_PRESETS: {
|
|
|
330
342
|
readonly code: "Fira Code";
|
|
331
343
|
};
|
|
332
344
|
};
|
|
345
|
+
readonly ocean: {
|
|
346
|
+
readonly dark: {
|
|
347
|
+
readonly bg: "#0a1628";
|
|
348
|
+
readonly sf: "#0f1d33";
|
|
349
|
+
readonly sfH: "#142540";
|
|
350
|
+
readonly bd: "#1a2e50";
|
|
351
|
+
readonly tx: "#e0e8f0";
|
|
352
|
+
readonly tx2: "#8ca0b8";
|
|
353
|
+
readonly txM: "#7b92aa";
|
|
354
|
+
readonly ac: "#0ea5e9";
|
|
355
|
+
readonly acD: "rgba(14,165,233,0.10)";
|
|
356
|
+
readonly acT: "#38bdf8";
|
|
357
|
+
readonly cdBg: "#081320";
|
|
358
|
+
readonly cdTx: "#94b4d0";
|
|
359
|
+
readonly sbBg: "#0a1628";
|
|
360
|
+
readonly hdBg: "rgba(10,22,40,0.90)";
|
|
361
|
+
};
|
|
362
|
+
readonly light: {
|
|
363
|
+
readonly bg: "#f0f7ff";
|
|
364
|
+
readonly sf: "#ffffff";
|
|
365
|
+
readonly sfH: "#e8f0fa";
|
|
366
|
+
readonly bd: "#ccdcef";
|
|
367
|
+
readonly tx: "#0c1929";
|
|
368
|
+
readonly tx2: "#3d5a78";
|
|
369
|
+
readonly txM: "#4a6a88";
|
|
370
|
+
readonly ac: "#0369a1";
|
|
371
|
+
readonly acD: "rgba(3,105,161,0.07)";
|
|
372
|
+
readonly acT: "#025e8f";
|
|
373
|
+
readonly cdBg: "#e4edf7";
|
|
374
|
+
readonly cdTx: "#1a3050";
|
|
375
|
+
readonly sbBg: "#eef4fc";
|
|
376
|
+
readonly hdBg: "rgba(240,247,255,0.92)";
|
|
377
|
+
};
|
|
378
|
+
readonly fonts: {
|
|
379
|
+
readonly heading: "Outfit";
|
|
380
|
+
readonly body: "Inter";
|
|
381
|
+
readonly code: "JetBrains Mono";
|
|
382
|
+
};
|
|
383
|
+
};
|
|
384
|
+
readonly rose: {
|
|
385
|
+
readonly dark: {
|
|
386
|
+
readonly bg: "#0f0a10";
|
|
387
|
+
readonly sf: "#171118";
|
|
388
|
+
readonly sfH: "#1e1620";
|
|
389
|
+
readonly bd: "#2a1f2c";
|
|
390
|
+
readonly tx: "#f0e4f0";
|
|
391
|
+
readonly tx2: "#b09ab0";
|
|
392
|
+
readonly txM: "#8a7890";
|
|
393
|
+
readonly ac: "#f43f5e";
|
|
394
|
+
readonly acD: "rgba(244,63,94,0.10)";
|
|
395
|
+
readonly acT: "#fb7185";
|
|
396
|
+
readonly cdBg: "#0d080e";
|
|
397
|
+
readonly cdTx: "#c8aec8";
|
|
398
|
+
readonly sbBg: "#0f0a10";
|
|
399
|
+
readonly hdBg: "rgba(15,10,16,0.88)";
|
|
400
|
+
};
|
|
401
|
+
readonly light: {
|
|
402
|
+
readonly bg: "#fef7f7";
|
|
403
|
+
readonly sf: "#ffffff";
|
|
404
|
+
readonly sfH: "#fceef0";
|
|
405
|
+
readonly bd: "#f0d4d8";
|
|
406
|
+
readonly tx: "#1a0f12";
|
|
407
|
+
readonly tx2: "#6b4048";
|
|
408
|
+
readonly txM: "#8a5a64";
|
|
409
|
+
readonly ac: "#c81e3e";
|
|
410
|
+
readonly acD: "rgba(200,30,62,0.06)";
|
|
411
|
+
readonly acT: "#a81835";
|
|
412
|
+
readonly cdBg: "#f8eaec";
|
|
413
|
+
readonly cdTx: "#3a1a22";
|
|
414
|
+
readonly sbBg: "#fdf2f4";
|
|
415
|
+
readonly hdBg: "rgba(254,247,247,0.92)";
|
|
416
|
+
};
|
|
417
|
+
readonly fonts: {
|
|
418
|
+
readonly heading: "Playfair Display";
|
|
419
|
+
readonly body: "Source Sans 3";
|
|
420
|
+
readonly code: "Fira Code";
|
|
421
|
+
};
|
|
422
|
+
};
|
|
423
|
+
readonly forest: {
|
|
424
|
+
readonly dark: {
|
|
425
|
+
readonly bg: "#091209";
|
|
426
|
+
readonly sf: "#0f1a0f";
|
|
427
|
+
readonly sfH: "#152215";
|
|
428
|
+
readonly bd: "#1e2e1e";
|
|
429
|
+
readonly tx: "#e0f0e0";
|
|
430
|
+
readonly tx2: "#8aaa8a";
|
|
431
|
+
readonly txM: "#6a8a6a";
|
|
432
|
+
readonly ac: "#22c55e";
|
|
433
|
+
readonly acD: "rgba(34,197,94,0.10)";
|
|
434
|
+
readonly acT: "#4ade80";
|
|
435
|
+
readonly cdBg: "#070e07";
|
|
436
|
+
readonly cdTx: "#a0c4a0";
|
|
437
|
+
readonly sbBg: "#091209";
|
|
438
|
+
readonly hdBg: "rgba(9,18,9,0.90)";
|
|
439
|
+
};
|
|
440
|
+
readonly light: {
|
|
441
|
+
readonly bg: "#f4faf4";
|
|
442
|
+
readonly sf: "#ffffff";
|
|
443
|
+
readonly sfH: "#e8f4e8";
|
|
444
|
+
readonly bd: "#c8e0c8";
|
|
445
|
+
readonly tx: "#0a1a0a";
|
|
446
|
+
readonly tx2: "#3a5a3a";
|
|
447
|
+
readonly txM: "#5a7a5a";
|
|
448
|
+
readonly ac: "#15803d";
|
|
449
|
+
readonly acD: "rgba(21,128,61,0.07)";
|
|
450
|
+
readonly acT: "#116d34";
|
|
451
|
+
readonly cdBg: "#e4f2e4";
|
|
452
|
+
readonly cdTx: "#1a3a1a";
|
|
453
|
+
readonly sbBg: "#eef6ee";
|
|
454
|
+
readonly hdBg: "rgba(244,250,244,0.92)";
|
|
455
|
+
};
|
|
456
|
+
readonly fonts: {
|
|
457
|
+
readonly heading: "Merriweather";
|
|
458
|
+
readonly body: "Nunito Sans";
|
|
459
|
+
readonly code: "Source Code Pro";
|
|
460
|
+
};
|
|
461
|
+
};
|
|
462
|
+
readonly slate: {
|
|
463
|
+
readonly dark: {
|
|
464
|
+
readonly bg: "#0f1115";
|
|
465
|
+
readonly sf: "#16181e";
|
|
466
|
+
readonly sfH: "#1c1f26";
|
|
467
|
+
readonly bd: "#24272e";
|
|
468
|
+
readonly tx: "#e2e4e8";
|
|
469
|
+
readonly tx2: "#9498a0";
|
|
470
|
+
readonly txM: "#808690";
|
|
471
|
+
readonly ac: "#94a3b8";
|
|
472
|
+
readonly acD: "rgba(148,163,184,0.10)";
|
|
473
|
+
readonly acT: "#b0bec8";
|
|
474
|
+
readonly cdBg: "#0c0e12";
|
|
475
|
+
readonly cdTx: "#a8acb4";
|
|
476
|
+
readonly sbBg: "#0f1115";
|
|
477
|
+
readonly hdBg: "rgba(15,17,21,0.88)";
|
|
478
|
+
};
|
|
479
|
+
readonly light: {
|
|
480
|
+
readonly bg: "#f8fafc";
|
|
481
|
+
readonly sf: "#ffffff";
|
|
482
|
+
readonly sfH: "#f1f5f9";
|
|
483
|
+
readonly bd: "#d8dfe7";
|
|
484
|
+
readonly tx: "#0f172a";
|
|
485
|
+
readonly tx2: "#475569";
|
|
486
|
+
readonly txM: "#64748b";
|
|
487
|
+
readonly ac: "#475569";
|
|
488
|
+
readonly acD: "rgba(71,85,105,0.07)";
|
|
489
|
+
readonly acT: "#3a4a5c";
|
|
490
|
+
readonly cdBg: "#f0f4f8";
|
|
491
|
+
readonly cdTx: "#1e293b";
|
|
492
|
+
readonly sbBg: "#f5f7fa";
|
|
493
|
+
readonly hdBg: "rgba(248,250,252,0.92)";
|
|
494
|
+
};
|
|
495
|
+
readonly fonts: {
|
|
496
|
+
readonly heading: "Inter";
|
|
497
|
+
readonly body: "Inter";
|
|
498
|
+
readonly code: "JetBrains Mono";
|
|
499
|
+
};
|
|
500
|
+
};
|
|
501
|
+
readonly sunset: {
|
|
502
|
+
readonly dark: {
|
|
503
|
+
readonly bg: "#120c06";
|
|
504
|
+
readonly sf: "#1a1208";
|
|
505
|
+
readonly sfH: "#22180c";
|
|
506
|
+
readonly bd: "#2e2010";
|
|
507
|
+
readonly tx: "#f0e4d4";
|
|
508
|
+
readonly tx2: "#b0986a";
|
|
509
|
+
readonly txM: "#907850";
|
|
510
|
+
readonly ac: "#f97316";
|
|
511
|
+
readonly acD: "rgba(249,115,22,0.10)";
|
|
512
|
+
readonly acT: "#fb923c";
|
|
513
|
+
readonly cdBg: "#0e0a05";
|
|
514
|
+
readonly cdTx: "#c8aa78";
|
|
515
|
+
readonly sbBg: "#120c06";
|
|
516
|
+
readonly hdBg: "rgba(18,12,6,0.90)";
|
|
517
|
+
};
|
|
518
|
+
readonly light: {
|
|
519
|
+
readonly bg: "#fffbf5";
|
|
520
|
+
readonly sf: "#ffffff";
|
|
521
|
+
readonly sfH: "#fef3e6";
|
|
522
|
+
readonly bd: "#f0d8b8";
|
|
523
|
+
readonly tx: "#1a1008";
|
|
524
|
+
readonly tx2: "#6a5030";
|
|
525
|
+
readonly txM: "#8a6840";
|
|
526
|
+
readonly ac: "#c2410c";
|
|
527
|
+
readonly acD: "rgba(194,65,12,0.06)";
|
|
528
|
+
readonly acT: "#a63a0a";
|
|
529
|
+
readonly cdBg: "#faf0e2";
|
|
530
|
+
readonly cdTx: "#3a2810";
|
|
531
|
+
readonly sbBg: "#fdf6ec";
|
|
532
|
+
readonly hdBg: "rgba(255,251,245,0.92)";
|
|
533
|
+
};
|
|
534
|
+
readonly fonts: {
|
|
535
|
+
readonly heading: "Sora";
|
|
536
|
+
readonly body: "DM Sans";
|
|
537
|
+
readonly code: "Fira Code";
|
|
538
|
+
};
|
|
539
|
+
};
|
|
540
|
+
readonly carbon: {
|
|
541
|
+
readonly dark: {
|
|
542
|
+
readonly bg: "#080808";
|
|
543
|
+
readonly sf: "#101010";
|
|
544
|
+
readonly sfH: "#171717";
|
|
545
|
+
readonly bd: "#1f1f1f";
|
|
546
|
+
readonly tx: "#d4d4d4";
|
|
547
|
+
readonly tx2: "#888888";
|
|
548
|
+
readonly txM: "#787878";
|
|
549
|
+
readonly ac: "#e4e4e4";
|
|
550
|
+
readonly acD: "rgba(228,228,228,0.08)";
|
|
551
|
+
readonly acT: "#f0f0f0";
|
|
552
|
+
readonly cdBg: "#0a0a0a";
|
|
553
|
+
readonly cdTx: "#a0a0a0";
|
|
554
|
+
readonly sbBg: "#080808";
|
|
555
|
+
readonly hdBg: "rgba(8,8,8,0.90)";
|
|
556
|
+
};
|
|
557
|
+
readonly light: {
|
|
558
|
+
readonly bg: "#f5f5f5";
|
|
559
|
+
readonly sf: "#ffffff";
|
|
560
|
+
readonly sfH: "#ebebeb";
|
|
561
|
+
readonly bd: "#d4d4d4";
|
|
562
|
+
readonly tx: "#171717";
|
|
563
|
+
readonly tx2: "#525252";
|
|
564
|
+
readonly txM: "#6b6b6b";
|
|
565
|
+
readonly ac: "#262626";
|
|
566
|
+
readonly acD: "rgba(38,38,38,0.06)";
|
|
567
|
+
readonly acT: "#1a1a1a";
|
|
568
|
+
readonly cdBg: "#eaeaea";
|
|
569
|
+
readonly cdTx: "#1a1a1a";
|
|
570
|
+
readonly sbBg: "#f0f0f0";
|
|
571
|
+
readonly hdBg: "rgba(245,245,245,0.92)";
|
|
572
|
+
};
|
|
573
|
+
readonly fonts: {
|
|
574
|
+
readonly heading: "Geist";
|
|
575
|
+
readonly body: "Geist";
|
|
576
|
+
readonly code: "Geist Mono";
|
|
577
|
+
};
|
|
578
|
+
};
|
|
333
579
|
};
|
|
334
580
|
type PresetName = keyof typeof THEME_PRESETS;
|
|
335
581
|
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomehq/theme",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Tome default theme and React app shell",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.tsx",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"./entry": "./src/entry.tsx"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@tomehq/components": "0.
|
|
13
|
-
"@tomehq/core": "0.
|
|
12
|
+
"@tomehq/components": "0.7.0",
|
|
13
|
+
"@tomehq/core": "0.7.0"
|
|
14
14
|
},
|
|
15
15
|
"peerDependencies": {
|
|
16
16
|
"react": "^18.0.0 || ^19.0.0",
|
package/src/AiChat.tsx
CHANGED
|
@@ -35,78 +35,14 @@ const SendIcon = () => (
|
|
|
35
35
|
</svg>
|
|
36
36
|
);
|
|
37
37
|
|
|
38
|
-
// ── API HELPERS
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return prompt;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async function callOpenAI(
|
|
50
|
-
messages: Message[],
|
|
51
|
-
apiKey: string,
|
|
52
|
-
model: string,
|
|
53
|
-
context?: string,
|
|
54
|
-
): Promise<string> {
|
|
55
|
-
const res = await fetch("https://api.openai.com/v1/chat/completions", {
|
|
56
|
-
method: "POST",
|
|
57
|
-
headers: {
|
|
58
|
-
"Content-Type": "application/json",
|
|
59
|
-
"Authorization": `Bearer ${apiKey}`,
|
|
60
|
-
},
|
|
61
|
-
body: JSON.stringify({
|
|
62
|
-
model,
|
|
63
|
-
messages: [
|
|
64
|
-
{ role: "system", content: buildSystemPrompt(context) },
|
|
65
|
-
...messages.map((m) => ({ role: m.role, content: m.content })),
|
|
66
|
-
],
|
|
67
|
-
}),
|
|
68
|
-
});
|
|
69
|
-
if (!res.ok) {
|
|
70
|
-
const err = await res.text();
|
|
71
|
-
throw new Error(`OpenAI API error (${res.status}): ${err}`);
|
|
72
|
-
}
|
|
73
|
-
const data = await res.json();
|
|
74
|
-
return data.choices?.[0]?.message?.content || "No response.";
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async function callAnthropic(
|
|
78
|
-
messages: Message[],
|
|
79
|
-
apiKey: string,
|
|
80
|
-
model: string,
|
|
81
|
-
context?: string,
|
|
82
|
-
): Promise<string> {
|
|
83
|
-
const res = await fetch("https://api.anthropic.com/v1/messages", {
|
|
84
|
-
method: "POST",
|
|
85
|
-
headers: {
|
|
86
|
-
"Content-Type": "application/json",
|
|
87
|
-
"x-api-key": apiKey,
|
|
88
|
-
"anthropic-version": "2023-06-01",
|
|
89
|
-
"anthropic-dangerous-direct-browser-access": "true",
|
|
90
|
-
},
|
|
91
|
-
body: JSON.stringify({
|
|
92
|
-
model,
|
|
93
|
-
max_tokens: 1024,
|
|
94
|
-
system: buildSystemPrompt(context),
|
|
95
|
-
messages: messages.map((m) => ({ role: m.role, content: m.content })),
|
|
96
|
-
}),
|
|
97
|
-
});
|
|
98
|
-
if (!res.ok) {
|
|
99
|
-
const err = await res.text();
|
|
100
|
-
throw new Error(`Anthropic API error (${res.status}): ${err}`);
|
|
101
|
-
}
|
|
102
|
-
const data = await res.json();
|
|
103
|
-
return data.content?.[0]?.text || "No response.";
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function getDefaultModel(provider: string): string {
|
|
107
|
-
if (provider === "openai") return "gpt-4o-mini";
|
|
108
|
-
return "claude-sonnet-4-20250514";
|
|
109
|
-
}
|
|
38
|
+
// ── API HELPERS (shared with AI search) ─────────────────
|
|
39
|
+
import {
|
|
40
|
+
buildSystemPrompt,
|
|
41
|
+
callOpenAI,
|
|
42
|
+
callAnthropic,
|
|
43
|
+
getDefaultModel,
|
|
44
|
+
type AiMessage,
|
|
45
|
+
} from "./ai-api.js";
|
|
110
46
|
|
|
111
47
|
// ── COMPONENT ───────────────────────────────────────────
|
|
112
48
|
export function AiChat({ provider, model, apiKey, context }: AiChatProps) {
|
|
@@ -147,10 +83,11 @@ export function AiChat({ provider, model, apiKey, context }: AiChatProps) {
|
|
|
147
83
|
|
|
148
84
|
try {
|
|
149
85
|
let response: string;
|
|
86
|
+
const sysPrompt = buildSystemPrompt(context);
|
|
150
87
|
if (provider === "openai") {
|
|
151
|
-
response = await callOpenAI(updatedMessages, resolvedKey, resolvedModel,
|
|
88
|
+
response = await callOpenAI(updatedMessages as AiMessage[], resolvedKey, resolvedModel, sysPrompt);
|
|
152
89
|
} else {
|
|
153
|
-
response = await callAnthropic(updatedMessages, resolvedKey, resolvedModel,
|
|
90
|
+
response = await callAnthropic(updatedMessages as AiMessage[], resolvedKey, resolvedModel, sysPrompt);
|
|
154
91
|
}
|
|
155
92
|
setMessages((prev) => [...prev, { role: "assistant", content: response }]);
|
|
156
93
|
} catch (err) {
|