diff --git a/package-lock.json b/package-lock.json index b673cbff..c0b99357 100644 --- a/package-lock.json +++ b/package-lock.json @@ -817,9 +817,9 @@ } }, "node_modules/@mariozechner/mini-lit": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@mariozechner/mini-lit/-/mini-lit-0.1.8.tgz", - "integrity": "sha512-7jG0ESWq7emYgyp2xj7osN+DLXGfFkepPZE0nRCoIc7idLXWAGumSz/k7cZxoNyb50iVUGdVzT3rZPr8HtGClw==", + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@mariozechner/mini-lit/-/mini-lit-0.1.9.tgz", + "integrity": "sha512-RT+9+76YnFowTLyjJKDk6Ll6JC9qJ0SAbttdcJcgC64B9YA03Fa/PC6UxcI0PEmE+QWUdPTEyXJ1U5UsgzQxTw==", "dependencies": { "@preact/signals-core": "^1.12.1", "class-variance-authority": "^0.7.1", @@ -3698,6 +3698,15 @@ } } }, + "node_modules/ollama": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/ollama/-/ollama-0.6.0.tgz", + "integrity": "sha512-FHjdU2Ok5x2HZsxPui/MBJZ5J+HzmxoWYa/p9wk736eT+uAhS8nvIICar5YgwlG5MFNjDR6UA5F3RSKq+JseOA==", + "license": "MIT", + "dependencies": { + "whatwg-fetch": "^3.6.20" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4654,6 +4663,12 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "license": "BSD-2-Clause" }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "license": "MIT" + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -5451,17 +5466,18 @@ "jszip": "^3.10.1", "lit": "^3.3.1", "lucide": "^0.544.0", + "ollama": "^0.6.0", "pdfjs-dist": "^5.4.149", "xlsx": "^0.18.5" }, "devDependencies": { - "@mariozechner/mini-lit": "^0.1.8", + "@mariozechner/mini-lit": "^0.1.9", "@tailwindcss/cli": "^4.0.0-beta.14", "concurrently": "^9.2.1", "typescript": "^5.7.3" }, "peerDependencies": { - "@mariozechner/mini-lit": "^0.1.8" + "@mariozechner/mini-lit": "^0.1.9" } } } diff --git a/packages/ai/src/models.generated.ts b/packages/ai/src/models.generated.ts index 6f552571..ef2c8479 100644 --- a/packages/ai/src/models.generated.ts +++ b/packages/ai/src/models.generated.ts @@ -2221,13 +2221,13 @@ export const MODELS = { reasoning: true, input: ["text"], cost: { - input: 0, - output: 0, + input: 0.14, + output: 0.86, cacheRead: 0, cacheWrite: 0, }, - contextWindow: 32768, - maxTokens: 32768, + contextWindow: 131072, + maxTokens: 131072, } satisfies Model<"openai-completions">, "qwen/qwen3-235b-a22b-thinking-2507": { id: "qwen/qwen3-235b-a22b-thinking-2507", @@ -3283,23 +3283,6 @@ export const MODELS = { contextWindow: 32768, maxTokens: 4096, } satisfies Model<"openai-completions">, - "cohere/command-r-plus-08-2024": { - id: "cohere/command-r-plus-08-2024", - name: "Cohere: Command R+ (08-2024)", - api: "openai-completions", - provider: "openrouter", - baseUrl: "https://openrouter.ai/api/v1", - reasoning: false, - input: ["text"], - cost: { - input: 2.5, - output: 10, - cacheRead: 0, - cacheWrite: 0, - }, - contextWindow: 128000, - maxTokens: 4000, - } satisfies Model<"openai-completions">, "cohere/command-r-08-2024": { id: "cohere/command-r-08-2024", name: "Cohere: Command R (08-2024)", @@ -3317,6 +3300,23 @@ export const MODELS = { contextWindow: 128000, maxTokens: 4000, } satisfies Model<"openai-completions">, + "cohere/command-r-plus-08-2024": { + id: "cohere/command-r-plus-08-2024", + name: "Cohere: Command R+ (08-2024)", + api: "openai-completions", + provider: "openrouter", + baseUrl: "https://openrouter.ai/api/v1", + reasoning: false, + input: ["text"], + cost: { + input: 2.5, + output: 10, + cacheRead: 0, + cacheWrite: 0, + }, + contextWindow: 128000, + maxTokens: 4000, + } satisfies Model<"openai-completions">, "microsoft/phi-3.5-mini-128k-instruct": { id: "microsoft/phi-3.5-mini-128k-instruct", name: "Microsoft: Phi-3.5 Mini 128K Instruct", @@ -3351,22 +3351,22 @@ export const MODELS = { contextWindow: 65000, maxTokens: 4096, } satisfies Model<"openai-completions">, - "meta-llama/llama-3.1-8b-instruct": { - id: "meta-llama/llama-3.1-8b-instruct", - name: "Meta: Llama 3.1 8B Instruct", + "meta-llama/llama-3.1-70b-instruct": { + id: "meta-llama/llama-3.1-70b-instruct", + name: "Meta: Llama 3.1 70B Instruct", api: "openai-completions", provider: "openrouter", baseUrl: "https://openrouter.ai/api/v1", reasoning: false, input: ["text"], cost: { - input: 0.02, - output: 0.03, + input: 0.39999999999999997, + output: 0.39999999999999997, cacheRead: 0, cacheWrite: 0, }, contextWindow: 131072, - maxTokens: 16384, + maxTokens: 4096, } satisfies Model<"openai-completions">, "meta-llama/llama-3.1-405b-instruct": { id: "meta-llama/llama-3.1-405b-instruct", @@ -3385,22 +3385,22 @@ export const MODELS = { contextWindow: 32768, maxTokens: 16384, } satisfies Model<"openai-completions">, - "meta-llama/llama-3.1-70b-instruct": { - id: "meta-llama/llama-3.1-70b-instruct", - name: "Meta: Llama 3.1 70B Instruct", + "meta-llama/llama-3.1-8b-instruct": { + id: "meta-llama/llama-3.1-8b-instruct", + name: "Meta: Llama 3.1 8B Instruct", api: "openai-completions", provider: "openrouter", baseUrl: "https://openrouter.ai/api/v1", reasoning: false, input: ["text"], cost: { - input: 0.39999999999999997, - output: 0.39999999999999997, + input: 0.02, + output: 0.03, cacheRead: 0, cacheWrite: 0, }, contextWindow: 131072, - maxTokens: 4096, + maxTokens: 16384, } satisfies Model<"openai-completions">, "mistralai/mistral-nemo": { id: "mistralai/mistral-nemo", @@ -3572,23 +3572,6 @@ export const MODELS = { contextWindow: 128000, maxTokens: 4096, } satisfies Model<"openai-completions">, - "mistralai/mistral-small": { - id: "mistralai/mistral-small", - name: "Mistral Small", - api: "openai-completions", - provider: "openrouter", - baseUrl: "https://openrouter.ai/api/v1", - reasoning: false, - input: ["text"], - cost: { - input: 0.19999999999999998, - output: 0.6, - cacheRead: 0, - cacheWrite: 0, - }, - contextWindow: 32768, - maxTokens: 4096, - } satisfies Model<"openai-completions">, "mistralai/mistral-tiny": { id: "mistralai/mistral-tiny", name: "Mistral Tiny", @@ -3606,6 +3589,23 @@ export const MODELS = { contextWindow: 32768, maxTokens: 4096, } satisfies Model<"openai-completions">, + "mistralai/mistral-small": { + id: "mistralai/mistral-small", + name: "Mistral Small", + api: "openai-completions", + provider: "openrouter", + baseUrl: "https://openrouter.ai/api/v1", + reasoning: false, + input: ["text"], + cost: { + input: 0.19999999999999998, + output: 0.6, + cacheRead: 0, + cacheWrite: 0, + }, + contextWindow: 32768, + maxTokens: 4096, + } satisfies Model<"openai-completions">, "mistralai/mixtral-8x7b-instruct": { id: "mistralai/mixtral-8x7b-instruct", name: "Mistral: Mixtral 8x7B Instruct", diff --git a/packages/web-ui/package.json b/packages/web-ui/package.json index b25b1407..e6494133 100644 --- a/packages/web-ui/package.json +++ b/packages/web-ui/package.json @@ -22,14 +22,15 @@ "jszip": "^3.10.1", "lit": "^3.3.1", "lucide": "^0.544.0", + "ollama": "^0.6.0", "pdfjs-dist": "^5.4.149", "xlsx": "^0.18.5" }, "peerDependencies": { - "@mariozechner/mini-lit": "^0.1.8" + "@mariozechner/mini-lit": "^0.1.9" }, "devDependencies": { - "@mariozechner/mini-lit": "^0.1.8", + "@mariozechner/mini-lit": "^0.1.9", "@tailwindcss/cli": "^4.0.0-beta.14", "concurrently": "^9.2.1", "typescript": "^5.7.3" diff --git a/packages/web-ui/src/components/Messages.ts b/packages/web-ui/src/components/Messages.ts index 68162ba5..4261f85f 100644 --- a/packages/web-ui/src/components/Messages.ts +++ b/packages/web-ui/src/components/Messages.ts @@ -1,4 +1,4 @@ -import { Button, html, icon } from "@mariozechner/mini-lit"; +import { html } from "@mariozechner/mini-lit"; import type { AgentTool, AssistantMessage as AssistantMessageType, @@ -7,8 +7,7 @@ import type { UserMessage as UserMessageType, } from "@mariozechner/pi-ai"; import { LitElement, type TemplateResult } from "lit"; -import { customElement, property, state } from "lit/decorators.js"; -import { Bug, Loader, Wrench } from "lucide"; +import { customElement, property } from "lit/decorators.js"; import { renderTool } from "../tools/index.js"; import type { Attachment } from "../utils/attachment-utils.js"; import { formatUsage } from "../utils/format.js"; diff --git a/packages/web-ui/src/dialogs/ModelSelector.ts b/packages/web-ui/src/dialogs/ModelSelector.ts index 36ab9121..8ed06c70 100644 --- a/packages/web-ui/src/dialogs/ModelSelector.ts +++ b/packages/web-ui/src/dialogs/ModelSelector.ts @@ -101,7 +101,7 @@ export class ModelSelector extends DialogBase { // Fetch details for each model and convert to Model format const ollamaModelPromises: Promise | null>[] = models - .map(async (model) => { + .map(async (model: any) => { try { // Get model details const details = await ollama.show({ @@ -144,7 +144,7 @@ export class ModelSelector extends DialogBase { return null; } }) - .filter((m) => m !== null); + .filter((m: any) => m !== null); const results = await Promise.all(ollamaModelPromises); this.ollamaModels = results.filter((m): m is Model => m !== null); diff --git a/packages/web-ui/src/dialogs/SettingsDialog.ts b/packages/web-ui/src/dialogs/SettingsDialog.ts index 20717367..1ab617f3 100644 --- a/packages/web-ui/src/dialogs/SettingsDialog.ts +++ b/packages/web-ui/src/dialogs/SettingsDialog.ts @@ -179,6 +179,7 @@ export class SettingsDialog extends LitElement { }, width: "min(1000px, 90vw)", height: "min(800px, 90vh)", + backdropClassName: "bg-black/50 backdrop-blur-sm", children: html` ${DialogContent({ className: "h-full p-6", diff --git a/packages/web-ui/src/storage/backends/indexeddb-storage-backend.ts b/packages/web-ui/src/storage/backends/indexeddb-storage-backend.ts index e6b9f040..5c603df0 100644 --- a/packages/web-ui/src/storage/backends/indexeddb-storage-backend.ts +++ b/packages/web-ui/src/storage/backends/indexeddb-storage-backend.ts @@ -17,7 +17,7 @@ export class IndexedDBStorageBackend implements StorageBackend { request.onerror = () => reject(request.error); request.onsuccess = () => resolve(request.result); - request.onupgradeneeded = (event) => { + request.onupgradeneeded = (_event) => { const db = request.result; // Create object stores from config @@ -145,7 +145,7 @@ export class IndexedDBStorageBackend implements StorageBackend { } async getQuotaInfo(): Promise<{ usage: number; quota: number; percent: number }> { - if (navigator.storage && navigator.storage.estimate) { + if (navigator.storage?.estimate) { const estimate = await navigator.storage.estimate(); return { usage: estimate.usage || 0, @@ -157,7 +157,7 @@ export class IndexedDBStorageBackend implements StorageBackend { } async requestPersistence(): Promise { - if (navigator.storage && navigator.storage.persist) { + if (navigator.storage?.persist) { return await navigator.storage.persist(); } return false; diff --git a/packages/web-ui/src/storage/stores/sessions-store.ts b/packages/web-ui/src/storage/stores/sessions-store.ts index eabc0577..d6a05a03 100644 --- a/packages/web-ui/src/storage/stores/sessions-store.ts +++ b/packages/web-ui/src/storage/stores/sessions-store.ts @@ -83,4 +83,51 @@ export class SessionsStore extends Store { async requestPersistence(): Promise { return this.getBackend().requestPersistence(); } + + // Alias methods for backward compatibility + async saveSession(id: string, state: any, metadata: SessionMetadata | undefined, title?: string): Promise { + // If metadata is provided, use it; otherwise create it from state + const meta: SessionMetadata = metadata || { + id, + title: title || "", + createdAt: new Date().toISOString(), + lastModified: new Date().toISOString(), + messageCount: state.messages?.length || 0, + usage: state.usage || { + input: 0, + output: 0, + cacheRead: 0, + cacheWrite: 0, + cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }, + }, + modelId: state.model?.id || null, + thinkingLevel: state.thinkingLevel || "off", + preview: "", + }; + + const data: SessionData = { + id, + title: title || meta.title, + model: state.model, + thinkingLevel: state.thinkingLevel, + messages: state.messages || [], + createdAt: meta.createdAt, + lastModified: new Date().toISOString(), + }; + + await this.save(data, meta); + } + + async loadSession(id: string): Promise { + return this.get(id); + } + + async getLatestSessionId(): Promise { + const allMetadata = await this.getAllMetadata(); + if (allMetadata.length === 0) return null; + + // Sort by lastModified descending + allMetadata.sort((a, b) => b.lastModified.localeCompare(a.lastModified)); + return allMetadata[0].id; + } } diff --git a/packages/web-ui/src/tools/artifacts/artifacts-tool-renderer.ts b/packages/web-ui/src/tools/artifacts/artifacts-tool-renderer.ts index 980d7e65..bf556d26 100644 --- a/packages/web-ui/src/tools/artifacts/artifacts-tool-renderer.ts +++ b/packages/web-ui/src/tools/artifacts/artifacts-tool-renderer.ts @@ -1,8 +1,8 @@ -import { Diff, html, icon, iconDOM, type TemplateResult } from "@mariozechner/mini-lit"; +import { Diff, html, type TemplateResult } from "@mariozechner/mini-lit"; import "@mariozechner/mini-lit/dist/CodeBlock.js"; import type { ToolResultMessage } from "@mariozechner/pi-ai"; import { createRef, ref } from "lit/directives/ref.js"; -import { ChevronDown, ChevronRight, FileCode2, Loader } from "lucide"; +import { FileCode2 } from "lucide"; import "../../components/ConsoleBlock.js"; import { i18n } from "../../utils/i18n.js"; import { renderCollapsibleHeader, renderHeader } from "../renderer-registry.js"; @@ -232,7 +232,6 @@ export class ArtifactsToolRenderer implements ToolRenderer `; - case "delete": default: return html`
diff --git a/packages/web-ui/src/tools/artifacts/artifacts.ts b/packages/web-ui/src/tools/artifacts/artifacts.ts index 28446e6c..d47b7a88 100644 --- a/packages/web-ui/src/tools/artifacts/artifacts.ts +++ b/packages/web-ui/src/tools/artifacts/artifacts.ts @@ -1,5 +1,6 @@ import { Button, icon } from "@mariozechner/mini-lit"; -import { type AgentTool, type Message, StringEnum, type ToolCall, type ToolResultMessage } from "@mariozechner/pi-ai"; +import "@mariozechner/mini-lit/dist/MarkdownBlock.js"; +import { type AgentTool, type Message, StringEnum, type ToolCall } from "@mariozechner/pi-ai"; import { type Static, Type } from "@sinclair/typebox"; import { html, LitElement, type TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators.js"; @@ -12,7 +13,6 @@ import { HtmlArtifact } from "./HtmlArtifact.js"; import { MarkdownArtifact } from "./MarkdownArtifact.js"; import { SvgArtifact } from "./SvgArtifact.js"; import { TextArtifact } from "./TextArtifact.js"; -import "@mariozechner/mini-lit/dist/MarkdownBlock.js"; // Simple artifact model export interface Artifact {