@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.
Files changed (212) hide show
  1. package/LICENSE +789 -0
  2. package/fixtures/model-classify.json +42 -0
  3. package/fixtures/pricing-cost.json +56 -0
  4. package/fixtures/reasoning-infer.json +44 -0
  5. package/fixtures/sse/anthropic-messages/chinese.sse +24 -0
  6. package/fixtures/sse/anthropic-messages/multi-tool.sse +33 -0
  7. package/fixtures/sse/anthropic-messages/single-tool.sse +39 -0
  8. package/fixtures/sse/anthropic-messages/text.sse +27 -0
  9. package/fixtures/sse/anthropic-messages/truncated.sse +21 -0
  10. package/fixtures/sse/anthropic-messages/upstream-error.sse +12 -0
  11. package/fixtures/sse/expect.json +20 -0
  12. package/fixtures/sse/openai-chat/chinese.sse +14 -0
  13. package/fixtures/sse/openai-chat/multi-tool.sse +18 -0
  14. package/fixtures/sse/openai-chat/single-tool.sse +22 -0
  15. package/fixtures/sse/openai-chat/text.sse +14 -0
  16. package/fixtures/sse/openai-chat/truncated.sse +12 -0
  17. package/fixtures/sse/openai-chat/upstream-error.sse +6 -0
  18. package/fixtures/sse/openai-responses/chinese.sse +33 -0
  19. package/fixtures/sse/openai-responses/multi-tool.sse +36 -0
  20. package/fixtures/sse/openai-responses/single-tool.sse +27 -0
  21. package/fixtures/sse/openai-responses/text.sse +33 -0
  22. package/fixtures/sse/openai-responses/truncated.sse +30 -0
  23. package/fixtures/sse/openai-responses/upstream-error.sse +9 -0
  24. package/package.json +71 -3
  25. package/src/CopyInput.svelte +33 -0
  26. package/src/KitNotifier.svelte +33 -0
  27. package/src/chat/ApprovalCard.svelte +29 -0
  28. package/src/chat/ChatComposer.svelte +277 -0
  29. package/src/chat/ChatMessage.svelte +262 -0
  30. package/src/chat/ChatPanel.css +386 -0
  31. package/src/chat/ChatPanel.svelte +496 -0
  32. package/src/chat/ChatPanelApprovals.svelte +28 -0
  33. package/src/chat/ChatPanelComposer.svelte +317 -0
  34. package/src/chat/ChatPanelDialogs.svelte +242 -0
  35. package/src/chat/ChatPanelHeader.svelte +132 -0
  36. package/src/chat/ChatPanelMessages.svelte +166 -0
  37. package/src/chat/ChatPanelMode.svelte +190 -0
  38. package/src/chat/ChatPanelState.svelte.ts +1 -0
  39. package/src/chat/ChatPanelToolbar.svelte +425 -0
  40. package/src/chat/ChatSurface.svelte +168 -0
  41. package/src/chat/MessageItem.svelte +480 -0
  42. package/src/chat/ReasoningControl.svelte +286 -0
  43. package/src/chat/SkillPicker.svelte +133 -0
  44. package/src/chat/ToolCallItem.svelte +23 -0
  45. package/src/chat/UsageControl.svelte +216 -0
  46. package/src/chat/UsageDetails.svelte +76 -0
  47. package/src/chat/chat-attachments.svelte.ts +74 -0
  48. package/src/chat/chat-panel-history.svelte.ts +430 -0
  49. package/src/chat/chat-panel-props.ts +32 -0
  50. package/src/chat/index.ts +6 -0
  51. package/src/chat/run-session-history.ts +56 -0
  52. package/src/chat/run-session-types.ts +69 -0
  53. package/src/chat/run-session.svelte.ts +494 -0
  54. package/src/chat/test-support/chat-fixture.ts +178 -0
  55. package/src/chat/test-support/conversation-fixtures.ts +32 -0
  56. package/src/chat/test-support/run-session-fixture.ts +112 -0
  57. package/src/components/ui/alert/alert-action.svelte +20 -0
  58. package/src/components/ui/alert/alert-description.svelte +23 -0
  59. package/src/components/ui/alert/alert-title.svelte +23 -0
  60. package/src/components/ui/alert/alert.svelte +43 -0
  61. package/src/components/ui/alert/index.ts +17 -0
  62. package/src/components/ui/alert-dialog/alert-dialog-action.svelte +27 -0
  63. package/src/components/ui/alert-dialog/alert-dialog-cancel.svelte +27 -0
  64. package/src/components/ui/alert-dialog/alert-dialog-content.svelte +32 -0
  65. package/src/components/ui/alert-dialog/alert-dialog-description.svelte +17 -0
  66. package/src/components/ui/alert-dialog/alert-dialog-footer.svelte +23 -0
  67. package/src/components/ui/alert-dialog/alert-dialog-header.svelte +20 -0
  68. package/src/components/ui/alert-dialog/alert-dialog-media.svelte +20 -0
  69. package/src/components/ui/alert-dialog/alert-dialog-overlay.svelte +17 -0
  70. package/src/components/ui/alert-dialog/alert-dialog-portal.svelte +7 -0
  71. package/src/components/ui/alert-dialog/alert-dialog-title.svelte +17 -0
  72. package/src/components/ui/alert-dialog/alert-dialog-trigger.svelte +7 -0
  73. package/src/components/ui/alert-dialog/alert-dialog.svelte +7 -0
  74. package/src/components/ui/alert-dialog/index.ts +40 -0
  75. package/src/components/ui/button/button.svelte +81 -0
  76. package/src/components/ui/button/index.ts +17 -0
  77. package/src/components/ui/dialog/dialog-close.svelte +11 -0
  78. package/src/components/ui/dialog/dialog-content.svelte +48 -0
  79. package/src/components/ui/dialog/dialog-description.svelte +17 -0
  80. package/src/components/ui/dialog/dialog-footer.svelte +32 -0
  81. package/src/components/ui/dialog/dialog-header.svelte +20 -0
  82. package/src/components/ui/dialog/dialog-overlay.svelte +17 -0
  83. package/src/components/ui/dialog/dialog-portal.svelte +7 -0
  84. package/src/components/ui/dialog/dialog-title.svelte +17 -0
  85. package/src/components/ui/dialog/dialog-trigger.svelte +11 -0
  86. package/src/components/ui/dialog/dialog.svelte +7 -0
  87. package/src/components/ui/dialog/index.ts +34 -0
  88. package/src/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
  89. package/src/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +46 -0
  90. package/src/components/ui/dropdown-menu/dropdown-menu-content.svelte +31 -0
  91. package/src/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
  92. package/src/components/ui/dropdown-menu/dropdown-menu-group.svelte +7 -0
  93. package/src/components/ui/dropdown-menu/dropdown-menu-item.svelte +27 -0
  94. package/src/components/ui/dropdown-menu/dropdown-menu-label.svelte +24 -0
  95. package/src/components/ui/dropdown-menu/dropdown-menu-portal.svelte +7 -0
  96. package/src/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +17 -0
  97. package/src/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +36 -0
  98. package/src/components/ui/dropdown-menu/dropdown-menu-separator.svelte +17 -0
  99. package/src/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +20 -0
  100. package/src/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +31 -0
  101. package/src/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
  102. package/src/components/ui/dropdown-menu/dropdown-menu-sub.svelte +7 -0
  103. package/src/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
  104. package/src/components/ui/dropdown-menu/dropdown-menu.svelte +7 -0
  105. package/src/components/ui/dropdown-menu/index.ts +54 -0
  106. package/src/components/ui/empty/empty-content.svelte +23 -0
  107. package/src/components/ui/empty/empty-description.svelte +23 -0
  108. package/src/components/ui/empty/empty-header.svelte +20 -0
  109. package/src/components/ui/empty/empty-media.svelte +41 -0
  110. package/src/components/ui/empty/empty-title.svelte +20 -0
  111. package/src/components/ui/empty/empty.svelte +23 -0
  112. package/src/components/ui/empty/index.ts +22 -0
  113. package/src/components/ui/field/field-content.svelte +20 -0
  114. package/src/components/ui/field/field-description.svelte +25 -0
  115. package/src/components/ui/field/field-error.svelte +58 -0
  116. package/src/components/ui/field/field-group.svelte +23 -0
  117. package/src/components/ui/field/field-label.svelte +25 -0
  118. package/src/components/ui/field/field-legend.svelte +24 -0
  119. package/src/components/ui/field/field-separator.svelte +35 -0
  120. package/src/components/ui/field/field-set.svelte +20 -0
  121. package/src/components/ui/field/field-title.svelte +20 -0
  122. package/src/components/ui/field/field.svelte +47 -0
  123. package/src/components/ui/field/index.ts +33 -0
  124. package/src/components/ui/input/index.ts +7 -0
  125. package/src/components/ui/input/input.svelte +48 -0
  126. package/src/components/ui/label/index.ts +7 -0
  127. package/src/components/ui/label/label.svelte +20 -0
  128. package/src/components/ui/select/index.ts +40 -0
  129. package/src/components/ui/select/select-content.svelte +45 -0
  130. package/src/components/ui/select/select-group-heading.svelte +21 -0
  131. package/src/components/ui/select/select-group.svelte +17 -0
  132. package/src/components/ui/select/select-item.svelte +43 -0
  133. package/src/components/ui/select/select-label.svelte +20 -0
  134. package/src/components/ui/select/select-portal.svelte +7 -0
  135. package/src/components/ui/select/select-scroll-down-button.svelte +20 -0
  136. package/src/components/ui/select/select-scroll-up-button.svelte +20 -0
  137. package/src/components/ui/select/select-separator.svelte +18 -0
  138. package/src/components/ui/select/select-trigger.svelte +29 -0
  139. package/src/components/ui/select/select-value.svelte +7 -0
  140. package/src/components/ui/select/select.svelte +11 -0
  141. package/src/components/ui/separator/index.ts +7 -0
  142. package/src/components/ui/separator/separator.svelte +21 -0
  143. package/src/components/ui/sonner/index.ts +1 -0
  144. package/src/components/ui/sonner/sonner.svelte +40 -0
  145. package/src/components/ui/switch/index.ts +7 -0
  146. package/src/components/ui/switch/switch.svelte +34 -0
  147. package/src/components/ui/textarea/index.ts +7 -0
  148. package/src/components/ui/textarea/textarea.svelte +22 -0
  149. package/src/context.ts +34 -0
  150. package/src/dev/Demo.svelte +47 -0
  151. package/src/dev/main.ts +7 -0
  152. package/src/i18n/en.ts +645 -0
  153. package/src/i18n/index.ts +28 -0
  154. package/src/i18n/zh-CN.ts +610 -0
  155. package/src/index.ts +10 -0
  156. package/src/logs/LogPanel.svelte +103 -0
  157. package/src/logs/LogSettings.svelte +58 -0
  158. package/src/logs/index.ts +5 -0
  159. package/src/logs/logger.ts +96 -0
  160. package/src/markdown.ts +8 -0
  161. package/src/mcp/McpClientEditor.svelte +204 -0
  162. package/src/mcp/McpClientSettings.svelte +418 -0
  163. package/src/mcp/McpServerSettings.svelte +363 -0
  164. package/src/mcp/config.ts +26 -0
  165. package/src/mcp/index.ts +3 -0
  166. package/src/mcp/input.ts +74 -0
  167. package/src/notify.svelte.ts +43 -0
  168. package/src/ports/contract.ts +174 -0
  169. package/src/ports/fake-optional.ts +81 -0
  170. package/src/ports/fake.ts +488 -0
  171. package/src/ports/index.ts +7 -0
  172. package/src/ports/search.ts +56 -0
  173. package/src/ports/skill-sources.ts +45 -0
  174. package/src/ports/test-support/fake-fixture.ts +63 -0
  175. package/src/providers/EndpointKeysDialog.svelte +357 -0
  176. package/src/providers/EndpointModels.svelte +311 -0
  177. package/src/providers/EndpointPanel.svelte +266 -0
  178. package/src/providers/ModelPickerDialog.svelte +230 -0
  179. package/src/providers/ModelPricing.svelte +125 -0
  180. package/src/providers/ModelSelect.svelte +448 -0
  181. package/src/providers/ModelSettingsDialog.svelte +388 -0
  182. package/src/providers/ProviderDialogs.svelte +120 -0
  183. package/src/providers/ProviderList.svelte +159 -0
  184. package/src/providers/ProvidersSettings.svelte +491 -0
  185. package/src/providers/RequestConfigDialog.svelte +278 -0
  186. package/src/providers/SecretInput.svelte +284 -0
  187. package/src/providers/draft.ts +355 -0
  188. package/src/providers/edit-session.ts +170 -0
  189. package/src/providers/index.ts +5 -0
  190. package/src/providers/reasoning.ts +55 -0
  191. package/src/providers/revision.svelte.ts +6 -0
  192. package/src/providers/test-support/providers-fixture.ts +120 -0
  193. package/src/search/SearchAdvancedTools.svelte +182 -0
  194. package/src/search/SearchProviderCard.svelte +195 -0
  195. package/src/search/SearchSettings.svelte +500 -0
  196. package/src/search/index.ts +13 -0
  197. package/src/search/settings-flow.ts +67 -0
  198. package/src/session.ts +20 -0
  199. package/src/skills/SkillAdd.svelte +380 -0
  200. package/src/skills/SkillAuthoring.svelte +430 -0
  201. package/src/skills/SkillEditor.svelte +104 -0
  202. package/src/skills/SkillPreviewDialog.svelte +136 -0
  203. package/src/skills/SkillsSettings.svelte +147 -0
  204. package/src/skills/error.ts +32 -0
  205. package/src/skills/index.ts +4 -0
  206. package/src/skills/test-support/skills-fixture.ts +139 -0
  207. package/src/styles/kit.css +137 -0
  208. package/src/styles/tokens.css +22 -0
  209. package/src/tauri/index.ts +298 -0
  210. package/src/utils.ts +22 -0
  211. package/src/web/index.ts +441 -0
  212. package/README.md +0 -3
@@ -0,0 +1,298 @@
1
+ // The only directory allowed to import @tauri-apps/* (ESLint enforces): createTauriPorts() (docs/16 §2).
2
+ // Argument names are the camelCase of the Rust command parameters (docs/15 §5).
3
+ import { Channel, invoke } from '@tauri-apps/api/core'
4
+ import { KitClientError } from '../ports'
5
+ import type {
6
+ DesktopActions,
7
+ KitError,
8
+ KitPorts,
9
+ LogsPort,
10
+ PreparedSkill,
11
+ RunAccepted,
12
+ RunEvent,
13
+ SearchPort,
14
+ } from '../ports'
15
+
16
+ /** Which feature ports the host enabled; the rest stay absent so their UI areas are hidden. */
17
+ export interface TauriPortsOptions {
18
+ providers?: boolean
19
+ search?: boolean
20
+ chat?: boolean
21
+ /** Independent conversation storage capability (`aether:chat-history`). */
22
+ conversations?: boolean
23
+ skills?: boolean
24
+ /** Read-only discovery/pickers; generation additionally requires chat and providers. */
25
+ skillSources?: boolean
26
+ mcpClient?: boolean
27
+ mcpServer?: boolean
28
+ }
29
+
30
+ const CANCELLED: KitError = { code: 'cancelled', message: 'cancelled' }
31
+
32
+ /** Invokes `plugin:aether|<command>` and turns any rejection into a KitClientError at the boundary. */
33
+ async function call<T>(command: string, args: Record<string, unknown> = {}): Promise<T> {
34
+ try {
35
+ return await invoke<T>(`plugin:aether|${command}`, args)
36
+ } catch (error) {
37
+ const isKitError =
38
+ typeof error === 'object' &&
39
+ error !== null &&
40
+ typeof (error as Partial<KitError>).code === 'string' &&
41
+ typeof (error as Partial<KitError>).message === 'string'
42
+ throw new KitClientError(
43
+ isKitError ? (error as KitError) : { code: 'internal', message: String(error) },
44
+ )
45
+ }
46
+ }
47
+
48
+ /** The plugin always registers the log commands, so desktop hosts always get `logs`. */
49
+ export function createTauriPorts(
50
+ options: TauriPortsOptions = {},
51
+ ): KitPorts & { logs: LogsPort; desktop: DesktopActions } {
52
+ const ports: KitPorts & { logs: LogsPort; desktop: DesktopActions } = {
53
+ logs: {
54
+ tail: (limit) => call('logs_tail', { limit }),
55
+ ingest: (batch) => call('logs_ingest', { batch }),
56
+ getLevel: () => call('logs_get_level'),
57
+ setLevel: (level) => call('logs_set_level', { level }),
58
+ },
59
+ desktop: { openLogsDirectory: () => call('logs_open_dir') },
60
+ }
61
+ if (options.providers) {
62
+ ports.providers = {
63
+ list: () => call('providers_list'),
64
+ setEnabled: (id, enabled) => call('providers_set_enabled', { id, enabled }),
65
+ save: (input) => call('providers_save', { input }),
66
+ remove: (id) => call('providers_delete', { id }),
67
+ modelOptions: (filter = {}) => call('providers_model_options', { filter }),
68
+ // Aborting calls providers_cancel; the pending probe then rejects with `cancelled`.
69
+ probe: async (target, callOptions) => {
70
+ const signal = callOptions?.signal
71
+ if (signal?.aborted) throw new KitClientError(CANCELLED)
72
+ const jobId = crypto.randomUUID()
73
+ const cancel = () => void call('providers_cancel', { jobId }).catch(() => undefined)
74
+ signal?.addEventListener('abort', cancel, { once: true })
75
+ try {
76
+ return await call('providers_probe', { jobId, target })
77
+ } finally {
78
+ signal?.removeEventListener('abort', cancel)
79
+ }
80
+ },
81
+ revealNeedsPassword: false,
82
+ keyStrategies: false,
83
+ saveKey: (input) => call('providers_key_save', { input }),
84
+ removeKey: (endpointId, keyId) => call('providers_key_delete', { endpointId, keyId }),
85
+ revealKey: (keyId) => call('providers_key_reveal', { keyId }),
86
+ }
87
+ }
88
+ if (options.search) {
89
+ const searchCall = async <T>(
90
+ command: string,
91
+ args: Record<string, unknown> = {},
92
+ callOptions?: { signal?: AbortSignal },
93
+ ): Promise<T> => {
94
+ const signal = callOptions?.signal
95
+ if (signal?.aborted) throw new KitClientError(CANCELLED)
96
+ const jobId = crypto.randomUUID()
97
+ const cancel = () => void call('search_cancel', { jobId }).catch(() => undefined)
98
+ signal?.addEventListener('abort', cancel, { once: true })
99
+ try {
100
+ return await call<T>(command, { ...args, jobId })
101
+ } finally {
102
+ signal?.removeEventListener('abort', cancel)
103
+ }
104
+ }
105
+ const search: SearchPort = {
106
+ settings: (capability, o) => searchCall('search_settings', { capability }, o),
107
+ save: (input, o) => searchCall('search_save', { input }, o),
108
+ setDefault: (capability, provider, o) =>
109
+ searchCall('search_set_default', { capability, provider }, o),
110
+ savePreferences: (input, o) => searchCall('search_save_preferences', { input }, o),
111
+ saveKey: (capability, provider, value, keyId, o) =>
112
+ searchCall('search_save_key', { capability, provider, value, keyId: keyId ?? null }, o),
113
+ removeKey: (capability, provider, keyId, o) =>
114
+ searchCall('search_remove_key', { capability, provider, keyId }, o),
115
+ reveal: (capability, provider, keyId, currentPassword, o) =>
116
+ searchCall(
117
+ 'search_reveal',
118
+ { capability, provider, keyId, currentPassword: currentPassword ?? null },
119
+ o,
120
+ ),
121
+ check: (capability, provider, o) => searchCall('search_check', { capability, provider }, o),
122
+ search: (query, o) => searchCall('search_query', { query }, o),
123
+ fetch: (url, o) => searchCall('search_fetch', { url }, o),
124
+ }
125
+ ports.search = search
126
+ }
127
+ if (options.chat) {
128
+ ports.chat = {
129
+ start: async (request, onEvent, callOptions) => {
130
+ const signal = callOptions?.signal
131
+ if (signal?.aborted) throw new KitClientError(CANCELLED)
132
+ let accepted: RunAccepted | null = null
133
+ let ended = false
134
+ let requested = false
135
+ let dispatched = false
136
+ const cleanup = () => signal?.removeEventListener('abort', cancel)
137
+ const dispatchCancel = () => {
138
+ if (!accepted || ended || dispatched) return
139
+ dispatched = true
140
+ void call('chat_cancel', { runId: accepted.runId }).catch(() => undefined)
141
+ }
142
+ const cancel = () => {
143
+ requested = true
144
+ dispatchCancel()
145
+ }
146
+ signal?.addEventListener('abort', cancel, { once: true })
147
+ const channel = new Channel<RunEvent>((event) => {
148
+ if (ended) return
149
+ if (event.kind === 'end') {
150
+ ended = true
151
+ cleanup()
152
+ }
153
+ onEvent(event)
154
+ })
155
+ try {
156
+ accepted = await call<RunAccepted>('chat_run', { request, onEvent: channel })
157
+ if (requested || signal?.aborted) dispatchCancel()
158
+ return accepted
159
+ } catch (error) {
160
+ ended = true
161
+ cleanup()
162
+ throw error
163
+ }
164
+ },
165
+ cancel: (runId) => call('chat_cancel', { runId }),
166
+ getSnapshot: (runId) => call('chat_snapshot', { runId }),
167
+ approve: async (runId, callId, allow) => {
168
+ await call('chat_approve', { runId, callId, allow })
169
+ },
170
+ }
171
+ }
172
+ if (options.conversations) {
173
+ ports.conversations = {
174
+ list: (scope) => call('chat_conversations', { scope: scope ?? null }),
175
+ get: (id) => call('chat_conversation', { id }),
176
+ remove: async (id) => {
177
+ await call('chat_delete', { id })
178
+ },
179
+ rename: (id, title) => call('chat_rename', { id, title }),
180
+ editTurn: (conversationId, turnId, text, expectedText) =>
181
+ call('chat_edit_turn', { conversationId, turnId, text, expectedText }),
182
+ removeTurn: (conversationId, turnId) => call('chat_remove_turn', { conversationId, turnId }),
183
+ fork: (conversationId, turnId) => call('chat_fork', { conversationId, turnId }),
184
+ selectTurn: (conversationId, turnId) => call('chat_select_turn', { conversationId, turnId }),
185
+ }
186
+ }
187
+ if (options.skills) {
188
+ ports.skills = {
189
+ list: () => call('skills_list'),
190
+ get: (id) => call('skills_get', { id }),
191
+ save: (input) => call('skills_save', { input }),
192
+ preview: (source) => call('skills_preview', { source }),
193
+ install: (source, confirmedDigest, replace) =>
194
+ call('skills_install', { source, confirmedDigest, replace }),
195
+ duplicate: (id, newName) => call('skills_duplicate', { id, newName }),
196
+ reorder: (ids) => call('skills_reorder', { ids }),
197
+ remove: (id) => call('skills_delete', { id }),
198
+ }
199
+ }
200
+ if (options.skillSources) {
201
+ const sourceCall = async <T>(
202
+ command: string,
203
+ args: Record<string, unknown>,
204
+ o?: { signal?: AbortSignal },
205
+ ): Promise<T> => {
206
+ if (o?.signal?.aborted) throw new KitClientError(CANCELLED)
207
+ const result = await call<T>(command, args)
208
+ if (o?.signal?.aborted) throw new KitClientError(CANCELLED)
209
+ return result
210
+ }
211
+ ports.skillSources = {
212
+ search: (query, o) => sourceCall('skills_source_search', { query }, o),
213
+ prepare: (url, o) => sourceCall('skills_source_prepare', { url }, o),
214
+ discover: (o) => sourceCall('skills_system_discover', {}, o),
215
+ prepareSystem: (path, o) => sourceCall('skills_system_prepare', { path }, o),
216
+ pickDirectory: (o) => sourceCall('skills_pick_directory', {}, o),
217
+ pickSearchDirectory: (o) => sourceCall('skills_pick_search_directory', {}, o),
218
+ }
219
+ if (options.chat && options.providers) {
220
+ ports.skillSources.authoring = {
221
+ create: (o) => sourceCall<string>('skills_authoring_create', {}, o),
222
+ send: async (sessionId, input, model, onEvent, o) => {
223
+ const signal = o?.signal
224
+ if (signal?.aborted) throw new KitClientError(CANCELLED)
225
+ let accepted: RunAccepted | null = null
226
+ let ended = false
227
+ const cancel = () => {
228
+ if (accepted && !ended)
229
+ void call('skills_authoring_cancel', { sessionId, runId: accepted.runId }).catch(
230
+ () => undefined,
231
+ )
232
+ }
233
+ signal?.addEventListener('abort', cancel, { once: true })
234
+ const channel = new Channel<RunEvent>((event) => {
235
+ if (ended) return
236
+ if (event.kind === 'end') {
237
+ ended = true
238
+ signal?.removeEventListener('abort', cancel)
239
+ }
240
+ onEvent(event)
241
+ })
242
+ try {
243
+ accepted = await call<RunAccepted>('skills_authoring_send', {
244
+ sessionId,
245
+ input,
246
+ model,
247
+ onEvent: channel,
248
+ })
249
+ if (signal?.aborted) cancel()
250
+ return accepted
251
+ } catch (error) {
252
+ ended = true
253
+ signal?.removeEventListener('abort', cancel)
254
+ throw error
255
+ }
256
+ },
257
+ approve: async (sessionId, runId, callId, allow) => {
258
+ await call('skills_authoring_approve', { sessionId, runId, callId, allow })
259
+ },
260
+ cancel: async (sessionId, runId) => {
261
+ await call('skills_authoring_cancel', { sessionId, runId })
262
+ },
263
+ prepare: (sessionId, o) =>
264
+ sourceCall<PreparedSkill>('skills_authoring_prepare', { sessionId }, o),
265
+ close: async (sessionId) => {
266
+ await call('skills_authoring_close', { sessionId })
267
+ },
268
+ }
269
+ }
270
+ }
271
+ if (options.mcpClient) {
272
+ ports.mcpClient = {
273
+ list: () => call('mcp_client_list'),
274
+ save: (input) => call('mcp_client_save', { input }),
275
+ remove: (id) => call('mcp_client_delete', { id }),
276
+ refresh: (serverId) => call('mcp_client_refresh', { serverId }),
277
+ setToolApproval: async (serverId, tool, approval) => {
278
+ await call('mcp_client_set_tool_approval', { serverId, tool, approval })
279
+ },
280
+ }
281
+ }
282
+ if (options.mcpServer) {
283
+ ports.mcpServer = {
284
+ status: () => call('mcp_server_status'),
285
+ tokens: () => call('mcp_server_tokens'),
286
+ start: () => call('mcp_server_start'),
287
+ stop: () => call('mcp_server_stop'),
288
+ setPort: (port) => call('mcp_server_set_port', { port }),
289
+ issueToken: (name, scopes) => call('mcp_server_issue_token', { name, scopes }),
290
+ revokeToken: async (id) => {
291
+ await call('mcp_server_revoke_token', { id })
292
+ },
293
+ scopes: () => call('mcp_server_scopes'),
294
+ setScopes: (ids) => call('mcp_server_set_scopes', { ids }),
295
+ }
296
+ }
297
+ return ports
298
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { createCn } from 'cn/config'
2
+ import { createTV } from 'tailwind-variants'
3
+ export type { VariantProps } from 'tailwind-variants'
4
+
5
+ const twMergeConfig = {
6
+ extend: {
7
+ theme: {
8
+ text: ['kit-xs', 'kit-sm', 'kit-base', 'kit-lg'],
9
+ spacing: ['kit-control', 'kit-control-sm'],
10
+ radius: ['kit', 'kit-sm'],
11
+ },
12
+ },
13
+ }
14
+ export const cn = createCn(twMergeConfig)
15
+ export const tv = createTV({ twMergeConfig })
16
+
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ export type WithoutChild<T> = T extends { child?: any } ? Omit<T, 'child'> : T
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
+ export type WithoutChildren<T> = T extends { children?: any } ? Omit<T, 'children'> : T
21
+ export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>
22
+ export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?: U | null }