@alia.onl/sdk 15.7.0 → 19.0.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.
Files changed (150) hide show
  1. package/CHANGELOG.md +255 -12
  2. package/README.md +241 -155
  3. package/package.json +17 -5
  4. package/src/animations.ts +0 -1
  5. package/src/components/AliaAskProvider.tsx +127 -0
  6. package/src/components/AliaChatContent.tsx +604 -392
  7. package/src/components/AliaChatHeader.tsx +14 -38
  8. package/src/components/AliaChatScreen.tsx +56 -31
  9. package/src/components/AliaChatSheet.tsx +110 -36
  10. package/src/components/AliaComposer.tsx +1 -1
  11. package/src/components/AliaParticipants.tsx +202 -0
  12. package/src/components/AliaParticipantsHeader.tsx +60 -0
  13. package/src/components/AliaSharedConversation.tsx +86 -0
  14. package/src/components/AliaWelcomeMessage.tsx +18 -5
  15. package/src/components/Image.tsx +12 -0
  16. package/src/components/Markdown.tsx +498 -14
  17. package/src/components/PlanPreviewCard.tsx +7 -49
  18. package/src/components/ReplyMarkdown.tsx +359 -0
  19. package/src/components/RichBlocks.tsx +195 -0
  20. package/src/components/canvas/CanvasComponent.tsx +59 -0
  21. package/src/components/canvas/ChartRenderer.tsx +73 -0
  22. package/src/components/canvas/CodeRenderer.tsx +24 -0
  23. package/src/components/canvas/FormRenderer.tsx +101 -0
  24. package/src/components/canvas/MarkdownRenderer.tsx +14 -0
  25. package/src/components/canvas/TableRenderer.tsx +47 -0
  26. package/src/components/thought/FilesAndSources.tsx +120 -0
  27. package/src/components/thought/ThoughtPanel.tsx +417 -0
  28. package/src/components/thought/ToolStep.tsx +141 -0
  29. package/src/components/thread/AgentResultCard.tsx +125 -0
  30. package/src/components/thread/AgentTaskCard.tsx +127 -0
  31. package/src/components/thread/AliaThread.tsx +401 -0
  32. package/src/components/thread/MessageBlockBoundary.tsx +78 -0
  33. package/src/components/thread/NewConversationOffer.tsx +54 -0
  34. package/src/components/thread/ThreadRow.tsx +458 -0
  35. package/src/components/thread/ThreadSearch.tsx +129 -0
  36. package/src/components/thread/ToolResultCard.tsx +254 -0
  37. package/src/components/thread/TurnMenu.tsx +54 -0
  38. package/src/components/thread/TurnStatusLine.tsx +34 -0
  39. package/src/components/voice/AliaVoiceCall.tsx +21 -0
  40. package/src/components/voice/VoiceControls.tsx +2 -28
  41. package/src/components/voice/VoiceSession.tsx +39 -11
  42. package/src/csp.ts +50 -0
  43. package/src/hooks/useAliaActivity.ts +3 -3
  44. package/src/hooks/useAtBottom.ts +51 -0
  45. package/src/hooks/useAttachMenu.ts +94 -0
  46. package/src/hooks/useChatComposer.ts +299 -0
  47. package/src/hooks/useChatVoice.ts +129 -0
  48. package/src/hooks/useDictation.ts +2 -3
  49. package/src/hooks/useDocumentPicker.ts +3 -29
  50. package/src/hooks/useFailedTurnToast.ts +43 -0
  51. package/src/hooks/useMessageVote.ts +50 -0
  52. package/src/hooks/useOpenThought.ts +79 -0
  53. package/src/hooks/usePendingQuestions.ts +2 -2
  54. package/src/hooks/useReadAloud.ts +92 -0
  55. package/src/hooks/useShareHandler.ts +24 -0
  56. package/src/hooks/useSoundEffects.ts +1 -1
  57. package/src/hooks/useTTS.ts +2 -3
  58. package/src/hooks/useThoughtScope.ts +59 -0
  59. package/src/hooks/useThreadRows.ts +145 -0
  60. package/src/hooks/useThreadView.ts +68 -0
  61. package/src/hooks/useTimelineWindow.ts +256 -0
  62. package/src/hooks/useVoiceLauncher.ts +180 -0
  63. package/src/hooks/useVoiceRoom.ts +2 -6
  64. package/src/index.ts +43 -29
  65. package/src/lib/activity-store.ts +1 -1
  66. package/src/lib/add-menu.ts +7 -0
  67. package/src/lib/call-thread.ts +33 -0
  68. package/src/lib/character-runtime.ts +6 -4
  69. package/src/lib/citations.ts +79 -2
  70. package/src/lib/clipboard.ts +23 -0
  71. package/src/lib/content-utils.ts +10 -0
  72. package/src/lib/copy-en.ts +284 -0
  73. package/src/lib/copy.ts +32 -0
  74. package/src/lib/document-picker.ts +31 -0
  75. package/src/lib/flights.ts +22 -13
  76. package/src/lib/focus-return.ts +66 -0
  77. package/src/lib/keyboard.native.tsx +19 -0
  78. package/src/lib/keyboard.tsx +9 -0
  79. package/src/lib/labels.tsx +69 -17
  80. package/src/lib/origins.ts +15 -0
  81. package/src/lib/participants.ts +86 -0
  82. package/src/lib/power-level-options.ts +66 -0
  83. package/src/lib/questions.ts +2 -2
  84. package/src/lib/task-labels.ts +4 -4
  85. package/src/lib/tool-call-status.ts +1 -1
  86. package/src/lib/tool-icons.ts +36 -0
  87. package/src/lib/tool-renderers.tsx +48 -0
  88. package/src/lib/turn-state.ts +2 -2
  89. package/src/lib/voice-audio-engine.ts +14 -158
  90. package/src/lib/voice-call-request.ts +49 -0
  91. package/src/lib/voice-call.ts +76 -34
  92. package/src/lib/voice-controls-labels.ts +31 -0
  93. package/src/lib/voice-protocol.ts +32 -14
  94. package/src/lib/voice-worklets.ts +19 -0
  95. package/src/lib/work-log.ts +6 -6
  96. package/src/runtime/agents.ts +151 -0
  97. package/src/runtime/api.ts +123 -0
  98. package/src/runtime/attachment-utils.ts +96 -0
  99. package/src/runtime/composer-draft-store.ts +270 -0
  100. package/src/runtime/config.tsx +186 -0
  101. package/src/runtime/conversation-store.ts +49 -0
  102. package/src/runtime/conversations.ts +557 -0
  103. package/src/runtime/error-utils.ts +104 -0
  104. package/src/runtime/host-tools.ts +140 -0
  105. package/src/runtime/index.ts +113 -0
  106. package/src/runtime/message-history.ts +124 -0
  107. package/src/runtime/model.ts +39 -0
  108. package/src/runtime/oxy-files.ts +37 -0
  109. package/src/runtime/power-levels.ts +66 -0
  110. package/src/runtime/query-keys.ts +34 -0
  111. package/src/runtime/random-uuid.ts +25 -0
  112. package/src/runtime/routes.ts +51 -0
  113. package/src/runtime/sharing.ts +165 -0
  114. package/src/runtime/sse-frame-reader.ts +88 -0
  115. package/src/runtime/stream-events.ts +146 -0
  116. package/src/runtime/stream-outcome.ts +21 -0
  117. package/src/runtime/thought-store.ts +103 -0
  118. package/src/runtime/thread/agent-activity.ts +261 -0
  119. package/src/runtime/thread/automation-labels.ts +79 -0
  120. package/src/runtime/thread/conversation-export.ts +135 -0
  121. package/src/runtime/thread/message-days.ts +120 -0
  122. package/src/runtime/thread/message-processor.ts +93 -0
  123. package/src/runtime/thread/task-utils.ts +11 -0
  124. package/src/runtime/thread/thought-utils.ts +752 -0
  125. package/src/runtime/thread/thread-history.ts +139 -0
  126. package/src/runtime/thread/timeline.ts +202 -0
  127. package/src/runtime/thread/title-tags.ts +8 -0
  128. package/src/runtime/thread/tool-cards.ts +383 -0
  129. package/src/runtime/turn-failure.ts +108 -0
  130. package/src/runtime/types.ts +148 -0
  131. package/src/runtime/usage-limit-error.ts +44 -0
  132. package/src/runtime/use-agent-activity.ts +80 -0
  133. package/src/runtime/use-conversation-stream.ts +1427 -0
  134. package/src/runtime/use-conversation-thread.ts +556 -0
  135. package/src/runtime/use-start-conversation.ts +107 -0
  136. package/src/runtime/use-thread-history.ts +64 -0
  137. package/src/runtime/use-thread-search.ts +95 -0
  138. package/src/runtime/use-turn-edit.ts +99 -0
  139. package/src/tools.ts +2 -2
  140. package/src/types.ts +18 -47
  141. package/worklets/voice-processors.js +152 -0
  142. package/src/components/AliaChatMessageList.tsx +0 -532
  143. package/src/components/ThinkingBlock.tsx +0 -43
  144. package/src/hooks/useAliaChat.ts +0 -573
  145. package/src/lib/api-url.ts +0 -2
  146. package/src/lib/catalogue.ts +0 -236
  147. package/src/lib/chat-stream.ts +0 -655
  148. package/src/lib/chat-transport.ts +0 -98
  149. package/src/lib/delegation.ts +0 -34
  150. package/src/lib/work-log-copy.ts +0 -61
@@ -0,0 +1,24 @@
1
+ import { useLabels } from '../../lib/labels';
2
+ import { CodeBlock } from '@oxy.so/bloom/code';
3
+ import * as Clipboard from 'expo-clipboard';
4
+
5
+ interface CodeData {
6
+ language: string;
7
+ code: string;
8
+ }
9
+
10
+ /** Shared code surface and copy feedback; clipboard works on both platforms. */
11
+ export function CodeRenderer({ data, filename }: { data: CodeData; filename?: string }) {
12
+ const { t } = useLabels();
13
+ return (
14
+ <CodeBlock
15
+ code={data.code}
16
+ language={data.language}
17
+ filename={filename}
18
+ onCopy={async (code) => {
19
+ await Clipboard.setStringAsync(code);
20
+ }}
21
+ labels={{ copy: t('panels.code.copy'), copied: t('panels.code.copied') }}
22
+ />
23
+ );
24
+ }
@@ -0,0 +1,101 @@
1
+ import { useLabels } from '../../lib/labels';
2
+ import { Button } from '@oxy.so/bloom/button';
3
+ import { Checkbox } from '@oxy.so/bloom/checkbox';
4
+ import { Field } from '@oxy.so/bloom/field';
5
+ import {
6
+ Select,
7
+ SelectContent,
8
+ SelectIcon,
9
+ SelectItem,
10
+ SelectItemIndicator,
11
+ SelectItemText,
12
+ SelectTrigger,
13
+ SelectValue,
14
+ } from '@oxy.so/bloom/select';
15
+ import { TextFieldInput } from '@oxy.so/bloom/text-field';
16
+ import { useState } from 'react';
17
+ import { View } from 'react-native';
18
+
19
+ interface FormField {
20
+ name: string;
21
+ type: 'text' | 'select' | 'checkbox';
22
+ label: string;
23
+ options?: string[];
24
+ }
25
+
26
+ interface FormData {
27
+ fields: FormField[];
28
+ }
29
+
30
+ interface FormRendererProps {
31
+ data: FormData;
32
+ onSubmit?: (formData: Record<string, any>) => void;
33
+ }
34
+
35
+ /** A generated form on Bloom's own controls: `Field` + `TextFieldInput`, `Select`, `Checkbox`. */
36
+ export function FormRenderer({ data, onSubmit }: FormRendererProps) {
37
+ const { t } = useLabels();
38
+ const { fields } = data;
39
+ const [formValues, setFormValues] = useState<Record<string, any>>({});
40
+
41
+ const updateValue = (name: string, value: any) => {
42
+ setFormValues((prev) => ({ ...prev, [name]: value }));
43
+ };
44
+
45
+ return (
46
+ <View className="gap-4">
47
+ {fields.map((field, i) =>
48
+ field.type === 'checkbox' ? (
49
+ <Checkbox
50
+ key={i}
51
+ label={field.label}
52
+ checked={!!formValues[field.name]}
53
+ onCheckedChange={(v) => updateValue(field.name, v)}
54
+ />
55
+ ) : (
56
+ <Field key={i} label={field.label}>
57
+ {field.type === 'select' ? (
58
+ <Select
59
+ value={formValues[field.name]}
60
+ onValueChange={(v) => updateValue(field.name, v)}
61
+ >
62
+ <SelectTrigger label={field.label}>
63
+ <SelectValue placeholder={t('panels.form.select')} />
64
+ <SelectIcon />
65
+ </SelectTrigger>
66
+ <SelectContent
67
+ label={field.label}
68
+ items={(field.options ?? []).map((option) => ({ value: option, label: option }))}
69
+ valueExtractor={(item) => item.value}
70
+ renderItem={(item) => (
71
+ <SelectItem value={item.value} label={item.label}>
72
+ <SelectItemIndicator />
73
+ <SelectItemText>{item.label}</SelectItemText>
74
+ </SelectItem>
75
+ )}
76
+ />
77
+ </Select>
78
+ ) : (
79
+ <TextFieldInput
80
+ label={field.label}
81
+ value={formValues[field.name] || ''}
82
+ onValueChange={(v) => updateValue(field.name, v)}
83
+ placeholder={t('panels.form.enter', { field: field.label.toLowerCase() })}
84
+ />
85
+ )}
86
+ </Field>
87
+ ),
88
+ )}
89
+
90
+ {/* Only a form with somewhere to send its values offers to send them.
91
+ No caller passes `onSubmit` today — the workspace panel renders the
92
+ canvas without a path back into the conversation — and the button
93
+ used to render regardless, a Submit that did nothing (#608, rule 6). */}
94
+ {onSubmit === undefined ? null : (
95
+ <View className="mt-2">
96
+ <Button onPress={() => onSubmit(formValues)}>{t('panels.form.submit')}</Button>
97
+ </View>
98
+ )}
99
+ </View>
100
+ );
101
+ }
@@ -0,0 +1,14 @@
1
+ import { ReplyMarkdown } from '../ReplyMarkdown';
2
+
3
+ interface MarkdownData {
4
+ content: string;
5
+ }
6
+
7
+ interface MarkdownRendererProps {
8
+ data: MarkdownData;
9
+ }
10
+
11
+ /** A generated document, written by the same Markdown renderer as a chat reply. */
12
+ export function MarkdownRenderer({ data }: MarkdownRendererProps) {
13
+ return <ReplyMarkdown content={data.content} />;
14
+ }
@@ -0,0 +1,47 @@
1
+ import {
2
+ Table,
3
+ TableBody,
4
+ TableCell,
5
+ TableColumn,
6
+ TableHeader,
7
+ TableRow,
8
+ } from '@oxy.so/bloom/table';
9
+
10
+ interface TableData {
11
+ headers: string[];
12
+ rows: string[][];
13
+ }
14
+
15
+ interface TableRendererProps {
16
+ data: TableData;
17
+ /** Names the table for assistive tech — the canvas component's title. */
18
+ title?: string;
19
+ }
20
+
21
+ /** Below this width per column the table scrolls sideways instead of squeezing. */
22
+ const COLUMN_MIN_WIDTH = 100;
23
+
24
+ export function TableRenderer({ data, title }: TableRendererProps) {
25
+ const { headers, rows } = data;
26
+
27
+ return (
28
+ <Table size="sm" accessibilityLabel={title} minWidth={headers.length * COLUMN_MIN_WIDTH}>
29
+ <TableHeader>
30
+ {headers.map((header, i) => (
31
+ <TableColumn key={i} minWidth={COLUMN_MIN_WIDTH}>
32
+ {header}
33
+ </TableColumn>
34
+ ))}
35
+ </TableHeader>
36
+ <TableBody>
37
+ {rows.map((row, rowIdx) => (
38
+ <TableRow key={rowIdx}>
39
+ {row.map((cell, cellIdx) => (
40
+ <TableCell key={cellIdx}>{cell}</TableCell>
41
+ ))}
42
+ </TableRow>
43
+ ))}
44
+ </TableBody>
45
+ </Table>
46
+ );
47
+ }
@@ -0,0 +1,120 @@
1
+ import { useLabels } from '../../lib/labels';
2
+ import type { OutputFile, Source } from '../../runtime/model';
3
+ import {
4
+ Accordion,
5
+ AccordionContent,
6
+ AccordionItem,
7
+ AccordionTrigger,
8
+ } from '@oxy.so/bloom/accordion';
9
+ import { EmptyState } from '@oxy.so/bloom/empty-state';
10
+ import { RiFileTextLine } from '@oxy.so/bloom/icons/RiFileTextLine';
11
+ import { RiGlobalLine } from '@oxy.so/bloom/icons/RiGlobalLine';
12
+ import { Item } from '@oxy.so/bloom/item';
13
+ import { useTheme } from '@oxy.so/bloom/theme';
14
+ import { useState } from 'react';
15
+
16
+ /**
17
+ * "Files and sources": what a turn produced and what it read, as two Bloom
18
+ * `Accordion` sections of `Item` rows.
19
+ *
20
+ * An output row is pressable only when the canvas holds its artifact to open;
21
+ * otherwise it is a labelled row and says so to assistive tech. A name is
22
+ * truncated on screen and whole in the row's accessible label.
23
+ *
24
+ * An empty section stays, with its header and one muted line, so the tab can
25
+ * never look like it failed to load and never hides that a persisted turn
26
+ * produced nothing (#542).
27
+ */
28
+ export interface FilesAndSourcesProps {
29
+ outputs: OutputFile[];
30
+ sources: Source[];
31
+ /** What the host can do with a generated file; absent, no output is pressable. */
32
+ outputActions?: OutputActions;
33
+ onOpenSource: (source: Source) => void;
34
+ }
35
+
36
+ /** Where a generated file opens: the host's canvas, for as long as it holds the file. */
37
+ export interface OutputActions {
38
+ /**
39
+ * Whether `open` can show this output. A host that keeps the files it was told about answers
40
+ * `false` for one it no longer holds, so a reloaded thread lists the file by name with no
41
+ * press, rather than a press that opens nothing.
42
+ */
43
+ canOpen: (output: OutputFile) => boolean;
44
+ open: (output: OutputFile) => void;
45
+ }
46
+
47
+ const ALL_OPEN = ['outputs', 'sources'];
48
+
49
+ export function FilesAndSources({
50
+ outputs,
51
+ sources,
52
+ outputActions,
53
+ onOpenSource,
54
+ }: FilesAndSourcesProps) {
55
+ const { t } = useLabels();
56
+ const { colors } = useTheme();
57
+ const [open, setOpen] = useState<string[]>(ALL_OPEN);
58
+
59
+ return (
60
+ <Accordion
61
+ type="multiple"
62
+ value={open}
63
+ onValueChange={(next) =>
64
+ setOpen(Array.isArray(next) ? next : next === undefined ? [] : [next])
65
+ }
66
+ >
67
+ <AccordionItem value="outputs">
68
+ <AccordionTrigger>{t('thought.outputs')}</AccordionTrigger>
69
+ <AccordionContent>
70
+ {outputs.length === 0 ? (
71
+ <EmptyState variant="compact" description={t('thought.noOutputs')} />
72
+ ) : (
73
+ outputs.map((output) => {
74
+ // A row is a control only when the canvas can actually show
75
+ // the file — the caller says so per output, so a persisted
76
+ // turn whose artifact is gone lists the name without a dead
77
+ // button under it.
78
+ const openable = outputActions?.canOpen(output) === true;
79
+ return (
80
+ <Item
81
+ key={output.id}
82
+ role="listitem"
83
+ density="compact"
84
+ leading={<RiFileTextLine size="md" fill={colors.textSecondary} />}
85
+ title={output.name}
86
+ accessibilityLabel={
87
+ openable ? t('thought.openOutput', { name: output.name }) : output.name
88
+ }
89
+ onPress={openable ? () => outputActions?.open(output) : undefined}
90
+ />
91
+ );
92
+ })
93
+ )}
94
+ </AccordionContent>
95
+ </AccordionItem>
96
+
97
+ <AccordionItem value="sources">
98
+ <AccordionTrigger>{t('thought.sources')}</AccordionTrigger>
99
+ <AccordionContent>
100
+ {sources.length === 0 ? (
101
+ <EmptyState variant="compact" description={t('thought.noSources')} />
102
+ ) : (
103
+ sources.map((source, index) => (
104
+ <Item
105
+ key={source.url}
106
+ role="listitem"
107
+ density="compact"
108
+ leading={<RiGlobalLine size="sm" fill={colors.textSecondary} />}
109
+ title={source.title}
110
+ subtitle={source.domain}
111
+ accessibilityLabel={t('thought.sourceLabel', { n: index + 1, title: source.title })}
112
+ onPress={() => onOpenSource(source)}
113
+ />
114
+ ))
115
+ )}
116
+ </AccordionContent>
117
+ </AccordionItem>
118
+ </Accordion>
119
+ );
120
+ }