@elyracode/web-ui 0.9.10 → 0.9.12
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/CHANGELOG.md +7 -0
- package/dist/ChatPanel.d.ts +1 -1
- package/dist/ChatPanel.d.ts.map +1 -1
- package/dist/app.css +1 -1
- package/dist/components/AgentInterface.d.ts +1 -1
- package/dist/components/AgentInterface.d.ts.map +1 -1
- package/dist/components/AgentInterface.js +1 -1
- package/dist/components/AgentInterface.js.map +1 -1
- package/dist/components/MessageEditor.d.ts +2 -2
- package/dist/components/MessageEditor.d.ts.map +1 -1
- package/dist/components/Messages.d.ts +3 -3
- package/dist/components/Messages.d.ts.map +1 -1
- package/dist/components/Messages.js.map +1 -1
- package/dist/components/ProviderKeyInput.js +2 -2
- package/dist/components/ProviderKeyInput.js.map +1 -1
- package/dist/components/SandboxedIframe.d.ts +1 -1
- package/dist/components/SandboxedIframe.d.ts.map +1 -1
- package/dist/components/SandboxedIframe.js +1 -1
- package/dist/components/SandboxedIframe.js.map +1 -1
- package/dist/components/message-renderer-registry.js.map +1 -1
- package/dist/components/sandbox/ArtifactsRuntimeProvider.d.ts +4 -3
- package/dist/components/sandbox/ArtifactsRuntimeProvider.d.ts.map +1 -1
- package/dist/components/sandbox/ArtifactsRuntimeProvider.js +31 -31
- package/dist/components/sandbox/ArtifactsRuntimeProvider.js.map +1 -1
- package/dist/components/sandbox/AttachmentsRuntimeProvider.d.ts +1 -1
- package/dist/components/sandbox/AttachmentsRuntimeProvider.d.ts.map +1 -1
- package/dist/components/sandbox/AttachmentsRuntimeProvider.js +6 -5
- package/dist/components/sandbox/AttachmentsRuntimeProvider.js.map +1 -1
- package/dist/components/sandbox/ConsoleRuntimeProvider.d.ts +3 -2
- package/dist/components/sandbox/ConsoleRuntimeProvider.d.ts.map +1 -1
- package/dist/components/sandbox/ConsoleRuntimeProvider.js +12 -11
- package/dist/components/sandbox/ConsoleRuntimeProvider.js.map +1 -1
- package/dist/components/sandbox/FileDownloadRuntimeProvider.d.ts +3 -2
- package/dist/components/sandbox/FileDownloadRuntimeProvider.d.ts.map +1 -1
- package/dist/components/sandbox/FileDownloadRuntimeProvider.js +6 -4
- package/dist/components/sandbox/FileDownloadRuntimeProvider.js.map +1 -1
- package/dist/components/sandbox/RuntimeMessageRouter.d.ts +2 -1
- package/dist/components/sandbox/RuntimeMessageRouter.d.ts.map +1 -1
- package/dist/components/sandbox/RuntimeMessageRouter.js.map +1 -1
- package/dist/components/sandbox/SandboxRuntimeProvider.d.ts +3 -2
- package/dist/components/sandbox/SandboxRuntimeProvider.d.ts.map +1 -1
- package/dist/components/sandbox/runtime-messages.d.ts +140 -0
- package/dist/components/sandbox/runtime-messages.d.ts.map +1 -0
- package/dist/components/sandbox/runtime-messages.js +9 -0
- package/dist/components/sandbox/runtime-messages.js.map +1 -0
- package/dist/dialogs/AttachmentOverlay.d.ts.map +1 -1
- package/dist/dialogs/AttachmentOverlay.js +4 -4
- package/dist/dialogs/AttachmentOverlay.js.map +1 -1
- package/dist/dialogs/ModelSelector.d.ts +3 -3
- package/dist/dialogs/ModelSelector.d.ts.map +1 -1
- package/dist/dialogs/ModelSelector.js.map +1 -1
- package/dist/storage/stores/custom-providers-store.d.ts +2 -2
- package/dist/storage/stores/custom-providers-store.d.ts.map +1 -1
- package/dist/storage/types.d.ts +2 -2
- package/dist/storage/types.d.ts.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/HtmlArtifact.js.map +1 -1
- package/dist/tools/artifacts/PdfArtifact.d.ts.map +1 -1
- package/dist/tools/artifacts/PdfArtifact.js +1 -1
- package/dist/tools/artifacts/PdfArtifact.js.map +1 -1
- package/dist/tools/artifacts/artifacts-tool-renderer.d.ts.map +1 -1
- package/dist/tools/artifacts/artifacts-tool-renderer.js.map +1 -1
- package/dist/tools/artifacts/artifacts.js.map +1 -1
- package/dist/tools/extract-document.js +1 -1
- package/dist/tools/extract-document.js.map +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/javascript-repl.js.map +1 -1
- package/dist/tools/renderer-registry.d.ts +4 -3
- package/dist/tools/renderer-registry.d.ts.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 +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/tools/types.d.ts +1 -1
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/utils/attachment-utils.js +1 -1
- package/dist/utils/attachment-utils.js.map +1 -1
- package/dist/utils/format.d.ts +2 -2
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/model-discovery.d.ts +6 -6
- package/dist/utils/model-discovery.d.ts.map +1 -1
- package/dist/utils/model-discovery.js +3 -3
- package/dist/utils/model-discovery.js.map +1 -1
- package/dist/utils/proxy-utils.d.ts +1 -1
- package/example/package.json +1 -1
- package/package.json +5 -5
- package/src/ChatPanel.ts +1 -1
- package/src/components/AgentInterface.ts +5 -5
- package/src/components/MessageEditor.ts +2 -2
- package/src/components/Messages.ts +6 -6
- package/src/components/ProviderKeyInput.ts +3 -3
- package/src/components/SandboxedIframe.ts +7 -6
- package/src/components/message-renderer-registry.ts +1 -1
- package/src/components/sandbox/ArtifactsRuntimeProvider.ts +40 -44
- package/src/components/sandbox/AttachmentsRuntimeProvider.ts +9 -7
- package/src/components/sandbox/ConsoleRuntimeProvider.ts +19 -17
- package/src/components/sandbox/FileDownloadRuntimeProvider.ts +11 -7
- package/src/components/sandbox/RuntimeMessageRouter.ts +7 -8
- package/src/components/sandbox/SandboxRuntimeProvider.ts +4 -2
- package/src/components/sandbox/runtime-messages.ts +146 -0
- package/src/dialogs/AttachmentOverlay.ts +12 -11
- package/src/dialogs/CustomProviderDialog.ts +2 -2
- package/src/dialogs/ModelSelector.ts +11 -11
- package/src/storage/stores/custom-providers-store.ts +2 -2
- package/src/storage/types.ts +2 -2
- package/src/tools/artifacts/DocxArtifact.ts +2 -2
- package/src/tools/artifacts/ExcelArtifact.ts +3 -3
- package/src/tools/artifacts/HtmlArtifact.ts +1 -1
- package/src/tools/artifacts/PdfArtifact.ts +5 -4
- package/src/tools/artifacts/artifacts-tool-renderer.ts +4 -4
- package/src/tools/artifacts/artifacts.ts +4 -4
- package/src/tools/extract-document.ts +6 -6
- package/src/tools/index.ts +1 -1
- package/src/tools/javascript-repl.ts +3 -3
- package/src/tools/renderer-registry.ts +5 -5
- package/src/tools/renderers/BashRenderer.ts +3 -3
- package/src/tools/renderers/CalculateRenderer.ts +3 -3
- package/src/tools/renderers/DefaultRenderer.ts +5 -5
- package/src/tools/renderers/GetCurrentTimeRenderer.ts +5 -5
- package/src/tools/types.ts +1 -1
- package/src/utils/attachment-utils.ts +10 -3
- package/src/utils/format.ts +2 -2
- package/src/utils/model-discovery.ts +35 -22
- package/src/utils/proxy-utils.ts +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "@elyracode/mini-lit/dist/CodeBlock.js";
|
|
2
|
-
import type { ToolResultMessage } from "@elyracode/ai";
|
|
2
|
+
import type { TextContent, ToolResultMessage } from "@elyracode/ai";
|
|
3
3
|
import { createRef, ref } from "lit/directives/ref.js";
|
|
4
4
|
import { FileCode2 } from "lucide";
|
|
5
5
|
import "../../components/ConsoleBlock.js";
|
|
@@ -12,12 +12,12 @@ import { ArtifactPill } from "./ArtifactPill.js";
|
|
|
12
12
|
import type { ArtifactsPanel, ArtifactsParams } from "./artifacts.js";
|
|
13
13
|
|
|
14
14
|
// Helper to extract text from content blocks
|
|
15
|
-
function getTextOutput(result: ToolResultMessage<
|
|
15
|
+
function getTextOutput(result: ToolResultMessage<unknown> | undefined): string {
|
|
16
16
|
if (!result) return "";
|
|
17
17
|
return (
|
|
18
18
|
result.content
|
|
19
|
-
?.filter((c) => c.type === "text")
|
|
20
|
-
.map((c
|
|
19
|
+
?.filter((c): c is TextContent => c.type === "text")
|
|
20
|
+
.map((c) => c.text)
|
|
21
21
|
.join("\n") || ""
|
|
22
22
|
);
|
|
23
23
|
}
|
|
@@ -311,7 +311,7 @@ export class ArtifactsPanel extends LitElement {
|
|
|
311
311
|
// 2) Build an ordered list of successful artifact operations
|
|
312
312
|
const operations: Array<ArtifactsParams> = [];
|
|
313
313
|
for (const m of messages) {
|
|
314
|
-
if (
|
|
314
|
+
if (m.role === "artifact") {
|
|
315
315
|
const artifactMsg = m as ArtifactMessage;
|
|
316
316
|
switch (artifactMsg.action) {
|
|
317
317
|
case "create":
|
|
@@ -337,8 +337,8 @@ export class ArtifactsPanel extends LitElement {
|
|
|
337
337
|
}
|
|
338
338
|
}
|
|
339
339
|
// Handle tool result messages (from artifacts tool calls)
|
|
340
|
-
else if (
|
|
341
|
-
const toolCallId =
|
|
340
|
+
else if (m.role === "toolResult" && m.toolName === artifactToolName && !m.isError) {
|
|
341
|
+
const toolCallId = m.toolCallId;
|
|
342
342
|
const call = toolCalls.get(toolCallId);
|
|
343
343
|
if (!call) continue;
|
|
344
344
|
const params = call.arguments as ArtifactsParams;
|
|
@@ -431,7 +431,7 @@ export class ArtifactsPanel extends LitElement {
|
|
|
431
431
|
return this.getLogs(params);
|
|
432
432
|
default:
|
|
433
433
|
// Should never happen with TypeBox validation
|
|
434
|
-
return `Error: Unknown command ${(params as
|
|
434
|
+
return `Error: Unknown command ${(params as { command: string }).command}`;
|
|
435
435
|
}
|
|
436
436
|
}
|
|
437
437
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentTool } from "@elyracode/agent-core";
|
|
2
|
-
import type { ToolResultMessage } from "@elyracode/ai";
|
|
2
|
+
import type { TextContent, ToolResultMessage } from "@elyracode/ai";
|
|
3
3
|
import { html } from "lit";
|
|
4
4
|
import { createRef, ref } from "lit/directives/ref.js";
|
|
5
5
|
import { FileText } from "lucide";
|
|
@@ -103,17 +103,17 @@ export function createExtractDocumentTool(): AgentTool<typeof extractDocumentSch
|
|
|
103
103
|
try {
|
|
104
104
|
// Attempt direct fetch first
|
|
105
105
|
arrayBuffer = await fetchAndProcess(url);
|
|
106
|
-
} catch (directError
|
|
106
|
+
} catch (directError) {
|
|
107
107
|
// If CORS error and proxy is available, retry with proxy
|
|
108
108
|
if (isCorsError(directError) && tool.corsProxyUrl) {
|
|
109
109
|
try {
|
|
110
110
|
const proxiedUrl = tool.corsProxyUrl + encodeURIComponent(url);
|
|
111
111
|
arrayBuffer = await fetchAndProcess(proxiedUrl);
|
|
112
|
-
} catch (proxyError
|
|
112
|
+
} catch (proxyError) {
|
|
113
113
|
// Proxy fetch also failed - throw helpful message
|
|
114
114
|
throw new Error(
|
|
115
115
|
`TELL USER: Unable to fetch the document due to CORS restrictions.\n\n` +
|
|
116
|
-
`Tried with proxy but it also failed: ${proxyError.message}\n\n` +
|
|
116
|
+
`Tried with proxy but it also failed: ${proxyError instanceof Error ? proxyError.message : String(proxyError)}\n\n` +
|
|
117
117
|
`INSTRUCT USER: Please download the file manually and attach it to your message using the attachment button (paperclip icon) in the message input area. I can then extract the text from the attached file.`,
|
|
118
118
|
);
|
|
119
119
|
}
|
|
@@ -213,8 +213,8 @@ export const extractDocumentRenderer: ToolRenderer<ExtractDocumentParams, Extrac
|
|
|
213
213
|
|
|
214
214
|
const output =
|
|
215
215
|
result.content
|
|
216
|
-
?.filter((c) => c.type === "text")
|
|
217
|
-
.map((c
|
|
216
|
+
?.filter((c): c is TextContent => c.type === "text")
|
|
217
|
+
.map((c) => c.text)
|
|
218
218
|
.join("\n") || "";
|
|
219
219
|
|
|
220
220
|
return {
|
package/src/tools/index.ts
CHANGED
|
@@ -27,7 +27,7 @@ export function setShowJsonMode(enabled: boolean): void {
|
|
|
27
27
|
*/
|
|
28
28
|
export function renderTool(
|
|
29
29
|
toolName: string,
|
|
30
|
-
params:
|
|
30
|
+
params: unknown | undefined,
|
|
31
31
|
result: ToolResultMessage | undefined,
|
|
32
32
|
isStreaming?: boolean,
|
|
33
33
|
): ToolRenderResult {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentTool } from "@elyracode/agent-core";
|
|
2
|
-
import type { ToolResultMessage } from "@elyracode/ai";
|
|
2
|
+
import type { TextContent, ToolResultMessage } from "@elyracode/ai";
|
|
3
3
|
import { i18n } from "@elyracode/mini-lit";
|
|
4
4
|
import { html } from "lit";
|
|
5
5
|
import { createRef, ref } from "lit/directives/ref.js";
|
|
@@ -214,8 +214,8 @@ export const javascriptReplRenderer: ToolRenderer<JavaScriptReplParams, JavaScri
|
|
|
214
214
|
if (result && params) {
|
|
215
215
|
const output =
|
|
216
216
|
result.content
|
|
217
|
-
?.filter((c) => c.type === "text")
|
|
218
|
-
.map((c
|
|
217
|
+
?.filter((c): c is TextContent => c.type === "text")
|
|
218
|
+
.map((c) => c.text)
|
|
219
219
|
.join("\n") || "";
|
|
220
220
|
const files = result.details?.files || [];
|
|
221
221
|
|
|
@@ -2,7 +2,7 @@ import { icon } from "@elyracode/mini-lit";
|
|
|
2
2
|
import { html, type TemplateResult } from "lit";
|
|
3
3
|
import type { Ref } from "lit/directives/ref.js";
|
|
4
4
|
import { ref } from "lit/directives/ref.js";
|
|
5
|
-
import { ChevronsUpDown, ChevronUp, Loader } from "lucide";
|
|
5
|
+
import { ChevronsUpDown, ChevronUp, type IconNode, Loader } from "lucide";
|
|
6
6
|
import type { ToolRenderer } from "./types.js";
|
|
7
7
|
|
|
8
8
|
// Registry of tool renderers
|
|
@@ -28,10 +28,10 @@ export function getToolRenderer(toolName: string): ToolRenderer | undefined {
|
|
|
28
28
|
*/
|
|
29
29
|
export function renderHeader(
|
|
30
30
|
state: "inprogress" | "complete" | "error",
|
|
31
|
-
toolIcon:
|
|
31
|
+
toolIcon: IconNode,
|
|
32
32
|
text: string | TemplateResult,
|
|
33
33
|
): TemplateResult {
|
|
34
|
-
const statusIcon = (iconComponent:
|
|
34
|
+
const statusIcon = (iconComponent: IconNode, color: string) =>
|
|
35
35
|
html`<span class="inline-block ${color}">${icon(iconComponent, "sm")}</span>`;
|
|
36
36
|
|
|
37
37
|
switch (state) {
|
|
@@ -68,13 +68,13 @@ export function renderHeader(
|
|
|
68
68
|
*/
|
|
69
69
|
export function renderCollapsibleHeader(
|
|
70
70
|
state: "inprogress" | "complete" | "error",
|
|
71
|
-
toolIcon:
|
|
71
|
+
toolIcon: IconNode,
|
|
72
72
|
text: string | TemplateResult,
|
|
73
73
|
contentRef: Ref<HTMLElement>,
|
|
74
74
|
chevronRef: Ref<HTMLElement>,
|
|
75
75
|
defaultExpanded = false,
|
|
76
76
|
): TemplateResult {
|
|
77
|
-
const statusIcon = (iconComponent:
|
|
77
|
+
const statusIcon = (iconComponent: IconNode, color: string) =>
|
|
78
78
|
html`<span class="inline-block ${color}">${icon(iconComponent, "sm")}</span>`;
|
|
79
79
|
|
|
80
80
|
const toggleContent = (e: Event) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ToolResultMessage } from "@elyracode/ai";
|
|
1
|
+
import type { TextContent, ToolResultMessage } from "@elyracode/ai";
|
|
2
2
|
import { html } from "lit";
|
|
3
3
|
import { SquareTerminal } from "lucide";
|
|
4
4
|
import { i18n } from "../../utils/i18n.js";
|
|
@@ -18,8 +18,8 @@ export class BashRenderer implements ToolRenderer<BashParams, undefined> {
|
|
|
18
18
|
if (result && params?.command) {
|
|
19
19
|
const output =
|
|
20
20
|
result.content
|
|
21
|
-
?.filter((c) => c.type === "text")
|
|
22
|
-
.map((c
|
|
21
|
+
?.filter((c): c is TextContent => c.type === "text")
|
|
22
|
+
.map((c) => c.text)
|
|
23
23
|
.join("\n") || "";
|
|
24
24
|
const combined = output ? `> ${params.command}\n\n${output}` : `> ${params.command}`;
|
|
25
25
|
return {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ToolResultMessage } from "@elyracode/ai";
|
|
1
|
+
import type { TextContent, ToolResultMessage } from "@elyracode/ai";
|
|
2
2
|
import { html } from "lit";
|
|
3
3
|
import { Calculator } from "lucide";
|
|
4
4
|
import { i18n } from "../../utils/i18n.js";
|
|
@@ -18,8 +18,8 @@ export class CalculateRenderer implements ToolRenderer<CalculateParams, undefine
|
|
|
18
18
|
if (result && params?.expression) {
|
|
19
19
|
const output =
|
|
20
20
|
result.content
|
|
21
|
-
?.filter((c) => c.type === "text")
|
|
22
|
-
.map((c
|
|
21
|
+
?.filter((c): c is TextContent => c.type === "text")
|
|
22
|
+
.map((c) => c.text)
|
|
23
23
|
.join("\n") || "";
|
|
24
24
|
|
|
25
25
|
// Error: show expression in header, error below
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ToolResultMessage } from "@elyracode/ai";
|
|
1
|
+
import type { TextContent, ToolResultMessage } from "@elyracode/ai";
|
|
2
2
|
import { html } from "lit";
|
|
3
3
|
import { Code } from "lucide";
|
|
4
4
|
import { i18n } from "../../utils/i18n.js";
|
|
@@ -6,14 +6,14 @@ import { renderHeader } from "../renderer-registry.js";
|
|
|
6
6
|
import type { ToolRenderer, ToolRenderResult } from "../types.js";
|
|
7
7
|
|
|
8
8
|
export class DefaultRenderer implements ToolRenderer {
|
|
9
|
-
render(params:
|
|
9
|
+
render(params: unknown | undefined, result: ToolResultMessage | undefined, isStreaming?: boolean): ToolRenderResult {
|
|
10
10
|
const state = result ? (result.isError ? "error" : "complete") : isStreaming ? "inprogress" : "complete";
|
|
11
11
|
|
|
12
12
|
// Format params as JSON
|
|
13
13
|
let paramsJson = "";
|
|
14
14
|
if (params) {
|
|
15
15
|
try {
|
|
16
|
-
paramsJson = JSON.stringify(JSON.parse(params), null, 2);
|
|
16
|
+
paramsJson = JSON.stringify(JSON.parse(params as string), null, 2);
|
|
17
17
|
} catch {
|
|
18
18
|
try {
|
|
19
19
|
paramsJson = JSON.stringify(params, null, 2);
|
|
@@ -27,8 +27,8 @@ export class DefaultRenderer implements ToolRenderer {
|
|
|
27
27
|
if (result) {
|
|
28
28
|
let outputJson =
|
|
29
29
|
result.content
|
|
30
|
-
?.filter((c) => c.type === "text")
|
|
31
|
-
.map((c
|
|
30
|
+
?.filter((c): c is TextContent => c.type === "text")
|
|
31
|
+
.map((c) => c.text)
|
|
32
32
|
.join("\n") || i18n("(no output)");
|
|
33
33
|
let outputLanguage = "text";
|
|
34
34
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ToolResultMessage } from "@elyracode/ai";
|
|
1
|
+
import type { TextContent, ToolResultMessage } from "@elyracode/ai";
|
|
2
2
|
import { html } from "lit";
|
|
3
3
|
import { Clock } from "lucide";
|
|
4
4
|
import { i18n } from "../../utils/i18n.js";
|
|
@@ -21,8 +21,8 @@ export class GetCurrentTimeRenderer implements ToolRenderer<GetCurrentTimeParams
|
|
|
21
21
|
if (result && params) {
|
|
22
22
|
const output =
|
|
23
23
|
result.content
|
|
24
|
-
?.filter((c) => c.type === "text")
|
|
25
|
-
.map((c
|
|
24
|
+
?.filter((c): c is TextContent => c.type === "text")
|
|
25
|
+
.map((c) => c.text)
|
|
26
26
|
.join("\n") || "";
|
|
27
27
|
const headerText = params.timezone
|
|
28
28
|
? `${i18n("Getting current time in")} ${params.timezone}`
|
|
@@ -49,8 +49,8 @@ export class GetCurrentTimeRenderer implements ToolRenderer<GetCurrentTimeParams
|
|
|
49
49
|
if (result) {
|
|
50
50
|
const output =
|
|
51
51
|
result.content
|
|
52
|
-
?.filter((c) => c.type === "text")
|
|
53
|
-
.map((c
|
|
52
|
+
?.filter((c): c is TextContent => c.type === "text")
|
|
53
|
+
.map((c) => c.text)
|
|
54
54
|
.join("\n") || "";
|
|
55
55
|
|
|
56
56
|
// Error: show header, error below
|
package/src/tools/types.ts
CHANGED
|
@@ -6,7 +6,7 @@ export interface ToolRenderResult {
|
|
|
6
6
|
isCustom: boolean; // true = no card wrapper, false = wrap in card
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export interface ToolRenderer<TParams =
|
|
9
|
+
export interface ToolRenderer<TParams = unknown, TDetails = unknown> {
|
|
10
10
|
render(
|
|
11
11
|
params: TParams | undefined,
|
|
12
12
|
result: ToolResultMessage<TDetails> | undefined,
|
|
@@ -214,8 +214,8 @@ async function processPdf(
|
|
|
214
214
|
const page = await pdf.getPage(i);
|
|
215
215
|
const textContent = await page.getTextContent();
|
|
216
216
|
const pageText = textContent.items
|
|
217
|
-
.map((item
|
|
218
|
-
.filter((str
|
|
217
|
+
.map((item) => ("str" in item ? item.str : ""))
|
|
218
|
+
.filter((str) => str.trim())
|
|
219
219
|
.join(" ");
|
|
220
220
|
extractedText += `\n<page number="${i}">\n${pageText}\n</page>`;
|
|
221
221
|
}
|
|
@@ -298,7 +298,14 @@ async function processDocx(arrayBuffer: ArrayBuffer, fileName: string): Promise<
|
|
|
298
298
|
}
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
-
|
|
301
|
+
/** Structural shape of a docx-preview document tree node (the library types its tree as `any`). */
|
|
302
|
+
interface DocxElement {
|
|
303
|
+
type?: string;
|
|
304
|
+
text?: string;
|
|
305
|
+
children?: DocxElement[];
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function extractTextFromElement(element: DocxElement): string {
|
|
302
309
|
let text = "";
|
|
303
310
|
|
|
304
311
|
// Check type with lowercase
|
package/src/utils/format.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { Usage } from "@elyracode/ai";
|
|
1
|
+
import type { Api, Model, Usage } from "@elyracode/ai";
|
|
2
2
|
import { i18n } from "@elyracode/mini-lit";
|
|
3
3
|
|
|
4
4
|
export function formatCost(cost: number): string {
|
|
5
5
|
return `$${cost.toFixed(4)}`;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
export function formatModelCost(cost:
|
|
8
|
+
export function formatModelCost(cost: Model<Api>["cost"] | undefined): string {
|
|
9
9
|
if (!cost) return i18n("Free");
|
|
10
10
|
const input = cost.input || 0;
|
|
11
11
|
const output = cost.output || 0;
|
|
@@ -1,14 +1,27 @@
|
|
|
1
|
-
import type { Model } from "@elyracode/ai";
|
|
1
|
+
import type { Api, Model } from "@elyracode/ai";
|
|
2
2
|
import { LMStudioClient } from "@lmstudio/sdk";
|
|
3
3
|
import { Ollama } from "ollama/browser";
|
|
4
4
|
|
|
5
|
+
/** Minimal shape of a model entry from an OpenAI-compatible /v1/models endpoint. */
|
|
6
|
+
interface OpenAICompatibleModel {
|
|
7
|
+
id: string;
|
|
8
|
+
context_length?: number;
|
|
9
|
+
max_tokens?: number;
|
|
10
|
+
max_model_len?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Minimal shape of the response from an OpenAI-compatible /v1/models endpoint. */
|
|
14
|
+
interface OpenAICompatibleModelsResponse {
|
|
15
|
+
data?: OpenAICompatibleModel[];
|
|
16
|
+
}
|
|
17
|
+
|
|
5
18
|
/**
|
|
6
19
|
* Discover models from an Ollama server.
|
|
7
20
|
* @param baseUrl - Base URL of the Ollama server (e.g., "http://localhost:11434")
|
|
8
21
|
* @param apiKey - Optional API key (currently unused by Ollama)
|
|
9
22
|
* @returns Array of discovered models
|
|
10
23
|
*/
|
|
11
|
-
export async function discoverOllamaModels(baseUrl: string, _apiKey?: string): Promise<Model<
|
|
24
|
+
export async function discoverOllamaModels(baseUrl: string, _apiKey?: string): Promise<Model<Api>[]> {
|
|
12
25
|
try {
|
|
13
26
|
// Create Ollama client
|
|
14
27
|
const ollama = new Ollama({ host: baseUrl });
|
|
@@ -17,7 +30,7 @@ export async function discoverOllamaModels(baseUrl: string, _apiKey?: string): P
|
|
|
17
30
|
const { models } = await ollama.list();
|
|
18
31
|
|
|
19
32
|
// Fetch details for each model and convert to Model format
|
|
20
|
-
const ollamaModelPromises: Promise<Model<
|
|
33
|
+
const ollamaModelPromises: Promise<Model<Api> | null>[] = models.map(async (model) => {
|
|
21
34
|
try {
|
|
22
35
|
// Get model details
|
|
23
36
|
const details = await ollama.show({
|
|
@@ -25,14 +38,14 @@ export async function discoverOllamaModels(baseUrl: string, _apiKey?: string): P
|
|
|
25
38
|
});
|
|
26
39
|
|
|
27
40
|
// Check capabilities - filter out models that don't support tools
|
|
28
|
-
const capabilities: string[] =
|
|
41
|
+
const capabilities: string[] = details.capabilities || [];
|
|
29
42
|
if (!capabilities.includes("tools")) {
|
|
30
43
|
console.debug(`Skipping model ${model.name}: does not support tools`);
|
|
31
44
|
return null;
|
|
32
45
|
}
|
|
33
46
|
|
|
34
47
|
// Extract model info
|
|
35
|
-
const modelInfo
|
|
48
|
+
const modelInfo = (details.model_info || {}) as unknown as Record<string, string>;
|
|
36
49
|
|
|
37
50
|
// Get context window size - look for architecture-specific keys
|
|
38
51
|
const architecture = modelInfo["general.architecture"] || "";
|
|
@@ -43,10 +56,10 @@ export async function discoverOllamaModels(baseUrl: string, _apiKey?: string): P
|
|
|
43
56
|
const maxTokens = contextWindow * 10;
|
|
44
57
|
|
|
45
58
|
// Ollama only supports completions API
|
|
46
|
-
const ollamaModel: Model<
|
|
59
|
+
const ollamaModel: Model<Api> = {
|
|
47
60
|
id: model.name,
|
|
48
61
|
name: model.name,
|
|
49
|
-
api: "openai-completions"
|
|
62
|
+
api: "openai-completions",
|
|
50
63
|
provider: "", // Will be set by caller
|
|
51
64
|
baseUrl: `${baseUrl}/v1`,
|
|
52
65
|
reasoning: capabilities.includes("thinking"),
|
|
@@ -69,7 +82,7 @@ export async function discoverOllamaModels(baseUrl: string, _apiKey?: string): P
|
|
|
69
82
|
});
|
|
70
83
|
|
|
71
84
|
const results = await Promise.all(ollamaModelPromises);
|
|
72
|
-
return results.filter((m): m is Model<
|
|
85
|
+
return results.filter((m): m is Model<Api> => m !== null);
|
|
73
86
|
} catch (err) {
|
|
74
87
|
console.error("Failed to discover Ollama models:", err);
|
|
75
88
|
throw new Error(`Ollama discovery failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -82,7 +95,7 @@ export async function discoverOllamaModels(baseUrl: string, _apiKey?: string): P
|
|
|
82
95
|
* @param apiKey - Optional API key
|
|
83
96
|
* @returns Array of discovered models
|
|
84
97
|
*/
|
|
85
|
-
export async function discoverLlamaCppModels(baseUrl: string, apiKey?: string): Promise<Model<
|
|
98
|
+
export async function discoverLlamaCppModels(baseUrl: string, apiKey?: string): Promise<Model<Api>[]> {
|
|
86
99
|
try {
|
|
87
100
|
const headers: HeadersInit = {
|
|
88
101
|
"Content-Type": "application/json",
|
|
@@ -101,21 +114,21 @@ export async function discoverLlamaCppModels(baseUrl: string, apiKey?: string):
|
|
|
101
114
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
102
115
|
}
|
|
103
116
|
|
|
104
|
-
const data = await response.json();
|
|
117
|
+
const data = (await response.json()) as OpenAICompatibleModelsResponse;
|
|
105
118
|
|
|
106
119
|
if (!data.data || !Array.isArray(data.data)) {
|
|
107
120
|
throw new Error("Invalid response format from llama.cpp server");
|
|
108
121
|
}
|
|
109
122
|
|
|
110
|
-
return data.data.map((model
|
|
123
|
+
return data.data.map((model) => {
|
|
111
124
|
// llama.cpp doesn't always provide context window info
|
|
112
125
|
const contextWindow = model.context_length || 8192;
|
|
113
126
|
const maxTokens = model.max_tokens || 4096;
|
|
114
127
|
|
|
115
|
-
const llamaModel: Model<
|
|
128
|
+
const llamaModel: Model<Api> = {
|
|
116
129
|
id: model.id,
|
|
117
130
|
name: model.id,
|
|
118
|
-
api: "openai-completions"
|
|
131
|
+
api: "openai-completions",
|
|
119
132
|
provider: "", // Will be set by caller
|
|
120
133
|
baseUrl: `${baseUrl}/v1`,
|
|
121
134
|
reasoning: false,
|
|
@@ -144,7 +157,7 @@ export async function discoverLlamaCppModels(baseUrl: string, apiKey?: string):
|
|
|
144
157
|
* @param apiKey - Optional API key
|
|
145
158
|
* @returns Array of discovered models
|
|
146
159
|
*/
|
|
147
|
-
export async function discoverVLLMModels(baseUrl: string, apiKey?: string): Promise<Model<
|
|
160
|
+
export async function discoverVLLMModels(baseUrl: string, apiKey?: string): Promise<Model<Api>[]> {
|
|
148
161
|
try {
|
|
149
162
|
const headers: HeadersInit = {
|
|
150
163
|
"Content-Type": "application/json",
|
|
@@ -163,21 +176,21 @@ export async function discoverVLLMModels(baseUrl: string, apiKey?: string): Prom
|
|
|
163
176
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
164
177
|
}
|
|
165
178
|
|
|
166
|
-
const data = await response.json();
|
|
179
|
+
const data = (await response.json()) as OpenAICompatibleModelsResponse;
|
|
167
180
|
|
|
168
181
|
if (!data.data || !Array.isArray(data.data)) {
|
|
169
182
|
throw new Error("Invalid response format from vLLM server");
|
|
170
183
|
}
|
|
171
184
|
|
|
172
|
-
return data.data.map((model
|
|
185
|
+
return data.data.map((model) => {
|
|
173
186
|
// vLLM provides max_model_len which is the context window
|
|
174
187
|
const contextWindow = model.max_model_len || 8192;
|
|
175
188
|
const maxTokens = Math.min(contextWindow, 4096); // Cap max tokens
|
|
176
189
|
|
|
177
|
-
const vllmModel: Model<
|
|
190
|
+
const vllmModel: Model<Api> = {
|
|
178
191
|
id: model.id,
|
|
179
192
|
name: model.id,
|
|
180
|
-
api: "openai-completions"
|
|
193
|
+
api: "openai-completions",
|
|
181
194
|
provider: "", // Will be set by caller
|
|
182
195
|
baseUrl: `${baseUrl}/v1`,
|
|
183
196
|
reasoning: false,
|
|
@@ -206,7 +219,7 @@ export async function discoverVLLMModels(baseUrl: string, apiKey?: string): Prom
|
|
|
206
219
|
* @param apiKey - Optional API key (unused for LM Studio SDK)
|
|
207
220
|
* @returns Array of discovered models
|
|
208
221
|
*/
|
|
209
|
-
export async function discoverLMStudioModels(baseUrl: string, _apiKey?: string): Promise<Model<
|
|
222
|
+
export async function discoverLMStudioModels(baseUrl: string, _apiKey?: string): Promise<Model<Api>[]> {
|
|
210
223
|
try {
|
|
211
224
|
// Extract host and port from baseUrl
|
|
212
225
|
const url = new URL(baseUrl);
|
|
@@ -226,10 +239,10 @@ export async function discoverLMStudioModels(baseUrl: string, _apiKey?: string):
|
|
|
226
239
|
// Use 10x context length like Ollama does
|
|
227
240
|
const maxTokens = contextWindow;
|
|
228
241
|
|
|
229
|
-
const lmStudioModel: Model<
|
|
242
|
+
const lmStudioModel: Model<Api> = {
|
|
230
243
|
id: model.path,
|
|
231
244
|
name: model.displayName || model.path,
|
|
232
|
-
api: "openai-completions"
|
|
245
|
+
api: "openai-completions",
|
|
233
246
|
provider: "", // Will be set by caller
|
|
234
247
|
baseUrl: `${baseUrl}/v1`,
|
|
235
248
|
reasoning: model.trainedForToolUse || false,
|
|
@@ -263,7 +276,7 @@ export async function discoverModels(
|
|
|
263
276
|
type: "ollama" | "llama.cpp" | "vllm" | "lmstudio",
|
|
264
277
|
baseUrl: string,
|
|
265
278
|
apiKey?: string,
|
|
266
|
-
): Promise<Model<
|
|
279
|
+
): Promise<Model<Api>[]> {
|
|
267
280
|
switch (type) {
|
|
268
281
|
case "ollama":
|
|
269
282
|
return discoverOllamaModels(baseUrl, apiKey);
|
package/src/utils/proxy-utils.ts
CHANGED
|
@@ -125,7 +125,7 @@ export function isCorsError(error: unknown): boolean {
|
|
|
125
125
|
* @returns A streamFn compatible with Agent's streamFn option
|
|
126
126
|
*/
|
|
127
127
|
export function createStreamFn(getProxyUrl: () => Promise<string | undefined>) {
|
|
128
|
-
return async (model: Model<
|
|
128
|
+
return async (model: Model<Api>, context: Context, options?: SimpleStreamOptions) => {
|
|
129
129
|
const apiKey = options?.apiKey;
|
|
130
130
|
const proxyUrl = await getProxyUrl();
|
|
131
131
|
|