@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
package/src/web/index.ts CHANGED
@@ -1,6 +1,17 @@
1
1
  // Browser HTTP adapter. Only enabled capabilities are exposed; desktop/IPC never enter this module.
2
- import { isContract, validateRunAccepted, validateRunEvent, validateRunSnapshot } from '@ouraihub/aether-contracts'
3
- import type { ContractMap, ContractName, KitError, RunAccepted, RunEvent } from '@ouraihub/aether-contracts'
2
+ import {
3
+ isContract,
4
+ validateRunAccepted,
5
+ validateRunEvent,
6
+ validateRunSnapshot,
7
+ } from '@ouraihub/aether-contracts'
8
+ import type {
9
+ ContractMap,
10
+ ContractName,
11
+ KitError,
12
+ RunAccepted,
13
+ RunEvent,
14
+ } from '@ouraihub/aether-contracts'
4
15
  import { KitClientError } from '../ports/contract'
5
16
  import type { CallOptions, KitPorts } from '../ports/contract'
6
17
 
@@ -44,19 +55,34 @@ const failure = (code: KitError['code'], message: string, reason?: string): KitC
44
55
  const invalidResponse = () => failure('upstream', 'Invalid server response', 'invalid_response')
45
56
  const normalize = (error: unknown, signal?: AbortSignal): KitClientError => {
46
57
  if (error instanceof KitClientError) return error
47
- return signal?.aborted ? failure('cancelled', 'Request cancelled') : failure('network', 'Unable to contact server')
58
+ return signal?.aborted
59
+ ? failure('cancelled', 'Request cancelled')
60
+ : failure('network', 'Unable to contact server')
48
61
  }
49
62
  const id = encodeURIComponent
50
63
 
51
64
  export function createWebPorts(options: WebPortsOptions): KitPorts {
52
65
  const base = new URL(options.baseURL)
53
- if (!['http:', 'https:'].includes(base.protocol) || base.username || base.password || base.search || base.hash)
66
+ if (
67
+ !['http:', 'https:'].includes(base.protocol) ||
68
+ base.username ||
69
+ base.password ||
70
+ base.search ||
71
+ base.hash
72
+ )
54
73
  throw failure('bad_request', 'Invalid API base URL')
55
74
  const api = new URL('/api/v1/', base)
56
- const request = async (path: string, method: string, body?: unknown, signal?: AbortSignal): Promise<Response> => {
75
+ const request = async (
76
+ path: string,
77
+ method: string,
78
+ body?: unknown,
79
+ signal?: AbortSignal,
80
+ ): Promise<Response> => {
57
81
  if (signal?.aborted) throw failure('cancelled', 'Request cancelled')
58
82
  try {
59
- const headers = new Headers({ Accept: path.endsWith('/events') ? 'text/event-stream' : 'application/json' })
83
+ const headers = new Headers({
84
+ Accept: path.endsWith('/events') ? 'text/event-stream' : 'application/json',
85
+ })
60
86
  if (method !== 'GET') {
61
87
  const csrf = typeof options.csrf === 'function' ? await options.csrf() : options.csrf
62
88
  headers.set('X-CSRF-Token', csrf)
@@ -79,7 +105,8 @@ export function createWebPorts(options: WebPortsOptions): KitPorts {
79
105
  throw invalidResponse()
80
106
  }
81
107
  if (isContract('KitError', value)) throw new KitClientError(value)
82
- if (record(value) && isContract('KitError', value.error)) throw new KitClientError(value.error)
108
+ if (record(value) && isContract('KitError', value.error))
109
+ throw new KitClientError(value.error)
83
110
  throw invalidResponse()
84
111
  }
85
112
  return response
@@ -127,7 +154,9 @@ export function createWebPorts(options: WebPortsOptions): KitPorts {
127
154
  if (!accepted || ended || dispatched) return
128
155
  dispatched = true
129
156
  const runId = accepted.runId
130
- void cancel(runId).catch((error: unknown) => options.onStreamError?.(runId, normalize(error)))
157
+ void cancel(runId).catch((error: unknown) =>
158
+ options.onStreamError?.(runId, normalize(error)),
159
+ )
131
160
  }
132
161
  const abort = () => {
133
162
  requested = true
@@ -176,13 +205,22 @@ export function createWebPorts(options: WebPortsOptions): KitPorts {
176
205
  try {
177
206
  if (requested || signal?.aborted) {
178
207
  dispatched = true
179
- await cancel(runId).catch((error: unknown) => options.onStreamError?.(runId, normalize(error)))
208
+ await cancel(runId).catch((error: unknown) =>
209
+ options.onStreamError?.(runId, normalize(error)),
210
+ )
180
211
  }
181
212
  const stream = await request(`runs/${id(runId)}/events`, 'GET')
182
- if (!stream.headers.get('Content-Type')?.toLowerCase().startsWith('text/event-stream') || !stream.body)
213
+ if (
214
+ !stream.headers
215
+ .get('Content-Type')
216
+ ?.toLowerCase()
217
+ .startsWith('text/event-stream') ||
218
+ !stream.body
219
+ )
183
220
  throw invalidResponse()
184
221
  await consumeEvents(stream.body, emit, () => ended)
185
- if (!ended) throw failure('network', 'Event stream disconnected', 'stream_disconnected')
222
+ if (!ended)
223
+ throw failure('network', 'Event stream disconnected', 'stream_disconnected')
186
224
  } catch (error) {
187
225
  if (!ended) {
188
226
  dispatchCancel()
@@ -193,7 +231,9 @@ export function createWebPorts(options: WebPortsOptions): KitPorts {
193
231
  kind: 'end',
194
232
  status: snapshot.status,
195
233
  ...(snapshot.error ? { error: snapshot.error } : {}),
196
- ...(snapshot.exhausted !== undefined ? { exhausted: snapshot.exhausted } : {}),
234
+ ...(snapshot.exhausted !== undefined
235
+ ? { exhausted: snapshot.exhausted }
236
+ : {}),
197
237
  })
198
238
  } catch {
199
239
  /* A missing snapshot is unknown, never a fabricated completion. */
@@ -228,7 +268,11 @@ export function createWebPorts(options: WebPortsOptions): KitPorts {
228
268
  rename: (conversationId, title) =>
229
269
  json(`${path(conversationId)}/rename`, 'POST', contract('ConversationSummary'), { title }),
230
270
  editTurn: (conversationId, turnId, text, expectedText) =>
231
- json(`${path(conversationId)}/edit-turn`, 'POST', contract('Conversation'), { turnId, text, expectedText }),
271
+ json(`${path(conversationId)}/edit-turn`, 'POST', contract('Conversation'), {
272
+ turnId,
273
+ text,
274
+ expectedText,
275
+ }),
232
276
  removeTurn: (conversationId, turnId) =>
233
277
  json(`${path(conversationId)}/remove-turn`, 'POST', contract('Conversation'), { turnId }),
234
278
  fork: (conversationId, turnId) =>
@@ -245,16 +289,20 @@ export function createWebPorts(options: WebPortsOptions): KitPorts {
245
289
  list: () => json('providers', 'GET', providers),
246
290
  save: (input) => json('providers', 'POST', providers, input),
247
291
  remove: (providerId) => json(`providers/${id(providerId)}`, 'DELETE', providers),
248
- setEnabled: (providerId, enabled) => json(`providers/${id(providerId)}/enabled`, 'POST', providers, { enabled }),
292
+ setEnabled: (providerId, enabled) =>
293
+ json(`providers/${id(providerId)}/enabled`, 'POST', providers, { enabled }),
249
294
  modelOptions: (filter = {}) => {
250
295
  const query = new URLSearchParams()
251
296
  if (filter.modelType !== undefined) query.set('modelType', filter.modelType)
252
- if (filter.supportsTools !== undefined) query.set('supportsTools', String(filter.supportsTools))
297
+ if (filter.supportsTools !== undefined)
298
+ query.set('supportsTools', String(filter.supportsTools))
253
299
  return json(`providers/model-options?${query}`, 'GET', array(contract('ModelOption')))
254
300
  },
255
- probe: (target, call) => json('providers/probe', 'POST', contract('ProbeResult'), target, call),
301
+ probe: (target, call) =>
302
+ json('providers/probe', 'POST', contract('ProbeResult'), target, call),
256
303
  saveKey: (input) => json('providers/keys', 'POST', providers, input),
257
- removeKey: (endpointId, keyId) => json(`providers/${id(endpointId)}/keys/${id(keyId)}`, 'DELETE', providers),
304
+ removeKey: (endpointId, keyId) =>
305
+ json(`providers/${id(endpointId)}/keys/${id(keyId)}`, 'DELETE', providers),
258
306
  revealKey: (keyId, currentPassword) =>
259
307
  json(`providers/keys/${id(keyId)}/reveal`, 'POST', string, { currentPassword }),
260
308
  }
@@ -268,16 +316,26 @@ export function createWebPorts(options: WebPortsOptions): KitPorts {
268
316
  save: (input, call) => json('search/settings', 'POST', settings, input, call),
269
317
  setDefault: (capability, provider, call) =>
270
318
  json('search/default', 'POST', settings, { capability, provider }, call),
271
- savePreferences: (input, call) => json('search/preferences', 'PUT', contract('SearchPreferences'), input, call),
319
+ savePreferences: (input, call) =>
320
+ json('search/preferences', 'PUT', contract('SearchPreferences'), input, call),
272
321
  saveKey: (capability, provider, value, keyId, call) =>
273
322
  json('search/keys', 'POST', settings, { capability, provider, value, keyId }, call),
274
323
  removeKey: (capability, provider, keyId, call) =>
275
324
  json('search/keys', 'DELETE', settings, { capability, provider, keyId }, call),
276
325
  reveal: (capability, provider, keyId, currentPassword, call) =>
277
- json('search/keys/reveal', 'POST', string, { capability, provider, keyId, currentPassword }, call),
278
- check: (capability, provider, call) => json('search/check', 'POST', count, { capability, provider }, call),
279
- search: (query, call) => json('search/search', 'POST', contract('SearchResult'), { query }, call),
280
- fetch: (target, call) => json('search/fetch', 'POST', contract('SearchPage'), { url: target }, call),
326
+ json(
327
+ 'search/keys/reveal',
328
+ 'POST',
329
+ string,
330
+ { capability, provider, keyId, currentPassword },
331
+ call,
332
+ ),
333
+ check: (capability, provider, call) =>
334
+ json('search/check', 'POST', count, { capability, provider }, call),
335
+ search: (query, call) =>
336
+ json('search/search', 'POST', contract('SearchResult'), { query }, call),
337
+ fetch: (target, call) =>
338
+ json('search/fetch', 'POST', contract('SearchPage'), { url: target }, call),
281
339
  }
282
340
  }
283
341
  if (options.skills) {
@@ -289,7 +347,8 @@ export function createWebPorts(options: WebPortsOptions): KitPorts {
289
347
  install: (source, confirmedDigest, replace) =>
290
348
  json('skills/install', 'POST', skills, { source, confirmedDigest, replace }),
291
349
  save: (input) => json('skills/save', 'POST', skills, input),
292
- duplicate: (skillId, newName) => json(`skills/${id(skillId)}/duplicate`, 'POST', skills, { newName }),
350
+ duplicate: (skillId, newName) =>
351
+ json(`skills/${id(skillId)}/duplicate`, 'POST', skills, { newName }),
293
352
  reorder: (ids) => json('skills/reorder', 'POST', skills, { ids }),
294
353
  remove: (skillId) => json(`skills/${id(skillId)}`, 'DELETE', skills),
295
354
  }
@@ -299,9 +358,15 @@ export function createWebPorts(options: WebPortsOptions): KitPorts {
299
358
  ports.mcpClient = {
300
359
  list: () => json('mcp/servers', 'GET', servers),
301
360
  save: (input) =>
302
- json(input.id ? `mcp/servers/${id(input.id)}` : 'mcp/servers', input.id ? 'PUT' : 'POST', servers, input),
361
+ json(
362
+ input.id ? `mcp/servers/${id(input.id)}` : 'mcp/servers',
363
+ input.id ? 'PUT' : 'POST',
364
+ servers,
365
+ input,
366
+ ),
303
367
  remove: (serverId) => json(`mcp/servers/${id(serverId)}`, 'DELETE', servers),
304
- refresh: (serverId) => json(`mcp/servers/${id(serverId)}/refresh`, 'POST', array(contract('ToolDto')), {}),
368
+ refresh: (serverId) =>
369
+ json(`mcp/servers/${id(serverId)}/refresh`, 'POST', array(contract('ToolDto')), {}),
305
370
  setToolApproval: (serverId, tool, approval) =>
306
371
  ack(`mcp/servers/${id(serverId)}/tools/${id(tool)}/approval`, 'PUT', { approval }),
307
372
  }