@mariozechner/pi-web-ui 0.5.48 → 0.7.1
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/ChatPanel.d.ts +1 -0
- package/dist/ChatPanel.d.ts.map +1 -1
- package/dist/ChatPanel.js +3 -2
- package/dist/ChatPanel.js.map +1 -1
- package/dist/agent/transports/ProviderTransport.d.ts +1 -1
- package/dist/agent/transports/ProviderTransport.d.ts.map +1 -1
- package/dist/agent/transports/ProviderTransport.js +5 -10
- package/dist/agent/transports/ProviderTransport.js.map +1 -1
- package/dist/app.css +4188 -2
- package/dist/components/AgentInterface.d.ts +1 -0
- package/dist/components/AgentInterface.d.ts.map +1 -1
- package/dist/components/AgentInterface.js +13 -3
- package/dist/components/AgentInterface.js.map +1 -1
- package/dist/components/AttachmentTile.d.ts.map +1 -1
- package/dist/components/AttachmentTile.js +2 -1
- package/dist/components/AttachmentTile.js.map +1 -1
- package/dist/components/ConsoleBlock.d.ts.map +1 -1
- package/dist/components/ConsoleBlock.js +2 -1
- package/dist/components/ConsoleBlock.js.map +1 -1
- package/dist/components/CustomProviderCard.d.ts +17 -0
- package/dist/components/CustomProviderCard.d.ts.map +1 -0
- package/dist/components/CustomProviderCard.js +110 -0
- package/dist/components/CustomProviderCard.js.map +1 -0
- package/dist/components/Input.d.ts +2 -2
- package/dist/components/Input.d.ts.map +1 -1
- package/dist/components/Input.js +2 -1
- package/dist/components/Input.js.map +1 -1
- package/dist/components/MessageEditor.d.ts +1 -3
- package/dist/components/MessageEditor.d.ts.map +1 -1
- package/dist/components/MessageEditor.js +6 -31
- package/dist/components/MessageEditor.js.map +1 -1
- package/dist/components/MessageList.d.ts +1 -0
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js +6 -3
- package/dist/components/MessageList.js.map +1 -1
- package/dist/components/Messages.d.ts +2 -0
- package/dist/components/Messages.d.ts.map +1 -1
- package/dist/components/Messages.js +25 -14
- package/dist/components/Messages.js.map +1 -1
- package/dist/components/ProviderKeyInput.d.ts +1 -1
- package/dist/components/ProviderKeyInput.d.ts.map +1 -1
- package/dist/components/ProviderKeyInput.js +22 -36
- package/dist/components/ProviderKeyInput.js.map +1 -1
- package/dist/components/StreamingMessageContainer.d.ts +1 -0
- package/dist/components/StreamingMessageContainer.d.ts.map +1 -1
- package/dist/components/StreamingMessageContainer.js +5 -2
- package/dist/components/StreamingMessageContainer.js.map +1 -1
- package/dist/components/ThinkingBlock.d.ts +11 -0
- package/dist/components/ThinkingBlock.d.ts.map +1 -0
- package/dist/components/ThinkingBlock.js +58 -0
- package/dist/components/ThinkingBlock.js.map +1 -0
- package/dist/dialogs/ApiKeyPromptDialog.d.ts +1 -1
- package/dist/dialogs/ApiKeyPromptDialog.d.ts.map +1 -1
- package/dist/dialogs/ApiKeyPromptDialog.js +3 -1
- package/dist/dialogs/ApiKeyPromptDialog.js.map +1 -1
- package/dist/dialogs/AttachmentOverlay.d.ts.map +1 -1
- package/dist/dialogs/AttachmentOverlay.js +3 -2
- package/dist/dialogs/AttachmentOverlay.js.map +1 -1
- package/dist/dialogs/CustomProviderDialog.d.ts +25 -0
- package/dist/dialogs/CustomProviderDialog.d.ts.map +1 -0
- package/dist/dialogs/CustomProviderDialog.js +270 -0
- package/dist/dialogs/CustomProviderDialog.js.map +1 -0
- package/dist/dialogs/ModelSelector.d.ts +6 -6
- package/dist/dialogs/ModelSelector.d.ts.map +1 -1
- package/dist/dialogs/ModelSelector.js +60 -74
- package/dist/dialogs/ModelSelector.js.map +1 -1
- package/dist/dialogs/PersistentStorageDialog.d.ts +1 -1
- package/dist/dialogs/PersistentStorageDialog.d.ts.map +1 -1
- package/dist/dialogs/PersistentStorageDialog.js +4 -1
- package/dist/dialogs/PersistentStorageDialog.js.map +1 -1
- package/dist/dialogs/ProvidersModelsTab.d.ts +20 -0
- package/dist/dialogs/ProvidersModelsTab.d.ts.map +1 -0
- package/dist/dialogs/ProvidersModelsTab.js +191 -0
- package/dist/dialogs/ProvidersModelsTab.js.map +1 -0
- package/dist/dialogs/SessionListDialog.d.ts +1 -1
- package/dist/dialogs/SessionListDialog.d.ts.map +1 -1
- package/dist/dialogs/SessionListDialog.js +3 -1
- package/dist/dialogs/SessionListDialog.js.map +1 -1
- package/dist/dialogs/SettingsDialog.d.ts +1 -2
- package/dist/dialogs/SettingsDialog.d.ts.map +1 -1
- package/dist/dialogs/SettingsDialog.js +10 -3
- package/dist/dialogs/SettingsDialog.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/storage/app-storage.d.ts +3 -1
- package/dist/storage/app-storage.d.ts.map +1 -1
- package/dist/storage/app-storage.js +2 -1
- package/dist/storage/app-storage.js.map +1 -1
- package/dist/storage/stores/custom-providers-store.d.ts +25 -0
- package/dist/storage/stores/custom-providers-store.d.ts.map +1 -0
- package/dist/storage/stores/custom-providers-store.js +35 -0
- package/dist/storage/stores/custom-providers-store.js.map +1 -0
- package/dist/storage/stores/sessions-store.d.ts.map +1 -1
- package/dist/storage/stores/sessions-store.js +0 -1
- package/dist/storage/stores/sessions-store.js.map +1 -1
- package/dist/storage/types.d.ts +0 -2
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/tools/artifacts/ArtifactPill.d.ts +1 -1
- package/dist/tools/artifacts/ArtifactPill.d.ts.map +1 -1
- package/dist/tools/artifacts/ArtifactPill.js +2 -1
- package/dist/tools/artifacts/ArtifactPill.js.map +1 -1
- package/dist/tools/artifacts/DocxArtifact.js +1 -1
- package/dist/tools/artifacts/DocxArtifact.js.map +1 -1
- package/dist/tools/artifacts/ExcelArtifact.js +1 -1
- package/dist/tools/artifacts/ExcelArtifact.js.map +1 -1
- package/dist/tools/artifacts/GenericArtifact.js +1 -1
- package/dist/tools/artifacts/GenericArtifact.js.map +1 -1
- package/dist/tools/artifacts/HtmlArtifact.d.ts.map +1 -1
- package/dist/tools/artifacts/HtmlArtifact.js +5 -1
- package/dist/tools/artifacts/HtmlArtifact.js.map +1 -1
- package/dist/tools/artifacts/ImageArtifact.js +1 -1
- package/dist/tools/artifacts/ImageArtifact.js.map +1 -1
- package/dist/tools/artifacts/MarkdownArtifact.d.ts.map +1 -1
- package/dist/tools/artifacts/MarkdownArtifact.js +3 -1
- package/dist/tools/artifacts/MarkdownArtifact.js.map +1 -1
- package/dist/tools/artifacts/PdfArtifact.js +1 -1
- package/dist/tools/artifacts/PdfArtifact.js.map +1 -1
- package/dist/tools/artifacts/SvgArtifact.d.ts.map +1 -1
- package/dist/tools/artifacts/SvgArtifact.js +3 -1
- package/dist/tools/artifacts/SvgArtifact.js.map +1 -1
- package/dist/tools/artifacts/TextArtifact.d.ts.map +1 -1
- package/dist/tools/artifacts/TextArtifact.js +2 -1
- package/dist/tools/artifacts/TextArtifact.js.map +1 -1
- package/dist/tools/artifacts/artifacts-tool-renderer.d.ts.map +1 -1
- package/dist/tools/artifacts/artifacts-tool-renderer.js +18 -8
- package/dist/tools/artifacts/artifacts-tool-renderer.js.map +1 -1
- package/dist/tools/artifacts/artifacts.d.ts.map +1 -1
- package/dist/tools/artifacts/artifacts.js +3 -2
- package/dist/tools/artifacts/artifacts.js.map +1 -1
- package/dist/tools/extract-document.d.ts.map +1 -1
- package/dist/tools/extract-document.js +78 -58
- package/dist/tools/extract-document.js.map +1 -1
- package/dist/tools/javascript-repl.d.ts.map +1 -1
- package/dist/tools/javascript-repl.js +7 -3
- package/dist/tools/javascript-repl.js.map +1 -1
- package/dist/tools/renderer-registry.d.ts +1 -1
- package/dist/tools/renderer-registry.d.ts.map +1 -1
- package/dist/tools/renderer-registry.js +20 -6
- package/dist/tools/renderer-registry.js.map +1 -1
- package/dist/tools/renderers/BashRenderer.d.ts.map +1 -1
- package/dist/tools/renderers/BashRenderer.js +5 -2
- package/dist/tools/renderers/BashRenderer.js.map +1 -1
- package/dist/tools/renderers/CalculateRenderer.d.ts.map +1 -1
- package/dist/tools/renderers/CalculateRenderer.js +5 -2
- package/dist/tools/renderers/CalculateRenderer.js.map +1 -1
- package/dist/tools/renderers/DefaultRenderer.d.ts.map +1 -1
- package/dist/tools/renderers/DefaultRenderer.js +5 -2
- package/dist/tools/renderers/DefaultRenderer.js.map +1 -1
- package/dist/tools/renderers/GetCurrentTimeRenderer.d.ts.map +1 -1
- package/dist/tools/renderers/GetCurrentTimeRenderer.js +9 -3
- package/dist/tools/renderers/GetCurrentTimeRenderer.js.map +1 -1
- package/dist/utils/auth-token.js +1 -1
- package/dist/utils/auth-token.js.map +1 -1
- package/dist/utils/i18n.d.ts +105 -3
- package/dist/utils/i18n.d.ts.map +1 -1
- package/dist/utils/i18n.js +72 -2
- package/dist/utils/i18n.js.map +1 -1
- package/dist/utils/model-discovery.d.ts +38 -0
- package/dist/utils/model-discovery.d.ts.map +1 -0
- package/dist/utils/model-discovery.js +243 -0
- package/dist/utils/model-discovery.js.map +1 -0
- package/dist/utils/proxy-utils.d.ts +37 -0
- package/dist/utils/proxy-utils.d.ts.map +1 -0
- package/dist/utils/proxy-utils.js +97 -0
- package/dist/utils/proxy-utils.js.map +1 -0
- package/example/package.json +2 -2
- package/example/src/custom-messages.ts +1 -1
- package/example/src/main.ts +17 -6
- package/package.json +9 -8
- package/src/ChatPanel.ts +4 -2
- package/src/agent/transports/ProviderTransport.ts +5 -10
- package/src/app.css +24 -0
- package/src/components/AgentInterface.ts +14 -3
- package/src/components/AttachmentTile.ts +2 -1
- package/src/components/ConsoleBlock.ts +2 -1
- package/src/components/CustomProviderCard.ts +100 -0
- package/src/components/Input.ts +2 -1
- package/src/components/MessageEditor.ts +6 -33
- package/src/components/MessageList.ts +4 -3
- package/src/components/Messages.ts +32 -20
- package/src/components/ProviderKeyInput.ts +19 -38
- package/src/components/StreamingMessageContainer.ts +3 -2
- package/src/components/ThinkingBlock.ts +43 -0
- package/src/dialogs/ApiKeyPromptDialog.ts +3 -1
- package/src/dialogs/AttachmentOverlay.ts +3 -2
- package/src/dialogs/CustomProviderDialog.ts +274 -0
- package/src/dialogs/ModelSelector.ts +61 -75
- package/src/dialogs/PersistentStorageDialog.ts +4 -1
- package/src/dialogs/ProvidersModelsTab.ts +212 -0
- package/src/dialogs/SessionListDialog.ts +3 -1
- package/src/dialogs/SettingsDialog.ts +10 -13
- package/src/index.ts +8 -0
- package/src/storage/app-storage.ts +4 -0
- package/src/storage/stores/custom-providers-store.ts +62 -0
- package/src/storage/stores/sessions-store.ts +0 -1
- package/src/storage/types.ts +0 -3
- package/src/tools/artifacts/ArtifactPill.ts +2 -1
- package/src/tools/artifacts/DocxArtifact.ts +1 -1
- package/src/tools/artifacts/ExcelArtifact.ts +1 -1
- package/src/tools/artifacts/GenericArtifact.ts +1 -1
- package/src/tools/artifacts/HtmlArtifact.ts +5 -1
- package/src/tools/artifacts/ImageArtifact.ts +1 -1
- package/src/tools/artifacts/MarkdownArtifact.ts +3 -1
- package/src/tools/artifacts/PdfArtifact.ts +1 -1
- package/src/tools/artifacts/SvgArtifact.ts +3 -1
- package/src/tools/artifacts/TextArtifact.ts +2 -1
- package/src/tools/artifacts/artifacts-tool-renderer.ts +20 -8
- package/src/tools/artifacts/artifacts.ts +3 -2
- package/src/tools/extract-document.ts +82 -61
- package/src/tools/javascript-repl.ts +8 -3
- package/src/tools/renderer-registry.ts +20 -6
- package/src/tools/renderers/BashRenderer.ts +6 -2
- package/src/tools/renderers/CalculateRenderer.ts +6 -2
- package/src/tools/renderers/DefaultRenderer.ts +6 -2
- package/src/tools/renderers/GetCurrentTimeRenderer.ts +11 -3
- package/src/utils/auth-token.ts +1 -1
- package/src/utils/i18n.ts +120 -5
- package/src/utils/model-discovery.ts +277 -0
- package/src/utils/proxy-utils.ts +112 -0
- package/example/package-lock.json +0 -1965
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { html } from "@mariozechner/mini-lit";
|
|
2
1
|
import type { ToolResultMessage, Usage } from "@mariozechner/pi-ai";
|
|
3
|
-
import { LitElement } from "lit";
|
|
2
|
+
import { html, LitElement } from "lit";
|
|
4
3
|
import { customElement, property, query } from "lit/decorators.js";
|
|
5
4
|
import { ModelSelector } from "../dialogs/ModelSelector.js";
|
|
6
5
|
import type { MessageEditor } from "./MessageEditor.js";
|
|
@@ -29,6 +28,8 @@ export class AgentInterface extends LitElement {
|
|
|
29
28
|
@property({ attribute: false }) onBeforeSend?: () => void | Promise<void>;
|
|
30
29
|
// Optional callback called before executing a tool call - return false to prevent execution
|
|
31
30
|
@property({ attribute: false }) onBeforeToolCall?: (toolName: string, args: any) => boolean | Promise<boolean>;
|
|
31
|
+
// Optional callback called when cost display is clicked
|
|
32
|
+
@property({ attribute: false }) onCostClick?: () => void;
|
|
32
33
|
|
|
33
34
|
// References
|
|
34
35
|
@query("message-editor") private _messageEditor!: MessageEditor;
|
|
@@ -226,6 +227,7 @@ export class AgentInterface extends LitElement {
|
|
|
226
227
|
.tools=${state.tools}
|
|
227
228
|
.pendingToolCalls=${this.session ? this.session.state.pendingToolCalls : new Set<string>()}
|
|
228
229
|
.isStreaming=${state.isStreaming}
|
|
230
|
+
.onCostClick=${this.onCostClick}
|
|
229
231
|
></message-list>
|
|
230
232
|
|
|
231
233
|
<!-- Streaming message container - manages its own updates -->
|
|
@@ -235,6 +237,7 @@ export class AgentInterface extends LitElement {
|
|
|
235
237
|
.isStreaming=${state.isStreaming}
|
|
236
238
|
.pendingToolCalls=${state.pendingToolCalls}
|
|
237
239
|
.toolResultsById=${toolResultsById}
|
|
240
|
+
.onCostClick=${this.onCostClick}
|
|
238
241
|
></streaming-message-container>
|
|
239
242
|
</div>
|
|
240
243
|
`;
|
|
@@ -275,7 +278,15 @@ export class AgentInterface extends LitElement {
|
|
|
275
278
|
<div class="flex items-center gap-1">
|
|
276
279
|
${this.showThemeToggle ? html`<theme-toggle></theme-toggle>` : html``}
|
|
277
280
|
</div>
|
|
278
|
-
<div class="flex ml-auto items-center gap-3"
|
|
281
|
+
<div class="flex ml-auto items-center gap-3">
|
|
282
|
+
${
|
|
283
|
+
totalsText
|
|
284
|
+
? this.onCostClick
|
|
285
|
+
? html`<span class="cursor-pointer hover:text-foreground transition-colors" @click=${this.onCostClick}>${totalsText}</span>`
|
|
286
|
+
: html`<span>${totalsText}</span>`
|
|
287
|
+
: ""
|
|
288
|
+
}
|
|
289
|
+
</div>
|
|
279
290
|
</div>
|
|
280
291
|
`;
|
|
281
292
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { icon } from "@mariozechner/mini-lit/dist/icons.js";
|
|
2
2
|
import { LitElement } from "lit";
|
|
3
3
|
import { customElement, property } from "lit/decorators.js";
|
|
4
|
+
import { html } from "lit/html.js";
|
|
4
5
|
import { FileSpreadsheet, FileText, X } from "lucide";
|
|
5
6
|
import { AttachmentOverlay } from "../dialogs/AttachmentOverlay.js";
|
|
6
7
|
import type { Attachment } from "../utils/attachment-utils.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { icon } from "@mariozechner/mini-lit";
|
|
2
2
|
import { LitElement } from "lit";
|
|
3
3
|
import { property, state } from "lit/decorators.js";
|
|
4
|
+
import { html } from "lit/html.js";
|
|
4
5
|
import { Check, Copy } from "lucide";
|
|
5
6
|
import { i18n } from "../utils/i18n.js";
|
|
6
7
|
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { i18n } from "@mariozechner/mini-lit";
|
|
2
|
+
import { Button } from "@mariozechner/mini-lit/dist/Button.js";
|
|
3
|
+
import { html, LitElement, type TemplateResult } from "lit";
|
|
4
|
+
import { customElement, property } from "lit/decorators.js";
|
|
5
|
+
import type { CustomProvider } from "../storage/stores/custom-providers-store.js";
|
|
6
|
+
|
|
7
|
+
@customElement("custom-provider-card")
|
|
8
|
+
export class CustomProviderCard extends LitElement {
|
|
9
|
+
@property({ type: Object }) provider!: CustomProvider;
|
|
10
|
+
@property({ type: Boolean }) isAutoDiscovery = false;
|
|
11
|
+
@property({ type: Object }) status?: { modelCount: number; status: "connected" | "disconnected" | "checking" };
|
|
12
|
+
@property() onRefresh?: (provider: CustomProvider) => void;
|
|
13
|
+
@property() onEdit?: (provider: CustomProvider) => void;
|
|
14
|
+
@property() onDelete?: (provider: CustomProvider) => void;
|
|
15
|
+
|
|
16
|
+
protected createRenderRoot() {
|
|
17
|
+
return this;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private renderStatus(): TemplateResult {
|
|
21
|
+
if (!this.isAutoDiscovery) {
|
|
22
|
+
return html`
|
|
23
|
+
<div class="text-xs text-muted-foreground mt-1">
|
|
24
|
+
${i18n("Models")}: ${this.provider.models?.length || 0}
|
|
25
|
+
</div>
|
|
26
|
+
`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!this.status) return html``;
|
|
30
|
+
|
|
31
|
+
const statusIcon =
|
|
32
|
+
this.status.status === "connected"
|
|
33
|
+
? html`<span class="text-green-500">●</span>`
|
|
34
|
+
: this.status.status === "checking"
|
|
35
|
+
? html`<span class="text-yellow-500">●</span>`
|
|
36
|
+
: html`<span class="text-red-500">●</span>`;
|
|
37
|
+
|
|
38
|
+
const statusText =
|
|
39
|
+
this.status.status === "connected"
|
|
40
|
+
? `${this.status.modelCount} ${i18n("models")}`
|
|
41
|
+
: this.status.status === "checking"
|
|
42
|
+
? i18n("Checking...")
|
|
43
|
+
: i18n("Disconnected");
|
|
44
|
+
|
|
45
|
+
return html`
|
|
46
|
+
<div class="text-xs text-muted-foreground mt-1 flex items-center gap-1">
|
|
47
|
+
${statusIcon} ${statusText}
|
|
48
|
+
</div>
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
render(): TemplateResult {
|
|
53
|
+
return html`
|
|
54
|
+
<div class="border border-border rounded-lg p-4 space-y-2">
|
|
55
|
+
<div class="flex items-center justify-between">
|
|
56
|
+
<div class="flex-1">
|
|
57
|
+
<div class="font-medium text-sm text-foreground">${this.provider.name}</div>
|
|
58
|
+
<div class="text-xs text-muted-foreground mt-1">
|
|
59
|
+
<span class="capitalize">${this.provider.type}</span>
|
|
60
|
+
${this.provider.baseUrl ? html` • ${this.provider.baseUrl}` : ""}
|
|
61
|
+
</div>
|
|
62
|
+
${this.renderStatus()}
|
|
63
|
+
</div>
|
|
64
|
+
<div class="flex gap-2">
|
|
65
|
+
${
|
|
66
|
+
this.isAutoDiscovery && this.onRefresh
|
|
67
|
+
? Button({
|
|
68
|
+
onClick: () => this.onRefresh?.(this.provider),
|
|
69
|
+
variant: "ghost",
|
|
70
|
+
size: "sm",
|
|
71
|
+
children: i18n("Refresh"),
|
|
72
|
+
})
|
|
73
|
+
: ""
|
|
74
|
+
}
|
|
75
|
+
${
|
|
76
|
+
this.onEdit
|
|
77
|
+
? Button({
|
|
78
|
+
onClick: () => this.onEdit?.(this.provider),
|
|
79
|
+
variant: "ghost",
|
|
80
|
+
size: "sm",
|
|
81
|
+
children: i18n("Edit"),
|
|
82
|
+
})
|
|
83
|
+
: ""
|
|
84
|
+
}
|
|
85
|
+
${
|
|
86
|
+
this.onDelete
|
|
87
|
+
? Button({
|
|
88
|
+
onClick: () => this.onDelete?.(this.provider),
|
|
89
|
+
variant: "ghost",
|
|
90
|
+
size: "sm",
|
|
91
|
+
children: i18n("Delete"),
|
|
92
|
+
})
|
|
93
|
+
: ""
|
|
94
|
+
}
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
`;
|
|
99
|
+
}
|
|
100
|
+
}
|
package/src/components/Input.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type BaseComponentProps, fc
|
|
1
|
+
import { type BaseComponentProps, fc } from "@mariozechner/mini-lit/dist/mini.js";
|
|
2
|
+
import { html } from "lit";
|
|
2
3
|
import { type Ref, ref } from "lit/directives/ref.js";
|
|
3
4
|
import { i18n } from "../utils/i18n.js";
|
|
4
5
|
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { icon } from "@mariozechner/mini-lit";
|
|
2
|
+
import { Button } from "@mariozechner/mini-lit/dist/Button.js";
|
|
3
|
+
import { Select, type SelectOption } from "@mariozechner/mini-lit/dist/Select.js";
|
|
2
4
|
import type { Model } from "@mariozechner/pi-ai";
|
|
3
|
-
import { LitElement } from "lit";
|
|
5
|
+
import { html, LitElement } from "lit";
|
|
4
6
|
import { customElement, property, state } from "lit/decorators.js";
|
|
5
7
|
import { createRef, ref } from "lit/directives/ref.js";
|
|
6
8
|
import { Brain, Loader2, Paperclip, Send, Sparkles, Square } from "lucide";
|
|
7
|
-
import "./AttachmentTile.js";
|
|
8
9
|
import { type Attachment, loadAttachment } from "../utils/attachment-utils.js";
|
|
9
10
|
import { i18n } from "../utils/i18n.js";
|
|
11
|
+
import "./AttachmentTile.js";
|
|
10
12
|
|
|
11
13
|
@customElement("message-editor")
|
|
12
14
|
export class MessageEditor extends LitElement {
|
|
@@ -22,13 +24,6 @@ export class MessageEditor extends LitElement {
|
|
|
22
24
|
const oldValue = this._value;
|
|
23
25
|
this._value = val;
|
|
24
26
|
this.requestUpdate("value", oldValue);
|
|
25
|
-
this.updateComplete.then(() => {
|
|
26
|
-
const textarea = this.textareaRef.value;
|
|
27
|
-
if (textarea) {
|
|
28
|
-
textarea.style.height = "auto";
|
|
29
|
-
textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`;
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
27
|
}
|
|
33
28
|
|
|
34
29
|
@property() isStreaming = false;
|
|
@@ -60,8 +55,6 @@ export class MessageEditor extends LitElement {
|
|
|
60
55
|
private handleTextareaInput = (e: Event) => {
|
|
61
56
|
const textarea = e.target as HTMLTextAreaElement;
|
|
62
57
|
this.value = textarea.value;
|
|
63
|
-
textarea.style.height = "auto";
|
|
64
|
-
textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`;
|
|
65
58
|
this.onInput?.(this.value);
|
|
66
59
|
};
|
|
67
60
|
|
|
@@ -231,33 +224,13 @@ export class MessageEditor extends LitElement {
|
|
|
231
224
|
this.processingFiles = false;
|
|
232
225
|
};
|
|
233
226
|
|
|
234
|
-
private adjustTextareaHeight() {
|
|
235
|
-
const textarea = this.textareaRef.value;
|
|
236
|
-
if (textarea) {
|
|
237
|
-
// Reset height to auto to get accurate scrollHeight
|
|
238
|
-
textarea.style.height = "auto";
|
|
239
|
-
// Only adjust if there's content, otherwise keep minimal height
|
|
240
|
-
if (this.value.trim()) {
|
|
241
|
-
textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
227
|
override firstUpdated() {
|
|
247
228
|
const textarea = this.textareaRef.value;
|
|
248
229
|
if (textarea) {
|
|
249
|
-
// Don't adjust height on first render - let it be minimal
|
|
250
230
|
textarea.focus();
|
|
251
231
|
}
|
|
252
232
|
}
|
|
253
233
|
|
|
254
|
-
override updated() {
|
|
255
|
-
// Only adjust height when component updates if there's content
|
|
256
|
-
if (this.value) {
|
|
257
|
-
this.adjustTextareaHeight();
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
234
|
override render() {
|
|
262
235
|
// Check if current model supports thinking/reasoning
|
|
263
236
|
const model = this.currentModel;
|
|
@@ -304,7 +277,7 @@ export class MessageEditor extends LitElement {
|
|
|
304
277
|
class="w-full bg-transparent p-4 text-foreground placeholder-muted-foreground outline-none resize-none overflow-y-auto"
|
|
305
278
|
placeholder=${i18n("Type a message...")}
|
|
306
279
|
rows="1"
|
|
307
|
-
style="max-height: 200px;"
|
|
280
|
+
style="max-height: 200px; field-sizing: content; min-height: 1lh; height: auto;"
|
|
308
281
|
.value=${this.value}
|
|
309
282
|
@input=${this.handleTextareaInput}
|
|
310
283
|
@keydown=${this.handleKeyDown}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { html } from "@mariozechner/mini-lit";
|
|
2
1
|
import type {
|
|
3
2
|
AgentTool,
|
|
4
3
|
AssistantMessage as AssistantMessageType,
|
|
5
4
|
ToolResultMessage as ToolResultMessageType,
|
|
6
5
|
} from "@mariozechner/pi-ai";
|
|
7
|
-
import { LitElement, type TemplateResult } from "lit";
|
|
6
|
+
import { html, LitElement, type TemplateResult } from "lit";
|
|
8
7
|
import { property } from "lit/decorators.js";
|
|
9
8
|
import { repeat } from "lit/directives/repeat.js";
|
|
10
9
|
import type { AppMessage } from "./Messages.js";
|
|
@@ -15,6 +14,7 @@ export class MessageList extends LitElement {
|
|
|
15
14
|
@property({ type: Array }) tools: AgentTool[] = [];
|
|
16
15
|
@property({ type: Object }) pendingToolCalls?: Set<string>;
|
|
17
16
|
@property({ type: Boolean }) isStreaming: boolean = false;
|
|
17
|
+
@property({ attribute: false }) onCostClick?: () => void;
|
|
18
18
|
|
|
19
19
|
protected override createRenderRoot(): HTMLElement | DocumentFragment {
|
|
20
20
|
return this;
|
|
@@ -64,10 +64,11 @@ export class MessageList extends LitElement {
|
|
|
64
64
|
template: html`<assistant-message
|
|
65
65
|
.message=${amsg}
|
|
66
66
|
.tools=${this.tools}
|
|
67
|
-
.isStreaming=${
|
|
67
|
+
.isStreaming=${false}
|
|
68
68
|
.pendingToolCalls=${this.pendingToolCalls}
|
|
69
69
|
.toolResultsById=${resultByCallId}
|
|
70
70
|
.hideToolCalls=${false}
|
|
71
|
+
.onCostClick=${this.onCostClick}
|
|
71
72
|
></assistant-message>`,
|
|
72
73
|
});
|
|
73
74
|
index++;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { html } from "@mariozechner/mini-lit";
|
|
2
1
|
import type {
|
|
3
2
|
AgentTool,
|
|
4
3
|
AssistantMessage as AssistantMessageType,
|
|
@@ -6,12 +5,13 @@ import type {
|
|
|
6
5
|
ToolResultMessage as ToolResultMessageType,
|
|
7
6
|
UserMessage as UserMessageType,
|
|
8
7
|
} from "@mariozechner/pi-ai";
|
|
9
|
-
import { LitElement, type TemplateResult } from "lit";
|
|
8
|
+
import { html, LitElement, type TemplateResult } from "lit";
|
|
10
9
|
import { customElement, property } from "lit/decorators.js";
|
|
11
10
|
import { renderTool } from "../tools/index.js";
|
|
12
11
|
import type { Attachment } from "../utils/attachment-utils.js";
|
|
13
12
|
import { formatUsage } from "../utils/format.js";
|
|
14
13
|
import { i18n } from "../utils/i18n.js";
|
|
14
|
+
import "./ThinkingBlock.js";
|
|
15
15
|
|
|
16
16
|
export type UserMessageWithAttachments = UserMessageType & { attachments?: Attachment[] };
|
|
17
17
|
|
|
@@ -62,19 +62,21 @@ export class UserMessage extends LitElement {
|
|
|
62
62
|
: this.message.content.find((c) => c.type === "text")?.text || "";
|
|
63
63
|
|
|
64
64
|
return html`
|
|
65
|
-
<div class="
|
|
66
|
-
<
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
65
|
+
<div class="flex justify-start mx-4">
|
|
66
|
+
<div class="user-message-container py-2 px-4 rounded-xl">
|
|
67
|
+
<markdown-block .content=${content}></markdown-block>
|
|
68
|
+
${
|
|
69
|
+
this.message.attachments && this.message.attachments.length > 0
|
|
70
|
+
? html`
|
|
71
|
+
<div class="mt-3 flex flex-wrap gap-2">
|
|
72
|
+
${this.message.attachments.map(
|
|
73
|
+
(attachment) => html` <attachment-tile .attachment=${attachment}></attachment-tile> `,
|
|
74
|
+
)}
|
|
75
|
+
</div>
|
|
76
|
+
`
|
|
77
|
+
: ""
|
|
78
|
+
}
|
|
79
|
+
</div>
|
|
78
80
|
</div>
|
|
79
81
|
`;
|
|
80
82
|
}
|
|
@@ -88,6 +90,7 @@ export class AssistantMessage extends LitElement {
|
|
|
88
90
|
@property({ type: Boolean }) hideToolCalls = false;
|
|
89
91
|
@property({ type: Object }) toolResultsById?: Map<string, ToolResultMessageType>;
|
|
90
92
|
@property({ type: Boolean }) isStreaming: boolean = false;
|
|
93
|
+
@property({ attribute: false }) onCostClick?: () => void;
|
|
91
94
|
|
|
92
95
|
protected override createRenderRoot(): HTMLElement | DocumentFragment {
|
|
93
96
|
return this;
|
|
@@ -106,7 +109,9 @@ export class AssistantMessage extends LitElement {
|
|
|
106
109
|
if (chunk.type === "text" && chunk.text.trim() !== "") {
|
|
107
110
|
orderedParts.push(html`<markdown-block .content=${chunk.text}></markdown-block>`);
|
|
108
111
|
} else if (chunk.type === "thinking" && chunk.thinking.trim() !== "") {
|
|
109
|
-
orderedParts.push(
|
|
112
|
+
orderedParts.push(
|
|
113
|
+
html`<thinking-block .content=${chunk.thinking} .isStreaming=${this.isStreaming}></thinking-block>`,
|
|
114
|
+
);
|
|
110
115
|
} else if (chunk.type === "toolCall") {
|
|
111
116
|
if (!this.hideToolCalls) {
|
|
112
117
|
const tool = this.tools?.find((t) => t.name === chunk.name);
|
|
@@ -132,8 +137,10 @@ export class AssistantMessage extends LitElement {
|
|
|
132
137
|
<div>
|
|
133
138
|
${orderedParts.length ? html` <div class="px-4 flex flex-col gap-3">${orderedParts}</div> ` : ""}
|
|
134
139
|
${
|
|
135
|
-
this.message.usage
|
|
136
|
-
?
|
|
140
|
+
this.message.usage && !this.isStreaming
|
|
141
|
+
? this.onCostClick
|
|
142
|
+
? html` <div class="px-4 mt-2 text-xs text-muted-foreground cursor-pointer hover:text-foreground transition-colors" @click=${this.onCostClick}>${formatUsage(this.message.usage)}</div> `
|
|
143
|
+
: html` <div class="px-4 mt-2 text-xs text-muted-foreground">${formatUsage(this.message.usage)}</div> `
|
|
137
144
|
: ""
|
|
138
145
|
}
|
|
139
146
|
${
|
|
@@ -183,7 +190,12 @@ export class ToolMessageDebugView extends LitElement {
|
|
|
183
190
|
}
|
|
184
191
|
|
|
185
192
|
override render() {
|
|
186
|
-
const
|
|
193
|
+
const textOutput =
|
|
194
|
+
this.result?.content
|
|
195
|
+
?.filter((c) => c.type === "text")
|
|
196
|
+
.map((c: any) => c.text)
|
|
197
|
+
.join("\n") || "";
|
|
198
|
+
const output = this.pretty(textOutput);
|
|
187
199
|
const details = this.pretty(this.result?.details);
|
|
188
200
|
|
|
189
201
|
return html`
|
|
@@ -232,7 +244,7 @@ export class ToolMessage extends LitElement {
|
|
|
232
244
|
? {
|
|
233
245
|
role: "toolResult",
|
|
234
246
|
isError: true,
|
|
235
|
-
|
|
247
|
+
content: [],
|
|
236
248
|
toolCallId: this.toolCall.id,
|
|
237
249
|
toolName: this.toolCall.name,
|
|
238
250
|
timestamp: Date.now(),
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i18n } from "@mariozechner/mini-lit";
|
|
2
|
+
import { Badge } from "@mariozechner/mini-lit/dist/Badge.js";
|
|
3
|
+
import { Button } from "@mariozechner/mini-lit/dist/Button.js";
|
|
2
4
|
import { type Context, complete, getModel } from "@mariozechner/pi-ai";
|
|
3
|
-
import { LitElement } from "lit";
|
|
5
|
+
import { html, LitElement } from "lit";
|
|
4
6
|
import { customElement, property, state } from "lit/decorators.js";
|
|
5
7
|
import { getAppStorage } from "../storage/app-storage.js";
|
|
8
|
+
import { applyProxyIfNeeded } from "../utils/proxy-utils.js";
|
|
9
|
+
import { Input } from "./Input.js";
|
|
6
10
|
|
|
7
11
|
// Test models for each provider
|
|
8
12
|
const TEST_MODELS: Record<string, string> = {
|
|
@@ -23,6 +27,7 @@ export class ProviderKeyInput extends LitElement {
|
|
|
23
27
|
@state() private testing = false;
|
|
24
28
|
@state() private failed = false;
|
|
25
29
|
@state() private hasKey = false;
|
|
30
|
+
@state() private inputChanged = false;
|
|
26
31
|
|
|
27
32
|
protected createRenderRoot() {
|
|
28
33
|
return this;
|
|
@@ -51,16 +56,12 @@ export class ProviderKeyInput extends LitElement {
|
|
|
51
56
|
let model = getModel(provider as any, modelId);
|
|
52
57
|
if (!model) return false;
|
|
53
58
|
|
|
54
|
-
//
|
|
59
|
+
// Get proxy URL from settings (if available)
|
|
55
60
|
const proxyEnabled = await getAppStorage().settings.get<boolean>("proxy.enabled");
|
|
56
61
|
const proxyUrl = await getAppStorage().settings.get<string>("proxy.url");
|
|
57
62
|
|
|
58
|
-
if
|
|
59
|
-
|
|
60
|
-
...model,
|
|
61
|
-
baseUrl: `${proxyUrl}/?url=${encodeURIComponent(model.baseUrl)}`,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
63
|
+
// Apply proxy only if this provider/key combination requires it
|
|
64
|
+
model = applyProxyIfNeeded(model, apiKey, proxyEnabled ? proxyUrl || undefined : undefined);
|
|
64
65
|
|
|
65
66
|
const context: Context = {
|
|
66
67
|
messages: [{ role: "user", content: "Reply with: ok", timestamp: Date.now() }],
|
|
@@ -92,7 +93,7 @@ export class ProviderKeyInput extends LitElement {
|
|
|
92
93
|
try {
|
|
93
94
|
await getAppStorage().providerKeys.set(this.provider, this.keyInput);
|
|
94
95
|
this.hasKey = true;
|
|
95
|
-
this.
|
|
96
|
+
this.inputChanged = false;
|
|
96
97
|
this.requestUpdate();
|
|
97
98
|
} catch (error) {
|
|
98
99
|
console.error("Failed to save API key:", error);
|
|
@@ -111,17 +112,6 @@ export class ProviderKeyInput extends LitElement {
|
|
|
111
112
|
}
|
|
112
113
|
}
|
|
113
114
|
|
|
114
|
-
private async removeKey() {
|
|
115
|
-
try {
|
|
116
|
-
await getAppStorage().providerKeys.delete(this.provider);
|
|
117
|
-
this.hasKey = false;
|
|
118
|
-
this.keyInput = "";
|
|
119
|
-
this.requestUpdate();
|
|
120
|
-
} catch (error) {
|
|
121
|
-
console.error("Failed to remove API key:", error);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
115
|
render() {
|
|
126
116
|
return html`
|
|
127
117
|
<div class="space-y-3">
|
|
@@ -143,27 +133,18 @@ export class ProviderKeyInput extends LitElement {
|
|
|
143
133
|
value: this.keyInput,
|
|
144
134
|
onInput: (e: Event) => {
|
|
145
135
|
this.keyInput = (e.target as HTMLInputElement).value;
|
|
136
|
+
this.inputChanged = true;
|
|
146
137
|
this.requestUpdate();
|
|
147
138
|
},
|
|
148
139
|
className: "flex-1",
|
|
149
140
|
})}
|
|
150
|
-
${
|
|
151
|
-
this.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
className: "!text-destructive",
|
|
158
|
-
})
|
|
159
|
-
: Button({
|
|
160
|
-
onClick: () => this.saveKey(),
|
|
161
|
-
variant: "default",
|
|
162
|
-
size: "sm",
|
|
163
|
-
disabled: !this.keyInput || this.testing,
|
|
164
|
-
children: i18n("Save"),
|
|
165
|
-
})
|
|
166
|
-
}
|
|
141
|
+
${Button({
|
|
142
|
+
onClick: () => this.saveKey(),
|
|
143
|
+
variant: "default",
|
|
144
|
+
size: "sm",
|
|
145
|
+
disabled: !this.keyInput || this.testing || (this.hasKey && !this.inputChanged),
|
|
146
|
+
children: i18n("Save"),
|
|
147
|
+
})}
|
|
167
148
|
</div>
|
|
168
149
|
</div>
|
|
169
150
|
`;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { html } from "@mariozechner/mini-lit";
|
|
2
1
|
import type { AgentTool, Message, ToolResultMessage } from "@mariozechner/pi-ai";
|
|
3
|
-
import { LitElement } from "lit";
|
|
2
|
+
import { html, LitElement } from "lit";
|
|
4
3
|
import { property, state } from "lit/decorators.js";
|
|
5
4
|
|
|
6
5
|
export class StreamingMessageContainer extends LitElement {
|
|
@@ -8,6 +7,7 @@ export class StreamingMessageContainer extends LitElement {
|
|
|
8
7
|
@property({ type: Boolean }) isStreaming = false;
|
|
9
8
|
@property({ type: Object }) pendingToolCalls?: Set<string>;
|
|
10
9
|
@property({ type: Object }) toolResultsById?: Map<string, ToolResultMessage>;
|
|
10
|
+
@property({ attribute: false }) onCostClick?: () => void;
|
|
11
11
|
|
|
12
12
|
@state() private _message: Message | null = null;
|
|
13
13
|
private _pendingMessage: Message | null = null;
|
|
@@ -87,6 +87,7 @@ export class StreamingMessageContainer extends LitElement {
|
|
|
87
87
|
.pendingToolCalls=${this.pendingToolCalls}
|
|
88
88
|
.toolResultsById=${this.toolResultsById}
|
|
89
89
|
.hideToolCalls=${false}
|
|
90
|
+
.onCostClick=${this.onCostClick}
|
|
90
91
|
></assistant-message>
|
|
91
92
|
${this.isStreaming ? html`<span class="mx-4 inline-block w-2 h-4 bg-muted-foreground animate-pulse"></span>` : ""}
|
|
92
93
|
</div>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { icon } from "@mariozechner/mini-lit";
|
|
2
|
+
import { html, LitElement } from "lit";
|
|
3
|
+
import { customElement, property, state } from "lit/decorators.js";
|
|
4
|
+
import { ChevronRight } from "lucide";
|
|
5
|
+
|
|
6
|
+
@customElement("thinking-block")
|
|
7
|
+
export class ThinkingBlock extends LitElement {
|
|
8
|
+
@property() content!: string;
|
|
9
|
+
@property({ type: Boolean }) isStreaming = false;
|
|
10
|
+
@state() private isExpanded = false;
|
|
11
|
+
|
|
12
|
+
protected override createRenderRoot(): HTMLElement | DocumentFragment {
|
|
13
|
+
return this;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
override connectedCallback(): void {
|
|
17
|
+
super.connectedCallback();
|
|
18
|
+
this.style.display = "block";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private toggleExpanded() {
|
|
22
|
+
this.isExpanded = !this.isExpanded;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
override render() {
|
|
26
|
+
const shimmerClasses = this.isStreaming
|
|
27
|
+
? "animate-shimmer bg-gradient-to-r from-muted-foreground via-foreground to-muted-foreground bg-[length:200%_100%] bg-clip-text text-transparent"
|
|
28
|
+
: "";
|
|
29
|
+
|
|
30
|
+
return html`
|
|
31
|
+
<div class="thinking-block">
|
|
32
|
+
<div
|
|
33
|
+
class="thinking-header cursor-pointer select-none flex items-center gap-2 py-1 text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
34
|
+
@click=${this.toggleExpanded}
|
|
35
|
+
>
|
|
36
|
+
<span class="transition-transform inline-block ${this.isExpanded ? "rotate-90" : ""}">${icon(ChevronRight, "sm")}</span>
|
|
37
|
+
<span class="${shimmerClasses}">Thinking...</span>
|
|
38
|
+
</div>
|
|
39
|
+
${this.isExpanded ? html`<markdown-block .content=${this.content} .isThinking=${true}></markdown-block>` : ""}
|
|
40
|
+
</div>
|
|
41
|
+
`;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { DialogBase, DialogContent, DialogHeader, html } from "@mariozechner/mini-lit";
|
|
2
1
|
import { customElement, state } from "lit/decorators.js";
|
|
3
2
|
import "../components/ProviderKeyInput.js";
|
|
3
|
+
import { DialogContent, DialogHeader } from "@mariozechner/mini-lit/dist/Dialog.js";
|
|
4
|
+
import { DialogBase } from "@mariozechner/mini-lit/dist/DialogBase.js";
|
|
5
|
+
import { html } from "lit";
|
|
4
6
|
import { getAppStorage } from "../storage/app-storage.js";
|
|
5
7
|
import { i18n } from "../utils/i18n.js";
|
|
6
8
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Button, html, icon } from "@mariozechner/mini-lit";
|
|
2
1
|
import "@mariozechner/mini-lit/dist/ModeToggle.js";
|
|
2
|
+
import { icon } from "@mariozechner/mini-lit";
|
|
3
|
+
import { Button } from "@mariozechner/mini-lit/dist/Button.js";
|
|
3
4
|
import { renderAsync } from "docx-preview";
|
|
4
|
-
import { LitElement } from "lit";
|
|
5
|
+
import { html, LitElement } from "lit";
|
|
5
6
|
import { state } from "lit/decorators.js";
|
|
6
7
|
import { Download, X } from "lucide";
|
|
7
8
|
import * as pdfjsLib from "pdfjs-dist";
|