@slices.sh/ai-chat 0.1.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/LICENSE +21 -0
- package/dist/exports.json +794 -0
- package/dist/fixture/fixture-approval.d.ts +4 -0
- package/dist/fixture/fixture-approval.js +59 -0
- package/dist/fixture/fixture-artifacts.d.ts +2 -0
- package/dist/fixture/fixture-artifacts.js +48 -0
- package/dist/fixture/fixture-question.d.ts +5 -0
- package/dist/fixture/fixture-question.js +93 -0
- package/dist/fixture/fixture-script.d.ts +35 -0
- package/dist/fixture/fixture-script.js +280 -0
- package/dist/fixture/fixture-selection.d.ts +5 -0
- package/dist/fixture/fixture-selection.js +20 -0
- package/dist/fixture/fixture.d.ts +20 -0
- package/dist/fixture/fixture.js +75 -0
- package/dist/fixture/provider.d.ts +15 -0
- package/dist/fixture/provider.js +14 -0
- package/dist/headless/always-allow.d.ts +2 -0
- package/dist/headless/always-allow.js +24 -0
- package/dist/headless/answer.d.ts +6 -0
- package/dist/headless/answer.js +29 -0
- package/dist/headless/approval-error.d.ts +2 -0
- package/dist/headless/approval-error.js +16 -0
- package/dist/headless/approval-reason.d.ts +2 -0
- package/dist/headless/approval-reason.js +13 -0
- package/dist/headless/approval-receipt.d.ts +4 -0
- package/dist/headless/approval-receipt.js +13 -0
- package/dist/headless/approve.d.ts +4 -0
- package/dist/headless/approve.js +15 -0
- package/dist/headless/branch-navigation.d.ts +2 -0
- package/dist/headless/branch-navigation.js +11 -0
- package/dist/headless/branch-next.d.ts +2 -0
- package/dist/headless/branch-next.js +21 -0
- package/dist/headless/branch-page.d.ts +5 -0
- package/dist/headless/branch-page.js +13 -0
- package/dist/headless/branch-previous.d.ts +2 -0
- package/dist/headless/branch-previous.js +21 -0
- package/dist/headless/cancel-edit.d.ts +2 -0
- package/dist/headless/cancel-edit.js +10 -0
- package/dist/headless/cancel-queue-edit.d.ts +2 -0
- package/dist/headless/cancel-queue-edit.js +15 -0
- package/dist/headless/cancel-queued.d.ts +2 -0
- package/dist/headless/cancel-queued.js +15 -0
- package/dist/headless/chat-dictation/confirm.d.ts +2 -0
- package/dist/headless/chat-dictation/confirm.js +14 -0
- package/dist/headless/chat-dictation/index.d.ts +12 -0
- package/dist/headless/chat-dictation/index.js +9 -0
- package/dist/headless/chat-dictation/input.d.ts +3 -0
- package/dist/headless/chat-dictation/input.js +42 -0
- package/dist/headless/chat-dictation/root.d.ts +3 -0
- package/dist/headless/chat-dictation/root.js +42 -0
- package/dist/headless/chat-dictation/text.d.ts +3 -0
- package/dist/headless/chat-dictation/text.js +14 -0
- package/dist/headless/chat-dictation/voice.d.ts +3 -0
- package/dist/headless/chat-dictation/voice.js +35 -0
- package/dist/headless/citation-content.d.ts +3 -0
- package/dist/headless/citation-content.js +19 -0
- package/dist/headless/citation-description.d.ts +2 -0
- package/dist/headless/citation-description.js +12 -0
- package/dist/headless/citation-root.d.ts +2 -0
- package/dist/headless/citation-root.js +13 -0
- package/dist/headless/citation-title.d.ts +2 -0
- package/dist/headless/citation-title.js +12 -0
- package/dist/headless/citation-trigger.d.ts +2 -0
- package/dist/headless/citation-trigger.js +12 -0
- package/dist/headless/clear-answer.d.ts +5 -0
- package/dist/headless/clear-answer.js +19 -0
- package/dist/headless/composer-root.d.ts +14 -0
- package/dist/headless/composer-root.js +12 -0
- package/dist/headless/composer-standalone.d.ts +3 -0
- package/dist/headless/composer-standalone.js +10 -0
- package/dist/headless/composer.d.ts +3 -0
- package/dist/headless/composer.js +24 -0
- package/dist/headless/context-usage.d.ts +3 -0
- package/dist/headless/context-usage.js +13 -0
- package/dist/headless/contexts.d.ts +77 -0
- package/dist/headless/contexts.js +53 -0
- package/dist/headless/continue.d.ts +4 -0
- package/dist/headless/continue.js +26 -0
- package/dist/headless/copy.d.ts +11 -0
- package/dist/headless/copy.js +21 -0
- package/dist/headless/deny.d.ts +4 -0
- package/dist/headless/deny.js +15 -0
- package/dist/headless/edit-queued.d.ts +2 -0
- package/dist/headless/edit-queued.js +15 -0
- package/dist/headless/edit.d.ts +2 -0
- package/dist/headless/edit.js +17 -0
- package/dist/headless/edited-attachments.d.ts +5 -0
- package/dist/headless/edited-attachments.js +11 -0
- package/dist/headless/edited-input.d.ts +2 -0
- package/dist/headless/edited-input.js +28 -0
- package/dist/headless/empty.d.ts +3 -0
- package/dist/headless/empty.js +12 -0
- package/dist/headless/failed.d.ts +15 -0
- package/dist/headless/failed.js +17 -0
- package/dist/headless/feedback-error.d.ts +2 -0
- package/dist/headless/feedback-error.js +11 -0
- package/dist/headless/feedback-root.d.ts +2 -0
- package/dist/headless/feedback-root.js +24 -0
- package/dist/headless/feedback.d.ts +4 -0
- package/dist/headless/feedback.js +18 -0
- package/dist/headless/file-audio.d.ts +2 -0
- package/dist/headless/file-audio.js +16 -0
- package/dist/headless/file-context.d.ts +4 -0
- package/dist/headless/file-context.js +7 -0
- package/dist/headless/file-img.d.ts +2 -0
- package/dist/headless/file-img.js +21 -0
- package/dist/headless/file-kind-gate.d.ts +5 -0
- package/dist/headless/file-kind-gate.js +11 -0
- package/dist/headless/file-link.d.ts +3 -0
- package/dist/headless/file-link.js +14 -0
- package/dist/headless/file-root.d.ts +5 -0
- package/dist/headless/file-root.js +13 -0
- package/dist/headless/file-unavailable.d.ts +2 -0
- package/dist/headless/file-unavailable.js +12 -0
- package/dist/headless/file-video.d.ts +2 -0
- package/dist/headless/file-video.js +16 -0
- package/dist/headless/follow-ups.d.ts +5 -0
- package/dist/headless/follow-ups.js +20 -0
- package/dist/headless/forget-approval.d.ts +2 -0
- package/dist/headless/forget-approval.js +21 -0
- package/dist/headless/gate-content.d.ts +2 -0
- package/dist/headless/gate-content.js +6 -0
- package/dist/headless/index.d.ts +249 -0
- package/dist/headless/index.js +251 -0
- package/dist/headless/input.d.ts +11 -0
- package/dist/headless/input.js +18 -0
- package/dist/headless/jump-to-latest.d.ts +3 -0
- package/dist/headless/jump-to-latest.js +14 -0
- package/dist/headless/message-edit-root.d.ts +2 -0
- package/dist/headless/message-edit-root.js +13 -0
- package/dist/headless/message-editing.d.ts +2 -0
- package/dist/headless/message-editing.js +10 -0
- package/dist/headless/message-editor.d.ts +2 -0
- package/dist/headless/message-editor.js +19 -0
- package/dist/headless/message-footer.d.ts +3 -0
- package/dist/headless/message-footer.js +15 -0
- package/dist/headless/message-reading.d.ts +2 -0
- package/dist/headless/message-reading.js +10 -0
- package/dist/headless/message.d.ts +11 -0
- package/dist/headless/message.js +34 -0
- package/dist/headless/messages.d.ts +9 -0
- package/dist/headless/messages.js +19 -0
- package/dist/headless/model-picker.d.ts +2 -0
- package/dist/headless/model-picker.js +14 -0
- package/dist/headless/model.d.ts +4 -0
- package/dist/headless/model.js +13 -0
- package/dist/headless/models.d.ts +5 -0
- package/dist/headless/models.js +11 -0
- package/dist/headless/optional-tools.d.ts +7 -0
- package/dist/headless/optional-tools.js +12 -0
- package/dist/headless/other-answer.d.ts +5 -0
- package/dist/headless/other-answer.js +32 -0
- package/dist/headless/part-approval.d.ts +2 -0
- package/dist/headless/part-approval.js +33 -0
- package/dist/headless/part-file.d.ts +6 -0
- package/dist/headless/part-file.js +11 -0
- package/dist/headless/part-question.d.ts +2 -0
- package/dist/headless/part-question.js +57 -0
- package/dist/headless/part-reasoning.d.ts +15 -0
- package/dist/headless/part-reasoning.js +26 -0
- package/dist/headless/part-source.d.ts +5 -0
- package/dist/headless/part-source.js +20 -0
- package/dist/headless/part-text.d.ts +16 -0
- package/dist/headless/part-text.js +29 -0
- package/dist/headless/part-tool.d.ts +16 -0
- package/dist/headless/part-tool.js +14 -0
- package/dist/headless/parts.d.ts +11 -0
- package/dist/headless/parts.js +11 -0
- package/dist/headless/question-back.d.ts +2 -0
- package/dist/headless/question-back.js +16 -0
- package/dist/headless/question-error.d.ts +2 -0
- package/dist/headless/question-error.js +14 -0
- package/dist/headless/question-invalid.d.ts +8 -0
- package/dist/headless/question-invalid.js +18 -0
- package/dist/headless/question-item.d.ts +8 -0
- package/dist/headless/question-item.js +51 -0
- package/dist/headless/question-next.d.ts +3 -0
- package/dist/headless/question-next.js +16 -0
- package/dist/headless/question-other.d.ts +5 -0
- package/dist/headless/question-other.js +22 -0
- package/dist/headless/question-progress.d.ts +8 -0
- package/dist/headless/question-progress.js +14 -0
- package/dist/headless/question-receipt.d.ts +11 -0
- package/dist/headless/question-receipt.js +29 -0
- package/dist/headless/questions.d.ts +3 -0
- package/dist/headless/questions.js +13 -0
- package/dist/headless/queue-editing.d.ts +4 -0
- package/dist/headless/queue-editing.js +11 -0
- package/dist/headless/queue-item.d.ts +2 -0
- package/dist/headless/queue-item.js +10 -0
- package/dist/headless/queue-items.d.ts +2 -0
- package/dist/headless/queue-items.js +11 -0
- package/dist/headless/queue-preview.d.ts +6 -0
- package/dist/headless/queue-preview.js +11 -0
- package/dist/headless/queued-input.d.ts +2 -0
- package/dist/headless/queued-input.js +27 -0
- package/dist/headless/queued.d.ts +17 -0
- package/dist/headless/queued.js +16 -0
- package/dist/headless/read-aloud.d.ts +5 -0
- package/dist/headless/read-aloud.js +19 -0
- package/dist/headless/reasoning-disclosure.d.ts +3 -0
- package/dist/headless/reasoning-disclosure.js +17 -0
- package/dist/headless/reasoning-timer.d.ts +5 -0
- package/dist/headless/reasoning-timer.js +13 -0
- package/dist/headless/references.d.ts +6 -0
- package/dist/headless/references.js +13 -0
- package/dist/headless/regenerate.d.ts +3 -0
- package/dist/headless/regenerate.js +22 -0
- package/dist/headless/remembered-approval.d.ts +2 -0
- package/dist/headless/remembered-approval.js +14 -0
- package/dist/headless/root.d.ts +30 -0
- package/dist/headless/root.js +99 -0
- package/dist/headless/save-edit.d.ts +2 -0
- package/dist/headless/save-edit.js +16 -0
- package/dist/headless/save-queued.d.ts +2 -0
- package/dist/headless/save-queued.js +15 -0
- package/dist/headless/send-now.d.ts +2 -0
- package/dist/headless/send-now.js +17 -0
- package/dist/headless/settings.d.ts +2 -0
- package/dist/headless/settings.js +10 -0
- package/dist/headless/skip-questions.d.ts +6 -0
- package/dist/headless/skip-questions.js +18 -0
- package/dist/headless/source-context.d.ts +5 -0
- package/dist/headless/source-context.js +9 -0
- package/dist/headless/source-link.d.ts +2 -0
- package/dist/headless/source-link.js +13 -0
- package/dist/headless/source-primitives.d.ts +1 -0
- package/dist/headless/source-primitives.js +7 -0
- package/dist/headless/source-root.d.ts +5 -0
- package/dist/headless/source-root.js +9 -0
- package/dist/headless/source-sheet-close.d.ts +2 -0
- package/dist/headless/source-sheet-close.js +12 -0
- package/dist/headless/source-sheet-content.d.ts +3 -0
- package/dist/headless/source-sheet-content.js +16 -0
- package/dist/headless/source-sheet-description.d.ts +2 -0
- package/dist/headless/source-sheet-description.js +12 -0
- package/dist/headless/source-sheet-root.d.ts +2 -0
- package/dist/headless/source-sheet-root.js +13 -0
- package/dist/headless/source-sheet-title.d.ts +2 -0
- package/dist/headless/source-sheet-title.js +12 -0
- package/dist/headless/source-sheet-trigger.d.ts +2 -0
- package/dist/headless/source-sheet-trigger.js +12 -0
- package/dist/headless/source-unavailable.d.ts +2 -0
- package/dist/headless/source-unavailable.js +9 -0
- package/dist/headless/sources.d.ts +14 -0
- package/dist/headless/sources.js +12 -0
- package/dist/headless/speaker.d.ts +13 -0
- package/dist/headless/speaker.js +10 -0
- package/dist/headless/step-boundary.d.ts +4 -0
- package/dist/headless/step-boundary.js +16 -0
- package/dist/headless/stop.d.ts +10 -0
- package/dist/headless/stop.js +18 -0
- package/dist/headless/stopped.d.ts +11 -0
- package/dist/headless/stopped.js +17 -0
- package/dist/headless/submit-answers.d.ts +3 -0
- package/dist/headless/submit-answers.js +12 -0
- package/dist/headless/submit.d.ts +23 -0
- package/dist/headless/submit.js +24 -0
- package/dist/headless/suggestion.d.ts +10 -0
- package/dist/headless/suggestion.js +14 -0
- package/dist/headless/suggestions.d.ts +8 -0
- package/dist/headless/suggestions.js +12 -0
- package/dist/headless/thread.d.ts +3 -0
- package/dist/headless/thread.js +25 -0
- package/dist/headless/timing.d.ts +5 -0
- package/dist/headless/timing.js +13 -0
- package/dist/headless/toggle-tool.d.ts +4 -0
- package/dist/headless/toggle-tool.js +15 -0
- package/dist/headless/tool-error.d.ts +4 -0
- package/dist/headless/tool-error.js +13 -0
- package/dist/headless/tool-input.d.ts +4 -0
- package/dist/headless/tool-input.js +13 -0
- package/dist/headless/tool-output.d.ts +4 -0
- package/dist/headless/tool-output.js +13 -0
- package/dist/headless/tool-renderer.d.ts +13 -0
- package/dist/headless/tool-renderer.js +15 -0
- package/dist/headless/transcript.d.ts +23 -0
- package/dist/headless/transcript.js +24 -0
- package/dist/headless/try-again.d.ts +2 -0
- package/dist/headless/try-again.js +24 -0
- package/dist/headless/unavailable.d.ts +8 -0
- package/dist/headless/unavailable.js +9 -0
- package/dist/headless/usage.d.ts +13 -0
- package/dist/headless/usage.js +15 -0
- package/dist/headless/use-merged-ref.d.ts +2 -0
- package/dist/headless/use-merged-ref.js +17 -0
- package/dist/headless/use-question.d.ts +3 -0
- package/dist/headless/use-question.js +9 -0
- package/dist/headless/waiting.d.ts +13 -0
- package/dist/headless/waiting.js +12 -0
- package/dist/headless/writing.d.ts +13 -0
- package/dist/headless/writing.js +12 -0
- package/dist/hooks/chat-refusal.d.ts +18 -0
- package/dist/hooks/chat-refusal.js +44 -0
- package/dist/hooks/turn-mailbox.d.ts +14 -0
- package/dist/hooks/turn-mailbox.js +114 -0
- package/dist/hooks/use-branches.d.ts +10 -0
- package/dist/hooks/use-branches.js +69 -0
- package/dist/hooks/use-chat-instance.d.ts +28 -0
- package/dist/hooks/use-chat-instance.js +44 -0
- package/dist/hooks/use-chat-settings.d.ts +11 -0
- package/dist/hooks/use-chat-settings.js +33 -0
- package/dist/hooks/use-chat-sink.d.ts +19 -0
- package/dist/hooks/use-chat-sink.js +56 -0
- package/dist/hooks/use-composer.d.ts +33 -0
- package/dist/hooks/use-composer.js +45 -0
- package/dist/hooks/use-context-usage.d.ts +8 -0
- package/dist/hooks/use-context-usage.js +14 -0
- package/dist/hooks/use-copied.d.ts +14 -0
- package/dist/hooks/use-copied.js +22 -0
- package/dist/hooks/use-draft.d.ts +6 -0
- package/dist/hooks/use-draft.js +38 -0
- package/dist/hooks/use-feedback.d.ts +8 -0
- package/dist/hooks/use-feedback.js +28 -0
- package/dist/hooks/use-follow.d.ts +15 -0
- package/dist/hooks/use-follow.js +30 -0
- package/dist/hooks/use-media-load.d.ts +5 -0
- package/dist/hooks/use-media-load.js +12 -0
- package/dist/hooks/use-media.d.ts +3 -0
- package/dist/hooks/use-media.js +9 -0
- package/dist/hooks/use-question-check.d.ts +11 -0
- package/dist/hooks/use-question-check.js +29 -0
- package/dist/hooks/use-question-draft.d.ts +34 -0
- package/dist/hooks/use-question-draft.js +57 -0
- package/dist/hooks/use-question-steps.d.ts +18 -0
- package/dist/hooks/use-question-steps.js +31 -0
- package/dist/hooks/use-question-write.d.ts +8 -0
- package/dist/hooks/use-question-write.js +25 -0
- package/dist/hooks/use-read-aloud.d.ts +8 -0
- package/dist/hooks/use-read-aloud.js +60 -0
- package/dist/hooks/use-reasoning.d.ts +8 -0
- package/dist/hooks/use-reasoning.js +32 -0
- package/dist/hooks/use-remembered-approvals.d.ts +9 -0
- package/dist/hooks/use-remembered-approvals.js +40 -0
- package/dist/hooks/use-reply.d.ts +3 -0
- package/dist/hooks/use-reply.js +9 -0
- package/dist/hooks/use-report-missing-configuration.d.ts +9 -0
- package/dist/hooks/use-report-missing-configuration.js +14 -0
- package/dist/hooks/use-retry-delay.d.ts +5 -0
- package/dist/hooks/use-retry-delay.js +17 -0
- package/dist/hooks/use-sent-draft.d.ts +8 -0
- package/dist/hooks/use-sent-draft.js +25 -0
- package/dist/hooks/use-source-disclosure.d.ts +5 -0
- package/dist/hooks/use-source-disclosure.js +9 -0
- package/dist/hooks/use-sources.d.ts +3 -0
- package/dist/hooks/use-sources.js +9 -0
- package/dist/hooks/use-tool-approval-memory.d.ts +8 -0
- package/dist/hooks/use-tool-approval-memory.js +16 -0
- package/dist/hooks/use-tool-approval.d.ts +10 -0
- package/dist/hooks/use-tool-approval.js +26 -0
- package/dist/hooks/use-turn-queue.d.ts +32 -0
- package/dist/hooks/use-turn-queue.js +33 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +5 -0
- package/dist/next.d.ts +43 -0
- package/dist/next.js +10 -0
- package/dist/services/approval-memory.d.ts +9 -0
- package/dist/services/approval-memory.js +32 -0
- package/dist/services/approval.d.ts +14 -0
- package/dist/services/approval.js +37 -0
- package/dist/services/branches.d.ts +27 -0
- package/dist/services/branches.js +131 -0
- package/dist/services/chat-session.d.ts +20 -0
- package/dist/services/chat-session.js +61 -0
- package/dist/services/choices.d.ts +31 -0
- package/dist/services/choices.js +39 -0
- package/dist/services/continue.d.ts +8 -0
- package/dist/services/continue.js +24 -0
- package/dist/services/errors.d.ts +52 -0
- package/dist/services/errors.js +54 -0
- package/dist/services/media.d.ts +9 -0
- package/dist/services/media.js +19 -0
- package/dist/services/messages.d.ts +44 -0
- package/dist/services/messages.js +0 -0
- package/dist/services/optional.d.ts +7 -0
- package/dist/services/optional.js +7 -0
- package/dist/services/ports.d.ts +31 -0
- package/dist/services/ports.js +0 -0
- package/dist/services/questions.d.ts +67 -0
- package/dist/services/questions.js +119 -0
- package/dist/services/request.d.ts +26 -0
- package/dist/services/request.js +85 -0
- package/dist/services/selection.d.ts +10 -0
- package/dist/services/selection.js +49 -0
- package/dist/services/sources.d.ts +11 -0
- package/dist/services/sources.js +29 -0
- package/dist/services/tools.d.ts +11 -0
- package/dist/services/tools.js +0 -0
- package/dist/services/turn.d.ts +84 -0
- package/dist/services/turn.js +0 -0
- package/dist/services/types.d.ts +23 -0
- package/dist/services/types.js +15 -0
- package/package.json +822 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useChatSettings } from "../hooks/use-chat-settings.js";
|
|
4
|
+
import { useBranches } from "../hooks/use-branches.js";
|
|
5
|
+
import { useToolApprovalMemory } from "../hooks/use-tool-approval-memory.js";
|
|
6
|
+
import { useRememberedApprovals } from "../hooks/use-remembered-approvals.js";
|
|
7
|
+
import { MessageScroller } from "@shadcn/react/message-scroller";
|
|
8
|
+
import { useChat } from "@ai-sdk/react";
|
|
9
|
+
import { useCallback, useContext } from "react";
|
|
10
|
+
import { SinkProvider } from "@slices.sh/composer";
|
|
11
|
+
import { useChatInstance } from "../hooks/use-chat-instance.js";
|
|
12
|
+
import { useComposer } from "../hooks/use-composer.js";
|
|
13
|
+
import { useFollow } from "../hooks/use-follow.js";
|
|
14
|
+
import { useReply } from "../hooks/use-reply.js";
|
|
15
|
+
import { useTurnQueue } from "../hooks/use-turn-queue.js";
|
|
16
|
+
import { Provide } from "@slices.sh/core/part";
|
|
17
|
+
import { useChatSink } from "../hooks/use-chat-sink.js";
|
|
18
|
+
import {
|
|
19
|
+
SettingsContext,
|
|
20
|
+
FeedbackOptionsContext,
|
|
21
|
+
BranchContext,
|
|
22
|
+
ApprovalMemoryContext,
|
|
23
|
+
ApprovalAutomationContext,
|
|
24
|
+
ChatContext,
|
|
25
|
+
ChatConfigContext,
|
|
26
|
+
ComposerContext,
|
|
27
|
+
ComposerStandaloneContext,
|
|
28
|
+
FollowContext,
|
|
29
|
+
QueueContext,
|
|
30
|
+
SourceContext
|
|
31
|
+
} from "./contexts.js";
|
|
32
|
+
function Root(props) {
|
|
33
|
+
const outer = useContext(ChatContext);
|
|
34
|
+
const outerConfig = useContext(ChatConfigContext);
|
|
35
|
+
if (outer && !props.chat && (props.config === void 0 || props.config === outerConfig)) {
|
|
36
|
+
return /* @__PURE__ */ jsx(ComposerStandaloneContext, { value: "embedded", children: props.children });
|
|
37
|
+
}
|
|
38
|
+
return /* @__PURE__ */ jsx(MessageScroller.Provider, { autoScroll: true, defaultScrollPosition: "last-anchor", scrollPreviousItemPeek: 64, children: /* @__PURE__ */ jsx(Session, { ...props }) });
|
|
39
|
+
}
|
|
40
|
+
function Session({
|
|
41
|
+
config,
|
|
42
|
+
enabled,
|
|
43
|
+
name = config ?? "default",
|
|
44
|
+
chat: given,
|
|
45
|
+
settings: givenSettings,
|
|
46
|
+
queue = true,
|
|
47
|
+
rememberApprovals = true,
|
|
48
|
+
onFeedback,
|
|
49
|
+
children
|
|
50
|
+
}) {
|
|
51
|
+
const { chat, source, settings: ownSettings } = useChatInstance(name, given, { config, enabled });
|
|
52
|
+
const { status, messages } = useChat({ chat });
|
|
53
|
+
const waiting = useTurnQueue(chat);
|
|
54
|
+
const settings = useChatSettings(chat, given ? givenSettings ?? null : ownSettings, waiting.waiting);
|
|
55
|
+
const branches = useBranches(chat, source !== "missing" && waiting.waiting === 0);
|
|
56
|
+
const approvals = useToolApprovalMemory(chat, rememberApprovals);
|
|
57
|
+
const automation = useRememberedApprovals(chat, approvals);
|
|
58
|
+
const send = useReply(chat);
|
|
59
|
+
const stop = useCallback(() => {
|
|
60
|
+
if (chat.status !== "submitted" && chat.status !== "streaming") return false;
|
|
61
|
+
void chat.stop();
|
|
62
|
+
return true;
|
|
63
|
+
}, [chat]);
|
|
64
|
+
const composer = useComposer({
|
|
65
|
+
scope: chat,
|
|
66
|
+
onStop: stop,
|
|
67
|
+
onRemoveLast: settings.removeLast,
|
|
68
|
+
onSend: queue ? waiting.enqueue : send,
|
|
69
|
+
// Nothing answers a chat with no backend, and with no queue the composer is what refuses
|
|
70
|
+
// a second message: one turn at a time is a property of the chat, and the person should
|
|
71
|
+
// see which control is holding it.
|
|
72
|
+
disabled: source === "missing" || !queue && (status === "submitted" || status === "streaming")
|
|
73
|
+
});
|
|
74
|
+
const sink = useChatSink({ chat, source, config, queue, enqueue: waiting.enqueue, stop, removeLast: settings.removeLast });
|
|
75
|
+
const follow = useFollow(messages.findLast((message) => message.role === "user")?.id);
|
|
76
|
+
return /* @__PURE__ */ jsx(
|
|
77
|
+
Provide,
|
|
78
|
+
{
|
|
79
|
+
values: [
|
|
80
|
+
[ChatContext, chat],
|
|
81
|
+
[ChatConfigContext, config ?? "default"],
|
|
82
|
+
[ComposerStandaloneContext, "standalone"],
|
|
83
|
+
[SettingsContext, settings],
|
|
84
|
+
[FeedbackOptionsContext, { onFeedback }],
|
|
85
|
+
[BranchContext, branches],
|
|
86
|
+
[ApprovalMemoryContext, approvals],
|
|
87
|
+
[ApprovalAutomationContext, automation],
|
|
88
|
+
[SourceContext, source],
|
|
89
|
+
[ComposerContext, composer],
|
|
90
|
+
[FollowContext, follow],
|
|
91
|
+
[QueueContext, waiting]
|
|
92
|
+
],
|
|
93
|
+
children: /* @__PURE__ */ jsx(SinkProvider, { value: sink, children })
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
export {
|
|
98
|
+
Root
|
|
99
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { usePart, useRequired } from "@slices.sh/core/part";
|
|
3
|
+
import { BranchContext, MessageScope, SentDraftContext } from "./contexts.js";
|
|
4
|
+
function SaveEdit(props) {
|
|
5
|
+
const branches = useRequired(BranchContext, "Chat.SaveEdit requires Chat.Root.");
|
|
6
|
+
const message = useRequired(MessageScope, "Chat.SaveEdit requires Chat.Messages.");
|
|
7
|
+
const draft = useRequired(SentDraftContext, "Chat.SaveEdit requires Chat.MessageEditRoot.");
|
|
8
|
+
const empty = !draft.value?.trim() && !message.parts.some((part) => part.type === "file");
|
|
9
|
+
return usePart("button", props, {
|
|
10
|
+
defaults: { type: "submit" },
|
|
11
|
+
locked: { disabled: branches.blocked || draft.value === null || empty }
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
SaveEdit
|
|
16
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { usePart, useRequired } from "@slices.sh/core/part";
|
|
3
|
+
import { QueueContext, QueueScope } from "./contexts.js";
|
|
4
|
+
function SaveQueued(props) {
|
|
5
|
+
const queue = useRequired(QueueContext, "Chat.SaveQueued requires Chat.Root.");
|
|
6
|
+
const item = useRequired(QueueScope, "Chat.SaveQueued requires Chat.QueueItems.");
|
|
7
|
+
return usePart("button", props, {
|
|
8
|
+
defaults: { type: "button" },
|
|
9
|
+
locked: { disabled: item.draft === null || !item.draft.trim() && !item.files?.length },
|
|
10
|
+
behavior: { onClick: () => queue.change({ type: "save-edit", id: item.id }) }
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
SaveQueued
|
|
15
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { usePart, useRequired } from "@slices.sh/core/part";
|
|
3
|
+
import { QueueContext, QueueScope } from "./contexts.js";
|
|
4
|
+
function SendNow(props) {
|
|
5
|
+
const queue = useRequired(QueueContext, "Chat.SendNow requires Chat.Root.");
|
|
6
|
+
const item = useRequired(QueueScope, "Chat.SendNow requires Chat.QueueItems.");
|
|
7
|
+
return usePart("button", props, {
|
|
8
|
+
defaults: { type: "button" },
|
|
9
|
+
// An open question is no reason to wait: sending now skips it and sends this as the reply.
|
|
10
|
+
// A tool decision is one, and its buttons are in the transcript.
|
|
11
|
+
locked: { disabled: queue.blockedBy !== null && queue.blockedBy !== "question" || item.draft !== null },
|
|
12
|
+
behavior: { onClick: () => queue.change({ type: "send-now", id: item.id }) }
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
SendNow
|
|
17
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useRequired } from "@slices.sh/core/part";
|
|
3
|
+
import { SettingsContext } from "./contexts.js";
|
|
4
|
+
function Settings({ children }) {
|
|
5
|
+
const { choices } = useRequired(SettingsContext, "Chat.Settings requires Chat.Root.");
|
|
6
|
+
return choices && (choices.models?.length || choices.tools?.length) ? children : null;
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
Settings
|
|
10
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type PartProps } from "@slices.sh/core/part";
|
|
2
|
+
/**
|
|
3
|
+
* Dismisses the open question without answering it. The queue decides what the model hears next:
|
|
4
|
+
* the message the person typed meanwhile, as their reply, or else a nudge to carry on.
|
|
5
|
+
*/
|
|
6
|
+
export declare function SkipQuestions(props: PartProps<"button">): import("react").ReactNode;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { isToolUIPart } from "ai";
|
|
3
|
+
import { usePart, useRequired } from "@slices.sh/core/part";
|
|
4
|
+
import { PartScope, QueueContext, QuestionWriteContext } from "./contexts.js";
|
|
5
|
+
function SkipQuestions(props) {
|
|
6
|
+
const queue = useRequired(QueueContext, "Chat.SkipQuestions requires Chat.Root.");
|
|
7
|
+
const write = useRequired(QuestionWriteContext, "Chat.SkipQuestions requires Chat.PartQuestion.");
|
|
8
|
+
const part = useRequired(PartScope, "Chat.SkipQuestions requires Chat.Parts.");
|
|
9
|
+
const id = isToolUIPart(part) ? part.toolCallId : null;
|
|
10
|
+
return usePart("button", props, {
|
|
11
|
+
defaults: { type: "button" },
|
|
12
|
+
locked: { disabled: write.pending || id === null },
|
|
13
|
+
behavior: { onClick: () => id !== null && queue.change({ type: "skip-question", toolCallId: id }) }
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
SkipQuestions
|
|
18
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ChatSource } from "../services/types";
|
|
2
|
+
import type { SourceDisclosure } from "../hooks/use-source-disclosure";
|
|
3
|
+
export declare const SourceScope: import("react").Context<ChatSource | null>;
|
|
4
|
+
export declare const CitationDisclosureContext: import("react").Context<SourceDisclosure | null>;
|
|
5
|
+
export declare const SourceSheetContext: import("react").Context<SourceDisclosure | null>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createContext } from "react";
|
|
2
|
+
const SourceScope = createContext(null);
|
|
3
|
+
const CitationDisclosureContext = createContext(null);
|
|
4
|
+
const SourceSheetContext = createContext(null);
|
|
5
|
+
export {
|
|
6
|
+
CitationDisclosureContext,
|
|
7
|
+
SourceScope,
|
|
8
|
+
SourceSheetContext
|
|
9
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { usePart, useRequired } from "@slices.sh/core/part";
|
|
3
|
+
import { SourceScope } from "./source-context.js";
|
|
4
|
+
function SourceLink(props) {
|
|
5
|
+
const source = useRequired(SourceScope, "Chat.SourceLink requires Chat.SourceRoot.");
|
|
6
|
+
const element = usePart("a", props, {
|
|
7
|
+
locked: { href: source.href ?? void 0, target: "_blank", rel: "noopener noreferrer" }
|
|
8
|
+
});
|
|
9
|
+
return source.href ? element : null;
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
SourceLink
|
|
13
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Popover, Dialog, MotionPopover, MotionDialog } from "@slices.sh/core/motion-base-ui";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { type PartProps } from "@slices.sh/core/part";
|
|
2
|
+
export declare function SourceSheetClose(props: PartProps<"button">): string | number | bigint | boolean | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined> | import("react").JSX.Element | null | undefined;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { isValidElement } from "react";
|
|
4
|
+
import { Dialog } from "./source-primitives.js";
|
|
5
|
+
import { usePart } from "@slices.sh/core/part";
|
|
6
|
+
function SourceSheetClose(props) {
|
|
7
|
+
const element = usePart("button", props);
|
|
8
|
+
return isValidElement(element) ? /* @__PURE__ */ jsx(Dialog.Close, { render: element }) : element;
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
SourceSheetClose
|
|
12
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { MotionDialog } from "./source-primitives.js";
|
|
4
|
+
import { usePart, useRequired } from "@slices.sh/core/part";
|
|
5
|
+
import { SourceSheetContext } from "./source-context.js";
|
|
6
|
+
function SourceSheetContent(props) {
|
|
7
|
+
const disclosure = useRequired(SourceSheetContext, "Chat.SourceSheetContent requires Chat.SourceSheetRoot.");
|
|
8
|
+
return usePart(
|
|
9
|
+
"div",
|
|
10
|
+
{ ...props, render: props.render ?? /* @__PURE__ */ jsx(MotionDialog, {}) },
|
|
11
|
+
{ locked: { open: disclosure.open } }
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
SourceSheetContent
|
|
16
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { type PartProps } from "@slices.sh/core/part";
|
|
2
|
+
export declare function SourceSheetDescription(props: PartProps<"p">): string | number | bigint | boolean | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined> | import("react").JSX.Element | null | undefined;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { isValidElement } from "react";
|
|
4
|
+
import { Dialog } from "./source-primitives.js";
|
|
5
|
+
import { usePart } from "@slices.sh/core/part";
|
|
6
|
+
function SourceSheetDescription(props) {
|
|
7
|
+
const element = usePart("p", props);
|
|
8
|
+
return isValidElement(element) ? /* @__PURE__ */ jsx(Dialog.Description, { render: element }) : element;
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
SourceSheetDescription
|
|
12
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Dialog } from "./source-primitives.js";
|
|
4
|
+
import { useSourceDisclosure } from "../hooks/use-source-disclosure.js";
|
|
5
|
+
import { Provide } from "@slices.sh/core/part";
|
|
6
|
+
import { SourceSheetContext } from "./source-context.js";
|
|
7
|
+
function SourceSheetRoot({ children }) {
|
|
8
|
+
const disclosure = useSourceDisclosure();
|
|
9
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { open: disclosure.open, onOpenChange: disclosure.setOpen, children: /* @__PURE__ */ jsx(Provide, { values: [[SourceSheetContext, disclosure]], children }) });
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
SourceSheetRoot
|
|
13
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { type PartProps } from "@slices.sh/core/part";
|
|
2
|
+
export declare function SourceSheetTitle(props: PartProps<"h2">): string | number | bigint | boolean | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined> | import("react").JSX.Element | null | undefined;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { isValidElement } from "react";
|
|
4
|
+
import { Dialog } from "./source-primitives.js";
|
|
5
|
+
import { usePart } from "@slices.sh/core/part";
|
|
6
|
+
function SourceSheetTitle(props) {
|
|
7
|
+
const element = usePart("h2", props);
|
|
8
|
+
return isValidElement(element) ? /* @__PURE__ */ jsx(Dialog.Title, { render: element }) : element;
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
SourceSheetTitle
|
|
12
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { type PartProps } from "@slices.sh/core/part";
|
|
2
|
+
export declare function SourceSheetTrigger(props: PartProps<"button">): string | number | bigint | boolean | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined> | import("react").JSX.Element | null | undefined;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { isValidElement } from "react";
|
|
4
|
+
import { Dialog } from "./source-primitives.js";
|
|
5
|
+
import { usePart } from "@slices.sh/core/part";
|
|
6
|
+
function SourceSheetTrigger(props) {
|
|
7
|
+
const element = usePart("button", props);
|
|
8
|
+
return isValidElement(element) ? /* @__PURE__ */ jsx(Dialog.Trigger, { render: element }) : element;
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
SourceSheetTrigger
|
|
12
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useRequired } from "@slices.sh/core/part";
|
|
3
|
+
import { SourceScope } from "./source-context.js";
|
|
4
|
+
function SourceUnavailable({ children }) {
|
|
5
|
+
return useRequired(SourceScope, "Chat.SourceUnavailable requires Chat.SourceRoot.").href ? null : children;
|
|
6
|
+
}
|
|
7
|
+
export {
|
|
8
|
+
SourceUnavailable
|
|
9
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SourceUrlUIPart } from "ai";
|
|
2
|
+
import { type GateProps } from "@slices.sh/core/part";
|
|
3
|
+
/**
|
|
4
|
+
* What the answer was drawn from, the SDK's `source-url` parts, collected.
|
|
5
|
+
*
|
|
6
|
+
* A footer rather than a part in the flow: citations arrive interleaved with the prose and
|
|
7
|
+
* read as an appendix, and a reader who wants them wants all of them at once. A document
|
|
8
|
+
* source has no URL to open, and a citation nobody can follow is a row that looks like a
|
|
9
|
+
* link and is not one. Nothing is rendered where the backend sent none, which is most
|
|
10
|
+
* backends.
|
|
11
|
+
*/
|
|
12
|
+
export declare function Sources({ children }: GateProps<{
|
|
13
|
+
sources: SourceUrlUIPart[];
|
|
14
|
+
}>): import("react").ReactNode;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useRequired } from "@slices.sh/core/part";
|
|
3
|
+
import { MessageScope } from "./contexts.js";
|
|
4
|
+
import { gateContent } from "./gate-content.js";
|
|
5
|
+
function Sources({ children }) {
|
|
6
|
+
const message = useRequired(MessageScope, "Chat.Sources must be inside <Chat.Messages>.");
|
|
7
|
+
const sources = message.parts.filter((part) => part.type === "source-url");
|
|
8
|
+
return sources.length > 0 ? gateContent(children, { sources }) : null;
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
Sources
|
|
12
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type PartProps } from "@slices.sh/core/part";
|
|
2
|
+
import type { AiChatMessage } from "../services/types";
|
|
3
|
+
/**
|
|
4
|
+
* Who said it, in words.
|
|
5
|
+
*
|
|
6
|
+
* Colour and alignment are the only thing that told the two apart, which is nothing at all
|
|
7
|
+
* to a screen reader and very little on a low-contrast theme. The default skin hides this
|
|
8
|
+
* visually and leaves it in the accessibility tree, where it is the difference between a
|
|
9
|
+
* conversation and a run of anonymous paragraphs.
|
|
10
|
+
*/
|
|
11
|
+
export declare function Speaker(props: PartProps<"span", {
|
|
12
|
+
role: AiChatMessage["role"];
|
|
13
|
+
}>): import("react").ReactNode;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { usePart, useRequired } from "@slices.sh/core/part";
|
|
3
|
+
import { MessageScope } from "./contexts.js";
|
|
4
|
+
function Speaker(props) {
|
|
5
|
+
const message = useRequired(MessageScope, "Chat.Speaker must be inside <Chat.Messages>.");
|
|
6
|
+
return usePart("span", props, { state: { role: message.role } });
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
Speaker
|
|
10
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useRequired } from "@slices.sh/core/part";
|
|
3
|
+
import { MessageScope, PartScope } from "./contexts.js";
|
|
4
|
+
import { gateContent } from "./gate-content.js";
|
|
5
|
+
function StepBoundary({ children }) {
|
|
6
|
+
const part = useRequired(PartScope, "Chat.StepBoundary requires Chat.Parts.");
|
|
7
|
+
const message = useRequired(MessageScope, "Chat.StepBoundary requires Chat.Messages.");
|
|
8
|
+
if (part.type !== "step-start") return null;
|
|
9
|
+
const index = message.parts.indexOf(part);
|
|
10
|
+
return gateContent(children, {
|
|
11
|
+
number: message.parts.slice(0, index + 1).filter((p) => p.type === "step-start").length
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
StepBoundary
|
|
16
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type PartProps } from "@slices.sh/core/part";
|
|
2
|
+
/**
|
|
3
|
+
* Stops a reply that is streaming. Stopping is the chat's own behaviour, so it is not a mode
|
|
4
|
+
* of `Composer.Submit`: no generic part can express it.
|
|
5
|
+
*
|
|
6
|
+
* It is disabled while nothing streams, never unmounted: a button that came and went with
|
|
7
|
+
* every turn moved the controls beside it under a cursor already on its way, and dropped
|
|
8
|
+
* focus to the body when the turn ended with it focused.
|
|
9
|
+
*/
|
|
10
|
+
export declare function Stop(props: PartProps<"button">): import("react").ReactNode;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useChat } from "@ai-sdk/react";
|
|
3
|
+
import { usePart, useRequired } from "@slices.sh/core/part";
|
|
4
|
+
import { ChatContext } from "./contexts.js";
|
|
5
|
+
function Stop(props) {
|
|
6
|
+
const chat = useRequired(ChatContext, "Chat.Stop must be inside <Chat.Root>.");
|
|
7
|
+
const { status, stop } = useChat({ chat });
|
|
8
|
+
const running = status === "submitted" || status === "streaming";
|
|
9
|
+
return usePart("button", props, {
|
|
10
|
+
defaults: { type: "button" },
|
|
11
|
+
behavior: { onClick: () => void stop() },
|
|
12
|
+
locked: { type: "button", disabled: !running },
|
|
13
|
+
attributes: { active: running }
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
Stop
|
|
18
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type GateProps } from "@slices.sh/core/part";
|
|
2
|
+
/**
|
|
3
|
+
* This reply was cut off, and somebody should be told in words.
|
|
4
|
+
*
|
|
5
|
+
* Fading the text was the whole account of it before, which is a contrast regression that
|
|
6
|
+
* says nothing: the reader could not tell whether they had stopped it, the model had, or
|
|
7
|
+
* the network went. → components/headless/ai-chat/writing.ts
|
|
8
|
+
*/
|
|
9
|
+
export declare function Stopped({ children }: GateProps<{
|
|
10
|
+
reason: "length" | "interrupted";
|
|
11
|
+
}>): import("react").ReactNode;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useChat } from "@ai-sdk/react";
|
|
3
|
+
import { useRequired } from "@slices.sh/core/part";
|
|
4
|
+
import { gateContent } from "./gate-content.js";
|
|
5
|
+
import { ChatContext, MessageScope } from "./contexts.js";
|
|
6
|
+
import { isCutOff, isWriting } from "./writing.js";
|
|
7
|
+
function Stopped({ children }) {
|
|
8
|
+
const message = useRequired(MessageScope, "Chat.Stopped must be inside <Chat.Messages>.");
|
|
9
|
+
const chat = useRequired(ChatContext, "Chat.Stopped must be inside <Chat.Root>.");
|
|
10
|
+
const { messages, status } = useChat({ chat });
|
|
11
|
+
return isCutOff(message, isWriting(message, messages, status)) ? gateContent(children, {
|
|
12
|
+
reason: message.metadata?.finishReason === "length" ? "length" : "interrupted"
|
|
13
|
+
}) : null;
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
Stopped
|
|
17
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { usePart, useRequired } from "@slices.sh/core/part";
|
|
3
|
+
import { QuestionStepsContext, QuestionWriteContext } from "./contexts.js";
|
|
4
|
+
function SubmitAnswers(props) {
|
|
5
|
+
const write = useRequired(QuestionWriteContext, "Chat.SubmitAnswers requires Chat.PartQuestion.");
|
|
6
|
+
const steps = useRequired(QuestionStepsContext, "Chat.SubmitAnswers requires Chat.PartQuestion.");
|
|
7
|
+
const element = usePart("button", props, { locked: { type: "submit", disabled: write.pending } });
|
|
8
|
+
return steps.index === steps.count - 1 ? element : null;
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
SubmitAnswers
|
|
12
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type PartProps } from "@slices.sh/core/part";
|
|
2
|
+
/**
|
|
3
|
+
* One control that sends, and stops what it sent with the SDK's `stop`.
|
|
4
|
+
*
|
|
5
|
+
* The composer's only submit, and the only button that ever occupies this spot. A separate
|
|
6
|
+
* stop button had to appear between send and its neighbour mid-turn, which moved the most
|
|
7
|
+
* used control in the component under a cursor already on its way down; it also unmounted
|
|
8
|
+
* itself the instant the turn ended, dropping focus to the body if anyone had tabbed to it.
|
|
9
|
+
* Morphing solves both: the element is the same element, and it is `type="submit"` only
|
|
10
|
+
* while submitting is what it does. → docs/rules/one-submit-per-form.md
|
|
11
|
+
*
|
|
12
|
+
* It stops an answer while there is nothing to send, and sends while there is — which is
|
|
13
|
+
* the only reading that leaves the queue reachable by touch. Otherwise the one button
|
|
14
|
+
* beside the box said "stop" the whole time an answer was arriving, so a follow-up typed
|
|
15
|
+
* on a phone could be sent only from the software keyboard's own return key, and the
|
|
16
|
+
* control right next to it did something else. Where the composer refuses a second message
|
|
17
|
+
* outright (`queue` off) there is nothing to send by definition, so this is stop again.
|
|
18
|
+
*
|
|
19
|
+
* @deprecated Chat.Submit becomes Composer.Submit, and its stopping half is Chat.Stop.
|
|
20
|
+
*/
|
|
21
|
+
export declare function Submit(props: PartProps<"button", {
|
|
22
|
+
stopping: boolean;
|
|
23
|
+
}>): import("react").ReactNode;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useContext } from "react";
|
|
3
|
+
import { useChat } from "@ai-sdk/react";
|
|
4
|
+
import { usePart, useRequired } from "@slices.sh/core/part";
|
|
5
|
+
import { ChatContext, ComposerContext, ComposerAttachmentsContext } from "./contexts.js";
|
|
6
|
+
function Submit(props) {
|
|
7
|
+
const chat = useRequired(ChatContext, "Chat.Submit must be inside <Chat.Root>.");
|
|
8
|
+
const composer = useRequired(ComposerContext, "Chat.Submit must be inside <Chat.Root>.");
|
|
9
|
+
const { status, stop } = useChat({ chat });
|
|
10
|
+
const running = status === "submitted" || status === "streaming";
|
|
11
|
+
const attachments = useContext(ComposerAttachmentsContext);
|
|
12
|
+
const sendable = (composer.draft.trim().length > 0 || (attachments?.count ?? 0) > 0) && !composer.disabled && !attachments?.blocked;
|
|
13
|
+
const stopping = running && !sendable;
|
|
14
|
+
return usePart("button", props, {
|
|
15
|
+
state: { stopping },
|
|
16
|
+
defaults: { type: "submit" },
|
|
17
|
+
behavior: { onClick: stopping ? () => void stop() : void 0 },
|
|
18
|
+
locked: { type: stopping ? "button" : "submit", disabled: !stopping && !sendable },
|
|
19
|
+
attributes: { active: stopping }
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
Submit
|
|
24
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type PartProps } from "@slices.sh/core/part";
|
|
2
|
+
type SuggestionProps = PartProps<"button"> & {
|
|
3
|
+
text: string;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Sends its own text. It goes through the composer rather than the chat, so a suggestion
|
|
7
|
+
* queued behind a running turn waits exactly as a typed message does.
|
|
8
|
+
*/
|
|
9
|
+
export declare function Suggestion({ text, ...props }: SuggestionProps): import("react").ReactNode;
|
|
10
|
+
export {};
|