Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
Add error message for tools (#1163)
Browse files* feat: add error message for tools
* lint
---------
Co-authored-by: Nathan Sarrazin <[email protected]>
src/lib/components/OpenWebSearchResults.svelte
CHANGED
@@ -16,7 +16,10 @@
|
|
16 |
$: lastMessage = webSearchMessages
|
17 |
.filter((update) => update.subtype !== MessageWebSearchUpdateType.Sources)
|
18 |
.at(-1) as MessageWebSearchUpdate;
|
19 |
-
$:
|
|
|
|
|
|
|
20 |
</script>
|
21 |
|
22 |
<details
|
|
|
16 |
$: lastMessage = webSearchMessages
|
17 |
.filter((update) => update.subtype !== MessageWebSearchUpdateType.Sources)
|
18 |
.at(-1) as MessageWebSearchUpdate;
|
19 |
+
$: errored = webSearchMessages.some(
|
20 |
+
(update) => update.subtype === MessageWebSearchUpdateType.Error
|
21 |
+
);
|
22 |
+
$: loading = !sources && !errored;
|
23 |
</script>
|
24 |
|
25 |
<details
|
src/lib/components/chat/ChatMessage.svelte
CHANGED
@@ -29,7 +29,11 @@
|
|
29 |
type MessageWebSearchSourcesUpdate,
|
30 |
type MessageWebSearchUpdate,
|
31 |
} from "$lib/types/MessageUpdate";
|
32 |
-
import {
|
|
|
|
|
|
|
|
|
33 |
import type { ToolFront } from "$lib/types/Tool";
|
34 |
import { base } from "$app/paths";
|
35 |
import { useConvTreeStore } from "$lib/stores/convTree";
|
@@ -287,6 +291,7 @@
|
|
287 |
{#each Object.values(toolUpdates) as tool}
|
288 |
{#if tool.length}
|
289 |
{@const toolName = tool.find(isMessageToolCallUpdate)?.call.name}
|
|
|
290 |
{@const toolDone = tool.some(isMessageToolResultUpdate)}
|
291 |
{#if toolName && toolName !== "websearch"}
|
292 |
<details
|
@@ -301,7 +306,7 @@
|
|
301 |
>
|
302 |
<svg
|
303 |
class="absolute inset-0 text-purple-500/40 transition-opacity"
|
304 |
-
class:invisible={toolDone}
|
305 |
width="22"
|
306 |
height="22"
|
307 |
viewBox="0 0 38 38"
|
@@ -321,7 +326,7 @@
|
|
321 |
</div>
|
322 |
|
323 |
<span>
|
324 |
-
{toolDone ? "Called" : "Calling"} tool
|
325 |
<span class="font-semibold"
|
326 |
>{availableTools.find((el) => toolHasName(toolName, el))?.displayName}</span
|
327 |
>
|
@@ -341,6 +346,12 @@
|
|
341 |
</li>
|
342 |
{/each}
|
343 |
</ul>
|
|
|
|
|
|
|
|
|
|
|
|
|
344 |
{/if}
|
345 |
{/each}
|
346 |
</details>
|
|
|
29 |
type MessageWebSearchSourcesUpdate,
|
30 |
type MessageWebSearchUpdate,
|
31 |
} from "$lib/types/MessageUpdate";
|
32 |
+
import {
|
33 |
+
isMessageToolCallUpdate,
|
34 |
+
isMessageToolResultUpdate,
|
35 |
+
isMessageToolErrorUpdate,
|
36 |
+
} from "$lib/utils/messageUpdates";
|
37 |
import type { ToolFront } from "$lib/types/Tool";
|
38 |
import { base } from "$app/paths";
|
39 |
import { useConvTreeStore } from "$lib/stores/convTree";
|
|
|
291 |
{#each Object.values(toolUpdates) as tool}
|
292 |
{#if tool.length}
|
293 |
{@const toolName = tool.find(isMessageToolCallUpdate)?.call.name}
|
294 |
+
{@const toolError = tool.some(isMessageToolErrorUpdate)}
|
295 |
{@const toolDone = tool.some(isMessageToolResultUpdate)}
|
296 |
{#if toolName && toolName !== "websearch"}
|
297 |
<details
|
|
|
306 |
>
|
307 |
<svg
|
308 |
class="absolute inset-0 text-purple-500/40 transition-opacity"
|
309 |
+
class:invisible={toolDone || toolError}
|
310 |
width="22"
|
311 |
height="22"
|
312 |
viewBox="0 0 38 38"
|
|
|
326 |
</div>
|
327 |
|
328 |
<span>
|
329 |
+
{toolError ? "Error calling" : toolDone ? "Called" : "Calling"} tool
|
330 |
<span class="font-semibold"
|
331 |
>{availableTools.find((el) => toolHasName(toolName, el))?.displayName}</span
|
332 |
>
|
|
|
346 |
</li>
|
347 |
{/each}
|
348 |
</ul>
|
349 |
+
{:else if toolUpdate.subtype === MessageToolUpdateType.Error}
|
350 |
+
<div class="mt-1 flex items-center gap-2 opacity-80">
|
351 |
+
<h3 class="text-sm">Error</h3>
|
352 |
+
<div class="h-px flex-1 bg-gradient-to-r from-gray-500/20" />
|
353 |
+
</div>
|
354 |
+
<p class="text-sm">{toolUpdate.message}</p>
|
355 |
{/if}
|
356 |
{/each}
|
357 |
</details>
|
src/lib/server/textGeneration/tools.ts
CHANGED
@@ -69,19 +69,38 @@ async function* runTool(
|
|
69 |
call,
|
70 |
};
|
71 |
try {
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
} catch (cause) {
|
86 |
console.error(Error(`Failed while running tool ${call.name}`), { cause });
|
87 |
return {
|
|
|
69 |
call,
|
70 |
};
|
71 |
try {
|
72 |
+
try {
|
73 |
+
const toolResult = yield* tool.call(call.parameters, {
|
74 |
+
conv,
|
75 |
+
messages,
|
76 |
+
preprompt,
|
77 |
+
assistant,
|
78 |
+
});
|
79 |
+
if (toolResult.status === ToolResultStatus.Error) {
|
80 |
+
yield {
|
81 |
+
type: MessageUpdateType.Tool,
|
82 |
+
subtype: MessageToolUpdateType.Error,
|
83 |
+
uuid,
|
84 |
+
message: toolResult.message,
|
85 |
+
};
|
86 |
+
} else {
|
87 |
+
yield {
|
88 |
+
type: MessageUpdateType.Tool,
|
89 |
+
subtype: MessageToolUpdateType.Result,
|
90 |
+
uuid,
|
91 |
+
result: { ...toolResult, call } as ToolResult,
|
92 |
+
};
|
93 |
+
}
|
94 |
+
|
95 |
+
return { ...toolResult, call } as ToolResult;
|
96 |
+
} catch (e) {
|
97 |
+
yield {
|
98 |
+
type: MessageUpdateType.Tool,
|
99 |
+
subtype: MessageToolUpdateType.Error,
|
100 |
+
uuid,
|
101 |
+
message: e instanceof Error ? e.message : String(e),
|
102 |
+
};
|
103 |
+
}
|
104 |
} catch (cause) {
|
105 |
console.error(Error(`Failed while running tool ${call.name}`), { cause });
|
106 |
return {
|
src/lib/server/tools/index.ts
CHANGED
@@ -2,7 +2,7 @@ import type { Assistant } from "$lib/types/Assistant";
|
|
2 |
import type { Conversation } from "$lib/types/Conversation";
|
3 |
import type { Message } from "$lib/types/Message";
|
4 |
import type { MessageUpdate } from "$lib/types/MessageUpdate";
|
5 |
-
import type { Tool,
|
6 |
|
7 |
import calculator from "./calculator";
|
8 |
import directlyAnswer from "./directlyAnswer";
|
@@ -19,11 +19,17 @@ export interface BackendToolContext {
|
|
19 |
assistant?: Pick<Assistant, "rag" | "dynamicPrompt" | "generateSettings">;
|
20 |
}
|
21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
export interface BackendTool extends Tool {
|
23 |
call(
|
24 |
params: Record<string, string | number | boolean>,
|
25 |
context: BackendToolContext
|
26 |
-
): AsyncGenerator<MessageUpdate,
|
27 |
}
|
28 |
|
29 |
export const allTools: BackendTool[] = [
|
|
|
2 |
import type { Conversation } from "$lib/types/Conversation";
|
3 |
import type { Message } from "$lib/types/Message";
|
4 |
import type { MessageUpdate } from "$lib/types/MessageUpdate";
|
5 |
+
import type { Tool, ToolResultError, ToolResultSuccess } from "$lib/types/Tool";
|
6 |
|
7 |
import calculator from "./calculator";
|
8 |
import directlyAnswer from "./directlyAnswer";
|
|
|
19 |
assistant?: Pick<Assistant, "rag" | "dynamicPrompt" | "generateSettings">;
|
20 |
}
|
21 |
|
22 |
+
// typescript can't narrow a discriminated union after applying a generic like Omit to it
|
23 |
+
// so we have to define the omitted types and create a new union
|
24 |
+
type ToolResultSuccessOmitted = Omit<ToolResultSuccess, "call">;
|
25 |
+
type ToolResultErrorOmitted = Omit<ToolResultError, "call">;
|
26 |
+
type ToolResultOmitted = ToolResultSuccessOmitted | ToolResultErrorOmitted;
|
27 |
+
|
28 |
export interface BackendTool extends Tool {
|
29 |
call(
|
30 |
params: Record<string, string | number | boolean>,
|
31 |
context: BackendToolContext
|
32 |
+
): AsyncGenerator<MessageUpdate, ToolResultOmitted, undefined>;
|
33 |
}
|
34 |
|
35 |
export const allTools: BackendTool[] = [
|
src/lib/types/MessageUpdate.ts
CHANGED
@@ -74,6 +74,8 @@ export enum MessageToolUpdateType {
|
|
74 |
Call = "call",
|
75 |
/** The result of a tool call */
|
76 |
Result = "result",
|
|
|
|
|
77 |
}
|
78 |
interface MessageToolBaseUpdate<TSubType extends MessageToolUpdateType> {
|
79 |
type: MessageUpdateType.Tool;
|
@@ -87,7 +89,13 @@ export interface MessageToolResultUpdate
|
|
87 |
extends MessageToolBaseUpdate<MessageToolUpdateType.Result> {
|
88 |
result: ToolResult;
|
89 |
}
|
90 |
-
export
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
|
92 |
// Everything else
|
93 |
export interface MessageTitleUpdate {
|
|
|
74 |
Call = "call",
|
75 |
/** The result of a tool call */
|
76 |
Result = "result",
|
77 |
+
/** Error while running tool */
|
78 |
+
Error = "error",
|
79 |
}
|
80 |
interface MessageToolBaseUpdate<TSubType extends MessageToolUpdateType> {
|
81 |
type: MessageUpdateType.Tool;
|
|
|
89 |
extends MessageToolBaseUpdate<MessageToolUpdateType.Result> {
|
90 |
result: ToolResult;
|
91 |
}
|
92 |
+
export interface MessageToolErrorUpdate extends MessageToolBaseUpdate<MessageToolUpdateType.Error> {
|
93 |
+
message: string;
|
94 |
+
}
|
95 |
+
export type MessageToolUpdate =
|
96 |
+
| MessageToolCallUpdate
|
97 |
+
| MessageToolResultUpdate
|
98 |
+
| MessageToolErrorUpdate;
|
99 |
|
100 |
// Everything else
|
101 |
export interface MessageTitleUpdate {
|
src/lib/types/Tool.ts
CHANGED
@@ -31,13 +31,13 @@ export enum ToolResultStatus {
|
|
31 |
Success = "success",
|
32 |
Error = "error",
|
33 |
}
|
34 |
-
interface ToolResultSuccess {
|
35 |
status: ToolResultStatus.Success;
|
36 |
call: ToolCall;
|
37 |
outputs: Record<string, unknown>[];
|
38 |
display?: boolean;
|
39 |
}
|
40 |
-
interface ToolResultError {
|
41 |
status: ToolResultStatus.Error;
|
42 |
call: ToolCall;
|
43 |
message: string;
|
|
|
31 |
Success = "success",
|
32 |
Error = "error",
|
33 |
}
|
34 |
+
export interface ToolResultSuccess {
|
35 |
status: ToolResultStatus.Success;
|
36 |
call: ToolCall;
|
37 |
outputs: Record<string, unknown>[];
|
38 |
display?: boolean;
|
39 |
}
|
40 |
+
export interface ToolResultError {
|
41 |
status: ToolResultStatus.Error;
|
42 |
call: ToolCall;
|
43 |
message: string;
|
src/lib/utils/messageUpdates.ts
CHANGED
@@ -11,6 +11,8 @@ import {
|
|
11 |
type MessageWebSearchSourcesUpdate,
|
12 |
type MessageWebSearchErrorUpdate,
|
13 |
MessageWebSearchUpdateType,
|
|
|
|
|
14 |
} from "$lib/types/MessageUpdate";
|
15 |
|
16 |
export const isMessageWebSearchUpdate = (update: MessageUpdate): update is MessageWebSearchUpdate =>
|
@@ -32,8 +34,12 @@ export const isMessageToolUpdate = (update: MessageUpdate): update is MessageToo
|
|
32 |
update.type === MessageUpdateType.Tool;
|
33 |
export const isMessageToolCallUpdate = (update: MessageUpdate): update is MessageToolCallUpdate =>
|
34 |
isMessageToolUpdate(update) && update.subtype === MessageToolUpdateType.Call;
|
35 |
-
export const isMessageToolResultUpdate = (
|
|
|
|
|
36 |
isMessageToolUpdate(update) && update.subtype === MessageToolUpdateType.Result;
|
|
|
|
|
37 |
|
38 |
type MessageUpdateRequestOptions = {
|
39 |
base: string;
|
|
|
11 |
type MessageWebSearchSourcesUpdate,
|
12 |
type MessageWebSearchErrorUpdate,
|
13 |
MessageWebSearchUpdateType,
|
14 |
+
type MessageToolErrorUpdate,
|
15 |
+
type MessageToolResultUpdate,
|
16 |
} from "$lib/types/MessageUpdate";
|
17 |
|
18 |
export const isMessageWebSearchUpdate = (update: MessageUpdate): update is MessageWebSearchUpdate =>
|
|
|
34 |
update.type === MessageUpdateType.Tool;
|
35 |
export const isMessageToolCallUpdate = (update: MessageUpdate): update is MessageToolCallUpdate =>
|
36 |
isMessageToolUpdate(update) && update.subtype === MessageToolUpdateType.Call;
|
37 |
+
export const isMessageToolResultUpdate = (
|
38 |
+
update: MessageUpdate
|
39 |
+
): update is MessageToolResultUpdate =>
|
40 |
isMessageToolUpdate(update) && update.subtype === MessageToolUpdateType.Result;
|
41 |
+
export const isMessageToolErrorUpdate = (update: MessageUpdate): update is MessageToolErrorUpdate =>
|
42 |
+
isMessageToolUpdate(update) && update.subtype === MessageToolUpdateType.Error;
|
43 |
|
44 |
type MessageUpdateRequestOptions = {
|
45 |
base: string;
|