@theoremjs/react 0.3.4-next.671.gfa09ab2 → 0.3.4-next.673.ga492632
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/package.json +3 -3
- package/ui/ChatComposerBar.d.ts +9 -1
- package/ui/ChatComposerBar.js +6 -4
- package/ui/index.d.ts +1 -1
- package/ui/index.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theoremjs/react",
|
|
3
|
-
"version": "0.3.4-next.
|
|
3
|
+
"version": "0.3.4-next.673.ga492632",
|
|
4
4
|
"description": "React bindings for Theorem: headless hooks + transport, an Astryx chat UI, and a Web-standard server handler.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
"@stylexjs/stylex": "0.19.0",
|
|
61
61
|
"react": "^19.0.0",
|
|
62
62
|
"react-dom": "^19.0.0",
|
|
63
|
-
"@theoremjs/agents": "^0.3.4-next.
|
|
64
|
-
"@theoremjs/web": "^0.3.4-next.
|
|
63
|
+
"@theoremjs/agents": "^0.3.4-next.673.ga492632",
|
|
64
|
+
"@theoremjs/web": "^0.3.4-next.673.ga492632"
|
|
65
65
|
},
|
|
66
66
|
"peerDependenciesMeta": {
|
|
67
67
|
"@astryxdesign/core": {
|
package/ui/ChatComposerBar.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type ChatComposerInputHandle } from '@astryxdesign/core/Chat';
|
|
2
2
|
import { type AttachmentValidationIssue, type ComposerMenuAction, type ComposerPendingMessage, type ComposerProfileInterface, type ComposerRunPhase, type LiveProfileInterface } from '@theoremjs/agents/interface';
|
|
3
3
|
import type { ClientFailure } from '@theoremjs/web/client';
|
|
4
|
+
import { type ReactNode } from 'react';
|
|
4
5
|
/** A slot the profile declares: its allowed values, the one chosen, and how to choose another. */
|
|
5
6
|
/** The effort selector's icon. The studio's Agents list shows the same one. */
|
|
6
7
|
export declare const EFFORT_ICON: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
@@ -40,10 +41,12 @@ export type ChatComposerBarProps = {
|
|
|
40
41
|
onSubmit: () => void;
|
|
41
42
|
onStop: () => void;
|
|
42
43
|
onMenuAction: (action: ComposerMenuAction) => void;
|
|
43
|
-
onGenerationChange
|
|
44
|
+
onGenerationChange?: (next: {
|
|
44
45
|
modelId: string;
|
|
45
46
|
effort?: string;
|
|
46
47
|
}) => void;
|
|
48
|
+
/** Stands in for the model and effort selectors, for a bar whose choices are not one chat's. */
|
|
49
|
+
generationSelect?: ReactNode;
|
|
47
50
|
/** The profile's `inputs.slots` with the value chosen for each; one selector per slot, beside the model's. */
|
|
48
51
|
slotChoices?: SlotChoices;
|
|
49
52
|
onPendingMove: (id: string, direction: 'up' | 'down') => void;
|
|
@@ -63,6 +66,11 @@ export type LiveComposerBarProps = Omit<Pick<ChatComposerBarProps, 'draftText' |
|
|
|
63
66
|
/** Off while no call is connected. */
|
|
64
67
|
isDisabled: boolean;
|
|
65
68
|
};
|
|
69
|
+
/** The model and effort choices this profile offers; efforts only for a chosen model. */
|
|
70
|
+
export declare function generationOptions(iface: ComposerProfileInterface, selectedModel?: string): {
|
|
71
|
+
models: import("@theoremjs/agents/interface").InterfaceModelOption[];
|
|
72
|
+
efforts: import("@theoremjs/agents/interface").InterfaceEffortOption[];
|
|
73
|
+
};
|
|
66
74
|
/**
|
|
67
75
|
* Astryx composer wired to Theorem's send / stop / queue / steer / stash matrix.
|
|
68
76
|
* For a Live profile it is the text field and send button alone.
|
package/ui/ChatComposerBar.js
CHANGED
|
@@ -68,7 +68,7 @@ function PendingRow(props) {
|
|
|
68
68
|
return (_jsxs(HStack, { gap: 1, align: "center", width: "100%", children: [_jsx(HoverTip, { content: t(`@theorem.composer.pending.${message.kind}.description`), children: _jsx(Token, { label: t(`@theorem.composer.pending.${message.kind}`), isLabelHidden: true, color: message.kind === 'steer' ? 'blue' : 'default', icon: _jsx(Kind, { size: 14 }) }) }), _jsx(StackItem, { size: "fill", style: { width: 0 }, children: _jsx(Text, { size: "sm", maxLines: 1, hasTruncateTooltip: true, children: composerPendingPreview(message) }) }), _jsxs(HStack, { gap: 0.5, children: [_jsx(IconButton, { label: edit, tooltip: edit, size: "sm", variant: "ghost", icon: icon(IconPencil), onClick: () => props.onRestore(message.id) }), message.kind === 'stash' ? (_jsx(IconButton, { label: queue, tooltip: queue, size: "sm", variant: "ghost", icon: icon(IconCornerDownLeft), onClick: () => props.onQueue(message.id) })) : null, _jsx(IconButton, { label: sendNow, tooltip: sendNow, size: "sm", variant: "ghost", icon: icon(IconSend), onClick: () => props.onSendNow(message.id) }), props.moves.up ? (_jsx(IconButton, { label: moveUp, tooltip: moveUp, size: "sm", variant: "ghost", icon: icon(IconArrowUp), onClick: () => props.onMove(message.id, 'up') })) : null, props.moves.down ? (_jsx(IconButton, { label: moveDown, tooltip: moveDown, size: "sm", variant: "ghost", icon: icon(IconArrowDown), onClick: () => props.onMove(message.id, 'down') })) : null, _jsx(IconButton, { label: remove, tooltip: remove, size: "sm", variant: "ghost", icon: icon(IconX), onClick: () => props.onRemove(message.id) })] })] }));
|
|
69
69
|
}
|
|
70
70
|
/** The model and effort choices this profile offers; efforts only for a chosen model. */
|
|
71
|
-
function generationOptions(iface, selectedModel) {
|
|
71
|
+
export function generationOptions(iface, selectedModel) {
|
|
72
72
|
const models = modelSelectEnabled(iface) ? interfaceModelOptions(iface) : [];
|
|
73
73
|
const efforts = selectedModel && effortSelectEnabled(iface, selectedModel)
|
|
74
74
|
? interfaceEffortOptions(iface, selectedModel)
|
|
@@ -109,11 +109,13 @@ function SlotSelectors(props) {
|
|
|
109
109
|
function GenerationSelect(props) {
|
|
110
110
|
const { models, efforts } = generationOptions(props.iface, props.selectedModel);
|
|
111
111
|
const slotCount = Object.keys(props.slotChoices?.declared ?? {}).length;
|
|
112
|
+
if (props.control)
|
|
113
|
+
return (_jsxs(HStack, { gap: 1, children: [props.control, _jsx(SlotSelectors, { choices: props.slotChoices, isDisabled: props.isDisabled })] }));
|
|
112
114
|
if (models.length + efforts.length + slotCount === 0)
|
|
113
115
|
return null;
|
|
114
|
-
return (_jsxs(HStack, { gap: 1, children: [_jsx(ModelSelector, { label: labelText('composer.model', {}, props.iface.labels), models: models, value: props.selectedModel, isDisabled: props.isDisabled, onChange: (modelId) => props.onChange({ modelId }) }), _jsx(EffortSelector, { label: labelText('composer.effort', {}, props.iface.labels), efforts: efforts, value: props.selectedEffort, isDisabled: props.isDisabled, onChange: (effort) => {
|
|
116
|
+
return (_jsxs(HStack, { gap: 1, children: [_jsx(ModelSelector, { label: labelText('composer.model', {}, props.iface.labels), models: models, value: props.selectedModel, isDisabled: props.isDisabled, onChange: (modelId) => props.onChange?.({ modelId }) }), _jsx(EffortSelector, { label: labelText('composer.effort', {}, props.iface.labels), efforts: efforts, value: props.selectedEffort, isDisabled: props.isDisabled, onChange: (effort) => {
|
|
115
117
|
if (props.selectedModel)
|
|
116
|
-
props.onChange({ modelId: props.selectedModel, effort });
|
|
118
|
+
props.onChange?.({ modelId: props.selectedModel, effort });
|
|
117
119
|
} }), _jsx(SlotSelectors, { choices: props.slotChoices, isDisabled: props.isDisabled })] }));
|
|
118
120
|
}
|
|
119
121
|
function composerStatus(args) {
|
|
@@ -328,7 +330,7 @@ function ChatComposerBarBody(props) {
|
|
|
328
330
|
: (props.placeholder ??
|
|
329
331
|
t('@theorem.composer.placeholder', { handle: iface.identity.handle })),
|
|
330
332
|
// why: A profile that takes no text has no text field (false, not null: null gets Astryx's default one).
|
|
331
|
-
input: inputs.text && (_jsx(ComposerTextInput, { editorRef: editorRef, handleRef: props.inputRef, onStash: canStash ? () => props.onMenuAction('stash') : undefined })), drawer: composerDrawer(props, stagedFiles, () => voice.discardRecordingOrVoice()), headerActions: inputs.attachments ? (_jsx(AttachFilesButton, { accept: inputs.attachments.acceptAttr, onFiles: stageFiles })) : undefined, headerContext: hint ? _jsx(ComposerHint, { hint: hint, onAction: () => props.onMenuAction('stash') }) : undefined, footerActions: _jsx(GenerationSelect, { iface: iface, slotChoices: props.slotChoices, selectedModel: props.selectedModel, selectedEffort: props.selectedEffort, isDisabled: phase === 'streaming', onChange: props.onGenerationChange }),
|
|
333
|
+
input: inputs.text && (_jsx(ComposerTextInput, { editorRef: editorRef, handleRef: props.inputRef, onStash: canStash ? () => props.onMenuAction('stash') : undefined })), drawer: composerDrawer(props, stagedFiles, () => voice.discardRecordingOrVoice()), headerActions: inputs.attachments ? (_jsx(AttachFilesButton, { accept: inputs.attachments.acceptAttr, onFiles: stageFiles })) : undefined, headerContext: hint ? _jsx(ComposerHint, { hint: hint, onAction: () => props.onMenuAction('stash') }) : undefined, footerActions: _jsx(GenerationSelect, { iface: iface, slotChoices: props.slotChoices, selectedModel: props.selectedModel, selectedEffort: props.selectedEffort, isDisabled: phase === 'streaming', onChange: props.onGenerationChange, control: props.generationSelect }),
|
|
332
334
|
// why: Astryx: sendActions render to the left of the send button, at size="md".
|
|
333
335
|
sendActions: _jsxs(_Fragment, { children: [_jsx(SendMenu, { actions: menuActions, onAction: props.onMenuAction }), _jsx(ComposerRecordButton, { hasVoice: Boolean(inputs.voice), voice: voice })] }), sendButton: _jsx(ChatSendButton, { isStopShown: primary === 'stop', isDisabled: primaryDisabled, onSend: runPrimary, onStop: props.onStop }), status: composerStatus({
|
|
334
336
|
failure: props.failure,
|
package/ui/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export { useLiveCaptionLog } from '../client/live/use-live-caption-log.ts';
|
|
|
14
14
|
export { InkWaveform, type InkWaveformProps, type InkWaveLevels, } from '../components/InkWaveform.tsx';
|
|
15
15
|
export { useLiveRunnerModel } from '../components/live/use-live-runner-model.ts';
|
|
16
16
|
export { theoremTheme } from './built/theorem.js';
|
|
17
|
-
export { ChatComposerBar, type ChatComposerBarProps, EFFORT_ICON, type LiveComposerBarProps, } from './ChatComposerBar.tsx';
|
|
17
|
+
export { ChatComposerBar, type ChatComposerBarProps, EFFORT_ICON, generationOptions, type LiveComposerBarProps, } from './ChatComposerBar.tsx';
|
|
18
18
|
export { ChatTranscript, type ChatTranscriptProps } from './ChatTranscript.tsx';
|
|
19
19
|
export { ConsoleFrame, type ConsoleFrameProps, type ConsolePageProps, RequestCard, ResponseColumn, RunBar, useBytes, } from './ConsoleFrame.tsx';
|
|
20
20
|
export { TheoremDecisionAnswers, type TheoremDecisionAnswersProps } from './DecisionAnswers.tsx';
|
package/ui/index.js
CHANGED
|
@@ -17,7 +17,7 @@ export { useLiveCaptionLog } from "../client/live/use-live-caption-log.js";
|
|
|
17
17
|
export { InkWaveform, } from "../components/InkWaveform.js";
|
|
18
18
|
export { useLiveRunnerModel } from "../components/live/use-live-runner-model.js";
|
|
19
19
|
export { theoremTheme } from './built/theorem.js';
|
|
20
|
-
export { ChatComposerBar, EFFORT_ICON, } from "./ChatComposerBar.js";
|
|
20
|
+
export { ChatComposerBar, EFFORT_ICON, generationOptions, } from "./ChatComposerBar.js";
|
|
21
21
|
export { ChatTranscript } from "./ChatTranscript.js";
|
|
22
22
|
export { ConsoleFrame, RequestCard, ResponseColumn, RunBar, useBytes, } from "./ConsoleFrame.js";
|
|
23
23
|
export { TheoremDecisionAnswers } from "./DecisionAnswers.js";
|