@theoremjs/react 0.0.0-stage → 0.3.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 (231) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +246 -2
  3. package/client/attachment-hover-preview.d.ts +11 -0
  4. package/client/attachment-hover-preview.js +36 -0
  5. package/client/audio-level.d.ts +5 -0
  6. package/client/audio-level.js +24 -0
  7. package/client/composer-attachments.d.ts +30 -0
  8. package/client/composer-attachments.js +33 -0
  9. package/client/composer-drawer.d.ts +19 -0
  10. package/client/composer-drawer.js +15 -0
  11. package/client/composer-hints.d.ts +25 -0
  12. package/client/composer-hints.js +20 -0
  13. package/client/composer-primary.d.ts +16 -0
  14. package/client/composer-primary.js +25 -0
  15. package/client/decision-transport.d.ts +48 -0
  16. package/client/decision-transport.js +102 -0
  17. package/client/decode-composer-draft.d.ts +11 -0
  18. package/client/decode-composer-draft.js +12 -0
  19. package/client/encode-composer-draft.d.ts +9 -0
  20. package/client/encode-composer-draft.js +34 -0
  21. package/client/encode-files.d.ts +18 -0
  22. package/client/encode-files.js +54 -0
  23. package/client/failure.d.ts +32 -0
  24. package/client/failure.js +34 -0
  25. package/client/generation-selection.d.ts +15 -0
  26. package/client/generation-selection.js +24 -0
  27. package/client/host-call.d.ts +51 -0
  28. package/client/host-call.js +42 -0
  29. package/client/host-transport.d.ts +68 -0
  30. package/client/host-transport.js +74 -0
  31. package/client/image-output.d.ts +6 -0
  32. package/client/image-output.js +13 -0
  33. package/client/index.d.ts +20 -0
  34. package/client/index.js +18 -0
  35. package/client/ink-waveform.d.ts +17 -0
  36. package/client/ink-waveform.js +69 -0
  37. package/client/live/apply-live-turn-tool-event.d.ts +14 -0
  38. package/client/live/apply-live-turn-tool-event.js +39 -0
  39. package/client/live/live-captions.d.ts +23 -0
  40. package/client/live/live-captions.js +70 -0
  41. package/client/live/live-mic-forward.d.ts +29 -0
  42. package/client/live/live-mic-forward.js +37 -0
  43. package/client/live/live-state.d.ts +11 -0
  44. package/client/live/live-state.js +20 -0
  45. package/client/live/live-tool.d.ts +11 -0
  46. package/client/live/live-tool.js +1 -0
  47. package/client/live/live-video.d.ts +10 -0
  48. package/client/live/live-video.js +71 -0
  49. package/client/live/run-live-tool-call.d.ts +17 -0
  50. package/client/live/run-live-tool-call.js +32 -0
  51. package/client/live-client.d.ts +141 -0
  52. package/client/live-client.js +638 -0
  53. package/client/live-errors.d.ts +2 -0
  54. package/client/live-errors.js +9 -0
  55. package/client/live-messages.d.ts +110 -0
  56. package/client/live-messages.js +67 -0
  57. package/client/mic-capture.d.ts +4 -0
  58. package/client/mic-capture.js +6 -0
  59. package/client/oauth-popup.d.ts +26 -0
  60. package/client/oauth-popup.js +30 -0
  61. package/client/pcm-downsample.d.ts +4 -0
  62. package/client/pcm-downsample.js +45 -0
  63. package/client/run-commit.d.ts +61 -0
  64. package/client/run-commit.js +124 -0
  65. package/client/run-session.d.ts +80 -0
  66. package/client/run-session.js +215 -0
  67. package/client/schema-fields.d.ts +63 -0
  68. package/client/schema-fields.js +178 -0
  69. package/client/shaped-data.d.ts +118 -0
  70. package/client/shaped-data.js +314 -0
  71. package/client/source-citations.d.ts +13 -0
  72. package/client/source-citations.js +56 -0
  73. package/client/state-fields.d.ts +16 -0
  74. package/client/state-fields.js +44 -0
  75. package/client/tool-result.d.ts +78 -0
  76. package/client/tool-result.js +275 -0
  77. package/client/tool-resume.d.ts +33 -0
  78. package/client/tool-resume.js +11 -0
  79. package/client/trace-feed.d.ts +13 -0
  80. package/client/trace-feed.js +18 -0
  81. package/client/trace-story.d.ts +163 -0
  82. package/client/trace-story.js +416 -0
  83. package/client/trace-view.d.ts +130 -0
  84. package/client/trace-view.js +293 -0
  85. package/client/transcript-groups.d.ts +114 -0
  86. package/client/transcript-groups.js +167 -0
  87. package/client/transcript-scroll.d.ts +7 -0
  88. package/client/transcript-scroll.js +6 -0
  89. package/client/transport.d.ts +176 -0
  90. package/client/transport.js +256 -0
  91. package/client/turn-client.d.ts +35 -0
  92. package/client/turn-client.js +93 -0
  93. package/client/voice-label.d.ts +2 -0
  94. package/client/voice-label.js +15 -0
  95. package/client/voice-recorder.d.ts +27 -0
  96. package/client/voice-recorder.js +165 -0
  97. package/client/walk-away.d.ts +34 -0
  98. package/client/walk-away.js +48 -0
  99. package/client/wire-line.d.ts +56 -0
  100. package/client/wire-line.js +90 -0
  101. package/client/worklets/mic-capture.js +16 -0
  102. package/components/InkWaveform.d.ts +10 -0
  103. package/components/InkWaveform.js +108 -0
  104. package/components/live/use-live-runner-controls.d.ts +48 -0
  105. package/components/live/use-live-runner-controls.js +100 -0
  106. package/components/live/use-live-runner-model.d.ts +45 -0
  107. package/components/live/use-live-runner-model.js +175 -0
  108. package/components/live/use-live-runner-ui.d.ts +65 -0
  109. package/components/live/use-live-runner-ui.js +159 -0
  110. package/components/live/use-live-session-client.d.ts +41 -0
  111. package/components/live/use-live-session-client.js +123 -0
  112. package/components/use-composer-voice.d.ts +28 -0
  113. package/components/use-composer-voice.js +90 -0
  114. package/components/use-editor-selection.d.ts +3 -0
  115. package/components/use-editor-selection.js +16 -0
  116. package/components/use-voice-playback.d.ts +16 -0
  117. package/components/use-voice-playback.js +68 -0
  118. package/hooks/use-described.d.ts +8 -0
  119. package/hooks/use-described.js +23 -0
  120. package/hooks/use-theorem-chat-actions.d.ts +75 -0
  121. package/hooks/use-theorem-chat-actions.js +265 -0
  122. package/hooks/use-theorem-chat-state.d.ts +66 -0
  123. package/hooks/use-theorem-chat-state.js +118 -0
  124. package/hooks/use-theorem-chat.d.ts +63 -0
  125. package/hooks/use-theorem-chat.js +340 -0
  126. package/hooks/use-theorem-decision.d.ts +23 -0
  127. package/hooks/use-theorem-decision.js +75 -0
  128. package/hooks/use-theorem-host.d.ts +44 -0
  129. package/hooks/use-theorem-host.js +117 -0
  130. package/hooks/use-theorem-interface.d.ts +19 -0
  131. package/hooks/use-theorem-interface.js +25 -0
  132. package/hooks/use-trace-records.d.ts +4 -0
  133. package/hooks/use-trace-records.js +7 -0
  134. package/index.d.ts +14 -0
  135. package/index.js +14 -0
  136. package/live.d.ts +8 -0
  137. package/live.js +10 -0
  138. package/package.json +73 -4
  139. package/server/credential-store.d.ts +24 -0
  140. package/server/credential-store.js +14 -0
  141. package/server/decision-handler.d.ts +34 -0
  142. package/server/decision-handler.js +55 -0
  143. package/server/handler.d.ts +114 -0
  144. package/server/handler.js +568 -0
  145. package/server/json-response.d.ts +2 -0
  146. package/server/json-response.js +7 -0
  147. package/server/mod.d.ts +16 -0
  148. package/server/mod.js +15 -0
  149. package/server/request-check.d.ts +16 -0
  150. package/server/request-check.js +34 -0
  151. package/server/session-store.d.ts +74 -0
  152. package/server/session-store.js +49 -0
  153. package/server/steer-inbox.d.ts +35 -0
  154. package/server/steer-inbox.js +52 -0
  155. package/server/walk-away.d.ts +22 -0
  156. package/server/walk-away.js +41 -0
  157. package/styles/ink-controls.css +134 -0
  158. package/ui/ChatComposerBar.d.ts +39 -0
  159. package/ui/ChatComposerBar.js +251 -0
  160. package/ui/ChatTranscript.d.ts +30 -0
  161. package/ui/ChatTranscript.js +474 -0
  162. package/ui/ConsoleFrame.d.ts +47 -0
  163. package/ui/ConsoleFrame.js +46 -0
  164. package/ui/DecisionAnswers.d.ts +15 -0
  165. package/ui/DecisionAnswers.js +102 -0
  166. package/ui/LiveRunner.d.ts +28 -0
  167. package/ui/LiveRunner.js +193 -0
  168. package/ui/SchemaFields.d.ts +10 -0
  169. package/ui/SchemaFields.js +122 -0
  170. package/ui/ShapedData.d.ts +11 -0
  171. package/ui/ShapedData.js +151 -0
  172. package/ui/SidePanel.d.ts +57 -0
  173. package/ui/SidePanel.js +50 -0
  174. package/ui/StateFields.d.ts +36 -0
  175. package/ui/StateFields.js +96 -0
  176. package/ui/TheoremChat.d.ts +71 -0
  177. package/ui/TheoremChat.js +146 -0
  178. package/ui/TheoremDecision.d.ts +38 -0
  179. package/ui/TheoremDecision.js +87 -0
  180. package/ui/TheoremHost.d.ts +38 -0
  181. package/ui/TheoremHost.js +150 -0
  182. package/ui/ToolGateCard.d.ts +28 -0
  183. package/ui/ToolGateCard.js +100 -0
  184. package/ui/ToolResult.d.ts +10 -0
  185. package/ui/ToolResult.js +60 -0
  186. package/ui/ToolResultCharts.d.ts +5 -0
  187. package/ui/ToolResultCharts.js +86 -0
  188. package/ui/TraceCharts.d.ts +13 -0
  189. package/ui/TraceCharts.js +235 -0
  190. package/ui/TraceGuardrails.d.ts +10 -0
  191. package/ui/TraceGuardrails.js +56 -0
  192. package/ui/TraceInspector.d.ts +6 -0
  193. package/ui/TraceInspector.js +189 -0
  194. package/ui/TraceInspectorPanel.d.ts +24 -0
  195. package/ui/TraceInspectorPanel.js +57 -0
  196. package/ui/TraceOverview.d.ts +34 -0
  197. package/ui/TraceOverview.js +96 -0
  198. package/ui/TraceSpanDetail.d.ts +10 -0
  199. package/ui/TraceSpanDetail.js +188 -0
  200. package/ui/TraceStory.d.ts +20 -0
  201. package/ui/TraceStory.js +107 -0
  202. package/ui/TraceValues.d.ts +36 -0
  203. package/ui/TraceValues.js +113 -0
  204. package/ui/TraceWaterfall.d.ts +13 -0
  205. package/ui/TraceWaterfall.js +132 -0
  206. package/ui/VoiceNote.d.ts +12 -0
  207. package/ui/VoiceNote.js +28 -0
  208. package/ui/built/theme.css +774 -0
  209. package/ui/built/theorem.d.ts +13 -0
  210. package/ui/built/theorem.js +631 -0
  211. package/ui/built/theorem.variants.d.ts +16 -0
  212. package/ui/disclosure-motion.d.ts +6 -0
  213. package/ui/disclosure-motion.js +163 -0
  214. package/ui/icons.d.ts +4 -0
  215. package/ui/icons.js +37 -0
  216. package/ui/index.d.ts +25 -0
  217. package/ui/index.js +29 -0
  218. package/ui/labels-provider.d.ts +16 -0
  219. package/ui/labels-provider.js +61 -0
  220. package/ui/labels.d.ts +1153 -0
  221. package/ui/labels.js +603 -0
  222. package/ui/theme.d.ts +10 -0
  223. package/ui/theme.js +13 -0
  224. package/ui/theorem-theme.d.ts +10 -0
  225. package/ui/theorem-theme.js +83 -0
  226. package/ui/trace-palette.d.ts +24 -0
  227. package/ui/trace-palette.js +24 -0
  228. package/ui/trace-patterns.d.ts +32 -0
  229. package/ui/trace-patterns.js +44 -0
  230. package/ui/transcript-copy-text.d.ts +4 -0
  231. package/ui/transcript-copy-text.js +39 -0
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Server-held session state for `createTheoremHandler`.
3
+ *
4
+ * Everything that grants authority lives here, never in the request body:
5
+ * which tools the user allowed for the session, which paused tool calls may be
6
+ * resumed (and with exactly what input), and which provider interactions this
7
+ * session may continue.
8
+ *
9
+ * @module
10
+ */
11
+ import type { ToolGateAuth } from '@theoremjs/agents/interface';
12
+ import type { ToolGate, ToolId, TurnEventOf, TurnInput, TurnToolSnapshot } from '@theoremjs/agents/kernel';
13
+ /** A tool call the kernel paused on a gate, as the server saw it. */
14
+ export type PendingToolGate = {
15
+ name: string;
16
+ /** The model's arguments; an approval runs the call with exactly these. */
17
+ arguments: Record<string, unknown>;
18
+ /** The gate, and for a sign-in gate the credential slot and kind it waits for. */
19
+ gate: Pick<ToolGate, 'kind' | 'permission'> & {
20
+ auth?: ToolGateAuth;
21
+ };
22
+ snapshot?: TurnToolSnapshot;
23
+ promoted: ToolId[];
24
+ turnInput: TurnInput;
25
+ model?: string;
26
+ createdAt: number;
27
+ };
28
+ /**
29
+ * A paused call the server answered, and the event that settled it. A client
30
+ * the stream never reached still shows the call waiting; a message that walks
31
+ * away from it gets this answer again, not a refusal.
32
+ */
33
+ export type SettledToolGate = {
34
+ event: TurnEventOf<'tool'>;
35
+ /** When the call paused: a settled call is kept as long as its gate would have waited. */
36
+ createdAt: number;
37
+ };
38
+ export type TheoremSessionState = {
39
+ /** Tool ids the user allowed for the rest of this session. */
40
+ permissions: string[];
41
+ /** Paused tool calls by call id — the only calls `/invoke` will run. */
42
+ gates: Record<string, PendingToolGate>;
43
+ /** Paused calls the server answered and settled, by call id. */
44
+ settled: Record<string, SettledToolGate>;
45
+ /** Provider interaction ids this session produced, newest last. */
46
+ interactions: string[];
47
+ };
48
+ /**
49
+ * Where session state lives. The default is process memory — use a shared
50
+ * store (KV, Redis, a database row) when requests can reach different instances.
51
+ */
52
+ export interface TheoremSessionStore {
53
+ load(sessionId: string): TheoremSessionState | undefined | Promise<TheoremSessionState | undefined>;
54
+ save(sessionId: string, state: TheoremSessionState): void | Promise<void>;
55
+ }
56
+ export declare function emptySessionState(): TheoremSessionState;
57
+ /** Drop gates (waiting or settled) older than `ttlMs`. */
58
+ export declare function pruneGates<Gate extends {
59
+ createdAt: number;
60
+ }>(gates: Record<string, Gate>, now: number, ttlMs: number): Record<string, Gate>;
61
+ export type MemorySessionStoreOptions = {
62
+ /** Idle sessions are forgotten after this long. Default 24h. */
63
+ ttlMs?: number;
64
+ /** Oldest sessions are evicted past this count. Default 10 000. */
65
+ maxSessions?: number;
66
+ };
67
+ /** A value kept per session id; the shape of every store the handler takes. */
68
+ export type PerSessionStore<T> = {
69
+ load(sessionId: string): T | undefined | Promise<T | undefined>;
70
+ save(sessionId: string, value: T): void | Promise<void>;
71
+ };
72
+ /** A per-session value kept in process memory: forgotten when idle, oldest evicted first. */
73
+ export declare function createMemorySessionMap<T>(options?: MemorySessionStoreOptions): PerSessionStore<T>;
74
+ export declare function createMemorySessionStore(options?: MemorySessionStoreOptions): TheoremSessionStore;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Server-held session state for `createTheoremHandler`.
3
+ *
4
+ * Everything that grants authority lives here, never in the request body:
5
+ * which tools the user allowed for the session, which paused tool calls may be
6
+ * resumed (and with exactly what input), and which provider interactions this
7
+ * session may continue.
8
+ *
9
+ * @module
10
+ */
11
+ import { gateExpired } from '@theoremjs/agents/kernel';
12
+ export function emptySessionState() {
13
+ return { permissions: [], gates: {}, settled: {}, interactions: [] };
14
+ }
15
+ /** Drop gates (waiting or settled) older than `ttlMs`. */
16
+ export function pruneGates(gates, now, ttlMs) {
17
+ return Object.fromEntries(Object.entries(gates).filter(([, gate]) => !gateExpired(gate.createdAt, now, ttlMs)));
18
+ }
19
+ /** A per-session value kept in process memory: forgotten when idle, oldest evicted first. */
20
+ export function createMemorySessionMap(options = {}) {
21
+ const ttlMs = options.ttlMs ?? 24 * 60 * 60 * 1000;
22
+ const maxSessions = options.maxSessions ?? 10_000;
23
+ const sessions = new Map();
24
+ return {
25
+ load(sessionId) {
26
+ const entry = sessions.get(sessionId);
27
+ if (!entry)
28
+ return undefined;
29
+ if (Date.now() - entry.touched > ttlMs) {
30
+ sessions.delete(sessionId);
31
+ return undefined;
32
+ }
33
+ return structuredClone(entry.value);
34
+ },
35
+ save(sessionId, value) {
36
+ sessions.delete(sessionId);
37
+ sessions.set(sessionId, { value: structuredClone(value), touched: Date.now() });
38
+ while (sessions.size > maxSessions) {
39
+ const oldest = sessions.keys().next().value;
40
+ if (oldest === undefined)
41
+ break;
42
+ sessions.delete(oldest);
43
+ }
44
+ },
45
+ };
46
+ }
47
+ export function createMemorySessionStore(options = {}) {
48
+ return createMemorySessionMap(options);
49
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Mid-turn steer inbox — the client posts user messages while a turn streams;
3
+ * the turn's stage handler drains one unit per inject-capable stage.
4
+ *
5
+ * @module
6
+ */
7
+ import { type StageHandler, type TurnHistoryMessage } from '@theoremjs/agents';
8
+ import type { TheoremSteerRequest } from '../client/transport.ts';
9
+ /** One steer: the client's id for it, reported back in `stage.injected` once it lands. */
10
+ export type SteerUnit = {
11
+ id: string;
12
+ messages: TurnHistoryMessage[];
13
+ };
14
+ /**
15
+ * A steer as a client posts it (a checked `TheoremSteerRequest`): its user
16
+ * messages. Other roles are dropped — a client never injects system,
17
+ * assistant or tool turns — and a steer with no user message is refused.
18
+ */
19
+ export declare function steerUnitOf(steer: Pick<TheoremSteerRequest, 'id' | 'inject'>): SteerUnit;
20
+ /** Lands the inbox's next steer, one per steerable stage, named by its id. */
21
+ export declare function steerStage(inbox: SteerInbox, key: string): StageHandler;
22
+ /**
23
+ * Keyed by client turn id. The default lives in process memory, which is only
24
+ * correct when steer POSTs reach the same process as the turn — swap in a
25
+ * shared store (KV, Redis, Durable Object) for multi-instance hosts.
26
+ */
27
+ export interface SteerInbox {
28
+ open(turnId: string): void | Promise<void>;
29
+ /** Returns `false` when no turn with this id is open. */
30
+ enqueue(turnId: string, unit: SteerUnit): boolean | Promise<boolean>;
31
+ /** Next unit, FIFO, or `undefined`. */
32
+ consume(turnId: string): SteerUnit | undefined | Promise<SteerUnit | undefined>;
33
+ close(turnId: string): void | Promise<void>;
34
+ }
35
+ export declare function createMemorySteerInbox(): SteerInbox;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Mid-turn steer inbox — the client posts user messages while a turn streams;
3
+ * the turn's stage handler drains one unit per inject-capable stage.
4
+ *
5
+ * @module
6
+ */
7
+ import { TheoremError } from '@theoremjs/agents';
8
+ /** The stages a steer can land at. */
9
+ const STEER_STAGES = new Set(['pre_turn', 'post_tool', 'before_end']);
10
+ /**
11
+ * A steer as a client posts it (a checked `TheoremSteerRequest`): its user
12
+ * messages. Other roles are dropped — a client never injects system,
13
+ * assistant or tool turns — and a steer with no user message is refused.
14
+ */
15
+ export function steerUnitOf(steer) {
16
+ const messages = steer.inject.filter((message) => message.role === 'user');
17
+ // lexicon-exempt: internal diagnostic; the user reads the error kind's (or copy key's) wording
18
+ if (!messages.length)
19
+ throw new TheoremError('request', 'inject must contain user messages');
20
+ return { id: steer.id, messages };
21
+ }
22
+ /** Lands the inbox's next steer, one per steerable stage, named by its id. */
23
+ export function steerStage(inbox, key) {
24
+ return async ({ stage }) => {
25
+ if (!STEER_STAGES.has(stage))
26
+ return;
27
+ const unit = await inbox.consume(key);
28
+ return unit ? { inject: unit.messages, injectId: unit.id } : undefined;
29
+ };
30
+ }
31
+ export function createMemorySteerInbox() {
32
+ const queues = new Map();
33
+ return {
34
+ open(turnId) {
35
+ if (!queues.has(turnId))
36
+ queues.set(turnId, []);
37
+ },
38
+ enqueue(turnId, unit) {
39
+ const queue = queues.get(turnId);
40
+ if (!queue)
41
+ return false;
42
+ queue.push(structuredClone(unit));
43
+ return true;
44
+ },
45
+ consume(turnId) {
46
+ return queues.get(turnId)?.shift();
47
+ },
48
+ close(turnId) {
49
+ queues.delete(turnId);
50
+ },
51
+ };
52
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * A message that walks away from the calls its reply paused on, the same on
3
+ * every host (`createTheoremHandler`, the playground). The message's history
4
+ * leaves exactly those calls open; each settles cancelled, its events stream
5
+ * ahead of the reply, and the model reads each answer before the message.
6
+ *
7
+ * @module
8
+ */
9
+ import { type TurnEvent, type TurnInput } from '@theoremjs/agents';
10
+ /** Refuses a walk-away its history does not match, before any gate is answered. */
11
+ export declare function checkWalkAway(input: TurnInput, abandon: readonly string[]): void;
12
+ /** One walked-away call: its id, and the run that settles it (`invokeTool` with the abandoned resume). */
13
+ export type WalkedAwayCall = {
14
+ callId: string;
15
+ events: AsyncIterable<TurnEvent>;
16
+ };
17
+ /**
18
+ * Streams each call's tool events as it settles; each run's `done` stays with
19
+ * that run. Returns `input` with every call answered in its history, or
20
+ * undefined when a run failed: its `error` event went out and ends the reply.
21
+ */
22
+ export declare function walkAway(input: TurnInput, calls: readonly WalkedAwayCall[]): AsyncGenerator<TurnEvent, TurnInput | undefined>;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * A message that walks away from the calls its reply paused on, the same on
3
+ * every host (`createTheoremHandler`, the playground). The message's history
4
+ * leaves exactly those calls open; each settles cancelled, its events stream
5
+ * ahead of the reply, and the model reads each answer before the message.
6
+ *
7
+ * @module
8
+ */
9
+ import { TheoremError } from '@theoremjs/agents';
10
+ import { answerOpenToolCalls, assertOpenToolCalls, settlesToolCall, } from '@theoremjs/agents/interface';
11
+ /** Refuses a walk-away its history does not match, before any gate is answered. */
12
+ export function checkWalkAway(input, abandon) {
13
+ assertOpenToolCalls(input.history ?? [], abandon);
14
+ }
15
+ /**
16
+ * Streams each call's tool events as it settles; each run's `done` stays with
17
+ * that run. Returns `input` with every call answered in its history, or
18
+ * undefined when a run failed: its `error` event went out and ends the reply.
19
+ */
20
+ export async function* walkAway(input, calls) {
21
+ const answers = new Map();
22
+ for (const call of calls) {
23
+ for await (const event of call.events) {
24
+ if (event.type === 'error') {
25
+ yield event;
26
+ return undefined;
27
+ }
28
+ if (event.type !== 'tool')
29
+ continue;
30
+ yield event;
31
+ const readBack = settlesToolCall(event, call.callId) ? event.tool.readBack : undefined;
32
+ if (readBack !== undefined)
33
+ answers.set(call.callId, readBack);
34
+ }
35
+ if (!answers.has(call.callId)) {
36
+ // lexicon-exempt: internal diagnostic; the user reads error.internal
37
+ throw new TheoremError('internal', `walked-away call ${call.callId} ended without settling`);
38
+ }
39
+ }
40
+ return { ...input, history: answerOpenToolCalls(input.history ?? [], answers) };
41
+ }
@@ -0,0 +1,134 @@
1
+ /* Shared ink waveform + borderless controls (live shell and turn voice composer). */
2
+
3
+ :root {
4
+ --ink-ease: cubic-bezier(0.22, 1, 0.36, 1);
5
+ --ink-duration: 0.3s;
6
+ }
7
+
8
+ .ink-state {
9
+ margin: 0;
10
+ font-size: 0.75rem;
11
+ font-weight: 700;
12
+ letter-spacing: 0.06em;
13
+ text-transform: lowercase;
14
+ color: var(--color-ink);
15
+ }
16
+
17
+ .ink-wave-slot {
18
+ flex: 1 1 auto;
19
+ display: flex;
20
+ align-items: flex-end;
21
+ justify-content: center;
22
+ min-height: min(52vh, 22rem);
23
+ margin-bottom: 1.5rem;
24
+ padding: 0 0.5rem;
25
+ }
26
+
27
+ .ink-wave {
28
+ display: block;
29
+ width: min(100%, 36rem);
30
+ height: min(52vh, 22rem);
31
+ color: var(--color-ink);
32
+ }
33
+
34
+ .ink-wave--hero {
35
+ width: min(100%, 56rem);
36
+ height: 100%;
37
+ min-height: 40dvh;
38
+ max-height: 80dvh;
39
+ }
40
+
41
+ .ink-wave__bar {
42
+ stroke: currentcolor;
43
+ stroke-linecap: square;
44
+ }
45
+
46
+ .ink-divider {
47
+ flex-shrink: 0;
48
+ width: 100%;
49
+ height: 0;
50
+ margin: 0 0 1.5rem;
51
+ border: none;
52
+ border-top: 1px solid rgba(0, 0, 0, 0.14);
53
+ }
54
+
55
+ .ink-controls {
56
+ display: flex;
57
+ align-items: center;
58
+ justify-content: space-between;
59
+ gap: 1rem;
60
+ flex-shrink: 0;
61
+ }
62
+
63
+ .ink-controls__left,
64
+ .ink-controls__right {
65
+ display: flex;
66
+ align-items: center;
67
+ gap: 0.65rem;
68
+ }
69
+
70
+ .ink-control {
71
+ display: inline-flex;
72
+ align-items: center;
73
+ justify-content: center;
74
+ width: 2.5rem;
75
+ height: 2.5rem;
76
+ padding: 0;
77
+ color: var(--color-ink);
78
+ background: transparent;
79
+ border: none;
80
+ cursor: pointer;
81
+ opacity: 0.55;
82
+ transition: opacity var(--ink-duration) var(--ink-ease);
83
+ }
84
+
85
+ .ink-control:not(:disabled):hover {
86
+ opacity: 1;
87
+ }
88
+
89
+ .ink-control:disabled {
90
+ opacity: 0.22;
91
+ cursor: default;
92
+ }
93
+
94
+ .ink-control--active {
95
+ opacity: 0.9;
96
+ }
97
+
98
+ .ink-tooltip {
99
+ position: relative;
100
+ display: inline-flex;
101
+ }
102
+
103
+ .ink-tooltip__label {
104
+ position: absolute;
105
+ left: 50%;
106
+ z-index: 6;
107
+ padding: 0.28rem 0.45rem;
108
+ font-family: var(--font-mono, ui-monospace, monospace);
109
+ font-size: 0.62rem;
110
+ font-weight: 700;
111
+ letter-spacing: 0.08em;
112
+ line-height: 1.2;
113
+ text-transform: lowercase;
114
+ white-space: nowrap;
115
+ color: var(--color-paper, #f4f1ea);
116
+ background: var(--color-ink, #111);
117
+ border-radius: 0;
118
+ pointer-events: none;
119
+ transform: translateX(-50%);
120
+ }
121
+
122
+ .ink-tooltip__label--top {
123
+ bottom: calc(100% + 0.45rem);
124
+ }
125
+
126
+ .ink-tooltip__label--bottom {
127
+ top: calc(100% + 0.45rem);
128
+ }
129
+
130
+ @media (prefers-reduced-motion: reduce) {
131
+ .ink-control {
132
+ transition: none;
133
+ }
134
+ }
@@ -0,0 +1,39 @@
1
+ import { type ChatComposerInputHandle } from '@astryxdesign/core/Chat';
2
+ import { type AttachmentValidationIssue, type ComposerMenuAction, type ComposerPendingMessage, type ComposerProfileInterface, type ComposerRunPhase } from '@theoremjs/agents/interface';
3
+ import type { ClientFailure } from '../client/failure.ts';
4
+ export declare const NO_FOCUS_RING: React.CSSProperties;
5
+ export type ChatComposerBarProps = {
6
+ iface: ComposerProfileInterface;
7
+ draftText: string;
8
+ pendingFiles: readonly File[];
9
+ pendingVoice: readonly File[];
10
+ pendingMessages: readonly ComposerPendingMessage[];
11
+ /** Files the last send refused, one per reason; worded with the profile's lexicon. */
12
+ issues: readonly AttachmentValidationIssue[];
13
+ phase: ComposerRunPhase;
14
+ failure: ClientFailure | null;
15
+ selectedModel?: string;
16
+ selectedEffort?: string;
17
+ placeholder?: string;
18
+ /** Imperative handle for the editor (focus, insert). */
19
+ inputRef?: React.Ref<ChatComposerInputHandle>;
20
+ onDraftTextChange: (text: string) => void;
21
+ onFilesSelected: (files: File[]) => void;
22
+ onAttachmentRemove: (index: number) => void;
23
+ onVoiceStaged: (file: File) => void;
24
+ onVoiceClear: () => void;
25
+ onSubmit: () => void;
26
+ onStop: () => void;
27
+ onMenuAction: (action: ComposerMenuAction) => void;
28
+ onGenerationChange: (next: {
29
+ modelId: string;
30
+ effort?: string;
31
+ }) => void;
32
+ onPendingMove: (id: string, direction: 'up' | 'down') => void;
33
+ onPendingRemove: (id: string) => void;
34
+ onPendingQueue: (id: string) => void;
35
+ onPendingRestore: (id: string) => void;
36
+ onPendingSendNow: (id: string) => void;
37
+ };
38
+ /** Astryx composer wired to Theorem's send / stop / queue / steer / stash matrix. */
39
+ export declare function ChatComposerBar(props: ChatComposerBarProps): import("react").JSX.Element;