@ouraihub/aether-ui 0.1.0 → 0.1.2

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.
Files changed (90) hide show
  1. package/package.json +3 -3
  2. package/src/chat/ApprovalCard.svelte +8 -2
  3. package/src/chat/ChatComposer.svelte +319 -0
  4. package/src/chat/ChatMessage.svelte +262 -0
  5. package/src/chat/ChatPanel.css +386 -0
  6. package/src/chat/ChatPanel.svelte +276 -1880
  7. package/src/chat/ChatPanelApprovals.svelte +28 -0
  8. package/src/chat/ChatPanelComposer.svelte +336 -0
  9. package/src/chat/ChatPanelDialogs.svelte +242 -0
  10. package/src/chat/ChatPanelHeader.svelte +108 -0
  11. package/src/chat/ChatPanelMessages.svelte +166 -0
  12. package/src/chat/ChatPanelMode.svelte +190 -0
  13. package/src/chat/ChatPanelState.svelte.ts +1 -0
  14. package/src/chat/ChatPanelToolbar.svelte +436 -0
  15. package/src/chat/ChatSurface.svelte +168 -0
  16. package/src/chat/ContextUsageStatus.svelte +97 -0
  17. package/src/chat/MessageItem.svelte +111 -214
  18. package/src/chat/ModelEffortPicker.svelte +326 -0
  19. package/src/chat/PickerEffort.svelte +71 -0
  20. package/src/chat/ReasoningControl.svelte +184 -0
  21. package/src/chat/ReasoningSlider.svelte +174 -0
  22. package/src/chat/SkillPicker.svelte +14 -6
  23. package/src/chat/UsageControl.svelte +223 -0
  24. package/src/chat/UsageDetails.svelte +44 -90
  25. package/src/chat/chat-attachments.svelte.ts +78 -0
  26. package/src/chat/chat-panel-history.svelte.ts +430 -0
  27. package/src/chat/chat-panel-models.svelte.ts +97 -0
  28. package/src/chat/chat-panel-props.ts +38 -0
  29. package/src/chat/context-status.ts +101 -0
  30. package/src/chat/icons/LICENSE-REMIX +186 -0
  31. package/src/chat/icons/LICENSE-SIMPLE-ICONS +30 -0
  32. package/src/chat/icons/PathIcon.svelte +8 -0
  33. package/src/chat/icons/effort-icons.ts +65 -0
  34. package/src/chat/icons/status-icons.ts +105 -0
  35. package/src/chat/index.ts +25 -1
  36. package/src/chat/model-effort.ts +177 -0
  37. package/src/chat/run-session-history.ts +56 -0
  38. package/src/chat/run-session-types.ts +69 -0
  39. package/src/chat/run-session.svelte.ts +73 -135
  40. package/src/chat/test-support/chat-fixture.ts +194 -0
  41. package/src/chat/test-support/conversation-fixtures.ts +32 -0
  42. package/src/chat/test-support/run-session-fixture.ts +112 -0
  43. package/src/dev/Demo.svelte +3 -1
  44. package/src/i18n/en-chat.d.ts +1 -0
  45. package/src/i18n/en-chat.js +201 -0
  46. package/src/i18n/en.ts +58 -180
  47. package/src/i18n/index.ts +7 -2
  48. package/src/i18n/zh-CN-chat.d.ts +1 -0
  49. package/src/i18n/zh-CN-chat.js +190 -0
  50. package/src/i18n/zh-CN.ts +8 -153
  51. package/src/logs/LogPanel.svelte +9 -3
  52. package/src/logs/LogSettings.svelte +3 -1
  53. package/src/mcp/McpClientEditor.svelte +204 -0
  54. package/src/mcp/McpClientSettings.svelte +57 -130
  55. package/src/mcp/McpServerSettings.svelte +47 -11
  56. package/src/mcp/input.ts +2 -1
  57. package/src/ports/contract.ts +11 -2
  58. package/src/ports/fake-optional.ts +81 -0
  59. package/src/ports/fake.ts +90 -86
  60. package/src/ports/search.ts +11 -2
  61. package/src/ports/test-support/fake-fixture.ts +63 -0
  62. package/src/providers/EndpointKeysDialog.svelte +27 -13
  63. package/src/providers/EndpointModels.svelte +311 -0
  64. package/src/providers/EndpointPanel.svelte +33 -258
  65. package/src/providers/ModelPickerDialog.svelte +59 -16
  66. package/src/providers/ModelPricing.svelte +125 -0
  67. package/src/providers/ModelSelect.svelte +22 -8
  68. package/src/providers/ModelSettingsDialog.svelte +61 -126
  69. package/src/providers/ProviderDialogs.svelte +120 -0
  70. package/src/providers/ProviderList.svelte +159 -0
  71. package/src/providers/ProvidersSettings.svelte +67 -207
  72. package/src/providers/RequestConfigDialog.svelte +40 -12
  73. package/src/providers/SecretInput.svelte +11 -3
  74. package/src/providers/draft.ts +39 -13
  75. package/src/providers/edit-session.ts +31 -7
  76. package/src/providers/reasoning.ts +18 -4
  77. package/src/providers/revision.svelte.ts +3 -1
  78. package/src/providers/test-support/providers-fixture.ts +120 -0
  79. package/src/search/SearchAdvancedTools.svelte +182 -0
  80. package/src/search/SearchProviderCard.svelte +195 -0
  81. package/src/search/SearchSettings.svelte +62 -265
  82. package/src/search/settings-flow.ts +8 -3
  83. package/src/skills/SkillAdd.svelte +51 -18
  84. package/src/skills/SkillAuthoring.svelte +69 -20
  85. package/src/skills/SkillEditor.svelte +13 -3
  86. package/src/skills/SkillPreviewDialog.svelte +19 -5
  87. package/src/skills/SkillsSettings.svelte +11 -4
  88. package/src/skills/test-support/skills-fixture.ts +139 -0
  89. package/src/tauri/index.ts +23 -7
  90. package/src/web/index.ts +90 -25
@@ -0,0 +1,112 @@
1
+ import { vi } from 'vitest'
2
+ import { createFakePorts } from '../../ports'
3
+ import type {
4
+ ConversationClient,
5
+ Conversation,
6
+ RunAccepted,
7
+ RunEvent,
8
+ RunRequest,
9
+ Turn,
10
+ } from '../../ports'
11
+ import { RunSession, type RunBase } from '../run-session.svelte'
12
+
13
+ export const sourceModel = { endpointId: 'original-endpoint', modelId: 'original-model' }
14
+ export const pickedModel = { endpointId: 'picked-endpoint', modelId: 'picked-model' }
15
+ export const base: RunBase = {
16
+ purpose: 'chat',
17
+ scope: null,
18
+ language: 'en',
19
+ model: pickedModel,
20
+ skills: [],
21
+ context: null,
22
+ }
23
+
24
+ export function required<T>(value: T | null | undefined): T {
25
+ if (value == null) throw new Error('Expected run-session fixture is missing')
26
+ return value
27
+ }
28
+
29
+ export function stored(overrides: Partial<Turn> = {}): Turn {
30
+ return {
31
+ id: 'source',
32
+ parentId: null,
33
+ questionId: 'question',
34
+ supersedesId: null,
35
+ kind: 'reply',
36
+ endpointId: sourceModel.endpointId,
37
+ modelId: sourceModel.modelId,
38
+ input: 'Original question',
39
+ text: 'Original **answer**',
40
+ status: 'completed',
41
+ errorCode: null,
42
+ reasoningText: 'Original reasoning',
43
+ reasoningEffort: 'default',
44
+ images: [],
45
+ generated: [],
46
+ ...overrides,
47
+ }
48
+ }
49
+
50
+ export function conversation(
51
+ turns: Turn[],
52
+ selectedTurnId: string | null = 'source',
53
+ ): Conversation {
54
+ return {
55
+ summary: {
56
+ id: 'conversation',
57
+ title: 'Conversation',
58
+ scope: null,
59
+ createdAt: 0,
60
+ updatedAt: 0,
61
+ selectedTurnId,
62
+ },
63
+ turns,
64
+ }
65
+ }
66
+
67
+ export interface Deferred<T> {
68
+ promise: Promise<T>
69
+ resolve: (value: T) => void
70
+ reject: (error: unknown) => void
71
+ }
72
+ export function deferred<T>(): Deferred<T> {
73
+ let resolve!: (value: T) => void
74
+ let reject!: (error: unknown) => void
75
+ const promise = new Promise<T>((yes, no) => {
76
+ resolve = yes
77
+ reject = no
78
+ })
79
+ return { promise, resolve, reject }
80
+ }
81
+
82
+ export function setup(withHistory = true) {
83
+ const runs: {
84
+ request: RunRequest
85
+ emit: (event: RunEvent) => void
86
+ accepted: Deferred<RunAccepted>
87
+ }[] = []
88
+ const get = vi.fn<ConversationClient['get']>(() => Promise.resolve(conversation([stored()])))
89
+ const cancel = vi.fn(() => Promise.resolve())
90
+ const approve = vi.fn(() => Promise.resolve())
91
+ const ports = createFakePorts({
92
+ chat: {
93
+ cancel,
94
+ approve,
95
+ start: (request, emit) => {
96
+ const accepted = deferred<RunAccepted>()
97
+ runs.push({ request, emit, accepted })
98
+ return accepted.promise
99
+ },
100
+ },
101
+ })
102
+ const chat = required(ports.chat)
103
+ if (withHistory) Object.assign(required(ports.conversations), { get })
104
+ else delete ports.conversations
105
+ return { session: new RunSession(chat, ports.conversations), runs, get, cancel, approve }
106
+ }
107
+
108
+ export const accepted: RunAccepted = {
109
+ runId: 'run',
110
+ conversationId: 'conversation',
111
+ turnId: 'candidate',
112
+ }
@@ -14,7 +14,9 @@
14
14
  let answer = $state('none')
15
15
 
16
16
  async function ask() {
17
- answer = String(await notify.confirm({ title: 'Delete?', body: 'This cannot be undone.', danger: true }))
17
+ answer = String(
18
+ await notify.confirm({ title: 'Delete?', body: 'This cannot be undone.', danger: true }),
19
+ )
18
20
  }
19
21
  </script>
20
22
 
@@ -0,0 +1 @@
1
+ export const enChat: Readonly<Record<string, string>>
@@ -0,0 +1,201 @@
1
+ export const enChat = {
2
+ 'chat.usageEntry': 'Usage',
3
+ 'chat.networkOn': 'Web search on · click to turn off',
4
+ 'chat.networkOff': 'Web search off · click to turn on',
5
+ 'chat.title': 'Chat',
6
+ 'chat.history': 'Conversation',
7
+ 'chat.historyFailed': 'Could not load conversations',
8
+ 'chat.newConversation': 'New conversation',
9
+ 'chat.close': 'Close',
10
+ 'chat.messages': 'Messages',
11
+ 'chat.input': 'Message',
12
+ 'chat.placeholder': 'Type a message, Ctrl/Cmd+Enter to send',
13
+ 'chat.send': 'Send',
14
+ 'chat.stop': 'Stop',
15
+ 'chat.regenerate': 'Regenerate',
16
+ 'chat.stopped': 'Stopped',
17
+ 'chat.interrupted': 'Interrupted: the app closed during this reply',
18
+ 'chat.exhausted': 'Reached the tool call round limit',
19
+ 'chat.copy': 'Copy',
20
+ 'chat.copied': 'Copied',
21
+ 'chat.copyFailed': 'Could not copy',
22
+ 'chat.insert': 'Insert',
23
+ 'chat.retry': 'Retry',
24
+ 'chat.more': 'More actions',
25
+ 'chat.translationReply': 'Translation',
26
+ 'chat.noSourceModel': 'Source model unknown',
27
+ 'chat.switchModel': 'Switch model',
28
+ 'chat.translate': 'Translate',
29
+ 'chat.editReply': 'Edit',
30
+ 'chat.replyText': 'Reply Markdown',
31
+ 'chat.replyModel': 'Reply model',
32
+ 'chat.targetLanguage': 'Target language',
33
+ 'chat.branch': 'Branch',
34
+ 'chat.copyConversation': 'Copy as new conversation',
35
+ 'chat.save': 'Save',
36
+ 'chat.saveFile': 'Save to local file',
37
+ 'chat.export': 'Export',
38
+ 'chat.exportMarkdown': 'Export as Markdown',
39
+ 'chat.exportFailed': 'Could not download Markdown',
40
+ 'chat.saveNote': 'Save to note',
41
+ 'chat.saveNoteFailed': 'Could not save the note',
42
+ 'chat.useContext': 'Set as context',
43
+ 'chat.deleteReply': 'Delete',
44
+ 'chat.deleteReplyTitle': 'Delete this message?',
45
+ 'chat.deleteReparentBody':
46
+ 'Later turns will attach to the previous reply. This cannot be undone.',
47
+ 'chat.sourceModelUnavailable': 'The source model is unavailable. Use @ to pick another model.',
48
+ 'chat.candidateHint':
49
+ 'The original reply is retained. Click 👍 to set a candidate as context and continue from it.',
50
+ 'chat.editReplyHint':
51
+ 'Edits only replace this reply. A concurrent change will reject the edit and keep your draft.',
52
+ 'chat.replyRefreshFailed': 'Could not reload the saved replies.',
53
+ 'chat.delete': 'Delete conversation',
54
+ 'chat.deleteTitle': 'Delete this conversation?',
55
+ 'chat.network': 'Web search',
56
+ 'chat.sources': 'Sources',
57
+ 'chat.networkPrivacy':
58
+ 'External search sends this question; preferred native search may send conversation ' +
59
+ 'and attached note context to the model provider.',
60
+ 'chat.searching': 'Searching the web…',
61
+ 'chat.searchResults': '{count} results found',
62
+ 'chat.reasoning': 'Reasoning',
63
+ 'chat.toolProcess': 'Tool activity',
64
+ 'chat.showMore': 'Show more',
65
+ 'chat.showLess': 'Show less',
66
+ 'chat.reasoningEffort': 'Reasoning effort',
67
+ 'chat.reasoningStrength': 'Strength',
68
+ 'chat.reasoningFaster': 'Faster',
69
+ 'chat.reasoningSmarter': 'Smarter',
70
+ 'chat.resetReasoning': 'Reset to default',
71
+ 'chat.reasoningDefaultHint':
72
+ 'Default sends no reasoning control; the provider decides. Choose an effort to override it.',
73
+ 'chat.reasoningUnconfigured':
74
+ 'No reasoning capabilities are configured for this model. ' +
75
+ 'Turn on “Reasoning” in model settings and choose its supported efforts to enable the slider.',
76
+ 'chat.unknown': 'Unknown',
77
+ 'chat.contextUsage': 'Context usage',
78
+ 'chat.usage': 'Token usage',
79
+ 'chat.usageSettings': 'Usage and settings',
80
+ 'chat.runSettings': 'Run settings',
81
+ 'chat.reported': 'Measured',
82
+ 'chat.estimated': 'Estimated',
83
+ 'chat.modelsFailed': 'Could not load model capabilities',
84
+ 'chat.modelsLoading': 'Loading models…',
85
+ 'chat.retryModels': 'Retry loading models',
86
+ 'chat.historyLoading': 'Loading conversations…',
87
+ 'chat.retryHistory': 'Retry conversation operation',
88
+ 'chat.rename': 'Rename conversation',
89
+ 'chat.conversationTitle': 'Conversation title',
90
+ 'chat.expandInput': 'Expand input',
91
+ 'chat.collapseInput': 'Collapse input',
92
+ 'chat.backToBottom': 'Back to bottom',
93
+ 'chat.draftRecoverable':
94
+ 'Your unsent message is available to restore after clearing the current draft.',
95
+ 'chat.restoreDraft': 'Restore unsent message',
96
+ 'chat.tools': 'More tools',
97
+ 'chat.uploadAttachment': 'Upload attachment',
98
+ 'chat.generateImage': 'Generate image',
99
+ 'chat.generateImageOff': 'Turn off image generation',
100
+ 'chat.quickPanel': 'Quick panel',
101
+ 'chat.toolbarCustomize': 'Customize toolbar',
102
+ 'chat.toolbarRestore': 'Restore default',
103
+ 'chat.toolbarDrag': 'Drag or use ↑/↓ to reorder {name}',
104
+ 'chat.paintingUnconfigured': 'Choose a painting model in settings first',
105
+ 'chat.toolsUnsupported': 'The current model does not support tools',
106
+ 'chat.generatedImages': 'Generated images',
107
+ 'chat.openGeneratedImage': 'Open generated image {index}',
108
+ 'chat.removeImage': 'Remove image {index}',
109
+ 'chat.openImage': 'Open image {index}',
110
+ 'chat.imageExpired': 'Image expired',
111
+ 'chat.visionUnsupported': 'The current model does not support images',
112
+ 'chat.imageLimit': 'Up to {max} images per message',
113
+ 'chat.imageType': 'Only PNG, JPEG, WebP and GIF images are supported',
114
+ 'chat.imageSize': 'Each image must be 4 MiB or smaller',
115
+ 'chat.currentUsage': 'This turn',
116
+ 'chat.totalUsage': 'Known conversation total',
117
+ 'chat.usage.inputTokens': 'Input',
118
+ 'chat.usage.outputTokens': 'Output',
119
+ 'chat.usage.cacheReadTokens': 'Cache read',
120
+ 'chat.usage.cacheWriteTokens': 'Cache write',
121
+ 'chat.usage.reasoningTokens': 'Reasoning tokens',
122
+ 'chat.usageHint':
123
+ 'Cache is included in input; reasoning is included in output. ' +
124
+ 'Unknown counts are not treated as zero.',
125
+ 'chat.cost': 'Cost',
126
+ 'chat.effort.default': 'Default',
127
+ 'chat.effort.none': 'None',
128
+ 'chat.effort.auto': 'Auto',
129
+ 'chat.effort.minimal': 'Minimal',
130
+ 'chat.effort.low': 'Low',
131
+ 'chat.effort.medium': 'Medium',
132
+ 'chat.effort.high': 'High',
133
+ 'chat.effort.xhigh': 'Very high',
134
+ 'chat.effort.max': 'Maximum',
135
+ 'chat.effortHint.default': 'Use the provider default',
136
+ 'chat.effortHint.none': 'No reasoning — fastest and cheapest',
137
+ 'chat.effortHint.auto': 'The provider decides the depth',
138
+ 'chat.effortHint.minimal': 'Minimal reasoning',
139
+ 'chat.effortHint.low': 'Light reasoning — fastest',
140
+ 'chat.effortHint.medium': 'Balanced reasoning',
141
+ 'chat.effortHint.high': 'Deep reasoning',
142
+ 'chat.effortHint.xhigh': 'Very deep reasoning',
143
+ 'chat.effortHint.max': 'Maximum reasoning',
144
+ 'chat.picker.search': 'Search models… (add a level: opus high)',
145
+ 'chat.picker.searchLabel': 'Search models, optionally with a level',
146
+ 'chat.picker.trigger': 'Model and reasoning: {name} · {effort}',
147
+ 'chat.picker.choose': 'Choose model',
148
+ 'chat.picker.keyed': 'API key',
149
+ 'chat.picker.price': '{currency} {input} / {output} per 1M tokens from',
150
+ 'chat.picker.context': '{size} context',
151
+ 'chat.picker.group': 'Model group {provider}, {state}',
152
+ 'chat.picker.expanded': 'expanded',
153
+ 'chat.picker.collapsed': 'collapsed',
154
+ 'chat.picker.select': 'Select {name} · {provider}',
155
+ 'chat.picker.effortFor': 'Effort · {name}',
156
+ 'chat.picker.setDefault': 'Set as default',
157
+ 'chat.picker.resetOff': 'Reset to off',
158
+ 'chat.picker.refresh': 'Refresh',
159
+ 'chat.picker.refreshing': 'Updating…',
160
+ 'chat.picker.empty': 'No models available; configure a provider first',
161
+ 'chat.picker.noMatch': 'No matching models',
162
+ 'chat.picker.reloaded': 'Reloaded local catalog: {count} chat models',
163
+ 'chat.status.label': '{platform} context usage: {summary} · {spending}. View usage details',
164
+ 'chat.mode.label': 'Permission mode',
165
+ 'chat.mode.default': 'Ask each time',
166
+ 'chat.mode.defaultHint': 'Follow each tool’s approval setting.',
167
+ 'chat.mode.plan': 'Plan only',
168
+ 'chat.mode.planHint': 'Read and plan without changes.',
169
+ 'chat.mode.accept_edits': 'Accept edits',
170
+ 'chat.mode.accept_editsHint': 'Approve edits; other actions follow their rules.',
171
+ 'chat.mode.auto': 'Smart approval',
172
+ 'chat.mode.autoHint': 'Approve app tools; rules may require a prompt.',
173
+ 'chat.mode.full_access': 'Full access',
174
+ 'chat.mode.full_accessHint': 'No prompts for this run; blocked tools stay blocked.',
175
+ 'chat.mode.planBadge': 'Plan only',
176
+ 'chat.mode.fullAccessTitle': 'Allow full access for this run?',
177
+ 'chat.mode.fullAccessBody':
178
+ 'For this run only, tools may change data and execute commands without asking. ' +
179
+ 'Blocked tools stay blocked. This choice is not saved.',
180
+ 'chat.mode.ruleNotice':
181
+ 'Rules can miss risks and are not a sandbox. MCP tools keep their approval settings.',
182
+ 'chat.mode.navigate': 'Select',
183
+ 'chat.mode.confirm': 'Confirm',
184
+ 'chat.mode.close': 'Close',
185
+ 'chat.deleteBody': 'Its messages cannot be restored.',
186
+ 'chat.deleteFailed': 'Could not delete the conversation',
187
+ 'chat.empty': 'Ask anything to start',
188
+ 'chat.noModels': 'No chat model yet. Add a provider and its models first.',
189
+ 'chat.openSettings': 'Open settings',
190
+ 'chat.context.remove': 'Do not send {label} with the next message',
191
+ 'chat.tool.calling': 'Calling {name}',
192
+ 'chat.tool.ok': '{name}: {summary}',
193
+ 'chat.tool.error': '{name} failed: {summary}',
194
+ 'chat.tool.denied': '{name}: denied',
195
+ 'chat.tool.unknown': '{name}: result unknown, it may have run',
196
+ 'chat.approval.title': 'Allow {name}?',
197
+ 'chat.approval.host': 'App tool',
198
+ 'chat.approval.mcp': 'MCP server {server}',
199
+ 'chat.approval.allow': 'Allow once',
200
+ 'chat.approval.deny': 'Deny',
201
+ }