@signal9/era-ui 34.2.8 → 34.3.0
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 +12 -0
- package/dist/ai/conversation/conversation-scroll-button.svelte +2 -2
- package/dist/ai/conversations/conversations-item.svelte +39 -0
- package/dist/ai/conversations/conversations-item.svelte.d.ts +12 -0
- package/dist/ai/conversations/conversations.svelte.d.ts +6 -0
- package/dist/ai/index.d.ts +2 -1
- package/dist/ai/model-selector/index.d.ts +1 -0
- package/dist/ai/model-selector/model-selector.svelte +65 -31
- package/dist/ai/model-selector/model-selector.svelte.d.ts +24 -7
- package/dist/ai/queue/index.d.ts +1 -1
- package/dist/ai/queue/queue-item.svelte +63 -6
- package/dist/ai/queue/queue-item.svelte.d.ts +12 -3
- package/dist/ai/queue/queue.svelte +33 -9
- package/dist/ai/queue/queue.svelte.d.ts +6 -2
- package/dist/ai/tool/index.d.ts +1 -1
- package/dist/ai/tool/index.js +1 -1
- package/dist/ai/tool/tool-chip.svelte +2 -12
- package/dist/ai/tool/tool-chip.svelte.d.ts +1 -1
- package/dist/ai/tool/tool.svelte +46 -16
- package/dist/ai/tool/tool.svelte.d.ts +11 -2
- package/dist/era-ui.css +1 -1
- package/dist/styles/surfaces/bevel.css +2 -2
- package/package.json +1 -1
- package/skills/era-ui/references/releases/34.md +12 -0
- package/skills/era-ui/references/releases/index.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## [34.3.0](https://github.com/sig-nine/era-ui/compare/v34.2.9...v34.3.0) (2026-08-25)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* **ai:** generalize durable provider primitives ([808f9e3](https://github.com/sig-nine/era-ui/commit/808f9e3ff5d0446cc80d9e020c9fdf1259ce934e))
|
|
6
|
+
|
|
7
|
+
## [34.2.9](https://github.com/sig-nine/era-ui/compare/v34.2.8...v34.2.9) (2026-08-25)
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **bevel:** deepen compact keycap travel ([ad95c3b](https://github.com/sig-nine/era-ui/commit/ad95c3b260549392fa35e8422fc955d15670ef58))
|
|
12
|
+
|
|
1
13
|
## [34.2.8](https://github.com/sig-nine/era-ui/compare/v34.2.7...v34.2.8) (2026-08-24)
|
|
2
14
|
|
|
3
15
|
### Bug Fixes
|
|
@@ -13,10 +13,16 @@
|
|
|
13
13
|
|
|
14
14
|
let {
|
|
15
15
|
title = $bindable(''),
|
|
16
|
+
id,
|
|
16
17
|
starred = $bindable(false),
|
|
17
18
|
status,
|
|
19
|
+
childStatus,
|
|
20
|
+
role,
|
|
21
|
+
depth = 0,
|
|
22
|
+
rootActive = false,
|
|
18
23
|
active = false,
|
|
19
24
|
leading,
|
|
25
|
+
actions,
|
|
20
26
|
onSelect,
|
|
21
27
|
onRename,
|
|
22
28
|
onStar,
|
|
@@ -25,16 +31,28 @@
|
|
|
25
31
|
class: className,
|
|
26
32
|
...restProps
|
|
27
33
|
}: Omit<HTMLAttributes<HTMLDivElement>, 'title'> & {
|
|
34
|
+
/** Stable consumer-owned identity, exposed as data-conversation-id. */
|
|
35
|
+
id?: string;
|
|
28
36
|
/** Conversation label; double-click to rename in place. Bindable. */
|
|
29
37
|
title?: string;
|
|
30
38
|
/** Bindable star state; the rail's star button toggles it. */
|
|
31
39
|
starred?: boolean;
|
|
32
40
|
/** Drives the status dot tone; omit for no dot. */
|
|
33
41
|
status?: ConversationStatus;
|
|
42
|
+
/** Separate delegated-child status mark. */
|
|
43
|
+
childStatus?: ConversationStatus;
|
|
44
|
+
/** Optional visible role label. */
|
|
45
|
+
role?: string;
|
|
46
|
+
/** Nesting depth; indentation follows the density axis. */
|
|
47
|
+
depth?: number;
|
|
48
|
+
/** Marks a root whose active child owns the current work. */
|
|
49
|
+
rootActive?: boolean;
|
|
34
50
|
/** Highlighted as the open conversation. */
|
|
35
51
|
active?: boolean;
|
|
36
52
|
/** Overrides the leading icon (e.g. an expand chevron). */
|
|
37
53
|
leading?: Snippet;
|
|
54
|
+
/** Consumer-owned actions, rendered ahead of built-in row actions. */
|
|
55
|
+
actions?: Snippet;
|
|
38
56
|
/** Row activated (click / Enter on the title). */
|
|
39
57
|
onSelect?: () => void;
|
|
40
58
|
/** Fired after a non-empty rename commits, with the new title. */
|
|
@@ -127,7 +145,13 @@
|
|
|
127
145
|
</script>
|
|
128
146
|
|
|
129
147
|
<div
|
|
148
|
+
data-conversation-id={id}
|
|
130
149
|
data-active={active || undefined}
|
|
150
|
+
data-root-active={rootActive || undefined}
|
|
151
|
+
data-depth={depth || undefined}
|
|
152
|
+
style:padding-inline-start={depth > 0
|
|
153
|
+
? `calc(var(--era-inset-control) + ${Math.max(0, depth)} * var(--era-sp))`
|
|
154
|
+
: undefined}
|
|
131
155
|
class={cn(
|
|
132
156
|
// The trailing buttons are pill-tier icon buttons: h-pill box + h-icon glyph =
|
|
133
157
|
// 2px of air around the glyph (the icon tier would hug it flush — density.css:
|
|
@@ -167,6 +191,20 @@
|
|
|
167
191
|
aria-hidden="true"
|
|
168
192
|
></span>
|
|
169
193
|
{/if}
|
|
194
|
+
{#if role}
|
|
195
|
+
<span
|
|
196
|
+
class="shrink-0 text-[0.625rem] era-text-trim-caps tracking-[0.12em] text-muted uppercase"
|
|
197
|
+
>
|
|
198
|
+
{role}
|
|
199
|
+
</span>
|
|
200
|
+
{/if}
|
|
201
|
+
{#if childStatus}
|
|
202
|
+
<span
|
|
203
|
+
class={cn('size-gutter shrink-0 rounded-full', DOT[childStatus].class)}
|
|
204
|
+
title={DOT[childStatus].label}
|
|
205
|
+
aria-label={`Child: ${DOT[childStatus].label}`}
|
|
206
|
+
></span>
|
|
207
|
+
{/if}
|
|
170
208
|
|
|
171
209
|
{#if editing}
|
|
172
210
|
<!-- `bare`: the row is already the field's container, so the input brings no
|
|
@@ -201,6 +239,7 @@
|
|
|
201
239
|
data-rail
|
|
202
240
|
class="flex shrink-0 items-center gap-gutter opacity-0 group-hover/row:opacity-100 focus-within:opacity-100"
|
|
203
241
|
>
|
|
242
|
+
{#if actions}{@render actions()}{/if}
|
|
204
243
|
<Button
|
|
205
244
|
icon
|
|
206
245
|
size="pill"
|
|
@@ -2,16 +2,28 @@ import type { Snippet } from 'svelte';
|
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
3
|
import type { ConversationStatus } from './conversations.svelte.js';
|
|
4
4
|
type $$ComponentProps = Omit<HTMLAttributes<HTMLDivElement>, 'title'> & {
|
|
5
|
+
/** Stable consumer-owned identity, exposed as data-conversation-id. */
|
|
6
|
+
id?: string;
|
|
5
7
|
/** Conversation label; double-click to rename in place. Bindable. */
|
|
6
8
|
title?: string;
|
|
7
9
|
/** Bindable star state; the rail's star button toggles it. */
|
|
8
10
|
starred?: boolean;
|
|
9
11
|
/** Drives the status dot tone; omit for no dot. */
|
|
10
12
|
status?: ConversationStatus;
|
|
13
|
+
/** Separate delegated-child status mark. */
|
|
14
|
+
childStatus?: ConversationStatus;
|
|
15
|
+
/** Optional visible role label. */
|
|
16
|
+
role?: string;
|
|
17
|
+
/** Nesting depth; indentation follows the density axis. */
|
|
18
|
+
depth?: number;
|
|
19
|
+
/** Marks a root whose active child owns the current work. */
|
|
20
|
+
rootActive?: boolean;
|
|
11
21
|
/** Highlighted as the open conversation. */
|
|
12
22
|
active?: boolean;
|
|
13
23
|
/** Overrides the leading icon (e.g. an expand chevron). */
|
|
14
24
|
leading?: Snippet;
|
|
25
|
+
/** Consumer-owned actions, rendered ahead of built-in row actions. */
|
|
26
|
+
actions?: Snippet;
|
|
15
27
|
/** Row activated (click / Enter on the title). */
|
|
16
28
|
onSelect?: () => void;
|
|
17
29
|
/** Fired after a non-empty rename commits, with the new title. */
|
|
@@ -10,6 +10,12 @@ export interface ConversationEntry {
|
|
|
10
10
|
updatedAt: number;
|
|
11
11
|
starred?: boolean;
|
|
12
12
|
status?: ConversationStatus;
|
|
13
|
+
/** Optional parent identity for consumer-owned nested conversation trees. */
|
|
14
|
+
parentId?: string;
|
|
15
|
+
/** Reader-facing role label, for example "Research" or "Sub-agent". */
|
|
16
|
+
role?: string;
|
|
17
|
+
/** Distinct child execution state when a root row summarizes delegated work. */
|
|
18
|
+
childStatus?: ConversationStatus;
|
|
13
19
|
}
|
|
14
20
|
/** A rendered section: a bucket, its display label, and its member rows. */
|
|
15
21
|
export interface ConversationGroup {
|
package/dist/ai/index.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export * as Swarm from './swarm/index.js';
|
|
|
22
22
|
export { Response, repairStreamingMarkdown } from './response/index.js';
|
|
23
23
|
export { default as ContextGauge } from './context/context.svelte';
|
|
24
24
|
export { default as ModelSelector } from './model-selector/model-selector.svelte';
|
|
25
|
+
export type { ModelGroup, ModelOption } from './model-selector/index.js';
|
|
25
26
|
export { default as OpenInChat, providers as openInProviders } from './open-in-chat/open-in-chat.svelte';
|
|
26
27
|
export { default as WebPreview } from './web-preview/web-preview.svelte';
|
|
27
28
|
export * as ChainOfThought from './chain-of-thought/index.js';
|
|
@@ -33,7 +34,7 @@ export { CopyButton } from '../ui/copy-button/index.js';
|
|
|
33
34
|
export { StickToBottom } from './stick-to-bottom.svelte.js';
|
|
34
35
|
export type { PromptAttachment, PromptMessage, ChatStatus } from './prompt-input/index.js';
|
|
35
36
|
export type { MessageRole, MessageVersion } from './message/index.js';
|
|
36
|
-
export type { ToolState } from './tool/index.js';
|
|
37
|
+
export type { ToolState, ToolStatus } from './tool/index.js';
|
|
37
38
|
export type { UsageBreakdown } from './message/index.js';
|
|
38
39
|
export type { ConversationEntry, ConversationGroup, ConversationStatus, TimeBucket } from './conversations/index.js';
|
|
39
40
|
export type { RunState, LogTone, RunTools } from './run-status/index.js';
|
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
|
|
4
|
+
export interface ModelOption {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
provider?: string;
|
|
8
|
+
/** Consumer-rendered local icon; preferred over any remote logo. */
|
|
9
|
+
icon?: Snippet;
|
|
10
|
+
/** Short, optional secondary detail such as context window or price tier. */
|
|
11
|
+
metadata?: string;
|
|
12
|
+
/** Optional remote logo for applications that explicitly permit it. */
|
|
13
|
+
logo?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ModelGroup {
|
|
17
|
+
id: string;
|
|
18
|
+
label: string;
|
|
19
|
+
models: ModelOption[];
|
|
20
|
+
}
|
|
21
|
+
</script>
|
|
22
|
+
|
|
1
23
|
<script lang="ts">
|
|
2
24
|
import * as Dialog from '../../ui/dialog/index.js';
|
|
3
25
|
import * as Command from '../../ui/command/index.js';
|
|
@@ -6,18 +28,26 @@
|
|
|
6
28
|
|
|
7
29
|
let {
|
|
8
30
|
open = $bindable(false),
|
|
9
|
-
models,
|
|
31
|
+
models = [],
|
|
32
|
+
groups,
|
|
10
33
|
value = $bindable(''),
|
|
34
|
+
offline = false,
|
|
11
35
|
onSelect,
|
|
12
36
|
class: className
|
|
13
37
|
}: {
|
|
14
38
|
open?: boolean;
|
|
15
|
-
/**
|
|
16
|
-
models
|
|
39
|
+
/** Flat provider-neutral options; used as one ungrouped list unless groups is supplied. */
|
|
40
|
+
models?: ModelOption[];
|
|
41
|
+
/** Consumer-owned provider or capability groups. */
|
|
42
|
+
groups?: ModelGroup[];
|
|
17
43
|
value?: string;
|
|
18
|
-
|
|
44
|
+
/** Never loads remote logo URLs; local icon snippets continue to render. */
|
|
45
|
+
offline?: boolean;
|
|
46
|
+
onSelect?: (id: string, model: ModelOption) => void;
|
|
19
47
|
class?: string;
|
|
20
48
|
} = $props();
|
|
49
|
+
|
|
50
|
+
const visibleGroups = $derived(groups ?? [{ id: 'models', label: 'Models', models }]);
|
|
21
51
|
</script>
|
|
22
52
|
|
|
23
53
|
<Dialog.Root bind:open>
|
|
@@ -27,33 +57,37 @@
|
|
|
27
57
|
<Command.List>
|
|
28
58
|
<Command.Viewport>
|
|
29
59
|
<Command.Empty>No models found.</Command.Empty>
|
|
30
|
-
|
|
31
|
-
<Command.
|
|
32
|
-
{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
onSelect
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
{#each visibleGroups as group (group.id)}
|
|
61
|
+
<Command.Group>
|
|
62
|
+
<Command.GroupHeading>{group.label}</Command.GroupHeading>
|
|
63
|
+
<Command.GroupItems>
|
|
64
|
+
{#each group.models as model (model.id)}
|
|
65
|
+
<Command.Item
|
|
66
|
+
value={model.id}
|
|
67
|
+
keywords={[model.name, model.provider ?? '', model.metadata ?? '']}
|
|
68
|
+
onSelect={() => {
|
|
69
|
+
value = model.id;
|
|
70
|
+
onSelect?.(model.id, model);
|
|
71
|
+
open = false;
|
|
72
|
+
}}
|
|
73
|
+
>
|
|
74
|
+
{#if model.icon}
|
|
75
|
+
{@render model.icon()}
|
|
76
|
+
{:else if model.logo && !offline}
|
|
77
|
+
<img src={model.logo} alt="" class="size-icon shrink-0 dark:invert" />
|
|
78
|
+
{/if}
|
|
79
|
+
<span class="min-w-0 flex-1 truncate">{model.name}</span>
|
|
80
|
+
{#if model.metadata}
|
|
81
|
+
<span class="shrink-0 text-body text-muted">{model.metadata}</span>
|
|
82
|
+
{/if}
|
|
83
|
+
{#if value === model.id}
|
|
84
|
+
<span class="shrink-0 text-body text-muted">current</span>
|
|
85
|
+
{/if}
|
|
86
|
+
</Command.Item>
|
|
87
|
+
{/each}
|
|
88
|
+
</Command.GroupItems>
|
|
89
|
+
</Command.Group>
|
|
90
|
+
{/each}
|
|
57
91
|
</Command.Viewport>
|
|
58
92
|
</Command.List>
|
|
59
93
|
</Command.Root>
|
|
@@ -1,13 +1,30 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
export interface ModelOption {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
provider?: string;
|
|
6
|
+
/** Consumer-rendered local icon; preferred over any remote logo. */
|
|
7
|
+
icon?: Snippet;
|
|
8
|
+
/** Short, optional secondary detail such as context window or price tier. */
|
|
9
|
+
metadata?: string;
|
|
10
|
+
/** Optional remote logo for applications that explicitly permit it. */
|
|
11
|
+
logo?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ModelGroup {
|
|
14
|
+
id: string;
|
|
15
|
+
label: string;
|
|
16
|
+
models: ModelOption[];
|
|
17
|
+
}
|
|
1
18
|
type $$ComponentProps = {
|
|
2
19
|
open?: boolean;
|
|
3
|
-
/**
|
|
4
|
-
models
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
provider?: string;
|
|
8
|
-
}[];
|
|
20
|
+
/** Flat provider-neutral options; used as one ungrouped list unless groups is supplied. */
|
|
21
|
+
models?: ModelOption[];
|
|
22
|
+
/** Consumer-owned provider or capability groups. */
|
|
23
|
+
groups?: ModelGroup[];
|
|
9
24
|
value?: string;
|
|
10
|
-
|
|
25
|
+
/** Never loads remote logo URLs; local icon snippets continue to render. */
|
|
26
|
+
offline?: boolean;
|
|
27
|
+
onSelect?: (id: string, model: ModelOption) => void;
|
|
11
28
|
class?: string;
|
|
12
29
|
};
|
|
13
30
|
declare const ModelSelector: import("svelte").Component<$$ComponentProps, {}, "value" | "open">;
|
package/dist/ai/queue/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { default as Root } from './queue.svelte';
|
|
2
|
-
export { default as Item } from './queue-item.svelte';
|
|
2
|
+
export { default as Item, type QueueStatus, type QueueTone } from './queue-item.svelte';
|
|
@@ -1,26 +1,83 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
export type QueueStatus = 'queued' | 'running' | 'complete' | 'cancelled' | 'error';
|
|
3
|
+
export type QueueTone = 'default' | 'accent' | 'success' | 'warning' | 'destructive' | 'info';
|
|
4
|
+
</script>
|
|
5
|
+
|
|
1
6
|
<script lang="ts">
|
|
2
7
|
import type { Snippet } from 'svelte';
|
|
8
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
9
|
+
import X from '@lucide/svelte/icons/x';
|
|
10
|
+
import { Button } from '../../ui/button/index.js';
|
|
3
11
|
import { cn } from '../../utils/index.js';
|
|
4
12
|
|
|
5
13
|
let {
|
|
6
|
-
|
|
14
|
+
id,
|
|
15
|
+
status = 'queued',
|
|
16
|
+
tone,
|
|
17
|
+
label,
|
|
18
|
+
cancelLabel = 'Cancel queued work',
|
|
19
|
+
leading,
|
|
20
|
+
trailing,
|
|
7
21
|
children,
|
|
8
|
-
|
|
9
|
-
|
|
22
|
+
onCancel,
|
|
23
|
+
class: className,
|
|
24
|
+
...restProps
|
|
25
|
+
}: Omit<HTMLAttributes<HTMLLIElement>, 'id'> & {
|
|
26
|
+
id: string;
|
|
27
|
+
status?: QueueStatus;
|
|
28
|
+
tone?: QueueTone;
|
|
29
|
+
label?: string;
|
|
30
|
+
cancelLabel?: string;
|
|
31
|
+
leading?: Snippet;
|
|
32
|
+
trailing?: Snippet;
|
|
33
|
+
children?: Snippet;
|
|
34
|
+
onCancel?: (id: string) => void;
|
|
35
|
+
} = $props();
|
|
36
|
+
|
|
37
|
+
const visual = $derived(
|
|
38
|
+
tone ??
|
|
39
|
+
(
|
|
40
|
+
{
|
|
41
|
+
queued: 'warning',
|
|
42
|
+
running: 'accent',
|
|
43
|
+
complete: 'success',
|
|
44
|
+
cancelled: 'default',
|
|
45
|
+
error: 'destructive'
|
|
46
|
+
} as const
|
|
47
|
+
)[status]
|
|
48
|
+
);
|
|
49
|
+
const cancellable = $derived(status === 'queued' || status === 'running');
|
|
10
50
|
</script>
|
|
11
51
|
|
|
12
52
|
<li
|
|
53
|
+
data-queue-id={id}
|
|
54
|
+
data-status={status}
|
|
55
|
+
aria-label={label}
|
|
13
56
|
class={cn(
|
|
14
|
-
'flex min-w-0 items-center gap-gutter rounded-control px-inset-control py-gutter text-body hover:bg-highlight',
|
|
15
|
-
|
|
57
|
+
'flex min-w-0 items-center gap-gutter rounded-control px-inset-control py-gutter text-body hover:bg-highlight hover:shadow-highlight',
|
|
58
|
+
status === 'complete' || status === 'cancelled' ? 'text-muted line-through' : 'text-fg',
|
|
16
59
|
className
|
|
17
60
|
)}
|
|
61
|
+
{...restProps}
|
|
18
62
|
>
|
|
63
|
+
{#if leading}{@render leading()}{/if}
|
|
19
64
|
<span
|
|
20
65
|
class={cn(
|
|
21
66
|
'size-2 shrink-0 rounded-full',
|
|
22
|
-
|
|
67
|
+
visual === 'accent' && 'animate-pulse bg-primary',
|
|
68
|
+
visual === 'success' && 'bg-success',
|
|
69
|
+
visual === 'warning' && 'bg-warning',
|
|
70
|
+
visual === 'destructive' && 'bg-destructive',
|
|
71
|
+
visual === 'info' && 'bg-info',
|
|
72
|
+
visual === 'default' && 'border border-divider bg-transparent'
|
|
23
73
|
)}
|
|
74
|
+
aria-hidden="true"
|
|
24
75
|
></span>
|
|
25
76
|
<span class="min-w-0 flex-1 truncate">{@render children?.()}</span>
|
|
77
|
+
{#if trailing}{@render trailing()}{/if}
|
|
78
|
+
{#if cancellable && onCancel}
|
|
79
|
+
<Button icon size="pill" aria-label={cancelLabel} onclick={() => onCancel?.(id)}>
|
|
80
|
+
<X class="size-icon" />
|
|
81
|
+
</Button>
|
|
82
|
+
{/if}
|
|
26
83
|
</li>
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
+
export type QueueStatus = 'queued' | 'running' | 'complete' | 'cancelled' | 'error';
|
|
2
|
+
export type QueueTone = 'default' | 'accent' | 'success' | 'warning' | 'destructive' | 'info';
|
|
1
3
|
import type { Snippet } from 'svelte';
|
|
2
|
-
type
|
|
3
|
-
|
|
4
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
5
|
+
type $$ComponentProps = Omit<HTMLAttributes<HTMLLIElement>, 'id'> & {
|
|
6
|
+
id: string;
|
|
7
|
+
status?: QueueStatus;
|
|
8
|
+
tone?: QueueTone;
|
|
9
|
+
label?: string;
|
|
10
|
+
cancelLabel?: string;
|
|
11
|
+
leading?: Snippet;
|
|
12
|
+
trailing?: Snippet;
|
|
4
13
|
children?: Snippet;
|
|
5
|
-
|
|
14
|
+
onCancel?: (id: string) => void;
|
|
6
15
|
};
|
|
7
16
|
declare const QueueItem: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
17
|
type QueueItem = ReturnType<typeof QueueItem>;
|
|
@@ -1,14 +1,38 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
4
|
import { cn } from '../../utils/index.js';
|
|
4
|
-
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
full = false,
|
|
8
|
+
fullLabel = 'Queue is full',
|
|
9
|
+
label = 'Queued work',
|
|
10
|
+
fullContent,
|
|
11
|
+
children,
|
|
12
|
+
class: className,
|
|
13
|
+
...restProps
|
|
14
|
+
}: HTMLAttributes<HTMLUListElement> & {
|
|
15
|
+
full?: boolean;
|
|
16
|
+
fullLabel?: string;
|
|
17
|
+
label?: string;
|
|
18
|
+
fullContent?: Snippet;
|
|
19
|
+
children?: Snippet;
|
|
20
|
+
} = $props();
|
|
5
21
|
</script>
|
|
6
22
|
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
>
|
|
13
|
-
|
|
14
|
-
|
|
23
|
+
<div data-queue-full={full || undefined} class="flex min-w-0 flex-col gap-gutter">
|
|
24
|
+
{#if full}
|
|
25
|
+
{#if fullContent}
|
|
26
|
+
{@render fullContent()}
|
|
27
|
+
{:else}
|
|
28
|
+
<p role="status" class="px-inset-control text-body text-warning">{fullLabel}</p>
|
|
29
|
+
{/if}
|
|
30
|
+
{/if}
|
|
31
|
+
<ul
|
|
32
|
+
aria-label={label}
|
|
33
|
+
class={cn('flex max-h-48 flex-col gap-gutter rounded-bar bg-well p-panel shadow-sm', className)}
|
|
34
|
+
{...restProps}
|
|
35
|
+
>
|
|
36
|
+
{@render children?.()}
|
|
37
|
+
</ul>
|
|
38
|
+
</div>
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
type
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
type $$ComponentProps = HTMLAttributes<HTMLUListElement> & {
|
|
4
|
+
full?: boolean;
|
|
5
|
+
fullLabel?: string;
|
|
6
|
+
label?: string;
|
|
7
|
+
fullContent?: Snippet;
|
|
3
8
|
children?: Snippet;
|
|
4
|
-
class?: string;
|
|
5
9
|
};
|
|
6
10
|
declare const Queue: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
11
|
type Queue = ReturnType<typeof Queue>;
|
package/dist/ai/tool/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { default as Root, type ToolState } from './tool.svelte';
|
|
1
|
+
export { default as Root, toolStepStatus, type ToolState, type ToolStatus } from './tool.svelte';
|
|
2
2
|
export { default as Header } from './tool-header.svelte';
|
|
3
3
|
export { default as Input } from './tool-input.svelte';
|
|
4
4
|
export { default as Output } from './tool-output.svelte';
|
package/dist/ai/tool/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { default as Root } from './tool.svelte';
|
|
1
|
+
export { default as Root, toolStepStatus } from './tool.svelte';
|
|
2
2
|
export { default as Header } from './tool-header.svelte';
|
|
3
3
|
export { default as Input } from './tool-input.svelte';
|
|
4
4
|
export { default as Output } from './tool-output.svelte';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type { Component, Snippet } from 'svelte';
|
|
3
3
|
import Wrench from '@lucide/svelte/icons/wrench';
|
|
4
4
|
import { cn } from '../../utils/index.js';
|
|
5
|
-
import type
|
|
5
|
+
import { toolStepStatus, type ToolState } from './tool.svelte';
|
|
6
6
|
|
|
7
7
|
let {
|
|
8
8
|
state: toolState = 'input-streaming',
|
|
@@ -25,17 +25,7 @@
|
|
|
25
25
|
class?: string;
|
|
26
26
|
} = $props();
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
const status = $derived(
|
|
30
|
-
(
|
|
31
|
-
{
|
|
32
|
-
'input-streaming': 'pending',
|
|
33
|
-
'input-available': 'running',
|
|
34
|
-
'output-available': 'done',
|
|
35
|
-
'output-error': 'error'
|
|
36
|
-
} as const
|
|
37
|
-
)[toolState]
|
|
38
|
-
);
|
|
28
|
+
const status = $derived(toolStepStatus(toolState));
|
|
39
29
|
</script>
|
|
40
30
|
|
|
41
31
|
<!-- Compact horizontal tool call: a quiet pill that brightens on hover and
|
package/dist/ai/tool/tool.svelte
CHANGED
|
@@ -1,37 +1,67 @@
|
|
|
1
1
|
<script lang="ts" module>
|
|
2
|
-
|
|
2
|
+
export type ToolStatus =
|
|
3
|
+
'pending' | 'running' | 'complete' | 'error' | 'approval-required' | 'cancelled';
|
|
3
4
|
export type ToolState =
|
|
4
|
-
'input-streaming' | 'input-available' | 'output-available' | 'output-error';
|
|
5
|
+
ToolStatus | 'input-streaming' | 'input-available' | 'output-available' | 'output-error';
|
|
6
|
+
export function toolStepStatus(state: ToolState): 'pending' | 'running' | 'done' | 'error' {
|
|
7
|
+
return (
|
|
8
|
+
{
|
|
9
|
+
pending: 'pending',
|
|
10
|
+
running: 'running',
|
|
11
|
+
complete: 'done',
|
|
12
|
+
error: 'error',
|
|
13
|
+
'approval-required': 'pending',
|
|
14
|
+
cancelled: 'done',
|
|
15
|
+
'input-streaming': 'pending',
|
|
16
|
+
'input-available': 'running',
|
|
17
|
+
'output-available': 'done',
|
|
18
|
+
'output-error': 'error'
|
|
19
|
+
} as const
|
|
20
|
+
)[state];
|
|
21
|
+
}
|
|
5
22
|
</script>
|
|
6
23
|
|
|
7
24
|
<script lang="ts">
|
|
8
25
|
import type { Snippet } from 'svelte';
|
|
9
26
|
import * as Step from '../../ui/step/index.js';
|
|
10
|
-
|
|
11
27
|
let {
|
|
12
|
-
|
|
28
|
+
status,
|
|
29
|
+
state = 'pending',
|
|
13
30
|
open = $bindable(false),
|
|
31
|
+
header,
|
|
32
|
+
input,
|
|
33
|
+
progress,
|
|
34
|
+
approval,
|
|
35
|
+
result,
|
|
36
|
+
error,
|
|
37
|
+
actions,
|
|
14
38
|
children,
|
|
15
39
|
class: className
|
|
16
40
|
}: {
|
|
41
|
+
status?: ToolStatus;
|
|
17
42
|
state?: ToolState;
|
|
18
43
|
open?: boolean;
|
|
44
|
+
header?: Snippet;
|
|
45
|
+
input?: Snippet;
|
|
46
|
+
progress?: Snippet;
|
|
47
|
+
approval?: Snippet;
|
|
48
|
+
result?: Snippet;
|
|
49
|
+
error?: Snippet;
|
|
50
|
+
actions?: Snippet;
|
|
19
51
|
children?: Snippet;
|
|
20
52
|
class?: string;
|
|
21
53
|
} = $props();
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
(
|
|
25
|
-
{
|
|
26
|
-
'input-streaming': 'pending',
|
|
27
|
-
'input-available': 'running',
|
|
28
|
-
'output-available': 'done',
|
|
29
|
-
'output-error': 'error'
|
|
30
|
-
} as const
|
|
31
|
-
)[toolState]
|
|
32
|
-
);
|
|
54
|
+
const resolved = $derived(status ?? state);
|
|
55
|
+
const stepStatus = $derived(toolStepStatus(resolved));
|
|
33
56
|
</script>
|
|
34
57
|
|
|
35
|
-
<Step.Root {
|
|
58
|
+
<Step.Root status={stepStatus} bind:open class={className} data-tool-status={resolved}>
|
|
59
|
+
{@render header?.()}
|
|
60
|
+
{@render input?.()}
|
|
61
|
+
{@render progress?.()}
|
|
62
|
+
{@render approval?.()}
|
|
63
|
+
{@render result?.()}
|
|
64
|
+
{@render error?.()}
|
|
65
|
+
{@render actions?.()}
|
|
36
66
|
{@render children?.()}
|
|
37
67
|
</Step.Root>
|