Spaces:
Running
Running
File size: 4,467 Bytes
2e21e16 f940e40 2e21e16 586e800 2e21e16 586e800 2e21e16 586e800 f940e40 2e21e16 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
<script lang="ts">
import { MessageToolUpdateType, type MessageToolUpdate } from "$lib/types/MessageUpdate";
import {
isMessageToolCallUpdate,
isMessageToolErrorUpdate,
isMessageToolResultUpdate,
} from "$lib/utils/messageUpdates";
import CarbonTools from "~icons/carbon/tools";
import { toolHasName } from "$lib/utils/tools";
import type { ToolFront } from "$lib/types/Tool";
import { page } from "$app/stores";
import { onMount } from "svelte";
import { browser } from "$app/environment";
export let tool: MessageToolUpdate[];
export let loading: boolean = false;
const toolName = tool.find(isMessageToolCallUpdate)?.call.name;
$: toolError = tool.some(isMessageToolErrorUpdate);
$: toolDone = tool.some(isMessageToolResultUpdate);
const availableTools: ToolFront[] = $page.data.tools;
let loadingBarEl: HTMLDivElement;
let animation: Animation | undefined = undefined;
let isShowingLoadingBar = false;
onMount(() => {
if (!toolError && !toolDone && loading && loadingBarEl) {
loadingBarEl.classList.remove("hidden");
isShowingLoadingBar = true;
animation = loadingBarEl.animate([{ width: "0%" }, { width: "calc(100%+1rem)" }], {
duration: availableTools.find((tool) => tool.name === toolName)?.timeToUseMS,
fill: "forwards",
});
}
return () => animation?.cancel();
});
// go to 100% quickly if loading is done
$: (!loading || toolDone || toolError) &&
browser &&
loadingBarEl &&
isShowingLoadingBar &&
(() => {
isShowingLoadingBar = false;
loadingBarEl.classList.remove("hidden");
animation?.cancel();
animation = loadingBarEl.animate(
[{ width: loadingBarEl.style.width }, { width: "calc(100%+1rem)" }],
{
duration: 300,
fill: "forwards",
}
);
setTimeout(() => {
loadingBarEl.classList.add("hidden");
}, 300);
})();
</script>
{#if toolName && toolName !== "websearch"}
<details
class="group/tool my-2.5 w-fit cursor-pointer rounded-lg border border-gray-200 bg-white pl-1 pr-2.5 text-sm shadow-sm transition-all open:mb-3
open:border-purple-500/10 open:bg-purple-600/5 open:shadow-sm dark:border-gray-800 dark:bg-gray-900 open:dark:border-purple-800/40 open:dark:bg-purple-800/10"
>
<summary
class="relative flex select-none list-none items-center gap-1.5 py-1 group-open/tool:text-purple-700 group-open/tool:dark:text-purple-300"
>
<div
bind:this={loadingBarEl}
class="absolute -m-1 hidden h-full w-[calc(100%+1rem)] rounded-lg bg-purple-500/5 transition-all dark:bg-purple-500/10"
/>
<div
class="relative grid size-[22px] place-items-center rounded bg-purple-600/10 dark:bg-purple-600/20"
>
<svg
class="absolute inset-0 text-purple-500/40 transition-opacity"
class:invisible={toolDone || toolError}
width="22"
height="22"
viewBox="0 0 38 38"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
class="loading-path"
d="M8 2.5H30C30 2.5 35.5 2.5 35.5 8V30C35.5 30 35.5 35.5 30 35.5H8C8 35.5 2.5 35.5 2.5 30V8C2.5 8 2.5 2.5 8 2.5Z"
stroke="currentColor"
stroke-width="1"
stroke-linecap="round"
id="shape"
/>
</svg>
<CarbonTools class="text-xs text-purple-700 dark:text-purple-500" />
</div>
<span>
{toolError ? "Error calling" : toolDone ? "Called" : "Calling"} tool
<span class="font-semibold"
>{availableTools.find((el) => toolHasName(toolName, el))?.displayName}</span
>
</span>
</summary>
{#each tool as toolUpdate}
{#if toolUpdate.subtype === MessageToolUpdateType.Call}
<div class="mt-1 flex items-center gap-2 opacity-80">
<h3 class="text-sm">Parameters</h3>
<div class="h-px flex-1 bg-gradient-to-r from-gray-500/20" />
</div>
<ul class="py-1 text-sm">
{#each Object.entries(toolUpdate.call.parameters ?? {}) as [k, v]}
<li>
<span class="font-semibold">{k}</span>:
<span>{v}</span>
</li>
{/each}
</ul>
{:else if toolUpdate.subtype === MessageToolUpdateType.Error}
<div class="mt-1 flex items-center gap-2 opacity-80">
<h3 class="text-sm">Error</h3>
<div class="h-px flex-1 bg-gradient-to-r from-gray-500/20" />
</div>
<p class="text-sm">{toolUpdate.message}</p>
{/if}
{/each}
</details>
{/if}
<style>
details summary::-webkit-details-marker {
display: none;
}
.loading-path {
stroke-dasharray: 61.45;
animation: loading 2s linear infinite;
}
</style>
|