@kitn.ai/ui 0.21.0 → 0.22.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/dist/components/chat-thread.d.ts +9 -0
- package/dist/{create-tween-D3Y5qiij.js → create-tween-COnPwAQN.js} +1 -1
- package/dist/{create-tween-DGKY1FDY.js → create-tween-DmTUaXWE.js} +1 -1
- package/dist/{create-tween-paho5Rh-.js → create-tween-qs-jjvNA.js} +1 -1
- package/dist/custom-elements.json +43 -7
- package/dist/elements/agent-card.js +1 -1
- package/dist/elements/artifact.js +1 -1
- package/dist/elements/attachments.js +1 -1
- package/dist/elements/audio-visualizer.js +1 -1
- package/dist/elements/avatar.js +1 -1
- package/dist/elements/badge.js +1 -1
- package/dist/elements/button.js +1 -1
- package/dist/elements/card.js +1 -1
- package/dist/elements/cards.js +1 -1
- package/dist/elements/chain-of-thought.js +1 -1
- package/dist/elements/chat-scope-picker.js +1 -1
- package/dist/elements/chat-workspace.js +1 -1
- package/dist/elements/chat.js +1 -1
- package/dist/elements/checkpoint.js +1 -1
- package/dist/elements/choice.js +1 -1
- package/dist/elements/chunks/{Icon-C-2LvGDG.js → Icon-CHG5z5L7.js} +1 -1
- package/dist/elements/chunks/{action-icons-CaYoImEk.js → action-icons-BAtCEEgg.js} +1 -1
- package/dist/elements/chunks/arrow-left-CFPTeL1Y.js +1 -0
- package/dist/elements/chunks/{artifact-BBIscOxJ.js → artifact-fBZOE4SO.js} +1 -1
- package/dist/elements/chunks/{attachments-BB56zoji.js → attachments-DpYMe5VQ.js} +1 -1
- package/dist/elements/chunks/{audio-visualizer-BxOx4THz.js → audio-visualizer-DFwzAcuL.js} +1 -1
- package/dist/elements/chunks/{badge-SxLSZ19R.js → badge-D6zodm6E.js} +1 -1
- package/dist/elements/chunks/{button-CmkUkz6c.js → button-C42vrGvO.js} +1 -1
- package/dist/elements/chunks/{card-renderer-Db4ffkWv.js → card-renderer-DMZsSuvU.js} +1 -1
- package/dist/elements/chunks/{chat-thread-B3Ks-cKr.js → chat-thread-CNNEhol-.js} +1 -1
- package/dist/elements/chunks/check-7Q3K-iXE.js +1 -0
- package/dist/elements/chunks/chevron-down-CpNYLn7E.js +1 -0
- package/dist/elements/chunks/chevron-right-DrH85Fha.js +1 -0
- package/dist/elements/chunks/{choice-card-Q9cYYDyM.js → choice-card-YoWjpsFV.js} +1 -1
- package/dist/elements/chunks/circle-C9KRjKYv.js +1 -0
- package/dist/elements/chunks/circle-check-Dmi7Y4zw.js +1 -0
- package/dist/elements/chunks/{circle-x-D0MEfxOM.js → circle-x-QIxXda6k.js} +1 -1
- package/dist/elements/chunks/{code-block-C8VzAraE.js → code-block-CqeugReY.js} +1 -1
- package/dist/elements/chunks/{collapsible-Cvj61obE.js → collapsible-sTv-_5lF.js} +1 -1
- package/dist/elements/chunks/{composer-D86ztyL0.js → composer-ldQyeVEB.js} +1 -1
- package/dist/elements/chunks/{confirm-card-BdyDAGLw.js → confirm-card-C0RNOwfn.js} +1 -1
- package/dist/elements/chunks/context-5qgypNHC.js +1 -0
- package/dist/elements/chunks/conversation-list-DLzOacXz.js +1 -0
- package/dist/elements/chunks/{create-tween-C_A_B638.js → create-tween-V4TXZ93X.js} +1 -1
- package/dist/elements/chunks/default-input-DeeRSDHc.js +1 -0
- package/dist/elements/chunks/{define-BzPnNsXg.js → define-lE-QvQFn.js} +1 -1
- package/dist/elements/chunks/{disclosure-DVKsoc1F.js → disclosure-DZSa9jog.js} +1 -1
- package/dist/elements/chunks/{download-BjA54IMJ.js → download-B2ZmnGqW.js} +1 -1
- package/dist/elements/chunks/{dropdown-BjVVHWXH.js → dropdown-R3B7cSRE.js} +1 -1
- package/dist/elements/chunks/{ellipsis-BNedmqfi.js → ellipsis-BmxceY4l.js} +1 -1
- package/dist/elements/chunks/{embed-DQsl4XEq.js → embed-BVrtTZPo.js} +1 -1
- package/dist/elements/chunks/{external-link-Di-dw2CU.js → external-link-BbdR7YO7.js} +1 -1
- package/dist/elements/chunks/{file-text-B3sAODCV.js → file-text-D7dijo1A.js} +1 -1
- package/dist/elements/chunks/{file-tree-Dgto-bMn.js → file-tree-0upJ5jeb.js} +1 -1
- package/dist/elements/chunks/{folder-D6rMadFV.js → folder-D8z58t7B.js} +1 -1
- package/dist/elements/chunks/{form-CILxvhQ7.js → form-p5BKJNw5.js} +1 -1
- package/dist/elements/chunks/{hover-card-BtiF4XiU.js → hover-card-CN9s2md5.js} +1 -1
- package/dist/elements/chunks/{icon-DKkmze3y.js → icon-CNiKP37E.js} +1 -1
- package/dist/elements/chunks/{info-CWRjZkuy.js → info-BSnuJiHI.js} +1 -1
- package/dist/elements/chunks/{input--QJBK6BA.js → input-BauDmzxX.js} +1 -1
- package/dist/elements/chunks/{kbd-C3zuKh8R.js → kbd-BlHJaP9b.js} +1 -1
- package/dist/elements/chunks/{link-BL5JA7Q0.js → link-DEi5iUWC.js} +1 -1
- package/dist/elements/chunks/{link-preview-CU37bbXh.js → link-preview-BaHyM6W4.js} +1 -1
- package/dist/elements/chunks/{loader-XmpyxyRH.js → loader-CmJG_Fkq.js} +1 -1
- package/dist/elements/chunks/{markdown-3Gv5UZ_o.js → markdown-D2jaMpCN.js} +1 -1
- package/dist/elements/chunks/{message-X5NZbq-W.js → message-C5UfXZ2Z.js} +1 -1
- package/dist/elements/chunks/{message-CnBA2OUt.js → message-CXWLmmLn.js} +1 -1
- package/dist/elements/chunks/message-square-hXylwsy0.js +1 -0
- package/dist/elements/chunks/{minimize-2-DwyrUTcM.js → minimize-2-C9ytZFMU.js} +1 -1
- package/dist/elements/chunks/model-switcher-CivGfD7-.js +1 -0
- package/dist/elements/chunks/{overlay-Cepd-KcS.js → overlay-DJL_sbOm.js} +1 -1
- package/dist/elements/chunks/{paperclip-CdwKjrlu.js → paperclip-CFaB8naM.js} +1 -1
- package/dist/elements/chunks/{progress-bar-DMVXBD3b.js → progress-bar-Br5SksfR.js} +1 -1
- package/dist/elements/chunks/{prompt-suggestion-Di_WZE_5.js → prompt-suggestion-CMIvtAhU.js} +1 -1
- package/dist/elements/chunks/{reasoning-D0jMch5u.js → reasoning-DpZcNzLq.js} +1 -1
- package/dist/elements/chunks/{resizable-1znbL1Gv.js → resizable-Q8i3T9a_.js} +1 -1
- package/dist/elements/chunks/{rotate-cw-DVhhgx8n.js → rotate-cw-B5IHCBFV.js} +1 -1
- package/dist/elements/chunks/{scroll-area-Bs4bFS1P.js → scroll-area-eLeydBje.js} +1 -1
- package/dist/elements/chunks/{scroll-button-Bet5NLc4.js → scroll-button-DWbz0yA1.js} +1 -1
- package/dist/elements/chunks/{separator-C5Gh8qGC.js → separator-Xic78AD_.js} +1 -1
- package/dist/elements/chunks/{settings-5vmEFg0K.js → settings-B8H51pAx.js} +1 -1
- package/dist/elements/chunks/{settings-group-BWLB38kz.js → settings-group-CsG9eYLe.js} +1 -1
- package/dist/elements/chunks/{share-BZ3G_DaB.js → share-CNTx0z__.js} +1 -1
- package/dist/elements/chunks/{skeleton-DafPJQTp.js → skeleton-CLlHTcMI.js} +1 -1
- package/dist/elements/chunks/{source-D_qj_6uJ.js → source-BoVcU5ok.js} +1 -1
- package/dist/elements/chunks/{star-Cuv7j2IE.js → star-CxQVTVhI.js} +1 -1
- package/dist/elements/chunks/{store-C1StPHfW.js → store-CLtS5CUG.js} +1 -1
- package/dist/elements/chunks/{tasks-card-EyoBZfpA.js → tasks-card-CzlkLmUt.js} +1 -1
- package/dist/elements/chunks/{text-shimmer-D9gRSh34.js → text-shimmer-D5NhpIQ1.js} +1 -1
- package/dist/elements/chunks/{textarea-DuhtHfcm.js → textarea-x5Uxsmtm.js} +1 -1
- package/dist/elements/chunks/{thumbs-up-B9hwv43w.js → thumbs-up-UobcJnx9.js} +1 -1
- package/dist/elements/chunks/{toast-store-Bm3DUEDe.js → toast-store-BOfs9eXq.js} +1 -1
- package/dist/elements/chunks/{tool-CDtW7L0z.js → tool-Be6Dh_dt.js} +1 -1
- package/dist/elements/chunks/{tooltip-eB226mGK.js → tooltip-RxMxyCLF.js} +1 -1
- package/dist/elements/chunks/{triangle-alert-C1SNzTqK.js → triangle-alert-C4yxH2XN.js} +1 -1
- package/dist/elements/chunks/{use-card-resolution-YZh2MvI5.js → use-card-resolution-jva9ehH6.js} +1 -1
- package/dist/elements/chunks/{variant-aurora-Cj1F7D0l.js → variant-aurora-Dx4VRcjS.js} +1 -1
- package/dist/elements/chunks/{variant-custom-T9gpt7QE.js → variant-custom-Y1ZTWgEa.js} +1 -1
- package/dist/elements/chunks/{variant-wave-CxU9z-TE.js → variant-wave-B9gml9Cg.js} +1 -1
- package/dist/elements/chunks/{video-CK4R7Rus.js → video-CrPHsytT.js} +1 -1
- package/dist/elements/chunks/x-_-OPHept.js +1 -0
- package/dist/elements/coachmark.js +1 -1
- package/dist/elements/code-block.js +1 -1
- package/dist/elements/command.js +1 -1
- package/dist/elements/compare.js +1 -1
- package/dist/elements/composer.js +1 -1
- package/dist/elements/confirm-card.js +1 -1
- package/dist/elements/context-meter.js +1 -1
- package/dist/elements/conversation-list.js +1 -1
- package/dist/elements/default-input.d.ts +27 -0
- package/dist/elements/dialog.js +1 -1
- package/dist/elements/editable-label.js +1 -1
- package/dist/elements/embed.js +1 -1
- package/dist/elements/empty.js +1 -1
- package/dist/elements/feedback-bar.js +1 -1
- package/dist/elements/file-tree.js +1 -1
- package/dist/elements/file-upload.js +1 -1
- package/dist/elements/form.js +1 -1
- package/dist/elements/hover-card.js +1 -1
- package/dist/elements/icon.js +1 -1
- package/dist/elements/image.js +1 -1
- package/dist/elements/input.js +1 -1
- package/dist/elements/kbd.js +1 -1
- package/dist/elements/link-preview.js +1 -1
- package/dist/elements/loader.js +1 -1
- package/dist/elements/markdown.js +1 -1
- package/dist/elements/menu.js +1 -1
- package/dist/elements/message-skills.js +1 -1
- package/dist/elements/message.js +1 -1
- package/dist/elements/model-switcher.js +1 -1
- package/dist/elements/nav.js +1 -1
- package/dist/elements/notice.js +1 -1
- package/dist/elements/pane-group.js +1 -1
- package/dist/elements/pane.js +1 -1
- package/dist/elements/popover.js +1 -1
- package/dist/elements/progress-bar.js +1 -1
- package/dist/elements/prompt-dock.js +1 -1
- package/dist/elements/prompt-input.js +1 -1
- package/dist/elements/prompt-suggestions.js +1 -1
- package/dist/elements/reasoning.js +1 -1
- package/dist/elements/remote.js +1 -1
- package/dist/elements/resizable.js +1 -1
- package/dist/elements/response-stream.js +2 -2
- package/dist/elements/screen.js +1 -1
- package/dist/elements/scroll-area.js +1 -1
- package/dist/elements/scroll-button.js +1 -1
- package/dist/elements/search.js +1 -1
- package/dist/elements/segmented.js +1 -1
- package/dist/elements/separator.js +1 -1
- package/dist/elements/setting-item.js +1 -1
- package/dist/elements/settings-group.js +1 -1
- package/dist/elements/skeleton.js +1 -1
- package/dist/elements/slot-text.d.ts +51 -0
- package/dist/elements/slots.d.ts +5 -0
- package/dist/elements/source.js +1 -1
- package/dist/elements/status.js +1 -1
- package/dist/elements/switch.js +1 -1
- package/dist/elements/tabs.js +1 -1
- package/dist/elements/tasks.js +1 -1
- package/dist/elements/text-shimmer.js +1 -1
- package/dist/elements/thinking-bar.js +1 -1
- package/dist/elements/thread.js +1 -1
- package/dist/elements/toast.js +1 -1
- package/dist/elements/tool.js +1 -1
- package/dist/elements/tooltip.js +1 -1
- package/dist/elements/voice-input.js +1 -1
- package/dist/elements/voice-output.js +1 -1
- package/dist/elements.d.ts +12 -6
- package/dist/index.js +1535 -1487
- package/dist/index.server.js +2330 -2296
- package/dist/kai.es.js +1 -1
- package/dist/llms/llms-full.txt +12 -3
- package/dist/mcp.es.js +809 -75
- package/dist/react/index.d.ts +13 -3
- package/dist/react.js +14 -14
- package/dist/register-impl-AxIlqjo7.js +145 -0
- package/dist/{solid-BCJUQqwS.js → solid-BGYSJyHG.js} +4901 -4691
- package/dist/{solid-BdENBcEq.js → solid-Dt2nEwfl.js} +4406 -4320
- package/dist/solid.js +1 -1
- package/dist/solid.server.js +1 -1
- package/dist/{variant-aurora-DOb_o4pC.js → variant-aurora-B44X69AG.js} +1 -1
- package/dist/{variant-aurora-BKHHiOgL.js → variant-aurora-BRhV8Flk.js} +2 -2
- package/dist/{variant-aurora-1wMcXRUS.js → variant-aurora-Ds5ou9BH.js} +2 -2
- package/dist/{variant-custom-DWSSgmd2.js → variant-custom-B20FhtYj.js} +2 -2
- package/dist/{variant-custom-CJGB0Kbw.js → variant-custom-BvA1Schl.js} +1 -1
- package/dist/{variant-custom-Co0CkXJF.js → variant-custom-D6Rtvneb.js} +2 -2
- package/dist/{variant-wave-CEODq-9q.js → variant-wave-BUQtkryq.js} +1 -1
- package/dist/{variant-wave-C3-45cL6.js → variant-wave-BVYnqy9L.js} +2 -2
- package/dist/{variant-wave-jdXBnCUZ.js → variant-wave-DXC6_LcH.js} +2 -2
- package/dist/wire/encode.d.ts +79 -6
- package/dist/wire/files.d.ts +116 -0
- package/dist/wire/index.d.ts +3 -1
- package/dist/wire/media-types.d.ts +106 -0
- package/dist/wire.js +596 -368
- package/frameworks/react/index.tsx +9 -5
- package/llms-full.txt +12 -3
- package/package.json +2 -1
- package/src/agent-tooling/archetypes.ts +43 -12
- package/src/agent-tooling/integrations/anthropic.ts +29 -5
- package/src/agent-tooling/integrations/cloudflare.ts +5 -0
- package/src/agent-tooling/integrations/langgraph.ts +13 -0
- package/src/agent-tooling/integrations/mastra.ts +46 -5
- package/src/agent-tooling/integrations/mock.ts +4 -0
- package/src/agent-tooling/integrations/ollama.ts +7 -0
- package/src/agent-tooling/integrations/openai.ts +2 -0
- package/src/agent-tooling/integrations/openrouter.ts +2 -0
- package/src/agent-tooling/integrations/pi.ts +26 -1
- package/src/agent-tooling/integrations/pydantic-ai.ts +37 -3
- package/src/agent-tooling/integrations/vercel-ai-sdk.ts +42 -6
- package/src/agent-tooling/mcp/tools/scaffold.ts +853 -32
- package/src/agent-tooling/registry.ts +57 -0
- package/src/agent-tooling/types.ts +132 -0
- package/src/components/chat-thread.tsx +10 -1
- package/src/components/context.tsx +18 -12
- package/src/components/conversation-item.tsx +6 -0
- package/src/components/model-switcher.tsx +38 -8
- package/src/components/toast.tsx +6 -1
- package/src/elements/button.tsx +26 -3
- package/src/elements/chat.tsx +28 -2
- package/src/elements/default-input.tsx +128 -5
- package/src/elements/element-meta.json +30 -4
- package/src/elements/element-types.d.ts +12 -6
- package/src/elements/menu.tsx +30 -3
- package/src/elements/slot-text.ts +73 -0
- package/src/elements/slots.ts +10 -0
- package/src/index.ts +9 -5
- package/src/wire/encode.ts +229 -14
- package/src/wire/files.ts +342 -0
- package/src/wire/index.ts +21 -0
- package/src/wire/media-types.ts +344 -0
- package/dist/elements/chunks/arrow-left-Bb46H7w9.js +0 -1
- package/dist/elements/chunks/check-C8desc_h.js +0 -1
- package/dist/elements/chunks/chevron-down-DKtc2HNB.js +0 -1
- package/dist/elements/chunks/chevron-right-Dw4GPhwL.js +0 -1
- package/dist/elements/chunks/circle-BeokBsvB.js +0 -1
- package/dist/elements/chunks/circle-check-wJSqt859.js +0 -1
- package/dist/elements/chunks/context-WHDl-xSx.js +0 -1
- package/dist/elements/chunks/conversation-list-CdR14_Y4.js +0 -1
- package/dist/elements/chunks/default-input-CSZqUM81.js +0 -1
- package/dist/elements/chunks/message-square-CnpAm_P0.js +0 -1
- package/dist/elements/chunks/model-switcher-CclaJEHt.js +0 -1
- package/dist/elements/chunks/x-D1qx0aLd.js +0 -1
- package/dist/register-impl-bzrZ44ft.js +0 -145
package/src/wire/index.ts
CHANGED
|
@@ -18,13 +18,34 @@ export { applyToolOutput, applyToolFailure, bufferText } from './sink-helpers';
|
|
|
18
18
|
export { toOpenAIMessages, toAnthropicMessages, WireEncodeError } from './encode';
|
|
19
19
|
export type {
|
|
20
20
|
AnthropicContentBlock,
|
|
21
|
+
AnthropicEncodeOptions,
|
|
21
22
|
AnthropicWireMessage,
|
|
23
|
+
FileEncodeOptions,
|
|
24
|
+
OpenAIContentPart,
|
|
22
25
|
OpenAIEncodeOptions,
|
|
23
26
|
OpenAIReasoningDetail,
|
|
24
27
|
OpenAIToolCall,
|
|
25
28
|
OpenAIWireMessage,
|
|
29
|
+
UnencodableFilePolicy,
|
|
26
30
|
} from './encode';
|
|
27
31
|
|
|
32
|
+
// What the encoders CAN represent, published as a value.
|
|
33
|
+
//
|
|
34
|
+
// The point is not introspection. A consumer who wants their own file picker,
|
|
35
|
+
// their own validation and their own error copy can build all three off
|
|
36
|
+
// `encodableMediaTypes()` and `resolveMediaPolicy(...).decide(...)` without
|
|
37
|
+
// using our composer at all -- the kit states a fact about itself and the
|
|
38
|
+
// application decides what to do about it. `<kai-chat accept="...">` is a
|
|
39
|
+
// convenience over exactly this, not a separate mechanism.
|
|
40
|
+
export { encodableMediaTypes, resolveMediaPolicy } from './media-types';
|
|
41
|
+
export type {
|
|
42
|
+
EncodableKind,
|
|
43
|
+
MediaDecision,
|
|
44
|
+
MediaPolicy,
|
|
45
|
+
MediaPolicyOptions,
|
|
46
|
+
MediaTypeFilter,
|
|
47
|
+
} from './media-types';
|
|
48
|
+
|
|
28
49
|
export { openaiChatFormat } from './formats/openai';
|
|
29
50
|
export { anthropicMessagesFormat } from './formats/anthropic';
|
|
30
51
|
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
// THE media-type declaration. One table, read by every layer that has an
|
|
2
|
+
// opinion about attachments.
|
|
3
|
+
//
|
|
4
|
+
// WHY THIS FILE EXISTS AT ALL. Two features want the same knowledge: the
|
|
5
|
+
// composer needs to know what a user is allowed to stage, and the encoders need
|
|
6
|
+
// to know what they can turn into provider content. Those are the same set. When
|
|
7
|
+
// each grows its own copy they drift, and the drift is not theoretical -- it is
|
|
8
|
+
// the exact defect #186 fixed one layer down, where a composer happily staged a
|
|
9
|
+
// `blob:` URL that the encoder could not represent. So the set is declared ONCE,
|
|
10
|
+
// here, and both layers derive from it rather than restating it.
|
|
11
|
+
//
|
|
12
|
+
// THE BOUNDARY THIS DRAWS. The kit owns "what CAN be encoded" -- a fact about
|
|
13
|
+
// `encode.ts`, not a policy. The developer owns "what I want to ALLOW", and can
|
|
14
|
+
// only ever NARROW the kit's set, never widen it: widening would just move a
|
|
15
|
+
// provider 400 later in the request. That asymmetry is why the filter is a
|
|
16
|
+
// declarative list rather than a hook, and why `encodableMediaTypes()` is public.
|
|
17
|
+
//
|
|
18
|
+
// No I/O, like the rest of `wire/`. Pattern matching and, for text, decoding
|
|
19
|
+
// base64 that is already inline -- computation over bytes already in hand, never
|
|
20
|
+
// a fetch.
|
|
21
|
+
|
|
22
|
+
/** What a media type BECOMES on the wire. Named for the Anthropic block set,
|
|
23
|
+
* which is the narrower of the two: `text` / `image` / `document` and nothing
|
|
24
|
+
* else. There is no arbitrary-file block on either API, which is why a text
|
|
25
|
+
* file has to ride as text content and a `.zip` has no representation at all. */
|
|
26
|
+
export type EncodableKind = 'image' | 'document' | 'text';
|
|
27
|
+
|
|
28
|
+
// WHAT A BROWSER ACTUALLY CALLS A FILE -- ONE OBSERVATION, NOT A STANDING FACT.
|
|
29
|
+
//
|
|
30
|
+
// Observed 2026-08-13 (UTC), Chrome 151.0.7922.137, macOS 26.5 arm64, with the
|
|
31
|
+
// files handed to a real `<input type="file">` so the browser built every `File`
|
|
32
|
+
// itself. Re-run it rather than trusting it:
|
|
33
|
+
// node scripts/probe-file-media-types.mjs
|
|
34
|
+
//
|
|
35
|
+
// .txt text/plain .js text/javascript .png image/png
|
|
36
|
+
// .md text/markdown .css text/css .zip application/zip
|
|
37
|
+
// .csv text/csv .html text/html .pdf application/pdf
|
|
38
|
+
// .json application/json .sh text/x-sh
|
|
39
|
+
// .xml text/xml .py text/x-python-script
|
|
40
|
+
// .yaml application/x-yaml .yml application/x-yaml
|
|
41
|
+
// .ts .tsx .rs .go .sql .toml .log -> "" (the browser could not name them)
|
|
42
|
+
//
|
|
43
|
+
// THESE VALUES ARE PLATFORM-SPECIFIC. Nineteen of the twenty-two match macOS's
|
|
44
|
+
// own `preferredMIMEType`, so the browser is answering out of the OS type
|
|
45
|
+
// database and Linux and Windows will answer differently. Nothing returned
|
|
46
|
+
// `application/octet-stream` -- Chrome's failure mode here is the EMPTY STRING.
|
|
47
|
+
// (`.ts` is not a TypeScript file to macOS: it resolves to an MPEG-2
|
|
48
|
+
// transport-stream UTI, which carries no MIME string at all, which is why it
|
|
49
|
+
// comes back empty rather than as `video/mp2t`.)
|
|
50
|
+
//
|
|
51
|
+
// EXACTLY TWO THINGS BELOW REST ON THIS TABLE, and both survive it being wrong
|
|
52
|
+
// somewhere else:
|
|
53
|
+
// 1. `application/x-yaml` is a row because it was measured here. A platform
|
|
54
|
+
// that says something else does not make this row wrong, only incomplete.
|
|
55
|
+
// 2. Seven of the twenty-two extensions are the ones a developer is likeliest
|
|
56
|
+
// to attach to a coding chat, and the browser names NONE of them. That is
|
|
57
|
+
// why an unnamed file is decided by DECODING its bytes and never by reading
|
|
58
|
+
// its filename -- see `decide()`. Another OS moves WHICH rows come back
|
|
59
|
+
// empty; it cannot move the fact that some do.
|
|
60
|
+
// Anything else read off this table is being read too hard.
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* ★ THE DECLARATION. Everything else in this file, and both `accept` surfaces,
|
|
64
|
+
* are derived from this array. Adding a row teaches the encoder AND widens the
|
|
65
|
+
* composer's picker; deleting one narrows both. If you find yourself writing a
|
|
66
|
+
* second list of media types anywhere in this repo, delete it and read this.
|
|
67
|
+
*
|
|
68
|
+
* Patterns are HTML `accept` syntax: an exact type (`image/png`) or a subtype
|
|
69
|
+
* wildcard (`text/*`). File EXTENSIONS (`.md`) are deliberately not supported --
|
|
70
|
+
* they map to media types only by convention, and guessing is how a `.md` full
|
|
71
|
+
* of base64 becomes a 400. An extension in a developer's `accept` THROWS rather
|
|
72
|
+
* than matching nothing; a file the browser could not name is settled by
|
|
73
|
+
* decoding it. Neither path ever consults a filename.
|
|
74
|
+
*
|
|
75
|
+
* On the image list: JPEG, PNG, GIF and WebP are the four formats BOTH APIs
|
|
76
|
+
* document. SVG and BMP are the ones people actually try, and both are a 400 at
|
|
77
|
+
* request time, so they are absent on purpose.
|
|
78
|
+
*
|
|
79
|
+
* On the text list: `text/*` is the core, because a media type in that tree is
|
|
80
|
+
* text by definition of the tree. The `application/` rows are the judgement
|
|
81
|
+
* calls -- textual formats that IANA files outside `text/` for historical
|
|
82
|
+
* reasons, and that people genuinely attach. `application/json` and
|
|
83
|
+
* `application/xml` are the two obvious ones.
|
|
84
|
+
*
|
|
85
|
+
* On YAML, since it is two rows for one format: `application/x-yaml` is what
|
|
86
|
+
* Chrome hands back for a `.yaml` on macOS, MEASURED in the table above.
|
|
87
|
+
* `application/yaml` is the IANA-registered type (RFC 9512, 2024) and is what a
|
|
88
|
+
* correctly configured server sends, so it is here on REGISTRY grounds rather
|
|
89
|
+
* than on a measurement. `text/yaml` and `text/x-yaml` are in the wild too and
|
|
90
|
+
* need no row of their own: `text/*` already covers both.
|
|
91
|
+
*/
|
|
92
|
+
const ENCODABLE: readonly { readonly pattern: string; readonly kind: EncodableKind }[] = [
|
|
93
|
+
{ pattern: 'image/jpeg', kind: 'image' },
|
|
94
|
+
{ pattern: 'image/png', kind: 'image' },
|
|
95
|
+
{ pattern: 'image/gif', kind: 'image' },
|
|
96
|
+
{ pattern: 'image/webp', kind: 'image' },
|
|
97
|
+
{ pattern: 'application/pdf', kind: 'document' },
|
|
98
|
+
{ pattern: 'text/*', kind: 'text' },
|
|
99
|
+
{ pattern: 'application/json', kind: 'text' },
|
|
100
|
+
{ pattern: 'application/xml', kind: 'text' },
|
|
101
|
+
{ pattern: 'application/x-yaml', kind: 'text' },
|
|
102
|
+
{ pattern: 'application/yaml', kind: 'text' },
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The media type an unnamed file gets once its BYTES have proven to be UTF-8
|
|
107
|
+
* text, and the type whose presence in the effective policy is what permits that
|
|
108
|
+
* proof to be attempted at all.
|
|
109
|
+
*
|
|
110
|
+
* `text/plain` is not a guess dressed up as a fact. It is the media type for
|
|
111
|
+
* "text, no further structure claimed", which is exactly what a successful
|
|
112
|
+
* decode establishes and the most any decode could ever establish. A `.rs` file
|
|
113
|
+
* arriving as `text/plain` is true; arriving as `text/x-rust` would be the
|
|
114
|
+
* filename talking.
|
|
115
|
+
*/
|
|
116
|
+
export const UNNAMED_TEXT_MEDIA_TYPE = 'text/plain';
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Media types that say nothing about the bytes they label.
|
|
120
|
+
*
|
|
121
|
+
* The empty string is what `File.type` is when the OS type database had no
|
|
122
|
+
* answer (seven of the twenty-two rows above). `application/octet-stream` is the
|
|
123
|
+
* same non-answer written down: RFC 2046 defines it as "arbitrary binary data",
|
|
124
|
+
* and it is what `FileReader.readAsDataURL` substitutes for an empty type --
|
|
125
|
+
* measured in Chrome 151 AND in the jsdom the unit suite runs on, both of which
|
|
126
|
+
* produce `data:application/octet-stream;base64,...` for a `File` whose `type`
|
|
127
|
+
* is `''`. So the same typeless file reaches the composer as `''` and reaches
|
|
128
|
+
* the encoder as `application/octet-stream`, and both spellings have to mean the
|
|
129
|
+
* same thing or the two layers disagree about one file.
|
|
130
|
+
*/
|
|
131
|
+
const NAMES_NOTHING: readonly string[] = ['', 'application/octet-stream'];
|
|
132
|
+
|
|
133
|
+
/** A developer's narrowing filter. A comma-separated string (so it works as an
|
|
134
|
+
* HTML attribute under the `kai-` contract) or an array (so it composes in JS).
|
|
135
|
+
* Both spell the same thing; the string form is what `<kai-chat accept="...">`
|
|
136
|
+
* takes and what the `kai` MCP scaffolder can emit as data. */
|
|
137
|
+
export type MediaTypeFilter = string | readonly string[];
|
|
138
|
+
|
|
139
|
+
/** One media type, decided against the effective set.
|
|
140
|
+
*
|
|
141
|
+
* `unsupported` and `filtered` are split because the developer needs different
|
|
142
|
+
* things from them: `unsupported` means fix your expectations (no API takes
|
|
143
|
+
* this), `filtered` means fix your `accept` (the kit could have sent it). */
|
|
144
|
+
export type MediaDecision =
|
|
145
|
+
| { status: 'allowed'; kind: EncodableKind }
|
|
146
|
+
| { status: 'unsupported' }
|
|
147
|
+
| { status: 'filtered' }
|
|
148
|
+
/**
|
|
149
|
+
* Nobody named this file, so its media type cannot decide it. LOOK AT THE
|
|
150
|
+
* BYTES: decode them as UTF-8 (`classifyAttachment` does), and it is `text`
|
|
151
|
+
* if they decode and unencodable if they do not. Do not look at the filename.
|
|
152
|
+
*
|
|
153
|
+
* ★ THIS VARIANT IS WHERE THE DEVELOPER'S FILTER IS ENFORCED, so the caller
|
|
154
|
+
* cannot get it wrong by forgetting to check. It is returned ONLY when the
|
|
155
|
+
* effective policy still admits `text/plain` -- the one thing a decode can
|
|
156
|
+
* establish. Narrow `accept` to `image/png` and an unnamed file comes back
|
|
157
|
+
* `unsupported` instead, so the decode path is unreachable and a typeless
|
|
158
|
+
* `.rs` cannot slip past an images-only filter. That is the whole reason the
|
|
159
|
+
* check lives here rather than at each call site: there is one place to get
|
|
160
|
+
* right, and the callers physically cannot reach the bytes without being told
|
|
161
|
+
* to.
|
|
162
|
+
*/
|
|
163
|
+
| { status: 'undetermined' };
|
|
164
|
+
|
|
165
|
+
export interface MediaPolicy {
|
|
166
|
+
/** The effective patterns: the kit's capability set narrowed by the
|
|
167
|
+
* developer's filter. Never wider than `encodableMediaTypes()`. */
|
|
168
|
+
readonly types: readonly string[];
|
|
169
|
+
/** The same set as an HTML `accept` attribute value, ready to put on an
|
|
170
|
+
* `<input type="file">`. This is what makes the picker and the encoder
|
|
171
|
+
* provably one thing rather than two lists that agree today. */
|
|
172
|
+
readonly accept: string;
|
|
173
|
+
/**
|
|
174
|
+
* What this policy makes of one media type, including "I cannot tell from
|
|
175
|
+
* this, go and read the bytes" -- see `undetermined`.
|
|
176
|
+
*
|
|
177
|
+
* The primitive behind "expose information, do not make decisions": it answers
|
|
178
|
+
* a question and returns a fact, so a consumer can build their own picker,
|
|
179
|
+
* their own validation and their own error copy on top of it without the kit
|
|
180
|
+
* deciding anything on their behalf.
|
|
181
|
+
*/
|
|
182
|
+
decide(mediaType: string | undefined): MediaDecision;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export interface MediaPolicyOptions {
|
|
186
|
+
/** Narrow the kit's capability set. Omitted means the full set. Anything here
|
|
187
|
+
* that the kit cannot encode is dropped rather than honoured, because
|
|
188
|
+
* allowing it would only relocate the failure to the provider. */
|
|
189
|
+
accept?: MediaTypeFilter;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// NOTE ON WHAT IS DELIBERATELY ABSENT: there is no size cap, no file count, and
|
|
193
|
+
// no truncation path here, and their absence is a decision rather than an
|
|
194
|
+
// omission. How many bytes to send is a cost decision that lands on the
|
|
195
|
+
// consumer's invoice, and a component library that grows a limits engine starts
|
|
196
|
+
// making application choices on their behalf. The kit encodes what it is given.
|
|
197
|
+
// A developer who wants a ceiling has `File.size` and `decide()` and can enforce
|
|
198
|
+
// one in three lines of their own code, where it belongs.
|
|
199
|
+
|
|
200
|
+
const normalize = (value: string): string => value.trim().toLowerCase();
|
|
201
|
+
|
|
202
|
+
/** Does this media type say anything at all about the bytes it labels? Exported
|
|
203
|
+
* so `files.ts` decides "nameless" by the same rule `decide()` does, rather
|
|
204
|
+
* than growing a second opinion about which spellings mean "I don't know". */
|
|
205
|
+
export const namesNothing = (mediaType: string | undefined): boolean =>
|
|
206
|
+
NAMES_NOTHING.includes(mediaType === undefined ? '' : normalize(mediaType));
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* A file EXTENSION in `accept` is a hard error, and the loudness is the point.
|
|
210
|
+
*
|
|
211
|
+
* HTML's own `accept` takes extensions, the prop is called `accept`, and it is
|
|
212
|
+
* documented as HTML `accept` syntax -- so `accept=".py"` is a reasonable thing
|
|
213
|
+
* for a developer to write, and it is a trap. Measured on this branch before the
|
|
214
|
+
* throw existed: `.py` alone resolved to zero effective types and a picker with
|
|
215
|
+
* `accept=""`, a composer that silently accepted NOTHING. `".py,text/plain"` was
|
|
216
|
+
* worse, because the half that worked made it read as correct while the `.py`
|
|
217
|
+
* vanished without a word.
|
|
218
|
+
*
|
|
219
|
+
* A silent empty set is the one outcome nobody can debug, so this throws. It is
|
|
220
|
+
* safe to throw: no released version of this kit ships the prop, so no existing
|
|
221
|
+
* app can be relying on the old silence.
|
|
222
|
+
*/
|
|
223
|
+
const assertMediaType = (entry: string): string => {
|
|
224
|
+
if (!entry.startsWith('.')) return entry;
|
|
225
|
+
throw new Error(
|
|
226
|
+
`\`accept\` entry "${entry}" is a file extension, and this kit takes media types only. ` +
|
|
227
|
+
`HTML's own accept attribute does take extensions, which is exactly why this throws rather ` +
|
|
228
|
+
`than quietly matching nothing. Use a media type instead -- "text/*" covers source files, ` +
|
|
229
|
+
`"image/*" images, "application/pdf" PDFs, and \`encodableMediaTypes()\` is the full set. ` +
|
|
230
|
+
`You lose nothing by dropping the extension: a file the browser cannot name is decided by ` +
|
|
231
|
+
`decoding its bytes, which is stronger than matching its name.`,
|
|
232
|
+
);
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const splitFilter = (filter: MediaTypeFilter): string[] =>
|
|
236
|
+
(typeof filter === 'string' ? filter.split(',') : filter)
|
|
237
|
+
.map(normalize)
|
|
238
|
+
.filter((v) => v !== '')
|
|
239
|
+
.map(assertMediaType);
|
|
240
|
+
|
|
241
|
+
/** `image/png` -> `['image','png']`; `text/*` -> `['text','*']`. */
|
|
242
|
+
const parts = (pattern: string): [string, string] => {
|
|
243
|
+
const slash = pattern.indexOf('/');
|
|
244
|
+
return slash === -1 ? [pattern, ''] : [pattern.slice(0, slash), pattern.slice(slash + 1)];
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
const matches = (pattern: string, mediaType: string): boolean => {
|
|
248
|
+
const [pType, pSub] = parts(pattern);
|
|
249
|
+
const [mType, mSub] = parts(mediaType);
|
|
250
|
+
if (pType !== '*' && pType !== mType) return false;
|
|
251
|
+
return pSub === '*' || pSub === mSub;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* The narrower of two patterns, or `undefined` when they do not overlap.
|
|
256
|
+
*
|
|
257
|
+
* This is what "narrow, never widen" means mechanically. `accept: 'image/*'`
|
|
258
|
+
* against a capability of `image/png` yields `image/png`, not `image/*`: the
|
|
259
|
+
* developer asked for images, and the kit's answer is the images it can actually
|
|
260
|
+
* send. Conversely `accept: 'text/markdown'` against a capability of `text/*`
|
|
261
|
+
* yields `text/markdown`, because there the developer is the narrower one.
|
|
262
|
+
*/
|
|
263
|
+
const intersect = (capability: string, filter: string): string | undefined => {
|
|
264
|
+
if (matches(capability, filter)) return filter;
|
|
265
|
+
if (matches(filter, capability)) return capability;
|
|
266
|
+
return undefined;
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Every media type this kit's encoders can represent, as HTML `accept` patterns.
|
|
271
|
+
*
|
|
272
|
+
* PUBLIC ON PURPOSE, and not merely for introspection: a consumer who wants
|
|
273
|
+
* their own picker, their own validation and their own error copy can build all
|
|
274
|
+
* three against this without touching `<kai-chat>` at all. That demotes the
|
|
275
|
+
* `accept` prop from "the only door" to a convenience over a published fact,
|
|
276
|
+
* which is the composition-first shape this project already committed to.
|
|
277
|
+
*/
|
|
278
|
+
export function encodableMediaTypes(): readonly string[] {
|
|
279
|
+
return ENCODABLE.map((entry) => entry.pattern);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* The effective policy: the kit's capability set narrowed by the developer's
|
|
284
|
+
* filter, plus the text ceiling.
|
|
285
|
+
*
|
|
286
|
+
* BOTH LAYERS CALL THIS. The composer calls it to build its picker `accept`
|
|
287
|
+
* attribute and to filter what actually gets staged; the encoders call it to
|
|
288
|
+
* decide what reaches the wire. That shared call is the whole design -- it is
|
|
289
|
+
* why changing `ENCODABLE` above moves the picker and the encoder together
|
|
290
|
+
* rather than moving one and leaving the other to be noticed in production.
|
|
291
|
+
*/
|
|
292
|
+
export function resolveMediaPolicy(options: MediaPolicyOptions = {}): MediaPolicy {
|
|
293
|
+
const filter = options.accept === undefined ? undefined : splitFilter(options.accept);
|
|
294
|
+
|
|
295
|
+
const effective: { pattern: string; kind: EncodableKind }[] = [];
|
|
296
|
+
for (const capability of ENCODABLE) {
|
|
297
|
+
if (filter === undefined) {
|
|
298
|
+
effective.push({ ...capability });
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
for (const wanted of filter) {
|
|
302
|
+
const overlap = intersect(capability.pattern, wanted);
|
|
303
|
+
// A capability can overlap several filter entries (`text/*` against
|
|
304
|
+
// `text/plain,text/csv`), and each overlap is its own effective pattern.
|
|
305
|
+
if (overlap !== undefined && !effective.some((e) => e.pattern === overlap)) {
|
|
306
|
+
effective.push({ pattern: overlap, kind: capability.kind });
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return {
|
|
312
|
+
types: effective.map((e) => e.pattern),
|
|
313
|
+
accept: effective.map((e) => e.pattern).join(','),
|
|
314
|
+
decide(mediaType) {
|
|
315
|
+
const type = mediaType === undefined ? '' : normalize(mediaType);
|
|
316
|
+
|
|
317
|
+
if (namesNothing(type)) {
|
|
318
|
+
// Nothing here names the bytes, and the filename is not evidence, so
|
|
319
|
+
// the answer is in the bytes themselves -- but only if the developer's
|
|
320
|
+
// filter would still take what a decode can prove. See the
|
|
321
|
+
// `undetermined` variant: this is the single place that gate exists.
|
|
322
|
+
return effective.some((e) => matches(e.pattern, UNNAMED_TEXT_MEDIA_TYPE))
|
|
323
|
+
? { status: 'undetermined' }
|
|
324
|
+
: // `unsupported` rather than `filtered`, deliberately: `filtered`
|
|
325
|
+
// claims the kit COULD have encoded this file, and nobody has
|
|
326
|
+
// established what it is. Unread and unnamed, it is not a text
|
|
327
|
+
// file the filter excluded -- it is a file with no known type.
|
|
328
|
+
{ status: 'unsupported' };
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const hit = effective.find((e) => matches(e.pattern, type));
|
|
332
|
+
if (hit) return { status: 'allowed', kind: hit.kind };
|
|
333
|
+
// Distinguishing these two is the point: one is the kit's limit, the
|
|
334
|
+
// other is the developer's own filter looking back at them.
|
|
335
|
+
return ENCODABLE.some((e) => matches(e.pattern, type))
|
|
336
|
+
? { status: 'filtered' }
|
|
337
|
+
: { status: 'unsupported' };
|
|
338
|
+
},
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/** The policy every caller gets when nobody narrowed anything: the kit's full
|
|
343
|
+
* capability set. Built once -- it has no inputs. */
|
|
344
|
+
export const DEFAULT_MEDIA_POLICY: MediaPolicy = resolveMediaPolicy();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as o}from"./Icon-C-2LvGDG.js";import{c as m,m as r}from"./define-BzPnNsXg.js";var e=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],t=a=>m(o,r(a,{name:"ArrowLeft",iconNode:e})),p=t;export{p as a};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as m}from"./Icon-C-2LvGDG.js";import{c as o,m as r}from"./define-BzPnNsXg.js";var c=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],e=a=>o(m,r(a,{name:"Check",iconNode:c})),f=e;export{f as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as r}from"./Icon-C-2LvGDG.js";import{c as a,m}from"./define-BzPnNsXg.js";var e=[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]],n=o=>a(r,m(o,{name:"ChevronDown",iconNode:e})),p=n;export{p as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as o}from"./Icon-C-2LvGDG.js";import{c as a,m as r}from"./define-BzPnNsXg.js";var t=[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]],e=m=>a(o,r(m,{name:"ChevronRight",iconNode:t})),h=e;export{h as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as c}from"./Icon-C-2LvGDG.js";import{c as m,m as o}from"./define-BzPnNsXg.js";var a=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}]],e=r=>m(c,o(r,{name:"Circle",iconNode:a})),i=e;export{i as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as c}from"./Icon-C-2LvGDG.js";import{c as r,m as a}from"./define-BzPnNsXg.js";var e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],o=m=>r(c,a(m,{name:"CircleCheck",iconNode:e})),i=o;export{i as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{l as s,c as n,S as a,i as o,a as d,b as f,n as P,z,A,t as u,d as D,j as E}from"./define-BzPnNsXg.js";import{H,a as O,b as R}from"./hover-card-BtiF4XiU.js";import{c as h}from"./cn-CU7UAWzk.js";import{B as q}from"./button-CmkUkz6c.js";var G=u('<svg aria-label="Model context usage"height=20 role=img viewBox="0 0 24 24"width=20 style=color:currentcolor><circle cx=12 cy=12 fill=none opacity=0.25 r=10 stroke=currentColor stroke-width=2></circle><circle cx=12 cy=12 fill=none opacity=0.7 r=10 stroke=currentColor stroke-linecap=round stroke-width=2 style=transform:rotate(-90deg);transform-origin:center>'),J=u('<span class="font-medium text-muted-foreground">'),K=u('<div class="flex items-center justify-between gap-3 text-xs"><p></p><p class="font-mono text-muted-foreground"> / '),L=u('<div class=space-y-2><div class="h-1.5 w-full rounded-full bg-muted overflow-hidden"><div>'),b=u("<div>"),Q=u("<span class=text-muted-foreground>Total cost"),F=u("<span>"),V=u("<div><span class=text-muted-foreground>Input"),W=u("<div><span class=text-muted-foreground>Output"),X=u("<div><span class=text-muted-foreground>Reasoning"),Y=u("<div><span class=text-muted-foreground>Cache");const Z=10,U=100,y=.7,C=.9;function _(e,t=y,r=C){return e>r?"danger":e>t?"warn":"ok"}const M=z();function g(){const e=A(M);if(!e)throw new Error("Context components must be used within Context");return e}const j=new Intl.NumberFormat("en-US",{notation:"compact"}),N=new Intl.NumberFormat("en-US",{maximumFractionDigits:1,style:"percent"}),ee=new Intl.NumberFormat("en-US",{currency:"USD",style:"currency"});function te(e){const t=s(()=>({usedTokens:e.usedTokens,maxTokens:e.maxTokens,inputTokens:e.inputTokens,outputTokens:e.outputTokens,reasoningTokens:e.reasoningTokens,cacheTokens:e.cacheTokens,estimatedCost:e.estimatedCost,warnThreshold:e.warnThreshold??y,dangerThreshold:e.dangerThreshold??C}));return n(M.Provider,{get value(){return t()},get children(){return n(H,{openDelay:0,get children(){return e.children}})}})}function re(){const e=g(),t=2*Math.PI*Z,r=s(()=>e.usedTokens/e.maxTokens),l=s(()=>t*(1-r()));return(()=>{var i=G(),T=i.firstChild,x=T.nextSibling;return D(x,"stroke-dasharray",`${t} ${t}`),d(()=>D(x,"stroke-dashoffset",l())),i})()}function ne(e){const t=g(),r=s(()=>t.usedTokens/t.maxTokens),l=s(()=>N.format(r()));return n(O,{get children(){return n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){return n(q,{type:"button",variant:"ghost",get class(){return e.class},get children(){return[(()=>{var i=J();return o(i,l),i})(),n(re,{})]}})}})}})}function se(e){return n(R,{get class(){return h("min-w-60 divide-y divide-border overflow-hidden",e.class)},get children(){return e.children}})}function oe(e){const t=g(),r=s(()=>t.usedTokens/t.maxTokens),l=s(()=>N.format(r())),i=s(()=>j.format(t.usedTokens)),T=s(()=>j.format(t.maxTokens)),x=s(()=>`${Math.min(r()*U,U)}%`),$=s(()=>{const c=r();return c>t.dangerThreshold?"danger":c>t.warnThreshold?"warn":"ok"}),B=s(()=>{const c=$();return c==="danger"?"bg-red-400":c==="warn"?"bg-yellow-400":"bg-primary"});return(()=>{var c=b();return o(c,n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){return[(()=>{var w=K(),p=w.firstChild,k=p.nextSibling,m=k.firstChild;return o(p,l),o(k,i,m),o(k,T,null),w})(),(()=>{var w=L(),p=w.firstChild,k=p.firstChild;return d(m=>{var S=h("h-full rounded-full transition-all",B()),I=x();return S!==m.e&&f(k,m.e=S),I!==m.t&&P(k,"width",m.t=I),m},{e:void 0,t:void 0}),w})()]}})),d(()=>f(c,h("w-full space-y-2 p-3",e.class))),c})()}function ae(e){return(()=>{var t=b();return o(t,()=>e.children),d(()=>f(t,h("w-full p-3",e.class))),t})()}function ue(e){const t=g(),r=s(()=>ee.format(t.estimatedCost??0));return(()=>{var l=b();return o(l,n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){return[Q(),(()=>{var i=F();return o(i,r),i})()]}})),d(()=>f(l,h("flex w-full items-center justify-between gap-3 bg-muted p-3 text-xs",e.class))),l})()}function v(e){return(()=>{var t=F();return o(t,(()=>{var r=E(()=>e.tokens===void 0);return()=>r()?"\u2014":j.format(e.tokens)})()),t})()}function ie(e){const t=g();return n(a,{get when(){return e.children||t.inputTokens},get children(){return n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){var r=V();return r.firstChild,o(r,n(v,{get tokens(){return t.inputTokens}}),null),d(()=>f(r,h("flex items-center justify-between text-xs",e.class))),r}})}})}function le(e){const t=g();return n(a,{get when(){return e.children||t.outputTokens},get children(){return n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){var r=W();return r.firstChild,o(r,n(v,{get tokens(){return t.outputTokens}}),null),d(()=>f(r,h("flex items-center justify-between text-xs",e.class))),r}})}})}function ce(e){const t=g();return n(a,{get when(){return e.children||t.reasoningTokens},get children(){return n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){var r=X();return r.firstChild,o(r,n(v,{get tokens(){return t.reasoningTokens}}),null),d(()=>f(r,h("flex items-center justify-between text-xs",e.class))),r}})}})}function de(e){const t=g();return n(a,{get when(){return e.children||t.cacheTokens},get children(){return n(a,{get when(){return!e.children},get fallback(){return e.children},get children(){var r=Y();return r.firstChild,o(r,n(v,{get tokens(){return t.cacheTokens}}),null),d(()=>f(r,h("flex items-center justify-between text-xs",e.class))),r}})}})}export{te as C,y as D,ne as a,se as b,oe as c,ae as d,ie as e,le as f,ue as g,_ as h,ce as i,de as j,C as k};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{c as n,m as L,g as y,s as A,l as m,i as l,S as h,a as v,b as p,d as M,t as c,e as N,o as O,x as D,F as k}from"./define-BzPnNsXg.js";import{c as f}from"./cn-CU7UAWzk.js";import{a as R,b as q,C as E}from"./collapsible-Cvj61obE.js";import{B as C}from"./button-CmkUkz6c.js";import{B as F}from"./badge-SxLSZ19R.js";import{S as P}from"./scroll-area-Bs4bFS1P.js";import{m as U}from"./message-square-CnpAm_P0.js";import{I as G}from"./Icon-C-2LvGDG.js";var H=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M9 3v18",key:"fh3hqa"}],["path",{d:"m14 9 3 3-3 3",key:"8010ee"}]],J=i=>n(G,L(i,{name:"PanelLeftOpen",iconNode:H})),K=J;function Q(i,e){const[d,a]=y(e);return[()=>i()??d(),t=>a(t)]}var $=c('<span part=trailing class="ml-auto shrink-0 text-xs text-muted-foreground">'),V=c('<div class="flex items-center gap-2.5"><span>'),W=c("<button>"),X=c('<div class="flex items-center gap-2"><div>'),Y=c("<div> messages");function Z(i,e=Date.now()){if(!i)return"";const d=Date.parse(i);if(Number.isNaN(d))return"";const a=Math.max(0,Math.round((e-d)/1e3));if(a<60)return"just now";const t=Math.floor(a/60);if(t<60)return`${t}m ago`;const s=Math.floor(t/60);return s<24?`${s}h ago`:`${Math.floor(s/24)}d ago`}function B(i){const[e]=A(i,["conversation","isActive","onSelect","compact","class"]),d=m(()=>e.conversation.trailing??Z(e.conversation.updatedAt??e.conversation.lastMessageAt));return(()=>{var a=W();return a.$$click=()=>e.onSelect(e.conversation.id),l(a,n(h,{get when(){return e.compact},get fallback(){return[(()=>{var t=X(),s=t.firstChild;return l(s,()=>e.conversation.title),l(t,n(h,{get when(){return d()},get children(){var g=$();return l(g,d),g}}),null),v(()=>p(s,f("min-w-0 flex-1 truncate text-sm",e.isActive?"font-medium text-foreground":"text-foreground/80"))),t})(),(()=>{var t=Y(),s=t.firstChild;return l(t,()=>e.conversation.messageCount,s),v(()=>p(t,f("mt-0.5 truncate text-xs",e.isActive?"text-foreground/70":"text-muted-foreground"))),t})()]},get children(){var t=V(),s=t.firstChild;return l(t,n(U,{get class(){return f("size-3.5 shrink-0",e.isActive?"text-foreground":"text-muted-foreground")}}),s),l(s,()=>e.conversation.title),l(t,n(h,{get when(){return d()},get children(){var g=$();return l(g,d),g}}),null),v(()=>p(s,f("min-w-0 flex-1 truncate text-sm",e.isActive?"font-medium text-foreground":"text-foreground/80"))),t}})),v(t=>{var s=e.conversation.id,g=f("w-full rounded-lg text-left transition-colors",e.compact?"px-2.5 py-1.5":"px-2.5 py-2",e.isActive?"bg-muted":"hover:bg-muted/50",e.class);return s!==t.e&&M(a,"data-conversation-id",t.e=s),g!==t.t&&p(a,t.t=g),t},{e:void 0,t:void 0}),a})()}N(["click"]);var _=c('<div class="px-3 pb-2"><div class="flex items-center gap-2 rounded-md bg-surface-strong px-2.5 py-1.5"><svg width=13 height=13 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 class=text-muted-foreground><circle cx=11 cy=11 r=8></circle><line x1=21 y1=21 x2=16.65 y2=16.65></line></svg><input type=text placeholder="Search chats..."aria-label="Search chats"class="bg-transparent text-[13px] text-foreground placeholder:text-muted-foreground rounded-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring w-full">'),ee=c('<div class="space-y-0.5 py-1">'),te=c('<div class="shrink-0 border-t border-border">'),re=c("<div>"),ne=c('<svg width=16 height=16 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2><line x1=3 y1=12 x2=21 y2=12></line><line x1=3 y1=6 x2=21 y2=6></line><line x1=3 y1=18 x2=21 y2=18>'),oe=c('<svg width=16 height=16 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2><line x1=12 y1=5 x2=12 y2=19></line><line x1=5 y1=12 x2=19 y2=12>'),ae=c('<div class="flex items-center justify-between p-3 pb-2"><div class="flex items-center gap-2"><span class="text-sm font-semibold text-foreground">Chats'),ie=c('<div class="flex flex-1 flex-col items-center justify-center gap-1 p-6 text-center text-sm text-muted-foreground">No conversations yet'),se=c('<svg width=10 height=10 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2><polyline points="6 9 12 15 18 9">'),le=c("<span>"),ce=c('<div class="pl-2 mt-0.5 space-y-0.5">');function ue(i){return n(C,{variant:"ghost",size:"icon-sm","aria-label":"Open sidebar",get class(){return f("rounded-full bg-card/80 shadow-sm backdrop-blur",i.class)},get onClick(){return i.onExpand},get children(){return n(K,{class:"size-4"})}})}function de(i){const[e]=A(i,["groups","conversations","activeId","onSelect","onNewChat","onToggleSidebar","header","footer","empty","compact","onSearchChange","controllerRef","class"]),[d,a]=y(""),t=m(()=>e.conversations.length===0);let s;const g=o=>{var r;a(o),(r=e.onSearchChange)==null||r.call(e,o)};O(()=>{var o;(o=e.controllerRef)==null||o.call(e,{focus:r=>s?.focus(r),clearSearch:()=>g("")})});const S=m(()=>{const o=d().toLowerCase();return o?e.conversations.filter(r=>r.title.toLowerCase().includes(o)):e.conversations}),T=m(()=>{const o=new Map;for(const r of S()){const u=r.groupId;o.has(u)||o.set(u,[]),o.get(u).push(r)}return o}),x=m(()=>{const o=new Set((e.groups??[]).map(r=>r.id));return S().filter(r=>r.groupId==null||!o.has(r.groupId))});return(()=>{var o=re();return l(o,n(h,{get when(){return e.header},get fallback(){return(()=>{var r=ae(),u=r.firstChild,b=u.firstChild;return l(u,n(C,{variant:"ghost",size:"icon-sm","aria-label":"Toggle sidebar",get onClick(){return e.onToggleSidebar},get children(){return ne()}}),b),l(r,n(C,{variant:"ghost",size:"icon-sm","aria-label":"New chat",get onClick(){return e.onNewChat},get children(){return oe()}}),null),r})()},get children(){return e.header}}),null),l(o,n(h,{get when(){return!t()},get children(){var r=_(),u=r.firstChild,b=u.firstChild,w=b.nextSibling;w.$$input=j=>g(j.currentTarget.value);var I=s;return typeof I=="function"?D(I,w):s=w,v(()=>w.value=d()),r}}),null),l(o,n(h,{get when(){return!t()},get fallback(){return n(h,{get when(){return e.empty},get fallback(){return ie()},get children(){return e.empty}})},get children(){return n(P,{class:"flex-1 px-2",get children(){return[n(k,{get each(){return e.groups},children:r=>{const u=m(()=>T().get(r.id)??[]);return n(h,{get when(){return u().length>0},get children(){return n(z,{get name(){return r.name},get count(){return u().length},get conversations(){return u()},get activeId(){return e.activeId},get onSelect(){return e.onSelect},get compact(){return e.compact}})}})}}),n(h,{get when(){return x().length>0},get children(){return n(h,{get when(){return e.compact},get fallback(){return n(z,{name:"Ungrouped",get count(){return x().length},get conversations(){return x()},get activeId(){return e.activeId},get onSelect(){return e.onSelect}})},get children(){var r=ee();return l(r,n(k,{get each(){return x()},children:u=>n(B,{conversation:u,get isActive(){return u.id===e.activeId},get onSelect(){return e.onSelect},compact:!0})})),r}})}})]}})}}),null),l(o,n(h,{get when(){return e.footer},get children(){var r=te();return l(r,()=>e.footer),r}}),null),v(()=>p(o,f("flex flex-col h-full bg-sidebar",e.class))),o})()}function z(i){const[e,d]=y(!0);return n(E,{get open(){return e()},onOpenChange:d,get children(){return[n(R,{class:"flex items-center gap-1.5 w-full px-1.5 py-1 rounded-md text-[13px] text-muted-foreground font-medium hover:bg-muted/30 transition-colors cursor-pointer mt-1.5",get children(){return[(()=>{var a=se();return v(()=>M(a,"class",f("transition-transform",!e()&&"-rotate-90"))),a})(),(()=>{var a=le();return l(a,()=>i.name),a})(),n(F,{variant:"count",class:"ml-auto text-[11px]",get children(){return i.count}})]}}),n(q,{get children(){var a=ce();return l(a,n(k,{get each(){return i.conversations},children:t=>n(B,{conversation:t,get isActive(){return t.id===i.activeId},get onSelect(){return i.onSelect},get compact(){return i.compact}})})),a}})]}})}N(["input"]);export{de as C,ue as a,Q as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{c as t,m as x,s as y,y as T,q as I,i as c,g as U,A as H,O as P,t as d,z as j,e as D,F as k,S as g,j as V,u as S,x as _}from"./define-BzPnNsXg.js";import{c as z}from"./cn-CU7UAWzk.js";import{C as q,s as B,n as E}from"./composer-D86ztyL0.js";import{P as M}from"./prompt-suggestion-Di_WZE_5.js";import{B as m}from"./button-CmkUkz6c.js";import{T as O}from"./tooltip-eB226mGK.js";import{A as F,a as N,d as W,e as G,i as J}from"./attachments-BB56zoji.js";import{a as K}from"./action-icons-CaYoImEk.js";import{p as Q,g as X}from"./paperclip-CdwKjrlu.js";import{m as Y}from"./icon-DKkmze3y.js";import{I as Z}from"./Icon-C-2LvGDG.js";var ee=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]],te=e=>t(Z,x(e,{name:"Square",iconNode:ee})),re=te,ne=d("<div data-prompt-input>"),ae=d("<div>");const L=j();function le(){const e=H(L);if(!e)throw new Error("PromptInput subcomponents must be used within PromptInput");return e}function ie(e){const[r,l]=y(e,["isLoading","value","onValueChange","maxHeight","onSubmit","children","disabled","class","onClick"]),[u,b]=U(r.value??"");let i;const h=s=>{var v;b(s),(v=r.onValueChange)==null||v.call(r,s)},w=s=>{r.disabled||i==null||i.focus(),typeof r.onClick=="function"&&r.onClick(s)};return t(L.Provider,{get value(){return{isLoading:r.isLoading??!1,value:()=>r.value??u(),setValue:r.onValueChange??h,maxHeight:r.maxHeight??240,onSubmit:r.onSubmit,get disabled(){return r.disabled},get textareaRef(){return i},setTextareaRef:s=>{i=s}}},get children(){var s=ne();return s.$$click=w,I(s,x({get class(){return z("bg-surface cursor-text rounded-xl p-2 shadow-xs","focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-0",r.disabled&&"cursor-not-allowed opacity-60",r.class)}},l),!1,!0),c(s,()=>r.children),s}})}function se(e){const[r]=y(e,["class","placeholder","aria-label","triggers","kindIcons","onComposerChange"]),l=le(),u=T(),b=()=>z("text-foreground min-h-[44px] w-full bg-transparent shadow-none outline-none focus-visible:ring-0 focus-visible:ring-offset-0 overflow-y-auto whitespace-pre-wrap break-words",P(u.proseSize()),r.class);return t(q,{bare:!0,get value(){return l.value()},get placeholder(){return r.placeholder},get ariaLabel(){return r["aria-label"]},get disabled(){return l.disabled},get maxHeight(){return l.maxHeight},get editableClass(){return b()},editableRef:i=>l.setTextareaRef(i),get triggers(){return r.triggers},get kindIcons(){return r.kindIcons},onChange:i=>{var h;(h=r.onComposerChange)==null||h.call(r,i),l.setValue(i.text.replace(/^\s+/,""))},onSubmit:()=>{var i;l.disabled||(i=l.onSubmit)==null||i.call(l)}})}function oe(e){const[r,l]=y(e,["children","class"]);return(()=>{var u=ae();return I(u,x({get class(){return z("flex items-center gap-2",r.class)}},l),!1,!0),c(u,()=>r.children),u})()}D(["click"]);var ue=d('<div class="mb-2 flex flex-wrap gap-2">'),ce=d('<div class="px-3 pt-3">'),de=d("<slot name=input-top>"),ge=d("<input type=file multiple class=hidden>"),he=d('<div class="flex items-center gap-2"><slot name=toolbar-start style=display:contents>'),pe=d('<div class="flex items-center gap-2"><slot name=toolbar-end>'),me=d('<span class="px-1 text-xs">'),be=d('<svg width=16 height=16 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2><line x1=12 y1=19 x2=12 y2=5></line><polyline points="5 12 12 5 19 12">');function fe(e){return{id:typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():`${e.name}-${e.size}-${e.lastModified}`,type:"file",filename:e.name,mediaType:e.type||void 0,url:e.type.startsWith("image/")?URL.createObjectURL(e):void 0}}function ve(e){let r;const l=()=>e.attachments??[],u=()=>!!e.onAttachmentsChange,b=n=>{!(n!=null&&n.length)||!e.onAttachmentsChange||e.onAttachmentsChange([...l(),...Array.from(n).map(fe)])},i=n=>{var o;return(o=e.onAttachmentsChange)==null?void 0:o.call(e,l().filter(a=>a.id!==n))},h=()=>B(E(e.value)),w=()=>e.disabled||e.loading||!h().trim()&&l().length===0,s=()=>!!e.loading&&!!e.stoppable,v=()=>!!h().trim()||l().length>0,$=()=>{const n=e.submit??"always";return n==="always"||n==="auto"&&v()};return[t(g,{get when(){var n;return(n=e.suggestions)==null?void 0:n.length},get children(){var n=ue();return c(n,t(k,{get each(){return e.suggestions},children:o=>t(M,{onClick:()=>e.onSuggestionClick(o),children:o})})),n}}),t(ie,{get value(){return e.value},get onValueChange(){return e.onValueChange},get onSubmit(){return e.onSubmit},get isLoading(){return e.loading},get disabled(){return e.disabled},class:"relative",get children(){return[t(g,{get when(){return V(()=>!!u())()&&l().length},get children(){var n=ce();return c(n,t(F,{variant:"inline",get children(){return t(k,{get each(){return l()},children:o=>t(N,{data:o,onRemove:()=>i(o.id),get children(){return[t(W,{}),t(G,{}),t(J,{})]}})})}})),n}}),(()=>{var n=de();return n._$owner=S(),n})(),t(se,{get placeholder(){return e.placeholder},get"aria-label"(){return e.placeholder||"Message"},class:"min-h-[44px] pt-3 pl-4",get triggers(){return e.triggers},get kindIcons(){return e.kindIcons},get onComposerChange(){return e.onComposerChange}}),t(oe,{class:"mt-2 flex w-full items-center justify-between gap-2 px-3 pb-0",get children(){return[(()=>{var n=he(),o=n.firstChild;return o._$owner=S(),c(n,t(g,{get when(){return V(()=>!!u())()&&e.attach!==!1},get children(){return[(()=>{var a=ge();a.addEventListener("change",C=>{b(C.currentTarget.files),C.currentTarget.value=""});var f=r;return typeof f=="function"?_(f,a):r=a,a})(),t(m,{type:"button",variant:"outline",size:"icon-sm",class:"rounded-full","aria-label":"Attach files",get disabled(){return e.disabled},onClick:()=>r?.click(),get children(){return t(Q,{class:"size-4"})}})]}}),null),c(n,t(g,{get when(){return e.search},get children(){return t(m,{type:"button",variant:"outline",size:"sm",class:"rounded-full gap-1","aria-label":"Search the web",get disabled(){return e.disabled},onClick:()=>{var a;return(a=e.onSearch)==null?void 0:a.call(e)},get children(){return[t(X,{class:"size-4"}),"Search"]}})}}),null),c(n,t(g,{get when(){return e.voice},get children(){return t(m,{type:"button",variant:"outline",size:"icon-sm",class:"rounded-full","aria-label":"Voice input",get disabled(){return e.disabled},onClick:()=>{var a;return(a=e.onVoice)==null?void 0:a.call(e)},get children(){return t(Y,{class:"size-4"})}})}}),null),c(n,t(k,{get each(){return e.toolbarActions??[]},children:a=>{const f=K(a.icon),C=a.tooltip??a.label,A=t(m,{type:"button",variant:"outline",size:"icon-sm",class:"rounded-full",get"aria-label"(){return a.label},get"data-action"(){return a.id},get disabled(){return e.disabled},onClick:()=>{var p;return(p=e.onAction)==null?void 0:p.call(e,a.id)},get children(){return t(g,{when:f,get fallback(){return(()=>{var p=me();return c(p,()=>a.label),p})()},children:p=>{const R=p();return t(R,{class:"size-4"})}})}});return f?t(O,{content:C,children:A}):A}}),null),n})(),(()=>{var n=pe(),o=n.firstChild;return o._$owner=S(),c(n,t(g,{get when(){return s()},get fallback(){return t(g,{get when(){return $()},get children(){return t(m,{size:"icon-sm",class:"rounded-full",part:"send","data-testid":"send","aria-label":"Send message",get disabled(){return w()},get onClick(){return e.onSubmit},get children(){return be()}})}})},get children(){return t(m,{size:"icon-sm",variant:"outline",class:"rounded-full","data-testid":"stop","aria-label":"Stop",get onClick(){return e.onStop},get children(){return t(re,{class:"size-3"})}})}}),null),n})()]}})]}})]}export{ve as D};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as e}from"./Icon-C-2LvGDG.js";import{c as m,m as o}from"./define-BzPnNsXg.js";var r=[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z",key:"1lielz"}]],s=a=>m(e,o(a,{name:"MessageSquare",iconNode:r})),i=s;export{i as m};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{s as C,c as r,m as I,j as y,F as m,g as k,i as d,S as h,a as p,d as M,b as O,t as a,e as R}from"./define-BzPnNsXg.js";import{c as f}from"./cn-CU7UAWzk.js";import{c as j,D as S,a as $,b as z}from"./dropdown-BjVVHWXH.js";import{B}from"./button-CmkUkz6c.js";var D=a('<svg width=12 height=12 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2><polyline points="6 9 12 15 18 9">'),F=a('<span class="text-caption text-muted-foreground">'),q=a('<div class="flex flex-col"><span>'),E=a("<div class=pl-2>"),P=a('<div><button type=button class="flex w-full items-center justify-between rounded-md px-2 py-1.5 text-body outline-none transition-colors hover:bg-muted focus:bg-muted">');const x=o=>(()=>{var e=D();return p(()=>M(e,"class",o.class)),e})();function b(o){const e=()=>o.model.description??o.model.provider;return r(z,{onSelect:()=>o.onModelChange(o.model.id),get children(){var s=q(),u=s.firstChild;return d(u,()=>o.model.name),d(s,r(h,{get when(){return e()},get children(){var c=F();return d(c,e),c}}),null),p(()=>O(u,f("text-body",o.model.id===o.currentModelId&&"font-medium text-foreground"))),s}})}function _(o){const[e]=C(o,["models","currentModelId","onModelChange","class","defaultOpen","disabled","controllerRef"]),s=()=>e.models.find(t=>t.id===e.currentModelId),u=()=>e.models.filter(t=>!t.group),c=()=>{const t=[],n=new Map;for(const l of e.models)l.group&&(n.has(l.group)||(n.set(l.group,[]),t.push(l.group)),n.get(l.group).push(l));return t.map(l=>({name:l,models:n.get(l)}))};return r(h,{get when(){return e.models.length>1},get children(){return r(j,{get defaultOpen(){return e.defaultOpen},get disabled(){return e.disabled},get controllerRef(){return e.controllerRef},get children(){return[r(S,{as:t=>r(B,I({variant:"ghost",size:"sm",get class(){return f("gap-1 text-meta text-muted-foreground",e.class)}},t,{get children(){return[y(()=>{var n;return((n=s())==null?void 0:n.name)??e.currentModelId}),r(x,{})]}}))}),r($,{get children(){return[r(m,{get each(){return u()},children:t=>r(b,{model:t,get currentModelId(){return e.currentModelId},get onModelChange(){return e.onModelChange}})}),r(m,{get each(){return c()},children:t=>{const[n,l]=k(!1);return(()=>{var g=P(),i=g.firstChild;return i.$$click=()=>l(!n()),d(i,()=>t.name,null),d(i,r(x,{get class(){return f("transition-transform",n()&&"rotate-180")}}),null),d(g,r(h,{get when(){return n()},get children(){var v=E();return d(v,r(m,{get each(){return t.models},children:w=>r(b,{model:w,get currentModelId(){return e.currentModelId},get onModelChange(){return e.onModelChange}})})),v}}),null),p(()=>M(i,"aria-expanded",n())),g})()}})]}})]}})}})}R(["click"]);export{_ as M};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{I as m}from"./Icon-C-2LvGDG.js";import{c as o,m as r}from"./define-BzPnNsXg.js";var e=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],t=a=>o(m,r(a,{name:"X",iconNode:e})),p=t;export{p as x};
|