@draht/web-ui 2026.3.14 → 2026.3.25
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 +13 -13
- package/dist/ChatPanel.d.ts +1 -0
- package/dist/ChatPanel.d.ts.map +1 -1
- package/dist/ChatPanel.js +12 -11
- package/dist/ChatPanel.js.map +1 -1
- package/dist/components/AgentInterface.d.ts +1 -0
- package/dist/components/AgentInterface.d.ts.map +1 -1
- package/dist/components/AgentInterface.js +50 -48
- package/dist/components/AgentInterface.js.map +1 -1
- package/dist/components/AttachmentTile.d.ts.map +1 -1
- package/dist/components/AttachmentTile.js +7 -6
- package/dist/components/AttachmentTile.js.map +1 -1
- package/dist/components/ConsoleBlock.d.ts.map +1 -1
- package/dist/components/ConsoleBlock.js +6 -3
- package/dist/components/ConsoleBlock.js.map +1 -1
- package/dist/components/CustomProviderCard.d.ts.map +1 -1
- package/dist/components/CustomProviderCard.js +4 -6
- package/dist/components/CustomProviderCard.js.map +1 -1
- package/dist/components/ExpandableSection.d.ts.map +1 -1
- package/dist/components/ExpandableSection.js +6 -4
- package/dist/components/ExpandableSection.js.map +1 -1
- package/dist/components/Input.js.map +1 -1
- package/dist/components/MessageEditor.d.ts.map +1 -1
- package/dist/components/MessageEditor.js +124 -126
- package/dist/components/MessageEditor.js.map +1 -1
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js +6 -5
- package/dist/components/MessageList.js.map +1 -1
- package/dist/components/Messages.d.ts.map +1 -1
- package/dist/components/Messages.js +16 -18
- package/dist/components/Messages.js.map +1 -1
- package/dist/components/ProviderKeyInput.d.ts.map +1 -1
- package/dist/components/ProviderKeyInput.js +10 -7
- package/dist/components/ProviderKeyInput.js.map +1 -1
- package/dist/components/SandboxedIframe.d.ts.map +1 -1
- package/dist/components/SandboxedIframe.js +0 -7
- package/dist/components/SandboxedIframe.js.map +1 -1
- package/dist/components/StreamingMessageContainer.d.ts.map +1 -1
- package/dist/components/StreamingMessageContainer.js +9 -9
- package/dist/components/StreamingMessageContainer.js.map +1 -1
- package/dist/components/ThinkingBlock.d.ts.map +1 -1
- package/dist/components/ThinkingBlock.js +5 -3
- package/dist/components/ThinkingBlock.js.map +1 -1
- package/dist/components/message-renderer-registry.js.map +1 -1
- package/dist/components/sandbox/ArtifactsRuntimeProvider.d.ts.map +1 -1
- package/dist/components/sandbox/ArtifactsRuntimeProvider.js +0 -3
- package/dist/components/sandbox/ArtifactsRuntimeProvider.js.map +1 -1
- package/dist/components/sandbox/AttachmentsRuntimeProvider.d.ts.map +1 -1
- package/dist/components/sandbox/AttachmentsRuntimeProvider.js +0 -1
- package/dist/components/sandbox/AttachmentsRuntimeProvider.js.map +1 -1
- package/dist/components/sandbox/ConsoleRuntimeProvider.d.ts.map +1 -1
- package/dist/components/sandbox/ConsoleRuntimeProvider.js +5 -3
- package/dist/components/sandbox/ConsoleRuntimeProvider.js.map +1 -1
- package/dist/components/sandbox/FileDownloadRuntimeProvider.d.ts.map +1 -1
- package/dist/components/sandbox/FileDownloadRuntimeProvider.js +3 -1
- package/dist/components/sandbox/FileDownloadRuntimeProvider.js.map +1 -1
- package/dist/components/sandbox/RuntimeMessageBridge.d.ts.map +1 -1
- package/dist/components/sandbox/RuntimeMessageBridge.js.map +1 -1
- package/dist/components/sandbox/RuntimeMessageRouter.d.ts.map +1 -1
- package/dist/components/sandbox/RuntimeMessageRouter.js +5 -3
- package/dist/components/sandbox/RuntimeMessageRouter.js.map +1 -1
- package/dist/dialogs/ApiKeyPromptDialog.d.ts.map +1 -1
- package/dist/dialogs/ApiKeyPromptDialog.js +10 -8
- package/dist/dialogs/ApiKeyPromptDialog.js.map +1 -1
- package/dist/dialogs/AttachmentOverlay.d.ts.map +1 -1
- package/dist/dialogs/AttachmentOverlay.js +31 -31
- package/dist/dialogs/AttachmentOverlay.js.map +1 -1
- package/dist/dialogs/CustomProviderDialog.d.ts.map +1 -1
- package/dist/dialogs/CustomProviderDialog.js +12 -12
- package/dist/dialogs/CustomProviderDialog.js.map +1 -1
- package/dist/dialogs/ModelSelector.d.ts +2 -1
- package/dist/dialogs/ModelSelector.d.ts.map +1 -1
- package/dist/dialogs/ModelSelector.js +84 -36
- package/dist/dialogs/ModelSelector.js.map +1 -1
- package/dist/dialogs/PersistentStorageDialog.d.ts.map +1 -1
- package/dist/dialogs/PersistentStorageDialog.js +10 -7
- package/dist/dialogs/PersistentStorageDialog.js.map +1 -1
- package/dist/dialogs/ProvidersModelsTab.d.ts.map +1 -1
- package/dist/dialogs/ProvidersModelsTab.js +5 -2
- package/dist/dialogs/ProvidersModelsTab.js.map +1 -1
- package/dist/dialogs/SessionListDialog.d.ts.map +1 -1
- package/dist/dialogs/SessionListDialog.js +13 -11
- package/dist/dialogs/SessionListDialog.js.map +1 -1
- package/dist/dialogs/SettingsDialog.d.ts +2 -1
- package/dist/dialogs/SettingsDialog.d.ts.map +1 -1
- package/dist/dialogs/SettingsDialog.js +18 -9
- package/dist/dialogs/SettingsDialog.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/prompts/prompts.d.ts.map +1 -1
- package/dist/storage/app-storage.d.ts.map +1 -1
- package/dist/storage/app-storage.js +0 -5
- package/dist/storage/app-storage.js.map +1 -1
- package/dist/storage/backends/indexeddb-storage-backend.d.ts.map +1 -1
- package/dist/storage/backends/indexeddb-storage-backend.js +1 -2
- package/dist/storage/backends/indexeddb-storage-backend.js.map +1 -1
- package/dist/storage/store.d.ts.map +1 -1
- package/dist/storage/store.js +3 -1
- package/dist/storage/store.js.map +1 -1
- package/dist/storage/stores/custom-providers-store.d.ts.map +1 -1
- package/dist/storage/stores/custom-providers-store.js.map +1 -1
- package/dist/storage/stores/provider-keys-store.d.ts.map +1 -1
- package/dist/storage/stores/provider-keys-store.js.map +1 -1
- package/dist/storage/stores/sessions-store.d.ts.map +1 -1
- package/dist/storage/stores/sessions-store.js.map +1 -1
- package/dist/storage/stores/settings-store.d.ts.map +1 -1
- package/dist/storage/stores/settings-store.js.map +1 -1
- package/dist/tools/artifacts/ArtifactElement.d.ts.map +1 -1
- package/dist/tools/artifacts/ArtifactElement.js +4 -1
- package/dist/tools/artifacts/ArtifactElement.js.map +1 -1
- package/dist/tools/artifacts/ArtifactPill.js.map +1 -1
- package/dist/tools/artifacts/Console.d.ts.map +1 -1
- package/dist/tools/artifacts/Console.js +7 -4
- package/dist/tools/artifacts/Console.js.map +1 -1
- package/dist/tools/artifacts/DocxArtifact.d.ts.map +1 -1
- package/dist/tools/artifacts/DocxArtifact.js +5 -2
- package/dist/tools/artifacts/DocxArtifact.js.map +1 -1
- package/dist/tools/artifacts/ExcelArtifact.d.ts.map +1 -1
- package/dist/tools/artifacts/ExcelArtifact.js +5 -2
- package/dist/tools/artifacts/ExcelArtifact.js.map +1 -1
- package/dist/tools/artifacts/GenericArtifact.d.ts.map +1 -1
- package/dist/tools/artifacts/GenericArtifact.js +4 -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 +11 -9
- package/dist/tools/artifacts/HtmlArtifact.js.map +1 -1
- package/dist/tools/artifacts/ImageArtifact.d.ts.map +1 -1
- package/dist/tools/artifacts/ImageArtifact.js +4 -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 +6 -3
- package/dist/tools/artifacts/MarkdownArtifact.js.map +1 -1
- package/dist/tools/artifacts/PdfArtifact.d.ts.map +1 -1
- package/dist/tools/artifacts/PdfArtifact.js +6 -3
- 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 +6 -3
- 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 +5 -2
- 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 +0 -1
- 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 +12 -17
- package/dist/tools/artifacts/artifacts.js.map +1 -1
- package/dist/tools/extract-document.d.ts +1 -1
- package/dist/tools/extract-document.d.ts.map +1 -1
- package/dist/tools/extract-document.js.map +1 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/javascript-repl.d.ts +2 -2
- package/dist/tools/javascript-repl.d.ts.map +1 -1
- package/dist/tools/javascript-repl.js.map +1 -1
- 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.map +1 -1
- package/dist/tools/renderers/CalculateRenderer.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/tools/renderers/GetCurrentTimeRenderer.d.ts.map +1 -1
- package/dist/tools/renderers/GetCurrentTimeRenderer.js.map +1 -1
- package/dist/utils/attachment-utils.js.map +1 -1
- package/dist/utils/auth-token.js.map +1 -1
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/i18n.d.ts +14 -14
- package/dist/utils/i18n.d.ts.map +1 -1
- package/dist/utils/i18n.js.map +1 -1
- package/dist/utils/model-discovery.js.map +1 -1
- package/dist/utils/proxy-utils.d.ts +1 -1
- package/dist/utils/proxy-utils.d.ts.map +1 -1
- package/dist/utils/proxy-utils.js +5 -1
- package/dist/utils/proxy-utils.js.map +1 -1
- package/dist/utils/test-sessions.d.ts +47 -47
- package/dist/utils/test-sessions.js.map +1 -1
- package/package.json +5 -5
- package/src/ChatPanel.ts +2 -0
- package/src/components/AgentInterface.ts +15 -2
- package/src/components/MessageEditor.ts +3 -1
- package/src/components/ProviderKeyInput.ts +1 -1
- package/src/dialogs/ModelSelector.ts +72 -18
- package/src/dialogs/SettingsDialog.ts +5 -1
- package/src/index.ts +1 -0
- package/src/utils/proxy-utils.ts +6 -1
|
@@ -15,6 +15,37 @@ import { formatModelCost } from "../utils/format.js";
|
|
|
15
15
|
import { i18n } from "../utils/i18n.js";
|
|
16
16
|
import { discoverModels } from "../utils/model-discovery.js";
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Score a query against a text using subsequence matching.
|
|
20
|
+
* All query characters must appear in order in the text.
|
|
21
|
+
* Higher score = tighter match (fewer gaps between matched characters).
|
|
22
|
+
* Returns 0 if no match.
|
|
23
|
+
*/
|
|
24
|
+
function subsequenceScore(query: string, text: string): number {
|
|
25
|
+
let qi = 0;
|
|
26
|
+
let ti = 0;
|
|
27
|
+
let gaps = 0;
|
|
28
|
+
let lastMatchIndex = -1;
|
|
29
|
+
|
|
30
|
+
while (qi < query.length && ti < text.length) {
|
|
31
|
+
if (query[qi] === text[ti]) {
|
|
32
|
+
if (lastMatchIndex >= 0) {
|
|
33
|
+
gaps += ti - lastMatchIndex - 1;
|
|
34
|
+
}
|
|
35
|
+
lastMatchIndex = ti;
|
|
36
|
+
qi++;
|
|
37
|
+
}
|
|
38
|
+
ti++;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// All query chars must match
|
|
42
|
+
if (qi < query.length) return 0;
|
|
43
|
+
|
|
44
|
+
// Score: longer query match = better, fewer gaps = better
|
|
45
|
+
// Normalize so exact substring gets highest score
|
|
46
|
+
return query.length / (query.length + gaps);
|
|
47
|
+
}
|
|
48
|
+
|
|
18
49
|
@customElement("agent-model-selector")
|
|
19
50
|
export class ModelSelector extends DialogBase {
|
|
20
51
|
@state() currentModel: Model<any> | null = null;
|
|
@@ -27,16 +58,24 @@ export class ModelSelector extends DialogBase {
|
|
|
27
58
|
@state() private customProviderModels: Model<any>[] = [];
|
|
28
59
|
|
|
29
60
|
private onSelectCallback?: (model: Model<any>) => void;
|
|
61
|
+
private allowedProviders?: Set<string>;
|
|
30
62
|
private scrollContainerRef = createRef<HTMLDivElement>();
|
|
31
63
|
private searchInputRef = createRef<HTMLInputElement>();
|
|
32
64
|
private lastMousePosition = { x: 0, y: 0 };
|
|
33
65
|
|
|
34
66
|
protected override modalWidth = "min(400px, 90vw)";
|
|
35
67
|
|
|
36
|
-
static async open(
|
|
68
|
+
static async open(
|
|
69
|
+
currentModel: Model<any> | null,
|
|
70
|
+
onSelect: (model: Model<any>) => void,
|
|
71
|
+
allowedProviders?: string[],
|
|
72
|
+
) {
|
|
37
73
|
const selector = new ModelSelector();
|
|
38
74
|
selector.currentModel = currentModel;
|
|
39
75
|
selector.onSelectCallback = onSelect;
|
|
76
|
+
if (allowedProviders) {
|
|
77
|
+
selector.allowedProviders = new Set(allowedProviders);
|
|
78
|
+
}
|
|
40
79
|
selector.open();
|
|
41
80
|
selector.loadCustomProviders();
|
|
42
81
|
}
|
|
@@ -173,19 +212,30 @@ export class ModelSelector extends DialogBase {
|
|
|
173
212
|
allModels.push({ provider: model.provider, id: model.id, model });
|
|
174
213
|
}
|
|
175
214
|
|
|
215
|
+
// Filter by allowed providers if set
|
|
216
|
+
if (this.allowedProviders) {
|
|
217
|
+
const allowed = this.allowedProviders;
|
|
218
|
+
allModels.splice(0, allModels.length, ...allModels.filter(({ provider }) => allowed.has(provider)));
|
|
219
|
+
}
|
|
220
|
+
|
|
176
221
|
// Filter models based on search and capability filters
|
|
177
222
|
let filteredModels = allModels;
|
|
178
223
|
|
|
179
|
-
// Apply search filter
|
|
224
|
+
// Apply search filter (subsequence match: characters must appear in order)
|
|
180
225
|
if (this.searchQuery) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
.
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
226
|
+
const query = this.searchQuery.toLowerCase().replace(/\s+/g, "");
|
|
227
|
+
if (query) {
|
|
228
|
+
const scored: Array<{ item: (typeof allModels)[0]; score: number }> = [];
|
|
229
|
+
for (const entry of filteredModels) {
|
|
230
|
+
const searchText = `${entry.provider} ${entry.id} ${entry.model.name}`.toLowerCase();
|
|
231
|
+
const score = subsequenceScore(query, searchText);
|
|
232
|
+
if (score > 0) {
|
|
233
|
+
scored.push({ item: entry, score });
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
scored.sort((a, b) => b.score - a.score);
|
|
237
|
+
filteredModels = scored.map((s) => s.item);
|
|
238
|
+
}
|
|
189
239
|
}
|
|
190
240
|
|
|
191
241
|
// Apply capability filters
|
|
@@ -196,14 +246,18 @@ export class ModelSelector extends DialogBase {
|
|
|
196
246
|
filteredModels = filteredModels.filter(({ model }) => model.input.includes("image"));
|
|
197
247
|
}
|
|
198
248
|
|
|
199
|
-
// Sort: current model first
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
249
|
+
// Sort: when not searching, current model first then by provider.
|
|
250
|
+
// When searching, preserve the score-based order from above,
|
|
251
|
+
// but still float the current model to the top.
|
|
252
|
+
if (!this.searchQuery) {
|
|
253
|
+
filteredModels.sort((a, b) => {
|
|
254
|
+
const aIsCurrent = modelsAreEqual(this.currentModel, a.model);
|
|
255
|
+
const bIsCurrent = modelsAreEqual(this.currentModel, b.model);
|
|
256
|
+
if (aIsCurrent && !bIsCurrent) return -1;
|
|
257
|
+
if (!aIsCurrent && bIsCurrent) return 1;
|
|
258
|
+
return a.provider.localeCompare(b.provider);
|
|
259
|
+
});
|
|
260
|
+
}
|
|
207
261
|
|
|
208
262
|
return filteredModels;
|
|
209
263
|
}
|
|
@@ -122,9 +122,12 @@ export class SettingsDialog extends LitElement {
|
|
|
122
122
|
return this;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
private onCloseCallback?: () => void;
|
|
126
|
+
|
|
127
|
+
static async open(tabs: SettingsTab[], onClose?: () => void) {
|
|
126
128
|
const dialog = new SettingsDialog();
|
|
127
129
|
dialog.tabs = tabs;
|
|
130
|
+
dialog.onCloseCallback = onClose;
|
|
128
131
|
dialog.isOpen = true;
|
|
129
132
|
document.body.appendChild(dialog);
|
|
130
133
|
}
|
|
@@ -173,6 +176,7 @@ export class SettingsDialog extends LitElement {
|
|
|
173
176
|
onClose: () => {
|
|
174
177
|
this.isOpen = false;
|
|
175
178
|
this.remove();
|
|
179
|
+
this.onCloseCallback?.();
|
|
176
180
|
},
|
|
177
181
|
width: "min(1000px, 90vw)",
|
|
178
182
|
height: "min(800px, 90vh)",
|
package/src/index.ts
CHANGED
|
@@ -55,6 +55,7 @@ export type { SandboxRuntimeProvider } from "./components/sandbox/SandboxRuntime
|
|
|
55
55
|
export { ThinkingBlock } from "./components/ThinkingBlock.js";
|
|
56
56
|
export { ApiKeyPromptDialog } from "./dialogs/ApiKeyPromptDialog.js";
|
|
57
57
|
export { AttachmentOverlay } from "./dialogs/AttachmentOverlay.js";
|
|
58
|
+
export { CustomProviderDialog } from "./dialogs/CustomProviderDialog.js";
|
|
58
59
|
// Dialogs
|
|
59
60
|
export { ModelSelector } from "./dialogs/ModelSelector.js";
|
|
60
61
|
export { PersistentStorageDialog } from "./dialogs/PersistentStorageDialog.js";
|
package/src/utils/proxy-utils.ts
CHANGED
|
@@ -25,7 +25,11 @@ export function shouldUseProxyForProvider(provider: string, apiKey: string): boo
|
|
|
25
25
|
case "anthropic":
|
|
26
26
|
// Anthropic OAuth tokens (sk-ant-oat-*) require proxy
|
|
27
27
|
// Regular API keys (sk-ant-api-*) do NOT require proxy
|
|
28
|
-
return apiKey.startsWith("sk-ant-oat");
|
|
28
|
+
return apiKey.startsWith("sk-ant-oat") || apiKey.startsWith("{");
|
|
29
|
+
|
|
30
|
+
case "openai-codex":
|
|
31
|
+
// Codex uses chatgpt.com/backend-api which has no CORS
|
|
32
|
+
return true;
|
|
29
33
|
|
|
30
34
|
// These providers work without proxy
|
|
31
35
|
case "openai":
|
|
@@ -36,6 +40,7 @@ export function shouldUseProxyForProvider(provider: string, apiKey: string): boo
|
|
|
36
40
|
case "xai":
|
|
37
41
|
case "ollama":
|
|
38
42
|
case "lmstudio":
|
|
43
|
+
case "github-copilot":
|
|
39
44
|
return false;
|
|
40
45
|
|
|
41
46
|
// Unknown providers - assume no proxy needed
|