Files

49 lines
2.5 KiB
TypeScript
Raw Permalink Normal View History

import '../ts_web/index.js';
import { ChatSession } from '../ts/index.js';
import { getModel } from '@push.rocks/smartai';
// Read API key from a meta tag so it doesn't need to be hardcoded.
// Set it in the HTML: <meta name="anthropic-token" content="sk-...">
const metaToken = document.querySelector<HTMLMetaElement>('meta[name="anthropic-token"]');
const apiKey = metaToken?.content;
const init = () => {
const chatWindow = document.querySelector('smartchat-window') as any;
if (!chatWindow) return;
if (!apiKey || apiKey === 'YOUR_KEY_HERE') {
// Mock mode — show sample messages to preview the UI
chatWindow.headerTitle = 'SmartChat AI (Preview)';
const mockMessages = [
{ role: 'user', content: 'Hey! Can you explain what TypeScript generics are?', timestamp: Date.now() - 60000 },
{ role: 'assistant', content: 'Generics let you write reusable code that works with multiple types while keeping type safety.\n\nFor example, instead of writing separate functions for arrays of strings and numbers, you write one:\n\n```ts\nfunction first<T>(items: T[]): T {\n return items[0];\n}\n```\n\nThe `<T>` is a type parameter — TypeScript infers the actual type when you call the function. So `first([1, 2, 3])` returns a `number`, and `first(["a", "b"])` returns a `string`.', timestamp: Date.now() - 45000 },
{ role: 'user', content: 'That makes sense! Can generics have constraints?', timestamp: Date.now() - 30000 },
{ role: 'tool', content: '', toolName: 'search_docs', timestamp: Date.now() - 25000 },
{ role: 'assistant', content: 'Yes! Use `extends` to constrain what types are allowed:\n\n```ts\nfunction getLength<T extends { length: number }>(item: T): number {\n return item.length;\n}\n```\n\nThis accepts strings, arrays, or any object with a `.length` property — but rejects numbers or booleans at compile time.', timestamp: Date.now() - 20000 },
];
// Inject mock messages by setting internal state
(chatWindow as any).messages = mockMessages;
(chatWindow as any).requestUpdate();
return;
}
const model = getModel({
provider: 'anthropic',
model: 'claude-sonnet-4-5-20250929',
apiKey,
});
const session = new ChatSession({
model,
system: 'You are a friendly, concise assistant. Keep responses short unless asked for detail.',
});
chatWindow.chatSession = session;
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}