@mariozechner/pi-web-ui 0.5.44 → 0.5.46
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 +178 -99
- package/dist/ChatPanel.d.ts +15 -10
- package/dist/ChatPanel.d.ts.map +1 -1
- package/dist/ChatPanel.js +68 -100
- package/dist/ChatPanel.js.map +1 -1
- package/dist/{state/agent-session.d.ts → agent/agent.d.ts} +23 -19
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/{state/agent-session.js → agent/agent.js} +50 -32
- package/dist/agent/agent.js.map +1 -0
- package/dist/{state → agent}/transports/AppTransport.d.ts +1 -3
- package/dist/agent/transports/AppTransport.d.ts.map +1 -0
- package/dist/{state → agent}/transports/AppTransport.js +5 -4
- package/dist/{state → agent}/transports/AppTransport.js.map +1 -1
- package/dist/{state → agent}/transports/ProviderTransport.d.ts +1 -3
- package/dist/agent/transports/ProviderTransport.d.ts.map +1 -0
- package/dist/{state → agent}/transports/ProviderTransport.js +6 -7
- package/dist/agent/transports/ProviderTransport.js.map +1 -0
- package/dist/{state → agent}/transports/index.d.ts.map +1 -1
- package/dist/agent/transports/index.js.map +1 -0
- package/dist/{state → agent}/transports/proxy-types.d.ts.map +1 -1
- package/dist/agent/transports/proxy-types.js.map +1 -0
- package/dist/agent/transports/types.d.ts +12 -0
- package/dist/agent/transports/types.d.ts.map +1 -0
- package/dist/{state → agent}/transports/types.js.map +1 -1
- package/dist/{state → agent}/types.d.ts.map +1 -1
- package/dist/{state → agent}/types.js.map +1 -1
- package/dist/app.css +1 -1
- package/dist/components/AgentInterface.d.ts +7 -4
- package/dist/components/AgentInterface.d.ts.map +1 -1
- package/dist/components/AgentInterface.js +29 -17
- package/dist/components/AgentInterface.js.map +1 -1
- package/dist/components/ConsoleBlock.d.ts +1 -0
- package/dist/components/ConsoleBlock.d.ts.map +1 -1
- package/dist/components/ConsoleBlock.js +7 -1
- package/dist/components/ConsoleBlock.js.map +1 -1
- package/dist/components/ExpandableSection.d.ts +15 -0
- package/dist/components/ExpandableSection.d.ts.map +1 -0
- package/dist/components/ExpandableSection.js +63 -0
- package/dist/components/ExpandableSection.js.map +1 -0
- package/dist/components/MessageEditor.d.ts +8 -1
- package/dist/components/MessageEditor.d.ts.map +1 -1
- package/dist/components/MessageEditor.js +149 -6
- package/dist/components/MessageEditor.js.map +1 -1
- package/dist/components/MessageList.d.ts +3 -2
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js +14 -1
- package/dist/components/MessageList.js.map +1 -1
- package/dist/components/Messages.d.ts +15 -6
- package/dist/components/Messages.d.ts.map +1 -1
- package/dist/components/Messages.js +17 -83
- package/dist/components/Messages.js.map +1 -1
- package/dist/components/ProviderKeyInput.d.ts.map +1 -1
- package/dist/components/ProviderKeyInput.js +6 -5
- package/dist/components/ProviderKeyInput.js.map +1 -1
- package/dist/components/SandboxedIframe.d.ts +29 -7
- package/dist/components/SandboxedIframe.d.ts.map +1 -1
- package/dist/components/SandboxedIframe.js +350 -282
- package/dist/components/SandboxedIframe.js.map +1 -1
- package/dist/components/message-renderer-registry.d.ts +12 -0
- package/dist/components/message-renderer-registry.d.ts.map +1 -0
- package/dist/components/message-renderer-registry.js +12 -0
- package/dist/components/message-renderer-registry.js.map +1 -0
- package/dist/components/sandbox/ArtifactsRuntimeProvider.d.ts +35 -0
- package/dist/components/sandbox/ArtifactsRuntimeProvider.d.ts.map +1 -0
- package/dist/components/sandbox/ArtifactsRuntimeProvider.js +189 -0
- package/dist/components/sandbox/ArtifactsRuntimeProvider.js.map +1 -0
- package/dist/components/sandbox/AttachmentsRuntimeProvider.d.ts +17 -0
- package/dist/components/sandbox/AttachmentsRuntimeProvider.d.ts.map +1 -0
- package/dist/components/sandbox/AttachmentsRuntimeProvider.js +64 -0
- package/dist/components/sandbox/AttachmentsRuntimeProvider.js.map +1 -0
- package/dist/components/sandbox/ConsoleRuntimeProvider.d.ts +42 -0
- package/dist/components/sandbox/ConsoleRuntimeProvider.d.ts.map +1 -0
- package/dist/components/sandbox/ConsoleRuntimeProvider.js +161 -0
- package/dist/components/sandbox/ConsoleRuntimeProvider.js.map +1 -0
- package/dist/components/sandbox/FileDownloadRuntimeProvider.d.ts +30 -0
- package/dist/components/sandbox/FileDownloadRuntimeProvider.d.ts.map +1 -0
- package/dist/components/sandbox/FileDownloadRuntimeProvider.js +97 -0
- package/dist/components/sandbox/FileDownloadRuntimeProvider.js.map +1 -0
- package/dist/components/sandbox/RuntimeMessageBridge.d.ts +19 -0
- package/dist/components/sandbox/RuntimeMessageBridge.d.ts.map +1 -0
- package/dist/components/sandbox/RuntimeMessageBridge.js +74 -0
- package/dist/components/sandbox/RuntimeMessageBridge.js.map +1 -0
- package/dist/components/sandbox/RuntimeMessageRouter.d.ts +65 -0
- package/dist/components/sandbox/RuntimeMessageRouter.d.ts.map +1 -0
- package/dist/components/sandbox/RuntimeMessageRouter.js +168 -0
- package/dist/components/sandbox/RuntimeMessageRouter.js.map +1 -0
- package/dist/components/sandbox/SandboxRuntimeProvider.d.ts +33 -0
- package/dist/components/sandbox/SandboxRuntimeProvider.d.ts.map +1 -0
- package/dist/components/sandbox/SandboxRuntimeProvider.js +2 -0
- package/dist/components/sandbox/SandboxRuntimeProvider.js.map +1 -0
- package/dist/dialogs/ApiKeyPromptDialog.d.ts.map +1 -1
- package/dist/dialogs/ApiKeyPromptDialog.js +2 -5
- package/dist/dialogs/ApiKeyPromptDialog.js.map +1 -1
- package/dist/dialogs/ModelSelector.js.map +1 -1
- package/dist/dialogs/PersistentStorageDialog.d.ts +17 -0
- package/dist/dialogs/PersistentStorageDialog.d.ts.map +1 -0
- package/dist/dialogs/PersistentStorageDialog.js +144 -0
- package/dist/dialogs/PersistentStorageDialog.js.map +1 -0
- package/dist/dialogs/SessionListDialog.d.ts +19 -0
- package/dist/dialogs/SessionListDialog.d.ts.map +1 -0
- package/dist/dialogs/SessionListDialog.js +152 -0
- package/dist/dialogs/SessionListDialog.js.map +1 -0
- package/dist/dialogs/SettingsDialog.d.ts.map +1 -1
- package/dist/dialogs/SettingsDialog.js +1 -0
- package/dist/dialogs/SettingsDialog.js.map +1 -1
- package/dist/index.d.ts +34 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -14
- package/dist/index.js.map +1 -1
- package/dist/prompts/prompts.d.ts +11 -0
- package/dist/prompts/prompts.d.ts.map +1 -0
- package/dist/prompts/prompts.js +272 -0
- package/dist/prompts/prompts.js.map +1 -0
- package/dist/storage/app-storage.d.ts +17 -12
- package/dist/storage/app-storage.d.ts.map +1 -1
- package/dist/storage/app-storage.js +13 -20
- package/dist/storage/app-storage.js.map +1 -1
- package/dist/storage/backends/indexeddb-storage-backend.d.ts +27 -0
- package/dist/storage/backends/indexeddb-storage-backend.d.ts.map +1 -0
- package/dist/storage/backends/indexeddb-storage-backend.js +166 -0
- package/dist/storage/backends/indexeddb-storage-backend.js.map +1 -0
- package/dist/storage/store.d.ts +23 -0
- package/dist/storage/store.d.ts.map +1 -0
- package/dist/storage/store.js +26 -0
- package/dist/storage/store.js.map +1 -0
- package/dist/storage/stores/provider-keys-store.d.ts +14 -0
- package/dist/storage/stores/provider-keys-store.d.ts.map +1 -0
- package/dist/storage/stores/provider-keys-store.js +27 -0
- package/dist/storage/stores/provider-keys-store.js.map +1 -0
- package/dist/storage/stores/sessions-store.d.ts +31 -0
- package/dist/storage/stores/sessions-store.d.ts.map +1 -0
- package/dist/storage/stores/sessions-store.js +113 -0
- package/dist/storage/stores/sessions-store.js.map +1 -0
- package/dist/storage/stores/settings-store.d.ts +14 -0
- package/dist/storage/stores/settings-store.d.ts.map +1 -0
- package/dist/storage/stores/settings-store.js +28 -0
- package/dist/storage/stores/settings-store.js.map +1 -0
- package/dist/storage/types.d.ts +156 -22
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/tools/artifacts/ArtifactElement.d.ts +0 -1
- package/dist/tools/artifacts/ArtifactElement.d.ts.map +1 -1
- package/dist/tools/artifacts/ArtifactElement.js +0 -1
- package/dist/tools/artifacts/ArtifactElement.js.map +1 -1
- package/dist/tools/artifacts/ArtifactPill.d.ts +4 -0
- package/dist/tools/artifacts/ArtifactPill.d.ts.map +1 -0
- package/dist/tools/artifacts/ArtifactPill.js +22 -0
- package/dist/tools/artifacts/ArtifactPill.js.map +1 -0
- package/dist/tools/artifacts/Console.d.ts +18 -0
- package/dist/tools/artifacts/Console.d.ts.map +1 -0
- package/dist/tools/artifacts/Console.js +95 -0
- package/dist/tools/artifacts/Console.js.map +1 -0
- package/dist/tools/artifacts/DocxArtifact.d.ts +22 -0
- package/dist/tools/artifacts/DocxArtifact.d.ts.map +1 -0
- package/dist/tools/artifacts/DocxArtifact.js +208 -0
- package/dist/tools/artifacts/DocxArtifact.js.map +1 -0
- package/dist/tools/artifacts/ExcelArtifact.d.ts +24 -0
- package/dist/tools/artifacts/ExcelArtifact.d.ts.map +1 -0
- package/dist/tools/artifacts/ExcelArtifact.js +216 -0
- package/dist/tools/artifacts/ExcelArtifact.js.map +1 -0
- package/dist/tools/artifacts/GenericArtifact.d.ts +19 -0
- package/dist/tools/artifacts/GenericArtifact.d.ts.map +1 -0
- package/dist/tools/artifacts/GenericArtifact.js +117 -0
- package/dist/tools/artifacts/GenericArtifact.js.map +1 -0
- package/dist/tools/artifacts/HtmlArtifact.d.ts +8 -11
- package/dist/tools/artifacts/HtmlArtifact.d.ts.map +1 -1
- package/dist/tools/artifacts/HtmlArtifact.js +56 -88
- package/dist/tools/artifacts/HtmlArtifact.js.map +1 -1
- package/dist/tools/artifacts/ImageArtifact.d.ts +20 -0
- package/dist/tools/artifacts/ImageArtifact.d.ts.map +1 -0
- package/dist/tools/artifacts/ImageArtifact.js +120 -0
- package/dist/tools/artifacts/ImageArtifact.js.map +1 -0
- package/dist/tools/artifacts/MarkdownArtifact.d.ts +0 -1
- package/dist/tools/artifacts/MarkdownArtifact.d.ts.map +1 -1
- package/dist/tools/artifacts/MarkdownArtifact.js +0 -4
- package/dist/tools/artifacts/MarkdownArtifact.js.map +1 -1
- package/dist/tools/artifacts/PdfArtifact.d.ts +25 -0
- package/dist/tools/artifacts/PdfArtifact.d.ts.map +1 -0
- package/dist/tools/artifacts/PdfArtifact.js +184 -0
- package/dist/tools/artifacts/PdfArtifact.js.map +1 -0
- package/dist/tools/artifacts/SvgArtifact.d.ts +0 -1
- package/dist/tools/artifacts/SvgArtifact.d.ts.map +1 -1
- package/dist/tools/artifacts/SvgArtifact.js +0 -4
- package/dist/tools/artifacts/SvgArtifact.js.map +1 -1
- package/dist/tools/artifacts/TextArtifact.d.ts +0 -1
- package/dist/tools/artifacts/TextArtifact.d.ts.map +1 -1
- package/dist/tools/artifacts/TextArtifact.js +0 -4
- package/dist/tools/artifacts/TextArtifact.js.map +1 -1
- package/dist/tools/artifacts/artifacts-tool-renderer.d.ts +11 -0
- package/dist/tools/artifacts/artifacts-tool-renderer.d.ts.map +1 -0
- package/dist/tools/artifacts/artifacts-tool-renderer.js +262 -0
- package/dist/tools/artifacts/artifacts-tool-renderer.js.map +1 -0
- package/dist/tools/artifacts/artifacts.d.ts +10 -13
- package/dist/tools/artifacts/artifacts.d.ts.map +1 -1
- package/dist/tools/artifacts/artifacts.js +166 -344
- package/dist/tools/artifacts/artifacts.js.map +1 -1
- package/dist/tools/artifacts/index.d.ts +1 -0
- package/dist/tools/artifacts/index.d.ts.map +1 -1
- package/dist/tools/artifacts/index.js +1 -0
- package/dist/tools/artifacts/index.js.map +1 -1
- package/dist/tools/extract-document.d.ts +24 -0
- package/dist/tools/extract-document.d.ts.map +1 -0
- package/dist/tools/extract-document.js +193 -0
- package/dist/tools/extract-document.js.map +1 -0
- package/dist/tools/index.d.ts +9 -7
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +17 -13
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/javascript-repl.d.ts +16 -15
- package/dist/tools/javascript-repl.d.ts.map +1 -1
- package/dist/tools/javascript-repl.js +101 -133
- package/dist/tools/javascript-repl.js.map +1 -1
- package/dist/tools/renderer-registry.d.ts +12 -0
- package/dist/tools/renderer-registry.d.ts.map +1 -1
- package/dist/tools/renderer-registry.js +78 -0
- package/dist/tools/renderer-registry.js.map +1 -1
- package/dist/tools/renderers/BashRenderer.d.ts +2 -4
- package/dist/tools/renderers/BashRenderer.d.ts.map +1 -1
- package/dist/tools/renderers/BashRenderer.js +30 -26
- package/dist/tools/renderers/BashRenderer.js.map +1 -1
- package/dist/tools/renderers/CalculateRenderer.d.ts +2 -4
- package/dist/tools/renderers/CalculateRenderer.d.ts.map +1 -1
- package/dist/tools/renderers/CalculateRenderer.js +32 -28
- package/dist/tools/renderers/CalculateRenderer.js.map +1 -1
- package/dist/tools/renderers/DefaultRenderer.d.ts +2 -4
- package/dist/tools/renderers/DefaultRenderer.d.ts.map +1 -1
- package/dist/tools/renderers/DefaultRenderer.js +78 -18
- package/dist/tools/renderers/DefaultRenderer.js.map +1 -1
- package/dist/tools/renderers/GetCurrentTimeRenderer.d.ts +2 -4
- package/dist/tools/renderers/GetCurrentTimeRenderer.d.ts.map +1 -1
- package/dist/tools/renderers/GetCurrentTimeRenderer.js +57 -21
- package/dist/tools/renderers/GetCurrentTimeRenderer.js.map +1 -1
- package/dist/tools/types.d.ts +5 -2
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/utils/i18n.d.ts +424 -1
- package/dist/utils/i18n.d.ts.map +1 -1
- package/dist/utils/i18n.js +131 -7
- package/dist/utils/i18n.js.map +1 -1
- package/example/package.json +2 -1
- package/example/src/custom-messages.ts +112 -0
- package/example/src/main.ts +391 -38
- package/package.json +48 -43
- package/scripts/count-prompt-tokens.ts +88 -0
- package/src/ChatPanel.ts +93 -101
- package/src/{state/agent-session.ts → agent/agent.ts} +80 -55
- package/src/{state → agent}/transports/AppTransport.ts +6 -6
- package/src/{state → agent}/transports/ProviderTransport.ts +13 -7
- package/src/{state → agent}/transports/types.ts +8 -2
- package/src/components/AgentInterface.ts +32 -16
- package/src/components/ConsoleBlock.ts +5 -1
- package/src/components/ExpandableSection.ts +46 -0
- package/src/components/MessageEditor.ts +159 -5
- package/src/components/MessageList.ts +18 -3
- package/src/components/Messages.ts +48 -89
- package/src/components/ProviderKeyInput.ts +6 -5
- package/src/components/SandboxedIframe.ts +412 -321
- package/src/components/message-renderer-registry.ts +28 -0
- package/src/components/sandbox/ArtifactsRuntimeProvider.ts +219 -0
- package/src/components/sandbox/AttachmentsRuntimeProvider.ts +66 -0
- package/src/components/sandbox/ConsoleRuntimeProvider.ts +187 -0
- package/src/components/sandbox/FileDownloadRuntimeProvider.ts +110 -0
- package/src/components/sandbox/RuntimeMessageBridge.ts +82 -0
- package/src/components/sandbox/RuntimeMessageRouter.ts +216 -0
- package/src/components/sandbox/SandboxRuntimeProvider.ts +35 -0
- package/src/dialogs/ApiKeyPromptDialog.ts +2 -5
- package/src/dialogs/ModelSelector.ts +2 -2
- package/src/dialogs/PersistentStorageDialog.ts +141 -0
- package/src/dialogs/SessionListDialog.ts +148 -0
- package/src/dialogs/SettingsDialog.ts +1 -0
- package/src/index.ts +61 -20
- package/src/prompts/prompts.ts +282 -0
- package/src/storage/app-storage.ts +27 -24
- package/src/storage/backends/indexeddb-storage-backend.ts +193 -0
- package/src/storage/store.ts +33 -0
- package/src/storage/stores/provider-keys-store.ts +33 -0
- package/src/storage/stores/sessions-store.ts +130 -0
- package/src/storage/stores/settings-store.ts +34 -0
- package/src/storage/types.ts +182 -22
- package/src/tools/artifacts/ArtifactElement.ts +0 -1
- package/src/tools/artifacts/ArtifactPill.ts +25 -0
- package/src/tools/artifacts/Console.ts +93 -0
- package/src/tools/artifacts/DocxArtifact.ts +213 -0
- package/src/tools/artifacts/ExcelArtifact.ts +231 -0
- package/src/tools/artifacts/GenericArtifact.ts +117 -0
- package/src/tools/artifacts/HtmlArtifact.ts +64 -94
- package/src/tools/artifacts/ImageArtifact.ts +116 -0
- package/src/tools/artifacts/MarkdownArtifact.ts +0 -1
- package/src/tools/artifacts/PdfArtifact.ts +201 -0
- package/src/tools/artifacts/SvgArtifact.ts +0 -1
- package/src/tools/artifacts/TextArtifact.ts +0 -1
- package/src/tools/artifacts/artifacts-tool-renderer.ts +298 -0
- package/src/tools/artifacts/artifacts.ts +190 -366
- package/src/tools/artifacts/index.ts +1 -0
- package/src/tools/extract-document.ts +250 -0
- package/src/tools/index.ts +25 -14
- package/src/tools/javascript-repl.ts +138 -160
- package/src/tools/renderer-registry.ts +98 -0
- package/src/tools/renderers/BashRenderer.ts +33 -30
- package/src/tools/renderers/CalculateRenderer.ts +36 -31
- package/src/tools/renderers/DefaultRenderer.ts +84 -21
- package/src/tools/renderers/GetCurrentTimeRenderer.ts +68 -23
- package/src/tools/types.ts +10 -2
- package/src/utils/i18n.ts +203 -8
- package/dist/state/agent-session.d.ts.map +0 -1
- package/dist/state/agent-session.js.map +0 -1
- package/dist/state/transports/AppTransport.d.ts.map +0 -1
- package/dist/state/transports/ProviderTransport.d.ts.map +0 -1
- package/dist/state/transports/ProviderTransport.js.map +0 -1
- package/dist/state/transports/index.js.map +0 -1
- package/dist/state/transports/proxy-types.js.map +0 -1
- package/dist/state/transports/types.d.ts +0 -11
- package/dist/state/transports/types.d.ts.map +0 -1
- package/dist/storage/backends/chrome-storage-backend.d.ts +0 -18
- package/dist/storage/backends/chrome-storage-backend.d.ts.map +0 -1
- package/dist/storage/backends/chrome-storage-backend.js +0 -67
- package/dist/storage/backends/chrome-storage-backend.js.map +0 -1
- package/dist/storage/backends/indexeddb-backend.d.ts +0 -20
- package/dist/storage/backends/indexeddb-backend.d.ts.map +0 -1
- package/dist/storage/backends/indexeddb-backend.js +0 -89
- package/dist/storage/backends/indexeddb-backend.js.map +0 -1
- package/dist/storage/backends/local-storage-backend.d.ts +0 -18
- package/dist/storage/backends/local-storage-backend.d.ts.map +0 -1
- package/dist/storage/backends/local-storage-backend.js +0 -69
- package/dist/storage/backends/local-storage-backend.js.map +0 -1
- package/dist/storage/repositories/provider-keys-repository.d.ts +0 -34
- package/dist/storage/repositories/provider-keys-repository.d.ts.map +0 -1
- package/dist/storage/repositories/provider-keys-repository.js +0 -50
- package/dist/storage/repositories/provider-keys-repository.js.map +0 -1
- package/dist/storage/repositories/settings-repository.d.ts +0 -34
- package/dist/storage/repositories/settings-repository.d.ts.map +0 -1
- package/dist/storage/repositories/settings-repository.js +0 -46
- package/dist/storage/repositories/settings-repository.js.map +0 -1
- package/src/storage/backends/chrome-storage-backend.ts +0 -82
- package/src/storage/backends/indexeddb-backend.ts +0 -107
- package/src/storage/backends/local-storage-backend.ts +0 -74
- package/src/storage/repositories/provider-keys-repository.ts +0 -55
- package/src/storage/repositories/settings-repository.ts +0 -51
- /package/dist/{state → agent}/transports/index.d.ts +0 -0
- /package/dist/{state → agent}/transports/index.js +0 -0
- /package/dist/{state → agent}/transports/proxy-types.d.ts +0 -0
- /package/dist/{state → agent}/transports/proxy-types.js +0 -0
- /package/dist/{state → agent}/transports/types.js +0 -0
- /package/dist/{state → agent}/types.d.ts +0 -0
- /package/dist/{state → agent}/types.js +0 -0
- /package/src/{state → agent}/transports/index.ts +0 -0
- /package/src/{state → agent}/transports/proxy-types.ts +0 -0
- /package/src/{state → agent}/types.ts +0 -0
|
@@ -7,7 +7,7 @@ import type { MessageEditor } from "./MessageEditor.js";
|
|
|
7
7
|
import "./MessageEditor.js";
|
|
8
8
|
import "./MessageList.js";
|
|
9
9
|
import "./Messages.js"; // Import for side effects to register the custom elements
|
|
10
|
-
import type {
|
|
10
|
+
import type { Agent, AgentEvent } from "../agent/agent.js";
|
|
11
11
|
import { getAppStorage } from "../storage/app-storage.js";
|
|
12
12
|
import "./StreamingMessageContainer.js";
|
|
13
13
|
import type { Attachment } from "../utils/attachment-utils.js";
|
|
@@ -18,14 +18,17 @@ import type { StreamingMessageContainer } from "./StreamingMessageContainer.js";
|
|
|
18
18
|
@customElement("agent-interface")
|
|
19
19
|
export class AgentInterface extends LitElement {
|
|
20
20
|
// Optional external session: when provided, this component becomes a view over the session
|
|
21
|
-
@property({ attribute: false }) session?:
|
|
22
|
-
@property() enableAttachments = true;
|
|
23
|
-
@property() enableModelSelector = true;
|
|
24
|
-
@property()
|
|
25
|
-
@property() showThemeToggle = false;
|
|
26
|
-
@property() showDebugToggle = false;
|
|
21
|
+
@property({ attribute: false }) session?: Agent;
|
|
22
|
+
@property({ type: Boolean }) enableAttachments = true;
|
|
23
|
+
@property({ type: Boolean }) enableModelSelector = true;
|
|
24
|
+
@property({ type: Boolean }) enableThinkingSelector = true;
|
|
25
|
+
@property({ type: Boolean }) showThemeToggle = false;
|
|
27
26
|
// Optional custom API key prompt handler - if not provided, uses default dialog
|
|
28
27
|
@property({ attribute: false }) onApiKeyRequired?: (provider: string) => Promise<boolean>;
|
|
28
|
+
// Optional callback called before sending a message
|
|
29
|
+
@property({ attribute: false }) onBeforeSend?: () => void | Promise<void>;
|
|
30
|
+
// Optional callback called before executing a tool call - return false to prevent execution
|
|
31
|
+
@property({ attribute: false }) onBeforeToolCall?: (toolName: string, args: any) => boolean | Promise<boolean>;
|
|
29
32
|
|
|
30
33
|
// References
|
|
31
34
|
@query("message-editor") private _messageEditor!: MessageEditor;
|
|
@@ -49,10 +52,23 @@ export class AgentInterface extends LitElement {
|
|
|
49
52
|
update();
|
|
50
53
|
}
|
|
51
54
|
|
|
55
|
+
public setAutoScroll(enabled: boolean) {
|
|
56
|
+
this._autoScroll = enabled;
|
|
57
|
+
}
|
|
58
|
+
|
|
52
59
|
protected override createRenderRoot(): HTMLElement | DocumentFragment {
|
|
53
60
|
return this;
|
|
54
61
|
}
|
|
55
62
|
|
|
63
|
+
override willUpdate(changedProperties: Map<string, any>) {
|
|
64
|
+
super.willUpdate(changedProperties);
|
|
65
|
+
|
|
66
|
+
// Re-subscribe when session property changes
|
|
67
|
+
if (changedProperties.has("session")) {
|
|
68
|
+
this.setupSessionSubscription();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
56
72
|
override async connectedCallback() {
|
|
57
73
|
super.connectedCallback();
|
|
58
74
|
|
|
@@ -85,11 +101,6 @@ export class AgentInterface extends LitElement {
|
|
|
85
101
|
|
|
86
102
|
// Subscribe to external session if provided
|
|
87
103
|
this.setupSessionSubscription();
|
|
88
|
-
|
|
89
|
-
// Attach debug listener if session provided
|
|
90
|
-
if (this.session) {
|
|
91
|
-
this.session = this.session; // explicitly set to trigger subscription
|
|
92
|
-
}
|
|
93
104
|
}
|
|
94
105
|
|
|
95
106
|
override disconnectedCallback() {
|
|
@@ -117,7 +128,7 @@ export class AgentInterface extends LitElement {
|
|
|
117
128
|
this._unsubscribeSession = undefined;
|
|
118
129
|
}
|
|
119
130
|
if (!this.session) return;
|
|
120
|
-
this._unsubscribeSession = this.session.subscribe(async (ev:
|
|
131
|
+
this._unsubscribeSession = this.session.subscribe(async (ev: AgentEvent) => {
|
|
121
132
|
if (ev.type === "state-update") {
|
|
122
133
|
if (this._streamingContainer) {
|
|
123
134
|
this._streamingContainer.isStreaming = ev.state.isStreaming;
|
|
@@ -166,7 +177,7 @@ export class AgentInterface extends LitElement {
|
|
|
166
177
|
|
|
167
178
|
// Check if API key exists for the provider (only needed in direct mode)
|
|
168
179
|
const provider = session.state.model.provider;
|
|
169
|
-
const apiKey = await getAppStorage().providerKeys.
|
|
180
|
+
const apiKey = await getAppStorage().providerKeys.get(provider);
|
|
170
181
|
|
|
171
182
|
// If no API key, prompt for it
|
|
172
183
|
if (!apiKey) {
|
|
@@ -183,6 +194,11 @@ export class AgentInterface extends LitElement {
|
|
|
183
194
|
}
|
|
184
195
|
}
|
|
185
196
|
|
|
197
|
+
// Call onBeforeSend hook before sending
|
|
198
|
+
if (this.onBeforeSend) {
|
|
199
|
+
await this.onBeforeSend();
|
|
200
|
+
}
|
|
201
|
+
|
|
186
202
|
// Only clear editor after we know we can send
|
|
187
203
|
this._messageEditor.value = "";
|
|
188
204
|
this._messageEditor.attachments = [];
|
|
@@ -286,7 +302,7 @@ export class AgentInterface extends LitElement {
|
|
|
286
302
|
.thinkingLevel=${state.thinkingLevel}
|
|
287
303
|
.showAttachmentButton=${this.enableAttachments}
|
|
288
304
|
.showModelSelector=${this.enableModelSelector}
|
|
289
|
-
.
|
|
305
|
+
.showThinkingSelector=${this.enableThinkingSelector}
|
|
290
306
|
.onSend=${(input: string, attachments: Attachment[]) => {
|
|
291
307
|
this.sendMessage(input, attachments);
|
|
292
308
|
}}
|
|
@@ -295,7 +311,7 @@ export class AgentInterface extends LitElement {
|
|
|
295
311
|
ModelSelector.open(state.model, (model) => session.setModel(model));
|
|
296
312
|
}}
|
|
297
313
|
.onThinkingChange=${
|
|
298
|
-
this.
|
|
314
|
+
this.enableThinkingSelector
|
|
299
315
|
? (level: "off" | "minimal" | "low" | "medium" | "high") => {
|
|
300
316
|
session.setThinkingLevel(level);
|
|
301
317
|
}
|
|
@@ -6,6 +6,7 @@ import { i18n } from "../utils/i18n.js";
|
|
|
6
6
|
|
|
7
7
|
export class ConsoleBlock extends LitElement {
|
|
8
8
|
@property() content: string = "";
|
|
9
|
+
@property() variant: "default" | "error" = "default";
|
|
9
10
|
@state() private copied = false;
|
|
10
11
|
|
|
11
12
|
protected override createRenderRoot(): HTMLElement | DocumentFragment {
|
|
@@ -38,6 +39,9 @@ export class ConsoleBlock extends LitElement {
|
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
override render() {
|
|
42
|
+
const isError = this.variant === "error";
|
|
43
|
+
const textClass = isError ? "text-destructive" : "text-foreground";
|
|
44
|
+
|
|
41
45
|
return html`
|
|
42
46
|
<div class="border border-border rounded-lg overflow-hidden">
|
|
43
47
|
<div class="flex items-center justify-between px-3 py-1.5 bg-muted border-b border-border">
|
|
@@ -52,7 +56,7 @@ export class ConsoleBlock extends LitElement {
|
|
|
52
56
|
</button>
|
|
53
57
|
</div>
|
|
54
58
|
<div class="console-scroll overflow-auto max-h-64">
|
|
55
|
-
<pre class="!bg-background !border-0 !rounded-none m-0 p-3 text-xs
|
|
59
|
+
<pre class="!bg-background !border-0 !rounded-none m-0 p-3 text-xs ${textClass} font-mono whitespace-pre-wrap">
|
|
56
60
|
${this.content || ""}</pre
|
|
57
61
|
>
|
|
58
62
|
</div>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { icon } from "@mariozechner/mini-lit";
|
|
2
|
+
import { html, LitElement, type TemplateResult } from "lit";
|
|
3
|
+
import { customElement, property, state } from "lit/decorators.js";
|
|
4
|
+
import { ChevronDown, ChevronRight } from "lucide";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Reusable expandable section component for tool renderers.
|
|
8
|
+
* Captures children in connectedCallback and re-renders them in the details area.
|
|
9
|
+
*/
|
|
10
|
+
@customElement("expandable-section")
|
|
11
|
+
export class ExpandableSection extends LitElement {
|
|
12
|
+
@property() summary!: string;
|
|
13
|
+
@property({ type: Boolean }) defaultExpanded = false;
|
|
14
|
+
@state() private expanded = false;
|
|
15
|
+
private capturedChildren: Node[] = [];
|
|
16
|
+
|
|
17
|
+
protected createRenderRoot() {
|
|
18
|
+
return this; // light DOM
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
override connectedCallback() {
|
|
22
|
+
super.connectedCallback();
|
|
23
|
+
// Capture children before first render
|
|
24
|
+
this.capturedChildren = Array.from(this.childNodes);
|
|
25
|
+
// Clear children (we'll re-insert them in render)
|
|
26
|
+
this.innerHTML = "";
|
|
27
|
+
this.expanded = this.defaultExpanded;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
override render(): TemplateResult {
|
|
31
|
+
return html`
|
|
32
|
+
<div>
|
|
33
|
+
<button
|
|
34
|
+
@click=${() => {
|
|
35
|
+
this.expanded = !this.expanded;
|
|
36
|
+
}}
|
|
37
|
+
class="flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors w-full text-left"
|
|
38
|
+
>
|
|
39
|
+
${icon(this.expanded ? ChevronDown : ChevronRight, "sm")}
|
|
40
|
+
<span>${this.summary}</span>
|
|
41
|
+
</button>
|
|
42
|
+
${this.expanded ? html`<div class="mt-2">${this.capturedChildren}</div>` : ""}
|
|
43
|
+
</div>
|
|
44
|
+
`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Button, html, icon } from "@mariozechner/mini-lit";
|
|
1
|
+
import { Button, html, icon, Select, type SelectOption } from "@mariozechner/mini-lit";
|
|
2
2
|
import type { Model } from "@mariozechner/pi-ai";
|
|
3
3
|
import { LitElement } from "lit";
|
|
4
4
|
import { customElement, property, state } from "lit/decorators.js";
|
|
5
5
|
import { createRef, ref } from "lit/directives/ref.js";
|
|
6
|
-
import { Loader2, Paperclip, Send, Sparkles, Square } from "lucide";
|
|
6
|
+
import { Brain, Loader2, Paperclip, Send, Sparkles, Square } from "lucide";
|
|
7
7
|
import "./AttachmentTile.js";
|
|
8
8
|
import { type Attachment, loadAttachment } from "../utils/attachment-utils.js";
|
|
9
9
|
import { i18n } from "../utils/i18n.js";
|
|
@@ -33,13 +33,15 @@ export class MessageEditor extends LitElement {
|
|
|
33
33
|
|
|
34
34
|
@property() isStreaming = false;
|
|
35
35
|
@property() currentModel?: Model<any>;
|
|
36
|
+
@property() thinkingLevel: "off" | "minimal" | "low" | "medium" | "high" = "off";
|
|
36
37
|
@property() showAttachmentButton = true;
|
|
37
38
|
@property() showModelSelector = true;
|
|
38
|
-
@property()
|
|
39
|
+
@property() showThinkingSelector = true;
|
|
39
40
|
@property() onInput?: (value: string) => void;
|
|
40
41
|
@property() onSend?: (input: string, attachments: Attachment[]) => void;
|
|
41
42
|
@property() onAbort?: () => void;
|
|
42
43
|
@property() onModelSelect?: () => void;
|
|
44
|
+
@property() onThinkingChange?: (level: "off" | "minimal" | "low" | "medium" | "high") => void;
|
|
43
45
|
@property() onFilesChange?: (files: Attachment[]) => void;
|
|
44
46
|
@property() attachments: Attachment[] = [];
|
|
45
47
|
@property() maxFiles = 10;
|
|
@@ -48,6 +50,7 @@ export class MessageEditor extends LitElement {
|
|
|
48
50
|
"image/*,application/pdf,.docx,.pptx,.xlsx,.xls,.txt,.md,.json,.xml,.html,.css,.js,.ts,.jsx,.tsx,.yml,.yaml";
|
|
49
51
|
|
|
50
52
|
@state() processingFiles = false;
|
|
53
|
+
@state() isDragging = false;
|
|
51
54
|
private fileInputRef = createRef<HTMLInputElement>();
|
|
52
55
|
|
|
53
56
|
protected override createRenderRoot(): HTMLElement | DocumentFragment {
|
|
@@ -74,6 +77,56 @@ export class MessageEditor extends LitElement {
|
|
|
74
77
|
}
|
|
75
78
|
};
|
|
76
79
|
|
|
80
|
+
private handlePaste = async (e: ClipboardEvent) => {
|
|
81
|
+
const items = e.clipboardData?.items;
|
|
82
|
+
if (!items) return;
|
|
83
|
+
|
|
84
|
+
const imageFiles: File[] = [];
|
|
85
|
+
|
|
86
|
+
// Check for image items in clipboard
|
|
87
|
+
for (let i = 0; i < items.length; i++) {
|
|
88
|
+
const item = items[i];
|
|
89
|
+
if (item.type.startsWith("image/")) {
|
|
90
|
+
const file = item.getAsFile();
|
|
91
|
+
if (file) {
|
|
92
|
+
imageFiles.push(file);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// If we found images, process them
|
|
98
|
+
if (imageFiles.length > 0) {
|
|
99
|
+
e.preventDefault(); // Prevent default paste behavior
|
|
100
|
+
|
|
101
|
+
if (imageFiles.length + this.attachments.length > this.maxFiles) {
|
|
102
|
+
alert(`Maximum ${this.maxFiles} files allowed`);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
this.processingFiles = true;
|
|
107
|
+
const newAttachments: Attachment[] = [];
|
|
108
|
+
|
|
109
|
+
for (const file of imageFiles) {
|
|
110
|
+
try {
|
|
111
|
+
if (file.size > this.maxFileSize) {
|
|
112
|
+
alert(`Image exceeds maximum size of ${Math.round(this.maxFileSize / 1024 / 1024)}MB`);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const attachment = await loadAttachment(file);
|
|
117
|
+
newAttachments.push(attachment);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.error("Error processing pasted image:", error);
|
|
120
|
+
alert(`Failed to process pasted image: ${String(error)}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
this.attachments = [...this.attachments, ...newAttachments];
|
|
125
|
+
this.onFilesChange?.(this.attachments);
|
|
126
|
+
this.processingFiles = false;
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
77
130
|
private handleSend = () => {
|
|
78
131
|
this.onSend?.(this.value, this.attachments);
|
|
79
132
|
};
|
|
@@ -122,6 +175,62 @@ export class MessageEditor extends LitElement {
|
|
|
122
175
|
this.onFilesChange?.(this.attachments);
|
|
123
176
|
}
|
|
124
177
|
|
|
178
|
+
private handleDragOver = (e: DragEvent) => {
|
|
179
|
+
e.preventDefault();
|
|
180
|
+
e.stopPropagation();
|
|
181
|
+
if (!this.isDragging) {
|
|
182
|
+
this.isDragging = true;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
private handleDragLeave = (e: DragEvent) => {
|
|
187
|
+
e.preventDefault();
|
|
188
|
+
e.stopPropagation();
|
|
189
|
+
// Only set isDragging to false if we're leaving the entire component
|
|
190
|
+
const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
|
|
191
|
+
const x = e.clientX;
|
|
192
|
+
const y = e.clientY;
|
|
193
|
+
if (x <= rect.left || x >= rect.right || y <= rect.top || y >= rect.bottom) {
|
|
194
|
+
this.isDragging = false;
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
private handleDrop = async (e: DragEvent) => {
|
|
199
|
+
e.preventDefault();
|
|
200
|
+
e.stopPropagation();
|
|
201
|
+
this.isDragging = false;
|
|
202
|
+
|
|
203
|
+
const files = Array.from(e.dataTransfer?.files || []);
|
|
204
|
+
if (files.length === 0) return;
|
|
205
|
+
|
|
206
|
+
if (files.length + this.attachments.length > this.maxFiles) {
|
|
207
|
+
alert(`Maximum ${this.maxFiles} files allowed`);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
this.processingFiles = true;
|
|
212
|
+
const newAttachments: Attachment[] = [];
|
|
213
|
+
|
|
214
|
+
for (const file of files) {
|
|
215
|
+
try {
|
|
216
|
+
if (file.size > this.maxFileSize) {
|
|
217
|
+
alert(`${file.name} exceeds maximum size of ${Math.round(this.maxFileSize / 1024 / 1024)}MB`);
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const attachment = await loadAttachment(file);
|
|
222
|
+
newAttachments.push(attachment);
|
|
223
|
+
} catch (error) {
|
|
224
|
+
console.error(`Error processing ${file.name}:`, error);
|
|
225
|
+
alert(`Failed to process ${file.name}: ${String(error)}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
this.attachments = [...this.attachments, ...newAttachments];
|
|
230
|
+
this.onFilesChange?.(this.attachments);
|
|
231
|
+
this.processingFiles = false;
|
|
232
|
+
};
|
|
233
|
+
|
|
125
234
|
private adjustTextareaHeight() {
|
|
126
235
|
const textarea = this.textareaRef.value;
|
|
127
236
|
if (textarea) {
|
|
@@ -150,8 +259,28 @@ export class MessageEditor extends LitElement {
|
|
|
150
259
|
}
|
|
151
260
|
|
|
152
261
|
override render() {
|
|
262
|
+
// Check if current model supports thinking/reasoning
|
|
263
|
+
const model = this.currentModel;
|
|
264
|
+
const supportsThinking = model?.reasoning === true; // Models with reasoning:true support thinking
|
|
265
|
+
|
|
153
266
|
return html`
|
|
154
|
-
<div
|
|
267
|
+
<div
|
|
268
|
+
class="bg-card rounded-xl border shadow-sm relative ${this.isDragging ? "border-primary border-2 bg-primary/5" : "border-border"}"
|
|
269
|
+
@dragover=${this.handleDragOver}
|
|
270
|
+
@dragleave=${this.handleDragLeave}
|
|
271
|
+
@drop=${this.handleDrop}
|
|
272
|
+
>
|
|
273
|
+
<!-- Drag overlay -->
|
|
274
|
+
${
|
|
275
|
+
this.isDragging
|
|
276
|
+
? html`
|
|
277
|
+
<div class="absolute inset-0 bg-primary/10 rounded-xl pointer-events-none z-10 flex items-center justify-center">
|
|
278
|
+
<div class="text-primary font-medium">${i18n("Drop files here")}</div>
|
|
279
|
+
</div>
|
|
280
|
+
`
|
|
281
|
+
: ""
|
|
282
|
+
}
|
|
283
|
+
|
|
155
284
|
<!-- Attachments -->
|
|
156
285
|
${
|
|
157
286
|
this.attachments.length > 0
|
|
@@ -179,6 +308,7 @@ export class MessageEditor extends LitElement {
|
|
|
179
308
|
.value=${this.value}
|
|
180
309
|
@input=${this.handleTextareaInput}
|
|
181
310
|
@keydown=${this.handleKeyDown}
|
|
311
|
+
@paste=${this.handlePaste}
|
|
182
312
|
${ref(this.textareaRef)}
|
|
183
313
|
></textarea>
|
|
184
314
|
|
|
@@ -194,7 +324,7 @@ export class MessageEditor extends LitElement {
|
|
|
194
324
|
|
|
195
325
|
<!-- Button Row -->
|
|
196
326
|
<div class="px-2 pb-2 flex items-center justify-between">
|
|
197
|
-
<!-- Left side - attachment and
|
|
327
|
+
<!-- Left side - attachment and thinking selector -->
|
|
198
328
|
<div class="flex gap-2 items-center">
|
|
199
329
|
${
|
|
200
330
|
this.showAttachmentButton
|
|
@@ -215,6 +345,30 @@ export class MessageEditor extends LitElement {
|
|
|
215
345
|
`
|
|
216
346
|
: ""
|
|
217
347
|
}
|
|
348
|
+
${
|
|
349
|
+
supportsThinking && this.showThinkingSelector
|
|
350
|
+
? html`
|
|
351
|
+
${Select({
|
|
352
|
+
value: this.thinkingLevel,
|
|
353
|
+
placeholder: i18n("Off"),
|
|
354
|
+
options: [
|
|
355
|
+
{ value: "off", label: i18n("Off"), icon: icon(Brain, "sm") },
|
|
356
|
+
{ value: "minimal", label: i18n("Minimal"), icon: icon(Brain, "sm") },
|
|
357
|
+
{ value: "low", label: i18n("Low"), icon: icon(Brain, "sm") },
|
|
358
|
+
{ value: "medium", label: i18n("Medium"), icon: icon(Brain, "sm") },
|
|
359
|
+
{ value: "high", label: i18n("High"), icon: icon(Brain, "sm") },
|
|
360
|
+
] as SelectOption[],
|
|
361
|
+
onChange: (value: string) => {
|
|
362
|
+
this.onThinkingChange?.(value as "off" | "minimal" | "low" | "medium" | "high");
|
|
363
|
+
},
|
|
364
|
+
width: "80px",
|
|
365
|
+
size: "sm",
|
|
366
|
+
variant: "ghost",
|
|
367
|
+
fitContent: true,
|
|
368
|
+
})}
|
|
369
|
+
`
|
|
370
|
+
: ""
|
|
371
|
+
}
|
|
218
372
|
</div>
|
|
219
373
|
|
|
220
374
|
<!-- Model selector and send on the right -->
|
|
@@ -2,15 +2,16 @@ import { html } from "@mariozechner/mini-lit";
|
|
|
2
2
|
import type {
|
|
3
3
|
AgentTool,
|
|
4
4
|
AssistantMessage as AssistantMessageType,
|
|
5
|
-
Message,
|
|
6
5
|
ToolResultMessage as ToolResultMessageType,
|
|
7
6
|
} from "@mariozechner/pi-ai";
|
|
8
7
|
import { LitElement, type TemplateResult } from "lit";
|
|
9
8
|
import { property } from "lit/decorators.js";
|
|
10
9
|
import { repeat } from "lit/directives/repeat.js";
|
|
10
|
+
import type { AppMessage } from "./Messages.js";
|
|
11
|
+
import { renderMessage } from "./message-renderer-registry.js";
|
|
11
12
|
|
|
12
13
|
export class MessageList extends LitElement {
|
|
13
|
-
@property({ type: Array }) messages:
|
|
14
|
+
@property({ type: Array }) messages: AppMessage[] = [];
|
|
14
15
|
@property({ type: Array }) tools: AgentTool[] = [];
|
|
15
16
|
@property({ type: Object }) pendingToolCalls?: Set<string>;
|
|
16
17
|
@property({ type: Boolean }) isStreaming: boolean = false;
|
|
@@ -36,6 +37,20 @@ export class MessageList extends LitElement {
|
|
|
36
37
|
const items: Array<{ key: string; template: TemplateResult }> = [];
|
|
37
38
|
let index = 0;
|
|
38
39
|
for (const msg of this.messages) {
|
|
40
|
+
// Skip artifact messages - they're for session persistence only, not UI display
|
|
41
|
+
if (msg.role === "artifact") {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Try custom renderer first
|
|
46
|
+
const customTemplate = renderMessage(msg);
|
|
47
|
+
if (customTemplate) {
|
|
48
|
+
items.push({ key: `msg:${index}`, template: customTemplate });
|
|
49
|
+
index++;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Fall back to built-in renderers
|
|
39
54
|
if (msg.role === "user") {
|
|
40
55
|
items.push({
|
|
41
56
|
key: `msg:${index}`,
|
|
@@ -58,7 +73,7 @@ export class MessageList extends LitElement {
|
|
|
58
73
|
index++;
|
|
59
74
|
} else {
|
|
60
75
|
// Skip standalone toolResult messages; they are rendered via paired tool-message above
|
|
61
|
-
//
|
|
76
|
+
// Skip unknown roles
|
|
62
77
|
}
|
|
63
78
|
}
|
|
64
79
|
return items;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { html } from "@mariozechner/mini-lit";
|
|
2
2
|
import type {
|
|
3
3
|
AgentTool,
|
|
4
4
|
AssistantMessage as AssistantMessageType,
|
|
@@ -6,17 +6,41 @@ import type {
|
|
|
6
6
|
ToolResultMessage as ToolResultMessageType,
|
|
7
7
|
UserMessage as UserMessageType,
|
|
8
8
|
} from "@mariozechner/pi-ai";
|
|
9
|
-
import type { AgentToolResult } from "@mariozechner/pi-ai/dist/agent/types.js";
|
|
10
9
|
import { LitElement, type TemplateResult } from "lit";
|
|
11
|
-
import { customElement, property
|
|
12
|
-
import {
|
|
13
|
-
import { renderToolParams, renderToolResult } from "../tools/index.js";
|
|
10
|
+
import { customElement, property } from "lit/decorators.js";
|
|
11
|
+
import { renderTool } from "../tools/index.js";
|
|
14
12
|
import type { Attachment } from "../utils/attachment-utils.js";
|
|
15
13
|
import { formatUsage } from "../utils/format.js";
|
|
16
14
|
import { i18n } from "../utils/i18n.js";
|
|
17
15
|
|
|
18
16
|
export type UserMessageWithAttachments = UserMessageType & { attachments?: Attachment[] };
|
|
19
|
-
|
|
17
|
+
|
|
18
|
+
// Artifact message type for session persistence
|
|
19
|
+
export interface ArtifactMessage {
|
|
20
|
+
role: "artifact";
|
|
21
|
+
action: "create" | "update" | "delete";
|
|
22
|
+
filename: string;
|
|
23
|
+
content?: string;
|
|
24
|
+
title?: string;
|
|
25
|
+
timestamp: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Base message union
|
|
29
|
+
type BaseMessage = AssistantMessageType | UserMessageWithAttachments | ToolResultMessageType | ArtifactMessage;
|
|
30
|
+
|
|
31
|
+
// Extensible interface - apps can extend via declaration merging
|
|
32
|
+
// Example:
|
|
33
|
+
// declare module "@mariozechner/pi-web-ui" {
|
|
34
|
+
// interface CustomMessages {
|
|
35
|
+
// "system-notification": SystemNotificationMessage;
|
|
36
|
+
// }
|
|
37
|
+
// }
|
|
38
|
+
export interface CustomMessages {
|
|
39
|
+
// Empty by default - apps extend via declaration merging
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// AppMessage is union of base messages + custom messages
|
|
43
|
+
export type AppMessage = BaseMessage | CustomMessages[keyof CustomMessages];
|
|
20
44
|
|
|
21
45
|
@customElement("user-message")
|
|
22
46
|
export class UserMessage extends LitElement {
|
|
@@ -88,7 +112,8 @@ export class AssistantMessage extends LitElement {
|
|
|
88
112
|
const tool = this.tools?.find((t) => t.name === chunk.name);
|
|
89
113
|
const pending = this.pendingToolCalls?.has(chunk.id) ?? false;
|
|
90
114
|
const result = this.toolResultsById?.get(chunk.id);
|
|
91
|
-
|
|
115
|
+
// A tool call is aborted if the message was aborted and there's no result for this tool call
|
|
116
|
+
const aborted = this.message.stopReason === "aborted" && !result;
|
|
92
117
|
orderedParts.push(
|
|
93
118
|
html`<tool-message
|
|
94
119
|
.tool=${tool}
|
|
@@ -133,7 +158,7 @@ export class AssistantMessage extends LitElement {
|
|
|
133
158
|
@customElement("tool-message-debug")
|
|
134
159
|
export class ToolMessageDebugView extends LitElement {
|
|
135
160
|
@property({ type: Object }) callArgs: any;
|
|
136
|
-
@property({ type:
|
|
161
|
+
@property({ type: Object }) result?: ToolResultMessageType;
|
|
137
162
|
@property({ type: Boolean }) hasResult: boolean = false;
|
|
138
163
|
|
|
139
164
|
protected override createRenderRoot(): HTMLElement | DocumentFragment {
|
|
@@ -189,7 +214,6 @@ export class ToolMessage extends LitElement {
|
|
|
189
214
|
@property({ type: Boolean }) pending: boolean = false;
|
|
190
215
|
@property({ type: Boolean }) aborted: boolean = false;
|
|
191
216
|
@property({ type: Boolean }) isStreaming: boolean = false;
|
|
192
|
-
@state() private _showDebug = false;
|
|
193
217
|
|
|
194
218
|
protected override createRenderRoot(): HTMLElement | DocumentFragment {
|
|
195
219
|
return this;
|
|
@@ -200,94 +224,29 @@ export class ToolMessage extends LitElement {
|
|
|
200
224
|
this.style.display = "block";
|
|
201
225
|
}
|
|
202
226
|
|
|
203
|
-
private toggleDebug = () => {
|
|
204
|
-
this._showDebug = !this._showDebug;
|
|
205
|
-
};
|
|
206
|
-
|
|
207
227
|
override render() {
|
|
208
|
-
const toolLabel = this.tool?.label || this.toolCall.name;
|
|
209
228
|
const toolName = this.tool?.name || this.toolCall.name;
|
|
210
|
-
const isError = this.result?.isError === true;
|
|
211
|
-
const hasResult = !!this.result;
|
|
212
|
-
|
|
213
|
-
let statusIcon: TemplateResult;
|
|
214
|
-
if (this.pending || (this.isStreaming && !hasResult)) {
|
|
215
|
-
statusIcon = html`<span class="inline-block text-muted-foreground animate-spin">${icon(Loader, "sm")}</span>`;
|
|
216
|
-
} else if (this.aborted && !hasResult) {
|
|
217
|
-
statusIcon = html`<span class="inline-block text-destructive">${icon(Wrench, "sm")}</span>`;
|
|
218
|
-
} else if (hasResult && isError) {
|
|
219
|
-
statusIcon = html`<span class="inline-block text-destructive">${icon(Wrench, "sm")}</span>`;
|
|
220
|
-
} else if (hasResult) {
|
|
221
|
-
statusIcon = html`<span class="inline-block text-muted-foreground">${icon(Wrench, "sm")}</span>`;
|
|
222
|
-
} else {
|
|
223
|
-
statusIcon = html`<span class="inline-block text-muted-foreground">${icon(Wrench, "sm")}</span>`;
|
|
224
|
-
}
|
|
225
229
|
|
|
226
|
-
//
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if ((parsed as any).error) errorMessage = (parsed as any).error;
|
|
232
|
-
else if ((parsed as any).message) errorMessage = (parsed as any).message;
|
|
233
|
-
} catch {}
|
|
234
|
-
errorMessage = errorMessage.replace(/^(Tool )?Error:\s*/i, "");
|
|
235
|
-
errorMessage = errorMessage.replace(/^Error:\s*/i, "");
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
const paramsTpl = renderToolParams(
|
|
230
|
+
// Render tool content (renderer handles errors and styling)
|
|
231
|
+
const result: ToolResultMessageType<any> | undefined = this.aborted
|
|
232
|
+
? { role: "toolResult", isError: true, output: "", toolCallId: this.toolCall.id, toolName: this.toolCall.name }
|
|
233
|
+
: this.result;
|
|
234
|
+
const renderResult = renderTool(
|
|
239
235
|
toolName,
|
|
240
236
|
this.toolCall.arguments,
|
|
241
|
-
|
|
237
|
+
result,
|
|
238
|
+
!this.aborted && (this.isStreaming || this.pending),
|
|
242
239
|
);
|
|
243
|
-
const resultTpl =
|
|
244
|
-
hasResult && !isError ? renderToolResult(toolName, this.toolCall.arguments, this.result!) : undefined;
|
|
245
240
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
${statusIcon}
|
|
251
|
-
<span class="font-medium">${toolLabel}</span>
|
|
252
|
-
</div>
|
|
253
|
-
${Button({
|
|
254
|
-
variant: this._showDebug ? "default" : "ghost",
|
|
255
|
-
size: "sm",
|
|
256
|
-
onClick: this.toggleDebug,
|
|
257
|
-
children: icon(Bug, "sm"),
|
|
258
|
-
className: "text-muted-foreground",
|
|
259
|
-
})}
|
|
260
|
-
</div>
|
|
241
|
+
// Handle custom rendering (no card wrapper)
|
|
242
|
+
if (renderResult.isCustom) {
|
|
243
|
+
return renderResult.content;
|
|
244
|
+
}
|
|
261
245
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
.result=${this.result}
|
|
267
|
-
.hasResult=${!!this.result}
|
|
268
|
-
></tool-message-debug>`
|
|
269
|
-
: html`
|
|
270
|
-
<div class="mt-2 text-sm text-muted-foreground">${paramsTpl}</div>
|
|
271
|
-
${
|
|
272
|
-
this.pending && !hasResult
|
|
273
|
-
? html`<div class="mt-2 text-sm text-muted-foreground">${i18n("Waiting for tool result…")}</div>`
|
|
274
|
-
: ""
|
|
275
|
-
}
|
|
276
|
-
${
|
|
277
|
-
this.aborted && !hasResult
|
|
278
|
-
? html`<div class="mt-2 text-sm text-muted-foreground">${i18n("Call was aborted; no result.")}</div>`
|
|
279
|
-
: ""
|
|
280
|
-
}
|
|
281
|
-
${
|
|
282
|
-
hasResult && isError
|
|
283
|
-
? html`<div class="mt-2 p-2 border border-destructive rounded bg-destructive/10 text-sm text-destructive">
|
|
284
|
-
${errorMessage}
|
|
285
|
-
</div>`
|
|
286
|
-
: ""
|
|
287
|
-
}
|
|
288
|
-
${resultTpl ? html`<div class="mt-2">${resultTpl}</div>` : ""}
|
|
289
|
-
`
|
|
290
|
-
}
|
|
246
|
+
// Default: wrap in card
|
|
247
|
+
return html`
|
|
248
|
+
<div class="p-2.5 border border-border rounded-md bg-card text-card-foreground shadow-xs">
|
|
249
|
+
${renderResult.content}
|
|
291
250
|
</div>
|
|
292
251
|
`;
|
|
293
252
|
}
|