@kitn.ai/ui 0.28.0 → 0.29.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/README.md +1 -1
- package/dist/agent-tooling/construct/public.d.ts +15 -0
- package/dist/agent-tooling/construct/schema.d.ts +111 -0
- package/dist/construct-cli.es.js +3 -3
- package/dist/construct.d.ts +5 -0
- package/dist/construct.js +327 -0
- package/dist/core-C8fzo39E.js +1 -12
- package/dist/engine-javascript-C1x7zo1_.js +1 -141
- package/dist/mcp.es.js +1 -1
- package/package.json +16 -16
- package/bin/route.test.js +0 -58
- package/src/agent-tooling/README.md +0 -192
- package/src/agent-tooling/archetypes.ts +0 -205
- package/src/agent-tooling/catalog/README.md +0 -676
- package/src/agent-tooling/catalog/catalog-types.ts +0 -231
- package/src/agent-tooling/catalog/fabrications.ts +0 -96
- package/src/agent-tooling/catalog/invariants.ts +0 -284
- package/src/agent-tooling/catalog/labs-titles.ts +0 -114
- package/src/agent-tooling/catalog/scenarios.ts +0 -87
- package/src/agent-tooling/catalog/surfaces.ts +0 -347
- package/src/agent-tooling/construct/cli-entry.ts +0 -8
- package/src/agent-tooling/construct/cli.ts +0 -147
- package/src/agent-tooling/construct/codegen.ts +0 -1635
- package/src/agent-tooling/construct/construct.v1.schema.json +0 -319
- package/src/agent-tooling/construct/dev.ts +0 -148
- package/src/agent-tooling/construct/fixtures/demo-widget.construct.json +0 -7
- package/src/agent-tooling/construct/fixtures/ops-console.construct.json +0 -44
- package/src/agent-tooling/construct/fixtures/owner-widget.construct.json +0 -32
- package/src/agent-tooling/construct/schema.ts +0 -452
- package/src/agent-tooling/integrations/anthropic.ts +0 -442
- package/src/agent-tooling/integrations/cloudflare.ts +0 -218
- package/src/agent-tooling/integrations/langgraph.ts +0 -133
- package/src/agent-tooling/integrations/mastra.ts +0 -182
- package/src/agent-tooling/integrations/mock.ts +0 -148
- package/src/agent-tooling/integrations/ollama.ts +0 -97
- package/src/agent-tooling/integrations/openai.ts +0 -95
- package/src/agent-tooling/integrations/openrouter.ts +0 -82
- package/src/agent-tooling/integrations/pi.ts +0 -176
- package/src/agent-tooling/integrations/pydantic-ai.ts +0 -108
- package/src/agent-tooling/integrations/vercel-ai-sdk.ts +0 -398
- package/src/agent-tooling/mcp/css-raw.d.ts +0 -12
- package/src/agent-tooling/mcp/manifest.ts +0 -422
- package/src/agent-tooling/mcp/server.ts +0 -116
- package/src/agent-tooling/mcp/stdio.ts +0 -18
- package/src/agent-tooling/mcp/tools/construct.ts +0 -130
- package/src/agent-tooling/mcp/tools/debug.ts +0 -621
- package/src/agent-tooling/mcp/tools/reference.ts +0 -980
- package/src/agent-tooling/mcp/tools/scaffold.ts +0 -6708
- package/src/agent-tooling/mcp/tools/theme.ts +0 -456
- package/src/agent-tooling/mcp/tools/types.ts +0 -14
- package/src/agent-tooling/mcp/validate-args.ts +0 -141
- package/src/agent-tooling/recipes/composed-thread.ts +0 -714
- package/src/agent-tooling/recipes/index.ts +0 -22
- package/src/agent-tooling/recipes/types.ts +0 -32
- package/src/agent-tooling/registry.ts +0 -132
- package/src/agent-tooling/route-emit.ts +0 -305
- package/src/agent-tooling/types.ts +0 -390
- package/src/components/artifact-card.tsx +0 -120
- package/src/components/artifact.tsx +0 -914
- package/src/components/attachment-types.ts +0 -66
- package/src/components/attachments.tsx +0 -536
- package/src/components/audio-visualizer/audio-visualizer.voice-fixture.ts +0 -257
- package/src/components/audio-visualizer/aurora.glsl.ts +0 -330
- package/src/components/audio-visualizer/fit-scale.ts +0 -112
- package/src/components/audio-visualizer/index.tsx +0 -528
- package/src/components/audio-visualizer/labs/lab-choreography.ts +0 -187
- package/src/components/audio-visualizer/labs/lab-shaders.ts +0 -363
- package/src/components/audio-visualizer/labs/lab-visualizer.tsx +0 -102
- package/src/components/audio-visualizer/shader-canvas.tsx +0 -876
- package/src/components/audio-visualizer/sizes.ts +0 -54
- package/src/components/audio-visualizer/variant-aurora.tsx +0 -305
- package/src/components/audio-visualizer/variant-bar.tsx +0 -175
- package/src/components/audio-visualizer/variant-custom.tsx +0 -344
- package/src/components/audio-visualizer/variant-grid.tsx +0 -175
- package/src/components/audio-visualizer/variant-radial.tsx +0 -163
- package/src/components/audio-visualizer/variant-wave.tsx +0 -130
- package/src/components/audio-visualizer/wave.glsl.ts +0 -130
- package/src/components/card-fallback.tsx +0 -60
- package/src/components/card-renderer.tsx +0 -220
- package/src/components/card.tsx +0 -212
- package/src/components/chain-of-thought.tsx +0 -348
- package/src/components/chat-container.tsx +0 -89
- package/src/components/chat-scope-picker.tsx +0 -57
- package/src/components/chat-thread.tsx +0 -1014
- package/src/components/checkpoint.tsx +0 -88
- package/src/components/choice-card.tsx +0 -743
- package/src/components/coachmark.tsx +0 -249
- package/src/components/code-block.tsx +0 -181
- package/src/components/composer-dom.ts +0 -159
- package/src/components/composer-highlight.ts +0 -242
- package/src/components/composer-history.ts +0 -82
- package/src/components/composer.tsx +0 -1075
- package/src/components/confirm-card.tsx +0 -402
- package/src/components/context.tsx +0 -377
- package/src/components/conversation-item.tsx +0 -241
- package/src/components/conversation-list.tsx +0 -429
- package/src/components/conversation-panel.tsx +0 -118
- package/src/components/dismissed-stub.tsx +0 -80
- package/src/components/embed.tsx +0 -200
- package/src/components/empty.tsx +0 -177
- package/src/components/feedback-bar.tsx +0 -166
- package/src/components/file-tree.tsx +0 -530
- package/src/components/file-upload.tsx +0 -167
- package/src/components/form-widgets.tsx +0 -525
- package/src/components/form.tsx +0 -1296
- package/src/components/home-panel.tsx +0 -159
- package/src/components/image.tsx +0 -65
- package/src/components/link-preview.tsx +0 -195
- package/src/components/loader.tsx +0 -367
- package/src/components/markdown.tsx +0 -162
- package/src/components/message-skills.tsx +0 -40
- package/src/components/message.tsx +0 -765
- package/src/components/model-switcher.tsx +0 -132
- package/src/components/prompt-input.tsx +0 -188
- package/src/components/prompt-suggestion.tsx +0 -150
- package/src/components/reasoning.tsx +0 -293
- package/src/components/response-compare-types.ts +0 -152
- package/src/components/response-compare.tsx +0 -455
- package/src/components/response-stream.tsx +0 -109
- package/src/components/screen.tsx +0 -181
- package/src/components/scroll-button.tsx +0 -93
- package/src/components/source.tsx +0 -192
- package/src/components/tasks-card.tsx +0 -801
- package/src/components/text-shimmer.tsx +0 -37
- package/src/components/thinking-bar.tsx +0 -50
- package/src/components/thread.tsx +0 -228
- package/src/components/toast.tsx +0 -503
- package/src/components/tool-classify.ts +0 -26
- package/src/components/tool-types.ts +0 -49
- package/src/components/tool.tsx +0 -190
- package/src/components/use-card-resolution.ts +0 -44
- package/src/components/voice-input.tsx +0 -222
- package/src/components/voice-output.tsx +0 -242
- package/src/components/widget-tab-bar.tsx +0 -73
- package/src/components/workspace-shell.tsx +0 -285
- package/src/diagnostics/hook.ts +0 -352
- package/src/diagnostics/index.ts +0 -82
- package/src/diagnostics/report-request.ts +0 -296
- package/src/elements/agent-card.tsx +0 -67
- package/src/elements/artifact.tsx +0 -194
- package/src/elements/attachments.tsx +0 -140
- package/src/elements/audio-visualizer.tsx +0 -227
- package/src/elements/autoloader.ts +0 -89
- package/src/elements/avatar.tsx +0 -33
- package/src/elements/badge.tsx +0 -32
- package/src/elements/button.tsx +0 -149
- package/src/elements/card.tsx +0 -133
- package/src/elements/cards.tsx +0 -266
- package/src/elements/chain-of-thought.tsx +0 -141
- package/src/elements/chat-scope-picker.tsx +0 -65
- package/src/elements/chat-types.ts +0 -102
- package/src/elements/chat-workspace.tsx +0 -188
- package/src/elements/chat.tsx +0 -304
- package/src/elements/checkbox-group.tsx +0 -164
- package/src/elements/checkbox.tsx +0 -134
- package/src/elements/checkpoint.tsx +0 -47
- package/src/elements/choice.tsx +0 -100
- package/src/elements/coachmark.tsx +0 -90
- package/src/elements/code-block.tsx +0 -60
- package/src/elements/command.tsx +0 -197
- package/src/elements/compare.tsx +0 -111
- package/src/elements/compiled.css +0 -2
- package/src/elements/composer.tsx +0 -162
- package/src/elements/confirm-card.tsx +0 -76
- package/src/elements/context-meter.tsx +0 -107
- package/src/elements/conversation-item.tsx +0 -120
- package/src/elements/conversation-list.tsx +0 -203
- package/src/elements/css.ts +0 -5
- package/src/elements/default-input.tsx +0 -392
- package/src/elements/define-entry.ts +0 -12
- package/src/elements/define.tsx +0 -563
- package/src/elements/diagnostic-events.ts +0 -114
- package/src/elements/dialog.tsx +0 -145
- package/src/elements/disclosure.ts +0 -95
- package/src/elements/dock.tsx +0 -215
- package/src/elements/dropdown.tsx +0 -123
- package/src/elements/editable-label.tsx +0 -140
- package/src/elements/element-data-types.ts +0 -152
- package/src/elements/element-diagnostics.ts +0 -392
- package/src/elements/element-manifest.json +0 -354
- package/src/elements/element-nonscalar.json +0 -187
- package/src/elements/element-types.d.ts +0 -4353
- package/src/elements/embed.tsx +0 -35
- package/src/elements/empty.tsx +0 -29
- package/src/elements/feedback-bar.tsx +0 -66
- package/src/elements/file-tree.tsx +0 -62
- package/src/elements/file-upload.tsx +0 -44
- package/src/elements/form.tsx +0 -94
- package/src/elements/hover-card.tsx +0 -80
- package/src/elements/icon.tsx +0 -41
- package/src/elements/image.tsx +0 -32
- package/src/elements/input.tsx +0 -492
- package/src/elements/kbd.tsx +0 -45
- package/src/elements/link-preview.tsx +0 -34
- package/src/elements/loader.tsx +0 -25
- package/src/elements/markdown.tsx +0 -38
- package/src/elements/menu.tsx +0 -241
- package/src/elements/message-skills.tsx +0 -83
- package/src/elements/message.tsx +0 -361
- package/src/elements/model-switcher.tsx +0 -121
- package/src/elements/nav.tsx +0 -87
- package/src/elements/notice.tsx +0 -53
- package/src/elements/pane-grid.tsx +0 -111
- package/src/elements/pane-group.tsx +0 -119
- package/src/elements/pane.tsx +0 -129
- package/src/elements/popover.tsx +0 -81
- package/src/elements/progress-bar.tsx +0 -39
- package/src/elements/prompt-dock.tsx +0 -82
- package/src/elements/prompt-input.tsx +0 -240
- package/src/elements/prompt-suggestions.tsx +0 -113
- package/src/elements/radio-group.tsx +0 -129
- package/src/elements/reasoning.tsx +0 -71
- package/src/elements/register-impl.ts +0 -148
- package/src/elements/register.ts +0 -76
- package/src/elements/remote.tsx +0 -225
- package/src/elements/resizable.globals.d.ts +0 -36
- package/src/elements/resizable.tsx +0 -704
- package/src/elements/response-stream.tsx +0 -40
- package/src/elements/screen.tsx +0 -90
- package/src/elements/scroll-area.tsx +0 -33
- package/src/elements/scroll-button.tsx +0 -179
- package/src/elements/search.tsx +0 -185
- package/src/elements/segmented.tsx +0 -129
- package/src/elements/select.tsx +0 -165
- package/src/elements/separator.tsx +0 -36
- package/src/elements/setting-item.tsx +0 -50
- package/src/elements/settings-group.tsx +0 -37
- package/src/elements/skeleton.tsx +0 -45
- package/src/elements/slider.tsx +0 -171
- package/src/elements/slot-text.ts +0 -73
- package/src/elements/slots.ts +0 -787
- package/src/elements/source.tsx +0 -126
- package/src/elements/status.tsx +0 -42
- package/src/elements/styles.css +0 -328
- package/src/elements/switch.tsx +0 -118
- package/src/elements/tabs.tsx +0 -95
- package/src/elements/tasks.tsx +0 -103
- package/src/elements/text-shimmer.tsx +0 -28
- package/src/elements/thinking-bar.tsx +0 -43
- package/src/elements/thread.tsx +0 -139
- package/src/elements/toast.tsx +0 -106
- package/src/elements/tool.tsx +0 -78
- package/src/elements/tooltip.tsx +0 -85
- package/src/elements/validate-messages.ts +0 -76
- package/src/elements/voice-input.tsx +0 -100
- package/src/elements/voice-output.tsx +0 -82
- package/src/index.ts +0 -430
- package/src/primitives/audio-bands.ts +0 -174
- package/src/primitives/card-component-types.ts +0 -63
- package/src/primitives/card-contract.ts +0 -80
- package/src/primitives/card-data-types.ts +0 -361
- package/src/primitives/card-host.tsx +0 -37
- package/src/primitives/card-recovery.ts +0 -160
- package/src/primitives/card-registry.tsx +0 -78
- package/src/primitives/card-resolution.ts +0 -36
- package/src/primitives/card-routing.ts +0 -85
- package/src/primitives/card-schemas/artifact.schema.json +0 -92
- package/src/primitives/card-schemas/card-envelope.schema.json +0 -14
- package/src/primitives/card-schemas/card-event.schema.json +0 -12
- package/src/primitives/card-schemas/choice.schema.json +0 -75
- package/src/primitives/card-schemas/confirm.schema.json +0 -65
- package/src/primitives/card-schemas/embed.schema.json +0 -63
- package/src/primitives/card-schemas/form.result.schema.json +0 -7
- package/src/primitives/card-schemas/form.schema.json +0 -53
- package/src/primitives/card-schemas/link.schema.json +0 -54
- package/src/primitives/card-schemas/tasks.result.schema.json +0 -16
- package/src/primitives/card-schemas/tasks.schema.json +0 -83
- package/src/primitives/card-tags.ts +0 -61
- package/src/primitives/card-validate-cards.ts +0 -255
- package/src/primitives/card-validate-schemas.ts +0 -58
- package/src/primitives/card-validate.ts +0 -131
- package/src/primitives/chat-config.tsx +0 -103
- package/src/primitives/composer-model.ts +0 -49
- package/src/primitives/composer-triggers.ts +0 -35
- package/src/primitives/controllable.ts +0 -21
- package/src/primitives/conversation-store.ts +0 -248
- package/src/primitives/create-kai-chat.ts +0 -66
- package/src/primitives/create-tween.ts +0 -266
- package/src/primitives/embed-providers.ts +0 -254
- package/src/primitives/field-mask.ts +0 -256
- package/src/primitives/field-semantics.ts +0 -115
- package/src/primitives/highlighter.ts +0 -157
- package/src/primitives/input-mask.ts +0 -853
- package/src/primitives/link-preview.ts +0 -87
- package/src/primitives/message-feedback.ts +0 -124
- package/src/primitives/pdf-preview.ts +0 -121
- package/src/primitives/toast-store.ts +0 -338
- package/src/primitives/url-scheme-policy.ts +0 -70
- package/src/primitives/use-audio-analysis.ts +0 -340
- package/src/primitives/use-auto-resize.ts +0 -31
- package/src/primitives/use-resize-observer.ts +0 -45
- package/src/primitives/use-sequencer.ts +0 -72
- package/src/primitives/use-speech-recognition.ts +0 -146
- package/src/primitives/use-stick-to-bottom.ts +0 -75
- package/src/primitives/use-text-stream.ts +0 -143
- package/src/primitives/use-voice-recorder.ts +0 -62
- package/src/primitives/visualizer-sequences.ts +0 -350
- package/src/remote/host-embed.ts +0 -345
- package/src/remote/index.ts +0 -2
- package/src/remote/origin.ts +0 -30
- package/src/remote/provider-runtime.ts +0 -262
- package/src/remote/provider.ts +0 -2
- package/src/remote/validate.ts +0 -22
- package/src/remote/version.ts +0 -12
- package/src/remote/wire.ts +0 -48
- package/src/schemas/from-tool-call.ts +0 -151
- package/src/schemas/index.ts +0 -341
- package/src/schemas/provider-subsets.ts +0 -538
- package/src/schemas/registry.ts +0 -355
- package/src/schemas/tool-defs.ts +0 -793
- package/src/solid.ts +0 -173
- package/src/state/index.ts +0 -44
- package/src/state/messages.ts +0 -53
- package/src/state/mock.ts +0 -297
- package/src/state/parts.ts +0 -295
- package/src/state/persistence.ts +0 -180
- package/src/state/stream.ts +0 -246
- package/src/state/suggestions.ts +0 -9
- package/src/state/threads.ts +0 -142
- package/src/test-utils/fake-clock.ts +0 -88
- package/src/types.ts +0 -95
- package/src/ui/action-icons.ts +0 -53
- package/src/ui/agent-card.tsx +0 -218
- package/src/ui/avatar.tsx +0 -23
- package/src/ui/badge.tsx +0 -21
- package/src/ui/button.tsx +0 -49
- package/src/ui/card.tsx +0 -245
- package/src/ui/checkbox-group.tsx +0 -153
- package/src/ui/checkbox.tsx +0 -63
- package/src/ui/collapsible.tsx +0 -163
- package/src/ui/command.tsx +0 -103
- package/src/ui/dialog.tsx +0 -223
- package/src/ui/dock.tsx +0 -630
- package/src/ui/dropdown.tsx +0 -636
- package/src/ui/editable-label.tsx +0 -112
- package/src/ui/hover-card.tsx +0 -345
- package/src/ui/icon.tsx +0 -167
- package/src/ui/input.tsx +0 -391
- package/src/ui/kbd.tsx +0 -118
- package/src/ui/nav.tsx +0 -282
- package/src/ui/notice.tsx +0 -84
- package/src/ui/overlay.tsx +0 -277
- package/src/ui/pane-grid.tsx +0 -117
- package/src/ui/pane-group.tsx +0 -291
- package/src/ui/pane.tsx +0 -193
- package/src/ui/popover.tsx +0 -106
- package/src/ui/progress-bar.tsx +0 -83
- package/src/ui/prompt-dock.tsx +0 -145
- package/src/ui/radio.tsx +0 -150
- package/src/ui/resizable.tsx +0 -693
- package/src/ui/scroll-area.tsx +0 -26
- package/src/ui/segmented.tsx +0 -109
- package/src/ui/select.tsx +0 -168
- package/src/ui/separator.tsx +0 -10
- package/src/ui/settings-group.tsx +0 -67
- package/src/ui/skeleton.tsx +0 -73
- package/src/ui/slider.tsx +0 -178
- package/src/ui/status.tsx +0 -48
- package/src/ui/switch.tsx +0 -119
- package/src/ui/tabs.tsx +0 -168
- package/src/ui/textarea.tsx +0 -21
- package/src/ui/tooltip.tsx +0 -118
- package/src/utils/cn.ts +0 -30
- package/src/wire/chunk.ts +0 -248
- package/src/wire/consume.ts +0 -599
- package/src/wire/diagnostics.ts +0 -727
- package/src/wire/encode-probe.ts +0 -214
- package/src/wire/encode.ts +0 -947
- package/src/wire/files.ts +0 -342
- package/src/wire/formats/anthropic.ts +0 -274
- package/src/wire/formats/openai.ts +0 -228
- package/src/wire/index.ts +0 -95
- package/src/wire/media-types.ts +0 -344
- package/src/wire/read.ts +0 -396
- package/src/wire/sink-helpers.ts +0 -50
- package/src/wire/sse.ts +0 -153
package/src/elements/css.ts
DELETED
|
@@ -1,392 +0,0 @@
|
|
|
1
|
-
import { For, Show } from 'solid-js';
|
|
2
|
-
import { PromptInput, PromptInputTextarea, PromptInputActions } from '../components/prompt-input';
|
|
3
|
-
import type { TriggerDef, ComposerChange } from '../components/composer';
|
|
4
|
-
import { type ComposerDoc, normalizeValue, serializeToText } from '../primitives/composer-model';
|
|
5
|
-
import { PromptSuggestion } from '../components/prompt-suggestion';
|
|
6
|
-
import { Button } from '../ui/button';
|
|
7
|
-
import { Tooltip } from '../ui/tooltip';
|
|
8
|
-
import { Paperclip, Globe, Mic, Square } from 'lucide-solid';
|
|
9
|
-
import {
|
|
10
|
-
Attachments,
|
|
11
|
-
Attachment,
|
|
12
|
-
AttachmentPreview,
|
|
13
|
-
AttachmentInfo,
|
|
14
|
-
AttachmentRemove,
|
|
15
|
-
type AttachmentData,
|
|
16
|
-
} from '../components/attachments';
|
|
17
|
-
import { actionIcon } from '../ui/action-icons';
|
|
18
|
-
import type { CustomAction } from './chat-types';
|
|
19
|
-
// The LEAF module, deliberately not the `../wire` barrel: this needs the media
|
|
20
|
-
// declaration, and importing the barrel would pull the whole stream adapter into
|
|
21
|
-
// the elements bundle for a table of strings. Sharing the module itself (rather
|
|
22
|
-
// than copying the list into the composer) is the entire point -- a second list
|
|
23
|
-
// here is the drift this design exists to prevent.
|
|
24
|
-
import { resolveMediaPolicy, type MediaTypeFilter } from '../wire/media-types';
|
|
25
|
-
// Also a leaf, and imported for the same reason: when the browser cannot name a
|
|
26
|
-
// file, the question "can this be sent?" is answered by decoding its bytes, and
|
|
27
|
-
// this module is where that decode already lives. Asking IT rather than growing
|
|
28
|
-
// a second decoder here is what keeps the composer's answer and the encoder's
|
|
29
|
-
// answer the same answer, byte for byte, instead of two that agree today.
|
|
30
|
-
import { classifyAttachment } from '../wire/files';
|
|
31
|
-
|
|
32
|
-
/** One file the composer refused, as facts rather than as a message. The kit
|
|
33
|
-
* says what happened; the application decides what the user reads. */
|
|
34
|
-
export interface RejectedAttachment {
|
|
35
|
-
filename: string;
|
|
36
|
-
/** The browser's media type for the file, or `''` when it could not tell. An
|
|
37
|
-
* empty one is not by itself why a file was rejected: an unnamed file is
|
|
38
|
-
* decided by decoding its bytes, so `''` here means the decode is what said
|
|
39
|
-
* no (binary), or that your `accept` left no text type for it to land in. */
|
|
40
|
-
mediaType: string;
|
|
41
|
-
/** `'filtered'` = this kit could have sent it, your `accept` excluded it.
|
|
42
|
-
* `'unsupported'` = no API takes this as message content at all. */
|
|
43
|
-
reason: 'filtered' | 'unsupported';
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface DefaultPromptInputProps {
|
|
47
|
-
/** String = controlled text mirror; ComposerDoc = a seed that pre-populates pills. */
|
|
48
|
-
value: string | ComposerDoc;
|
|
49
|
-
placeholder?: string;
|
|
50
|
-
disabled?: boolean;
|
|
51
|
-
loading?: boolean;
|
|
52
|
-
suggestions?: string[];
|
|
53
|
-
/** Attachments staged in the input. Provide `onAttachmentsChange` to enable
|
|
54
|
-
* the attach button + removable previews. */
|
|
55
|
-
attachments?: AttachmentData[];
|
|
56
|
-
/** When `false`, the built-in paperclip attach button is hidden even if
|
|
57
|
-
* `onAttachmentsChange` is provided (e.g. when a `+` menu already covers
|
|
58
|
-
* file-attach). Defaults to `true`. */
|
|
59
|
-
attach?: boolean;
|
|
60
|
-
/** Which attachment media types the user may stage, in HTML `accept` syntax
|
|
61
|
-
* (`'image/*,application/pdf'`). Omitted means no filter, exactly as before.
|
|
62
|
-
*
|
|
63
|
-
* NARROWED BY WHAT THE ENCODERS CAN SEND: `'image/*'` here resolves to the
|
|
64
|
-
* four image formats both APIs actually accept, not to every image type the
|
|
65
|
-
* OS will offer. It is the same string, resolved by the same function against
|
|
66
|
-
* the same declaration, as `toOpenAIMessages(msgs, { accept })` -- so a file
|
|
67
|
-
* the picker allows is a file the wire can carry. */
|
|
68
|
-
accept?: MediaTypeFilter;
|
|
69
|
-
/** Files that were dropped because `accept` excluded them. Carries the facts
|
|
70
|
-
* (name, media type, reason) and renders nothing itself: what the user should
|
|
71
|
-
* see is the application's call, not the kit's. */
|
|
72
|
-
onAttachmentsRejected?: (rejected: RejectedAttachment[]) => void;
|
|
73
|
-
/** Show a web-search (Globe) button in the left toolbar; calls `onWebSearch`. */
|
|
74
|
-
webSearch?: boolean;
|
|
75
|
-
/** Show a Voice (Mic) button in the left toolbar; calls `onVoice`. */
|
|
76
|
-
voice?: boolean;
|
|
77
|
-
/** Send-button visibility. `'always'` (default) always shows it; `'auto'` shows
|
|
78
|
-
* it only when there's text/attachments (an empty composer hides it, though
|
|
79
|
-
* Enter still submits). To hide it entirely (Enter-only), it's pure CSS:
|
|
80
|
-
* `::part(send){display:none}`, no prop needed. Restyle via `::part(send)`.
|
|
81
|
-
* The Stop button (stoppable + loading) is unaffected. */
|
|
82
|
-
submit?: 'always' | 'auto';
|
|
83
|
-
onValueChange: (v: string) => void;
|
|
84
|
-
onSubmit: () => void;
|
|
85
|
-
onSuggestionClick: (v: string) => void;
|
|
86
|
-
onAttachmentsChange?: (attachments: AttachmentData[]) => void;
|
|
87
|
-
onWebSearch?: () => void;
|
|
88
|
-
onVoice?: () => void;
|
|
89
|
-
/** When `true` and `loading` is also `true`, the send button is replaced by
|
|
90
|
-
* a Stop button that calls `onStop`. */
|
|
91
|
-
stoppable?: boolean;
|
|
92
|
-
/** Called when the user clicks the Stop button. */
|
|
93
|
-
onStop?: () => void;
|
|
94
|
-
/** Custom toolbar action buttons declared as `<kai-action>` light-DOM children. */
|
|
95
|
-
toolbarActions?: CustomAction[];
|
|
96
|
-
/** Called when a custom toolbar action button is clicked, with the action id. */
|
|
97
|
-
onAction?: (id: string) => void;
|
|
98
|
-
/** Rich entity triggers (`/` skills, `@` agents) passed to the composer. */
|
|
99
|
-
triggers?: TriggerDef[];
|
|
100
|
-
/** Default icon per entity kind (kind → image src) passed to the composer. */
|
|
101
|
-
kindIcons?: Record<string, string>;
|
|
102
|
-
/** Structured change (doc + entities) from the composer, on every edit. */
|
|
103
|
-
onComposerChange?: (change: ComposerChange) => void;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/** The staged file as a `data:` URI.
|
|
107
|
-
*
|
|
108
|
-
* NOT `URL.createObjectURL`. An object URL resolves only inside the tab that
|
|
109
|
-
* minted it, so it renders a perfect thumbnail here and is meaningless to
|
|
110
|
-
* anything downstream — `toOpenAIMessages` / `toAnthropicMessages` refuse it,
|
|
111
|
-
* and before they refused it the attachment reached the model as nothing at
|
|
112
|
-
* all. A data URI previews identically and is the one form both providers
|
|
113
|
-
* actually take. */
|
|
114
|
-
const readAsDataUrl = (file: File): Promise<string> =>
|
|
115
|
-
new Promise((resolve, reject) => {
|
|
116
|
-
const reader = new FileReader();
|
|
117
|
-
reader.onload = () => resolve(String(reader.result));
|
|
118
|
-
reader.onerror = () => reject(reader.error ?? new Error(`Could not read ${file.name}`));
|
|
119
|
-
reader.readAsDataURL(file);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
async function fileToAttachment(file: File): Promise<AttachmentData> {
|
|
123
|
-
const id =
|
|
124
|
-
typeof crypto !== 'undefined' && crypto.randomUUID
|
|
125
|
-
? crypto.randomUUID()
|
|
126
|
-
: `${file.name}-${file.size}-${file.lastModified}`;
|
|
127
|
-
return {
|
|
128
|
-
id,
|
|
129
|
-
type: 'file',
|
|
130
|
-
filename: file.name,
|
|
131
|
-
mediaType: file.type || undefined,
|
|
132
|
-
// EVERY file, not just images. A document used to get no `url` at all,
|
|
133
|
-
// which left it unencodable for exactly the same reason a blob: URL is.
|
|
134
|
-
url: await readAsDataUrl(file),
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export function DefaultPromptInput(props: DefaultPromptInputProps) {
|
|
139
|
-
let fileInput: HTMLInputElement | undefined;
|
|
140
|
-
const attachments = () => props.attachments ?? [];
|
|
141
|
-
const canAttach = () => !!props.onAttachmentsChange;
|
|
142
|
-
|
|
143
|
-
// The SAME resolver the encoders call, on the same declaration. Recomputed
|
|
144
|
-
// reactively so a host that swaps `accept` at runtime moves the picker hint
|
|
145
|
-
// and the filter together.
|
|
146
|
-
const mediaPolicy = () => resolveMediaPolicy({ accept: props.accept });
|
|
147
|
-
|
|
148
|
-
const addFiles = async (files: FileList | null) => {
|
|
149
|
-
if (!files?.length || !props.onAttachmentsChange) return;
|
|
150
|
-
|
|
151
|
-
// The `accept` ATTRIBUTE below is only a hint — every OS dialog offers an
|
|
152
|
-
// "All Files" escape, and it does not apply to drag-and-drop at all. So the
|
|
153
|
-
// filter that actually holds is this one, in JS, on the files as staged.
|
|
154
|
-
const policy = mediaPolicy();
|
|
155
|
-
const picked = Array.from(files);
|
|
156
|
-
// No `accept` means no filtering, which is what every existing consumer gets
|
|
157
|
-
// today. Opting in is what turns the picker into a guarantee.
|
|
158
|
-
const decisions = picked.map((file) =>
|
|
159
|
-
props.accept === undefined ? undefined : policy.decide(file.type),
|
|
160
|
-
);
|
|
161
|
-
// Read a file when its media type says yes, and ALSO when its media type
|
|
162
|
-
// says nothing at all: `undetermined` means the browser could not name it,
|
|
163
|
-
// and the only honest way to answer is to look at the bytes. Reading is the
|
|
164
|
-
// cost of that answer, so it is spent only on files that could still be
|
|
165
|
-
// staged — a file the filter already rejected is never read.
|
|
166
|
-
const needsBytes = (d: (typeof decisions)[number]): boolean =>
|
|
167
|
-
d === undefined || d.status === 'allowed' || d.status === 'undetermined';
|
|
168
|
-
// One parallel pass, index-aligned with `picked`, so the staged order is the
|
|
169
|
-
// PICK order rather than whichever file finished reading first.
|
|
170
|
-
const read = await Promise.all(
|
|
171
|
-
picked.map((file, i) => (needsBytes(decisions[i]) ? fileToAttachment(file) : undefined)),
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
const staged: AttachmentData[] = [];
|
|
175
|
-
const rejected: RejectedAttachment[] = [];
|
|
176
|
-
picked.forEach((file, i) => {
|
|
177
|
-
const decision = decisions[i];
|
|
178
|
-
const attachment = read[i];
|
|
179
|
-
if (decision === undefined || decision.status === 'allowed') {
|
|
180
|
-
if (attachment) staged.push(attachment);
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
if (decision.status === 'undetermined') {
|
|
184
|
-
// The bytes are in hand now, so the encoder can answer for real. Its
|
|
185
|
-
// verdict IS the composer's verdict: staging anything it would refuse is
|
|
186
|
-
// the exact defect (#186) this whole design exists to prevent.
|
|
187
|
-
if (attachment && classifyAttachment(attachment, policy).status === 'encodable') {
|
|
188
|
-
staged.push(attachment);
|
|
189
|
-
} else {
|
|
190
|
-
// Not `filtered`: the kit could not encode this either, so pointing
|
|
191
|
-
// the developer at their own `accept` would send them the wrong way.
|
|
192
|
-
rejected.push({ filename: file.name, mediaType: file.type, reason: 'unsupported' });
|
|
193
|
-
}
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
rejected.push({ filename: file.name, mediaType: file.type, reason: decision.status });
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
if (rejected.length > 0) props.onAttachmentsRejected?.(rejected);
|
|
200
|
-
if (staged.length === 0) return;
|
|
201
|
-
// Re-read `attachments()` AFTER the await — a second drop while these were
|
|
202
|
-
// being read would otherwise be overwritten by this call's stale snapshot.
|
|
203
|
-
props.onAttachmentsChange?.([...attachments(), ...staged]);
|
|
204
|
-
};
|
|
205
|
-
const removeAttachment = (id: string) =>
|
|
206
|
-
props.onAttachmentsChange?.(attachments().filter((a) => a.id !== id));
|
|
207
|
-
|
|
208
|
-
// `value` may be a string or a seeded ComposerDoc — compute emptiness from the
|
|
209
|
-
// flattened text so a pill-only seed still enables Send.
|
|
210
|
-
const valueText = () => serializeToText(normalizeValue(props.value));
|
|
211
|
-
const sendDisabled = () =>
|
|
212
|
-
props.disabled || props.loading || (!valueText().trim() && attachments().length === 0);
|
|
213
|
-
|
|
214
|
-
const showStop = () => !!props.loading && !!props.stoppable;
|
|
215
|
-
const hasContent = () => !!valueText().trim() || attachments().length > 0;
|
|
216
|
-
// Send-button visibility: 'always' (default) or 'auto' (only with content).
|
|
217
|
-
// Full-hide (Enter-only) is CSS: `::part(send){display:none}`.
|
|
218
|
-
const showSend = () => {
|
|
219
|
-
const mode = props.submit ?? 'always';
|
|
220
|
-
return mode === 'always' || (mode === 'auto' && hasContent());
|
|
221
|
-
};
|
|
222
|
-
|
|
223
|
-
return (
|
|
224
|
-
<>
|
|
225
|
-
<Show when={props.suggestions?.length}>
|
|
226
|
-
<div class="mb-2 flex flex-wrap gap-2">
|
|
227
|
-
<For each={props.suggestions}>
|
|
228
|
-
{(s) => (
|
|
229
|
-
<PromptSuggestion onClick={() => props.onSuggestionClick(s)}>{s}</PromptSuggestion>
|
|
230
|
-
)}
|
|
231
|
-
</For>
|
|
232
|
-
</div>
|
|
233
|
-
</Show>
|
|
234
|
-
<PromptInput
|
|
235
|
-
value={props.value}
|
|
236
|
-
onValueChange={props.onValueChange}
|
|
237
|
-
onSubmit={props.onSubmit}
|
|
238
|
-
isLoading={props.loading}
|
|
239
|
-
disabled={props.disabled}
|
|
240
|
-
class="relative"
|
|
241
|
-
>
|
|
242
|
-
<Show when={canAttach() && attachments().length}>
|
|
243
|
-
<div class="px-3 pt-3">
|
|
244
|
-
<Attachments variant="inline">
|
|
245
|
-
<For each={attachments()}>
|
|
246
|
-
{(att) => (
|
|
247
|
-
<Attachment data={att} onRemove={() => removeAttachment(att.id)}>
|
|
248
|
-
<AttachmentPreview />
|
|
249
|
-
<AttachmentInfo />
|
|
250
|
-
<AttachmentRemove />
|
|
251
|
-
</Attachment>
|
|
252
|
-
)}
|
|
253
|
-
</For>
|
|
254
|
-
</Attachments>
|
|
255
|
-
</div>
|
|
256
|
-
</Show>
|
|
257
|
-
{/* Consumer-injected content inside the card, above the textarea (e.g. an
|
|
258
|
-
inline status strip). A shadow-internal hole — unreachable from outside.
|
|
259
|
-
Native slot; inert outside a shadow root, projected by the custom element. */}
|
|
260
|
-
<slot name="input-top" />
|
|
261
|
-
<PromptInputTextarea placeholder={props.placeholder} aria-label={props.placeholder || 'Message'} class="min-h-[44px] pt-3 pl-4" triggers={props.triggers} kindIcons={props.kindIcons} onComposerChange={props.onComposerChange} />
|
|
262
|
-
<PromptInputActions class="mt-2 flex w-full items-center justify-between gap-2 px-3 pb-0">
|
|
263
|
-
<div class="flex items-center gap-2">
|
|
264
|
-
{/* Consumer-injected leading toolbar controls (e.g. a + menu). display:contents
|
|
265
|
-
ensures an empty slot adds no stray gap; projected nodes lay out as toolbar
|
|
266
|
-
items. Native slot; projected by the custom element. */}
|
|
267
|
-
<slot name="toolbar-start" style={{ display: 'contents' }} />
|
|
268
|
-
<Show when={canAttach() && props.attach !== false}>
|
|
269
|
-
<input
|
|
270
|
-
ref={fileInput}
|
|
271
|
-
type="file"
|
|
272
|
-
multiple
|
|
273
|
-
class="hidden"
|
|
274
|
-
// Derived from the same policy as the filter above, never spelled
|
|
275
|
-
// out again. `accept="image/*"` narrows to the image formats the
|
|
276
|
-
// wire can actually carry, so the OS dialog greys out the SVG
|
|
277
|
-
// that would otherwise 400 at request time.
|
|
278
|
-
accept={props.accept === undefined ? undefined : mediaPolicy().accept}
|
|
279
|
-
onChange={(e) => {
|
|
280
|
-
// Reading is async now, so this is deliberately not awaited.
|
|
281
|
-
// `addFiles` captures the FileList synchronously, before its
|
|
282
|
-
// first await, so clearing the input below cannot race it.
|
|
283
|
-
void addFiles(e.currentTarget.files);
|
|
284
|
-
e.currentTarget.value = ''; // allow re-picking the same file
|
|
285
|
-
}}
|
|
286
|
-
/>
|
|
287
|
-
<Button
|
|
288
|
-
type="button"
|
|
289
|
-
variant="outline"
|
|
290
|
-
size="icon-sm"
|
|
291
|
-
class="rounded-full"
|
|
292
|
-
aria-label="Attach files"
|
|
293
|
-
disabled={props.disabled}
|
|
294
|
-
onClick={() => fileInput?.click()}
|
|
295
|
-
>
|
|
296
|
-
<Paperclip class="size-4" />
|
|
297
|
-
</Button>
|
|
298
|
-
</Show>
|
|
299
|
-
<Show when={props.webSearch}>
|
|
300
|
-
<Button
|
|
301
|
-
type="button"
|
|
302
|
-
variant="outline"
|
|
303
|
-
size="sm"
|
|
304
|
-
class="rounded-full gap-1"
|
|
305
|
-
aria-label="Search the web"
|
|
306
|
-
disabled={props.disabled}
|
|
307
|
-
onClick={() => props.onWebSearch?.()}
|
|
308
|
-
>
|
|
309
|
-
<Globe class="size-4" />
|
|
310
|
-
Search
|
|
311
|
-
</Button>
|
|
312
|
-
</Show>
|
|
313
|
-
<Show when={props.voice}>
|
|
314
|
-
<Button
|
|
315
|
-
type="button"
|
|
316
|
-
variant="outline"
|
|
317
|
-
size="icon-sm"
|
|
318
|
-
class="rounded-full"
|
|
319
|
-
aria-label="Voice input"
|
|
320
|
-
disabled={props.disabled}
|
|
321
|
-
onClick={() => props.onVoice?.()}
|
|
322
|
-
>
|
|
323
|
-
<Mic class="size-4" />
|
|
324
|
-
</Button>
|
|
325
|
-
</Show>
|
|
326
|
-
<For each={props.toolbarActions ?? []}>
|
|
327
|
-
{(action) => {
|
|
328
|
-
const Icon = actionIcon(action.icon);
|
|
329
|
-
const label = action.tooltip ?? action.label;
|
|
330
|
-
const btn = (
|
|
331
|
-
<Button
|
|
332
|
-
type="button"
|
|
333
|
-
variant="outline"
|
|
334
|
-
size="icon-sm"
|
|
335
|
-
class="rounded-full"
|
|
336
|
-
aria-label={action.label}
|
|
337
|
-
data-action={action.id}
|
|
338
|
-
disabled={props.disabled}
|
|
339
|
-
onClick={() => props.onAction?.(action.id)}
|
|
340
|
-
>
|
|
341
|
-
<Show when={Icon} fallback={<span class="px-1 text-xs">{action.label}</span>}>
|
|
342
|
-
{(I) => { const C = I(); return <C class="size-4" />; }}
|
|
343
|
-
</Show>
|
|
344
|
-
</Button>
|
|
345
|
-
);
|
|
346
|
-
return Icon ? <Tooltip content={label}>{btn}</Tooltip> : btn;
|
|
347
|
-
}}
|
|
348
|
-
</For>
|
|
349
|
-
</div>
|
|
350
|
-
{/* Right cluster — consumer trailing controls (model/effort/voice…)
|
|
351
|
-
hug the send button, right-aligned. The `toolbar-end` slot and the send
|
|
352
|
-
button live together so justify-between pins them to the right edge
|
|
353
|
-
(left group stays left). Native slot; projected by the element. */}
|
|
354
|
-
<div class="flex items-center gap-2">
|
|
355
|
-
<slot name="toolbar-end" />
|
|
356
|
-
<Show
|
|
357
|
-
when={showStop()}
|
|
358
|
-
fallback={
|
|
359
|
-
<Show when={showSend()}>
|
|
360
|
-
<Button
|
|
361
|
-
size="icon-sm"
|
|
362
|
-
class="rounded-full"
|
|
363
|
-
part="send"
|
|
364
|
-
data-testid="send"
|
|
365
|
-
aria-label="Send message"
|
|
366
|
-
disabled={sendDisabled()}
|
|
367
|
-
onClick={props.onSubmit}
|
|
368
|
-
>
|
|
369
|
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
370
|
-
<line x1="12" y1="19" x2="12" y2="5" /><polyline points="5 12 12 5 19 12" />
|
|
371
|
-
</svg>
|
|
372
|
-
</Button>
|
|
373
|
-
</Show>
|
|
374
|
-
}
|
|
375
|
-
>
|
|
376
|
-
<Button
|
|
377
|
-
size="icon-sm"
|
|
378
|
-
variant="outline"
|
|
379
|
-
class="rounded-full"
|
|
380
|
-
data-testid="stop"
|
|
381
|
-
aria-label="Stop"
|
|
382
|
-
onClick={props.onStop}
|
|
383
|
-
>
|
|
384
|
-
<Square class="size-3" />
|
|
385
|
-
</Button>
|
|
386
|
-
</Show>
|
|
387
|
-
</div>
|
|
388
|
-
</PromptInputActions>
|
|
389
|
-
</PromptInput>
|
|
390
|
-
</>
|
|
391
|
-
);
|
|
392
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @kitn.ai/ui/define — the facade seam, public.
|
|
3
|
-
*
|
|
4
|
-
* The construct engine's GENERATED projects (and any consumer who wants to wrap
|
|
5
|
-
* a pure-Solid interior as one self-registering element) import from here. Its
|
|
6
|
-
* own subpath rather than ./solid because define.tsx carries ELEMENT_CSS (the
|
|
7
|
-
* full compiled kit CSS) and solid-element — weight ./solid consumers must not
|
|
8
|
-
* pay. SSR-safe by construction: defineWebComponent no-ops without
|
|
9
|
-
* customElements (see define.tsx).
|
|
10
|
-
*/
|
|
11
|
-
export { defineWebComponent } from './define';
|
|
12
|
-
export type { WebComponentContext } from './define';
|