@ouraihub/aether-ui 0.0.0-stage → 0.1.1
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/LICENSE +789 -0
- package/fixtures/model-classify.json +42 -0
- package/fixtures/pricing-cost.json +56 -0
- package/fixtures/reasoning-infer.json +44 -0
- package/fixtures/sse/anthropic-messages/chinese.sse +24 -0
- package/fixtures/sse/anthropic-messages/multi-tool.sse +33 -0
- package/fixtures/sse/anthropic-messages/single-tool.sse +39 -0
- package/fixtures/sse/anthropic-messages/text.sse +27 -0
- package/fixtures/sse/anthropic-messages/truncated.sse +21 -0
- package/fixtures/sse/anthropic-messages/upstream-error.sse +12 -0
- package/fixtures/sse/expect.json +20 -0
- package/fixtures/sse/openai-chat/chinese.sse +14 -0
- package/fixtures/sse/openai-chat/multi-tool.sse +18 -0
- package/fixtures/sse/openai-chat/single-tool.sse +22 -0
- package/fixtures/sse/openai-chat/text.sse +14 -0
- package/fixtures/sse/openai-chat/truncated.sse +12 -0
- package/fixtures/sse/openai-chat/upstream-error.sse +6 -0
- package/fixtures/sse/openai-responses/chinese.sse +33 -0
- package/fixtures/sse/openai-responses/multi-tool.sse +36 -0
- package/fixtures/sse/openai-responses/single-tool.sse +27 -0
- package/fixtures/sse/openai-responses/text.sse +33 -0
- package/fixtures/sse/openai-responses/truncated.sse +30 -0
- package/fixtures/sse/openai-responses/upstream-error.sse +9 -0
- package/package.json +71 -3
- package/src/CopyInput.svelte +33 -0
- package/src/KitNotifier.svelte +33 -0
- package/src/chat/ApprovalCard.svelte +29 -0
- package/src/chat/ChatComposer.svelte +277 -0
- package/src/chat/ChatMessage.svelte +262 -0
- package/src/chat/ChatPanel.css +386 -0
- package/src/chat/ChatPanel.svelte +496 -0
- package/src/chat/ChatPanelApprovals.svelte +28 -0
- package/src/chat/ChatPanelComposer.svelte +317 -0
- package/src/chat/ChatPanelDialogs.svelte +242 -0
- package/src/chat/ChatPanelHeader.svelte +132 -0
- package/src/chat/ChatPanelMessages.svelte +166 -0
- package/src/chat/ChatPanelMode.svelte +190 -0
- package/src/chat/ChatPanelState.svelte.ts +1 -0
- package/src/chat/ChatPanelToolbar.svelte +425 -0
- package/src/chat/ChatSurface.svelte +168 -0
- package/src/chat/MessageItem.svelte +480 -0
- package/src/chat/ReasoningControl.svelte +286 -0
- package/src/chat/SkillPicker.svelte +133 -0
- package/src/chat/ToolCallItem.svelte +23 -0
- package/src/chat/UsageControl.svelte +216 -0
- package/src/chat/UsageDetails.svelte +76 -0
- package/src/chat/chat-attachments.svelte.ts +74 -0
- package/src/chat/chat-panel-history.svelte.ts +430 -0
- package/src/chat/chat-panel-props.ts +32 -0
- package/src/chat/index.ts +6 -0
- package/src/chat/run-session-history.ts +56 -0
- package/src/chat/run-session-types.ts +69 -0
- package/src/chat/run-session.svelte.ts +494 -0
- package/src/chat/test-support/chat-fixture.ts +178 -0
- package/src/chat/test-support/conversation-fixtures.ts +32 -0
- package/src/chat/test-support/run-session-fixture.ts +112 -0
- package/src/components/ui/alert/alert-action.svelte +20 -0
- package/src/components/ui/alert/alert-description.svelte +23 -0
- package/src/components/ui/alert/alert-title.svelte +23 -0
- package/src/components/ui/alert/alert.svelte +43 -0
- package/src/components/ui/alert/index.ts +17 -0
- package/src/components/ui/alert-dialog/alert-dialog-action.svelte +27 -0
- package/src/components/ui/alert-dialog/alert-dialog-cancel.svelte +27 -0
- package/src/components/ui/alert-dialog/alert-dialog-content.svelte +32 -0
- package/src/components/ui/alert-dialog/alert-dialog-description.svelte +17 -0
- package/src/components/ui/alert-dialog/alert-dialog-footer.svelte +23 -0
- package/src/components/ui/alert-dialog/alert-dialog-header.svelte +20 -0
- package/src/components/ui/alert-dialog/alert-dialog-media.svelte +20 -0
- package/src/components/ui/alert-dialog/alert-dialog-overlay.svelte +17 -0
- package/src/components/ui/alert-dialog/alert-dialog-portal.svelte +7 -0
- package/src/components/ui/alert-dialog/alert-dialog-title.svelte +17 -0
- package/src/components/ui/alert-dialog/alert-dialog-trigger.svelte +7 -0
- package/src/components/ui/alert-dialog/alert-dialog.svelte +7 -0
- package/src/components/ui/alert-dialog/index.ts +40 -0
- package/src/components/ui/button/button.svelte +81 -0
- package/src/components/ui/button/index.ts +17 -0
- package/src/components/ui/dialog/dialog-close.svelte +11 -0
- package/src/components/ui/dialog/dialog-content.svelte +48 -0
- package/src/components/ui/dialog/dialog-description.svelte +17 -0
- package/src/components/ui/dialog/dialog-footer.svelte +32 -0
- package/src/components/ui/dialog/dialog-header.svelte +20 -0
- package/src/components/ui/dialog/dialog-overlay.svelte +17 -0
- package/src/components/ui/dialog/dialog-portal.svelte +7 -0
- package/src/components/ui/dialog/dialog-title.svelte +17 -0
- package/src/components/ui/dialog/dialog-trigger.svelte +11 -0
- package/src/components/ui/dialog/dialog.svelte +7 -0
- package/src/components/ui/dialog/index.ts +34 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +46 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-content.svelte +31 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-group.svelte +7 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-item.svelte +27 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-label.svelte +24 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-portal.svelte +7 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +17 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +36 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-separator.svelte +17 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +20 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +31 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-sub.svelte +7 -0
- package/src/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
- package/src/components/ui/dropdown-menu/dropdown-menu.svelte +7 -0
- package/src/components/ui/dropdown-menu/index.ts +54 -0
- package/src/components/ui/empty/empty-content.svelte +23 -0
- package/src/components/ui/empty/empty-description.svelte +23 -0
- package/src/components/ui/empty/empty-header.svelte +20 -0
- package/src/components/ui/empty/empty-media.svelte +41 -0
- package/src/components/ui/empty/empty-title.svelte +20 -0
- package/src/components/ui/empty/empty.svelte +23 -0
- package/src/components/ui/empty/index.ts +22 -0
- package/src/components/ui/field/field-content.svelte +20 -0
- package/src/components/ui/field/field-description.svelte +25 -0
- package/src/components/ui/field/field-error.svelte +58 -0
- package/src/components/ui/field/field-group.svelte +23 -0
- package/src/components/ui/field/field-label.svelte +25 -0
- package/src/components/ui/field/field-legend.svelte +24 -0
- package/src/components/ui/field/field-separator.svelte +35 -0
- package/src/components/ui/field/field-set.svelte +20 -0
- package/src/components/ui/field/field-title.svelte +20 -0
- package/src/components/ui/field/field.svelte +47 -0
- package/src/components/ui/field/index.ts +33 -0
- package/src/components/ui/input/index.ts +7 -0
- package/src/components/ui/input/input.svelte +48 -0
- package/src/components/ui/label/index.ts +7 -0
- package/src/components/ui/label/label.svelte +20 -0
- package/src/components/ui/select/index.ts +40 -0
- package/src/components/ui/select/select-content.svelte +45 -0
- package/src/components/ui/select/select-group-heading.svelte +21 -0
- package/src/components/ui/select/select-group.svelte +17 -0
- package/src/components/ui/select/select-item.svelte +43 -0
- package/src/components/ui/select/select-label.svelte +20 -0
- package/src/components/ui/select/select-portal.svelte +7 -0
- package/src/components/ui/select/select-scroll-down-button.svelte +20 -0
- package/src/components/ui/select/select-scroll-up-button.svelte +20 -0
- package/src/components/ui/select/select-separator.svelte +18 -0
- package/src/components/ui/select/select-trigger.svelte +29 -0
- package/src/components/ui/select/select-value.svelte +7 -0
- package/src/components/ui/select/select.svelte +11 -0
- package/src/components/ui/separator/index.ts +7 -0
- package/src/components/ui/separator/separator.svelte +21 -0
- package/src/components/ui/sonner/index.ts +1 -0
- package/src/components/ui/sonner/sonner.svelte +40 -0
- package/src/components/ui/switch/index.ts +7 -0
- package/src/components/ui/switch/switch.svelte +34 -0
- package/src/components/ui/textarea/index.ts +7 -0
- package/src/components/ui/textarea/textarea.svelte +22 -0
- package/src/context.ts +34 -0
- package/src/dev/Demo.svelte +47 -0
- package/src/dev/main.ts +7 -0
- package/src/i18n/en.ts +645 -0
- package/src/i18n/index.ts +28 -0
- package/src/i18n/zh-CN.ts +610 -0
- package/src/index.ts +10 -0
- package/src/logs/LogPanel.svelte +103 -0
- package/src/logs/LogSettings.svelte +58 -0
- package/src/logs/index.ts +5 -0
- package/src/logs/logger.ts +96 -0
- package/src/markdown.ts +8 -0
- package/src/mcp/McpClientEditor.svelte +204 -0
- package/src/mcp/McpClientSettings.svelte +418 -0
- package/src/mcp/McpServerSettings.svelte +363 -0
- package/src/mcp/config.ts +26 -0
- package/src/mcp/index.ts +3 -0
- package/src/mcp/input.ts +74 -0
- package/src/notify.svelte.ts +43 -0
- package/src/ports/contract.ts +174 -0
- package/src/ports/fake-optional.ts +81 -0
- package/src/ports/fake.ts +488 -0
- package/src/ports/index.ts +7 -0
- package/src/ports/search.ts +56 -0
- package/src/ports/skill-sources.ts +45 -0
- package/src/ports/test-support/fake-fixture.ts +63 -0
- package/src/providers/EndpointKeysDialog.svelte +357 -0
- package/src/providers/EndpointModels.svelte +311 -0
- package/src/providers/EndpointPanel.svelte +266 -0
- package/src/providers/ModelPickerDialog.svelte +230 -0
- package/src/providers/ModelPricing.svelte +125 -0
- package/src/providers/ModelSelect.svelte +448 -0
- package/src/providers/ModelSettingsDialog.svelte +388 -0
- package/src/providers/ProviderDialogs.svelte +120 -0
- package/src/providers/ProviderList.svelte +159 -0
- package/src/providers/ProvidersSettings.svelte +491 -0
- package/src/providers/RequestConfigDialog.svelte +278 -0
- package/src/providers/SecretInput.svelte +284 -0
- package/src/providers/draft.ts +355 -0
- package/src/providers/edit-session.ts +170 -0
- package/src/providers/index.ts +5 -0
- package/src/providers/reasoning.ts +55 -0
- package/src/providers/revision.svelte.ts +6 -0
- package/src/providers/test-support/providers-fixture.ts +120 -0
- package/src/search/SearchAdvancedTools.svelte +182 -0
- package/src/search/SearchProviderCard.svelte +195 -0
- package/src/search/SearchSettings.svelte +500 -0
- package/src/search/index.ts +13 -0
- package/src/search/settings-flow.ts +67 -0
- package/src/session.ts +20 -0
- package/src/skills/SkillAdd.svelte +380 -0
- package/src/skills/SkillAuthoring.svelte +430 -0
- package/src/skills/SkillEditor.svelte +104 -0
- package/src/skills/SkillPreviewDialog.svelte +136 -0
- package/src/skills/SkillsSettings.svelte +147 -0
- package/src/skills/error.ts +32 -0
- package/src/skills/index.ts +4 -0
- package/src/skills/test-support/skills-fixture.ts +139 -0
- package/src/styles/kit.css +137 -0
- package/src/styles/tokens.css +22 -0
- package/src/tauri/index.ts +298 -0
- package/src/utils.ts +22 -0
- package/src/web/index.ts +441 -0
- package/README.md +0 -3
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Button } from '#lib/components/ui/button/index.js'
|
|
3
|
+
import * as Empty from '#lib/components/ui/empty/index.js'
|
|
4
|
+
import * as Alert from '#lib/components/ui/alert/index.js'
|
|
5
|
+
import type { ConversationClient, ImageRef, ModelOption, ModelRef } from '../ports'
|
|
6
|
+
import type { ChatTurn, RunSession } from './run-session.svelte'
|
|
7
|
+
import MessageItem from './MessageItem.svelte'
|
|
8
|
+
import type { KitI18n } from '../i18n'
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
i18n,
|
|
12
|
+
session,
|
|
13
|
+
groups,
|
|
14
|
+
purpose,
|
|
15
|
+
history,
|
|
16
|
+
restoreBlocked,
|
|
17
|
+
actionBusy,
|
|
18
|
+
modelOptions,
|
|
19
|
+
modelError,
|
|
20
|
+
capability,
|
|
21
|
+
noModels,
|
|
22
|
+
onRetryModels,
|
|
23
|
+
onOpenSettings,
|
|
24
|
+
onInsert,
|
|
25
|
+
onSaveNote,
|
|
26
|
+
onExportMarkdown,
|
|
27
|
+
sourceLabel,
|
|
28
|
+
sourceModel,
|
|
29
|
+
canEdit,
|
|
30
|
+
onRetry,
|
|
31
|
+
onEdit,
|
|
32
|
+
onBranch,
|
|
33
|
+
onCopyConversation,
|
|
34
|
+
onSwitchModel,
|
|
35
|
+
onTranslate,
|
|
36
|
+
onDelete,
|
|
37
|
+
onUseContext,
|
|
38
|
+
}: {
|
|
39
|
+
i18n: KitI18n
|
|
40
|
+
session: RunSession
|
|
41
|
+
groups: [string, ChatTurn[]][]
|
|
42
|
+
purpose: string
|
|
43
|
+
history: ConversationClient | undefined
|
|
44
|
+
restoreBlocked: boolean
|
|
45
|
+
actionBusy: boolean
|
|
46
|
+
modelOptions: ModelOption[] | null
|
|
47
|
+
modelError: string | null
|
|
48
|
+
noModels: boolean
|
|
49
|
+
capability: ModelOption | null
|
|
50
|
+
onRetryModels: () => void
|
|
51
|
+
onOpenSettings?: (() => void) | undefined
|
|
52
|
+
onInsert?: ((markdown: string) => void) | undefined
|
|
53
|
+
onSaveNote?: ((markdown: string, images: ImageRef[]) => Promise<void> | void) | undefined
|
|
54
|
+
onExportMarkdown?: ((markdown: string) => Promise<void> | void) | undefined
|
|
55
|
+
sourceLabel: (turn: ChatTurn) => string
|
|
56
|
+
sourceModel: (turn: ChatTurn) => ModelRef | null
|
|
57
|
+
canEdit: (turn: ChatTurn) => boolean
|
|
58
|
+
onRetry?: (turn: ChatTurn) => void
|
|
59
|
+
onEdit?: (turn: ChatTurn) => void
|
|
60
|
+
onBranch?: (turn: ChatTurn) => void
|
|
61
|
+
onCopyConversation?: (turn: ChatTurn) => void
|
|
62
|
+
onSwitchModel?: (turn: ChatTurn, model: ModelRef) => void
|
|
63
|
+
onTranslate?: (turn: ChatTurn) => void
|
|
64
|
+
onDelete?: (turn: ChatTurn) => void
|
|
65
|
+
onUseContext?: (turn: ChatTurn) => void
|
|
66
|
+
} = $props()
|
|
67
|
+
const t = $derived(i18n.t)
|
|
68
|
+
</script>
|
|
69
|
+
|
|
70
|
+
{#if session.turns.length > 0}
|
|
71
|
+
<ol class="turns">
|
|
72
|
+
{#each groups as [questionId, replies] (questionId)}
|
|
73
|
+
{@const candidates = replies.filter((reply) => reply.kind === 'reply').length > 1}
|
|
74
|
+
{#each replies as turn, i (turn.id)}
|
|
75
|
+
<MessageItem
|
|
76
|
+
{turn}
|
|
77
|
+
{onInsert}
|
|
78
|
+
{onSaveNote}
|
|
79
|
+
{onExportMarkdown}
|
|
80
|
+
latest={turn.id === session.turns.at(-1)?.id}
|
|
81
|
+
modelLabel={turn.kind === 'translation'
|
|
82
|
+
? `${t('chat.translationReply')} · ${sourceLabel(turn)}`
|
|
83
|
+
: sourceLabel(turn)}
|
|
84
|
+
showInput={i === 0 && turn.kind !== 'translation'}
|
|
85
|
+
chosen={candidates && session.selectedTurnId === turn.id}
|
|
86
|
+
busy={actionBusy}
|
|
87
|
+
editable={canEdit(turn)}
|
|
88
|
+
onRetry={purpose === 'chat' && (turn.persisted || capability !== null)
|
|
89
|
+
? () => onRetry?.(turn)
|
|
90
|
+
: undefined}
|
|
91
|
+
onEdit={purpose === 'chat' && history && session.conversationId && turn.persisted
|
|
92
|
+
? () => onEdit?.(turn)
|
|
93
|
+
: undefined}
|
|
94
|
+
onBranch={purpose === 'chat' && history && session.conversationId && turn.persisted
|
|
95
|
+
? () => onBranch?.(turn)
|
|
96
|
+
: undefined}
|
|
97
|
+
onCopyConversation={purpose === 'chat' &&
|
|
98
|
+
history &&
|
|
99
|
+
session.conversationId &&
|
|
100
|
+
turn.persisted
|
|
101
|
+
? () => onCopyConversation?.(turn)
|
|
102
|
+
: undefined}
|
|
103
|
+
onSwitchModel={purpose === 'chat' && history && session.conversationId && turn.persisted
|
|
104
|
+
? (picked: ModelRef) => onSwitchModel?.(turn, picked)
|
|
105
|
+
: undefined}
|
|
106
|
+
modelOptions={turn.images.length > 0
|
|
107
|
+
? (modelOptions?.filter((option) => option.canVision) ?? null)
|
|
108
|
+
: modelOptions}
|
|
109
|
+
sourceModel={sourceModel(turn)}
|
|
110
|
+
onTranslate={purpose === 'chat' && history && session.conversationId && turn.persisted
|
|
111
|
+
? () => onTranslate?.(turn)
|
|
112
|
+
: undefined}
|
|
113
|
+
onDelete={purpose === 'chat' && history && session.conversationId && turn.persisted
|
|
114
|
+
? () => onDelete?.(turn)
|
|
115
|
+
: undefined}
|
|
116
|
+
onUseContext={candidates &&
|
|
117
|
+
purpose === 'chat' &&
|
|
118
|
+
history &&
|
|
119
|
+
session.conversationId &&
|
|
120
|
+
turn.persisted
|
|
121
|
+
? () => onUseContext?.(turn)
|
|
122
|
+
: undefined}
|
|
123
|
+
/>
|
|
124
|
+
{/each}
|
|
125
|
+
{/each}
|
|
126
|
+
</ol>
|
|
127
|
+
{/if}
|
|
128
|
+
{#if modelError}
|
|
129
|
+
<Alert.Root variant="destructive">
|
|
130
|
+
<Alert.Title>{t('chat.modelsFailed')}</Alert.Title>
|
|
131
|
+
<Alert.Description
|
|
132
|
+
>{modelError}<Button variant="outline" size="sm" onclick={onRetryModels}
|
|
133
|
+
>{t('chat.retryModels')}</Button
|
|
134
|
+
></Alert.Description
|
|
135
|
+
>
|
|
136
|
+
</Alert.Root>
|
|
137
|
+
{:else if modelOptions === null}
|
|
138
|
+
<p class="empty-message" role="status">{t('chat.modelsLoading')}</p>
|
|
139
|
+
{:else if noModels}
|
|
140
|
+
<Empty.Root
|
|
141
|
+
><Empty.Description>{t('chat.noModels')}</Empty.Description>{#if onOpenSettings}<Button
|
|
142
|
+
variant="outline"
|
|
143
|
+
size="sm"
|
|
144
|
+
onclick={onOpenSettings}>{t('chat.openSettings')}</Button
|
|
145
|
+
>{/if}</Empty.Root
|
|
146
|
+
>
|
|
147
|
+
{:else if session.turns.length === 0 && !restoreBlocked}
|
|
148
|
+
<p class="empty-message">{t('chat.empty')}</p>
|
|
149
|
+
{/if}
|
|
150
|
+
|
|
151
|
+
<style>
|
|
152
|
+
.turns {
|
|
153
|
+
display: flex;
|
|
154
|
+
flex-direction: column;
|
|
155
|
+
gap: 1rem;
|
|
156
|
+
padding: 0;
|
|
157
|
+
margin: 0;
|
|
158
|
+
list-style: none;
|
|
159
|
+
}
|
|
160
|
+
.empty-message {
|
|
161
|
+
color: var(--color-muted-foreground);
|
|
162
|
+
text-align: center;
|
|
163
|
+
padding: 1.5rem 0.5rem;
|
|
164
|
+
margin: 0;
|
|
165
|
+
}
|
|
166
|
+
</style>
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import ChevronDownIcon from '@lucide/svelte/icons/chevron-down'
|
|
3
|
+
import CheckIcon from '@lucide/svelte/icons/check'
|
|
4
|
+
import ShieldIcon from '@lucide/svelte/icons/shield'
|
|
5
|
+
import HandIcon from '@lucide/svelte/icons/hand'
|
|
6
|
+
import RouteIcon from '@lucide/svelte/icons/route'
|
|
7
|
+
import FilePenIcon from '@lucide/svelte/icons/file-pen'
|
|
8
|
+
import ShieldCheckIcon from '@lucide/svelte/icons/shield-check'
|
|
9
|
+
import ShieldAlertIcon from '@lucide/svelte/icons/shield-alert'
|
|
10
|
+
import InfoIcon from '@lucide/svelte/icons/info'
|
|
11
|
+
import * as DropdownMenu from '#lib/components/ui/dropdown-menu/index.js'
|
|
12
|
+
import { Button } from '#lib/components/ui/button/index.js'
|
|
13
|
+
import type { KitI18n } from '../i18n'
|
|
14
|
+
import type { PermissionMode } from '../ports'
|
|
15
|
+
let {
|
|
16
|
+
i18n,
|
|
17
|
+
mode,
|
|
18
|
+
allowedModes,
|
|
19
|
+
running,
|
|
20
|
+
chooseMode,
|
|
21
|
+
}: {
|
|
22
|
+
i18n: KitI18n
|
|
23
|
+
mode: PermissionMode
|
|
24
|
+
allowedModes: PermissionMode[]
|
|
25
|
+
running: boolean
|
|
26
|
+
chooseMode: (mode: PermissionMode) => Promise<void>
|
|
27
|
+
} = $props()
|
|
28
|
+
const t = $derived(i18n.t)
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
{#if mode === 'plan'}<span class="plan-badge" role="status">{t('chat.mode.planBadge')}</span>{/if}
|
|
32
|
+
{#if allowedModes.length > 1 || allowedModes.includes('full_access')}
|
|
33
|
+
<DropdownMenu.Root>
|
|
34
|
+
<DropdownMenu.Trigger disabled={running}>
|
|
35
|
+
{#snippet child({ props })}<Button
|
|
36
|
+
{...props}
|
|
37
|
+
variant="ghost"
|
|
38
|
+
size="sm"
|
|
39
|
+
class={mode === 'full_access' ? 'mode-danger' : undefined}
|
|
40
|
+
aria-label={`${t('chat.mode.label')}: ${t(`chat.mode.${mode}`)}`}
|
|
41
|
+
><ShieldIcon data-icon="inline-start" />{t(`chat.mode.${mode}`)}<ChevronDownIcon
|
|
42
|
+
data-icon="inline-end"
|
|
43
|
+
/></Button
|
|
44
|
+
>{/snippet}
|
|
45
|
+
</DropdownMenu.Trigger>
|
|
46
|
+
<DropdownMenu.Content side="top" align="end" class="mode-menu">
|
|
47
|
+
<DropdownMenu.Group aria-label={t('chat.mode.label')}>
|
|
48
|
+
{#each allowedModes as option (option)}
|
|
49
|
+
<DropdownMenu.Item
|
|
50
|
+
class={option === 'full_access' ? 'mode-option mode-danger' : 'mode-option'}
|
|
51
|
+
aria-current={option === mode ? 'true' : undefined}
|
|
52
|
+
onSelect={() => void chooseMode(option)}
|
|
53
|
+
>{#if option === 'default'}<HandIcon />
|
|
54
|
+
{:else if option === 'plan'}<RouteIcon />
|
|
55
|
+
{:else if option === 'accept_edits'}<FilePenIcon />
|
|
56
|
+
{:else if option === 'auto'}<ShieldCheckIcon />
|
|
57
|
+
{:else}<ShieldAlertIcon />{/if}
|
|
58
|
+
<span class="mode-name">{t(`chat.mode.${option}`)}</span>
|
|
59
|
+
<span class="mode-description">{t(`chat.mode.${option}Hint`)}</span>
|
|
60
|
+
<span class="mode-notice">
|
|
61
|
+
{#if option === 'auto' || option === 'full_access'}
|
|
62
|
+
<span
|
|
63
|
+
title={t(option === 'auto' ? 'chat.mode.ruleNotice' : 'chat.mode.fullAccessBody')}
|
|
64
|
+
>
|
|
65
|
+
<InfoIcon />
|
|
66
|
+
</span>
|
|
67
|
+
{/if}
|
|
68
|
+
</span>
|
|
69
|
+
<span class="mode-check"
|
|
70
|
+
>{#if option === mode}<CheckIcon />{/if}</span
|
|
71
|
+
></DropdownMenu.Item
|
|
72
|
+
>
|
|
73
|
+
{/each}
|
|
74
|
+
</DropdownMenu.Group>
|
|
75
|
+
<div class="mode-footer">
|
|
76
|
+
<span>{t('chat.mode.label')}</span>
|
|
77
|
+
<span class="mode-keys"
|
|
78
|
+
><kbd>↑↓</kbd>{t('chat.mode.navigate')}<kbd>↵</kbd>{t('chat.mode.confirm')}<kbd>Esc</kbd
|
|
79
|
+
>{t('chat.mode.close')}</span
|
|
80
|
+
>
|
|
81
|
+
</div>
|
|
82
|
+
</DropdownMenu.Content>
|
|
83
|
+
</DropdownMenu.Root>
|
|
84
|
+
{/if}
|
|
85
|
+
|
|
86
|
+
<style>
|
|
87
|
+
.plan-badge {
|
|
88
|
+
padding: 0.125rem 0.5rem;
|
|
89
|
+
border: 1px solid var(--color-border);
|
|
90
|
+
border-radius: 999px;
|
|
91
|
+
color: var(--color-muted-foreground);
|
|
92
|
+
font-size: var(--kit-font-size-sm, 0.8125rem);
|
|
93
|
+
white-space: nowrap;
|
|
94
|
+
}
|
|
95
|
+
:global(.mode-menu) {
|
|
96
|
+
width: min(35rem, calc(100vw - 1rem));
|
|
97
|
+
padding: 0.375rem;
|
|
98
|
+
border-radius: 0.75rem;
|
|
99
|
+
}
|
|
100
|
+
:global(.mode-option) {
|
|
101
|
+
display: grid;
|
|
102
|
+
grid-template-columns: 1rem 7.5rem minmax(0, 1fr) 1rem 0.875rem;
|
|
103
|
+
align-items: center;
|
|
104
|
+
column-gap: 0.5rem;
|
|
105
|
+
min-height: 2.125rem;
|
|
106
|
+
padding: 0.375rem 0.5rem;
|
|
107
|
+
border-radius: 0.5rem;
|
|
108
|
+
font-size: var(--kit-font-size-sm, 0.8125rem);
|
|
109
|
+
}
|
|
110
|
+
:global(.mode-option[aria-current='true']) {
|
|
111
|
+
background: var(--color-muted);
|
|
112
|
+
}
|
|
113
|
+
:global(.mode-option > svg) {
|
|
114
|
+
color: var(--color-muted-foreground);
|
|
115
|
+
width: 0.875rem;
|
|
116
|
+
height: 0.875rem;
|
|
117
|
+
}
|
|
118
|
+
.mode-name {
|
|
119
|
+
white-space: nowrap;
|
|
120
|
+
}
|
|
121
|
+
.mode-description {
|
|
122
|
+
color: var(--color-muted-foreground);
|
|
123
|
+
font-size: var(--kit-font-size-xs, 0.75rem);
|
|
124
|
+
text-align: right;
|
|
125
|
+
line-height: 1.5;
|
|
126
|
+
}
|
|
127
|
+
.mode-notice,
|
|
128
|
+
.mode-check {
|
|
129
|
+
display: flex;
|
|
130
|
+
align-items: center;
|
|
131
|
+
justify-content: center;
|
|
132
|
+
color: var(--color-muted-foreground);
|
|
133
|
+
}
|
|
134
|
+
.mode-notice {
|
|
135
|
+
color: var(--color-warning, var(--color-muted-foreground));
|
|
136
|
+
}
|
|
137
|
+
.mode-notice :global(svg),
|
|
138
|
+
.mode-check :global(svg) {
|
|
139
|
+
display: block;
|
|
140
|
+
width: 0.8125rem;
|
|
141
|
+
height: 0.8125rem;
|
|
142
|
+
}
|
|
143
|
+
:global(.mode-danger),
|
|
144
|
+
:global(.mode-danger) :is(.mode-name, .mode-description, .mode-notice),
|
|
145
|
+
:global(.mode-option.mode-danger > svg) {
|
|
146
|
+
color: var(--color-destructive);
|
|
147
|
+
}
|
|
148
|
+
.mode-footer {
|
|
149
|
+
display: flex;
|
|
150
|
+
justify-content: space-between;
|
|
151
|
+
align-items: center;
|
|
152
|
+
gap: 0.75rem;
|
|
153
|
+
padding: 0.625rem 0.375rem 0.125rem;
|
|
154
|
+
color: var(--color-muted-foreground);
|
|
155
|
+
font-size: var(--kit-font-size-xs, 0.75rem);
|
|
156
|
+
}
|
|
157
|
+
.mode-keys {
|
|
158
|
+
display: flex;
|
|
159
|
+
align-items: center;
|
|
160
|
+
gap: 0.25rem;
|
|
161
|
+
}
|
|
162
|
+
.mode-keys kbd {
|
|
163
|
+
padding: 0 0.25rem;
|
|
164
|
+
border-radius: 0.25rem;
|
|
165
|
+
background: var(--color-muted);
|
|
166
|
+
font: inherit;
|
|
167
|
+
}
|
|
168
|
+
.mode-keys kbd:not(:first-child) {
|
|
169
|
+
margin-left: 0.375rem;
|
|
170
|
+
}
|
|
171
|
+
@media (max-width: 480px) {
|
|
172
|
+
:global(.mode-option) {
|
|
173
|
+
grid-template-columns: 1rem minmax(0, 1fr) 1rem 0.875rem;
|
|
174
|
+
row-gap: 0.125rem;
|
|
175
|
+
}
|
|
176
|
+
.mode-description {
|
|
177
|
+
grid-column: 2;
|
|
178
|
+
grid-row: 2;
|
|
179
|
+
text-align: left;
|
|
180
|
+
}
|
|
181
|
+
.mode-notice {
|
|
182
|
+
grid-column: 3;
|
|
183
|
+
grid-row: 1;
|
|
184
|
+
}
|
|
185
|
+
.mode-check {
|
|
186
|
+
grid-column: 4;
|
|
187
|
+
grid-row: 1;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Chat panel state implementation.
|