@datalayer/agent-runtimes 1.5.17 → 1.5.18

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.
@@ -128,12 +128,12 @@ export const TAP_PROTOCOL_0_0_1 = {
128
128
  id: 'tap',
129
129
  version: '0.0.1',
130
130
  name: 'Trusted Agent Protocol',
131
- description: "An agent-recognition profile over Web Bot Auth for merchants: a signature tagged agent-browser-auth to browse or agent-payer-auth to pay. Built as a draft from Visa's public Merchant Specifications (2026-10-13) in agent-runtimes; planned for applications until Visa confirms it.",
131
+ description: "An agent-recognition profile over Web Bot Auth for merchants: a signature tagged agent-browser-auth to browse or agent-payer-auth to pay. Still a draft profile, built from Visa's public Merchant Specifications (2026-10-13) until Visa confirms it. In applications at test merchants only (decided 2026-10-14): the MCP gateway signs each UCP or ACP purchase with agent-payer-auth under the application's own key, and the test merchants verify it; browsing stays Web Bot Auth.",
132
132
  publisher: 'Visa',
133
133
  layer: 'identity',
134
134
  specUrl: 'https://developer.visa.com/capabilities/trusted-agent-protocol/trusted-agent-protocol-specifications',
135
135
  specVersion: 'draft (Merchant Specifications, read 2026-10-13)',
136
- status: 'planned',
136
+ status: 'shipped',
137
137
  connects: 'Merchants that recognise an agent by its signature',
138
138
  packages: {
139
139
  python: ['agent-runtimes'],
@@ -17,7 +17,7 @@ export const CROP_MONITORING_SCENE_0_0_1 = {
17
17
  cast: [
18
18
  {
19
19
  member: 'crop-monitoring',
20
- app: 'crop-monitoring:0.0.1',
20
+ app: 'crop-monitoring:0.0.2',
21
21
  ref: '',
22
22
  server: '',
23
23
  role: 'initiator',
@@ -330,7 +330,7 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
330
330
  cast: [
331
331
  {
332
332
  member: 'event-response',
333
- app: 'event-response:0.0.2',
333
+ app: 'event-response:0.0.3',
334
334
  ref: '',
335
335
  server: '',
336
336
  role: 'initiator',
@@ -354,7 +354,7 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
354
354
  },
355
355
  {
356
356
  member: 'disaster-assessment',
357
- app: 'disaster-assessment:0.0.1',
357
+ app: 'disaster-assessment:0.0.2',
358
358
  ref: '',
359
359
  server: '',
360
360
  role: 'contributor',
@@ -368,7 +368,7 @@ export const DISASTER_ASSESSMENT_SCENE_0_0_1 = {
368
368
  },
369
369
  {
370
370
  member: 'change-detection',
371
- app: 'change-detection:0.0.1',
371
+ app: 'change-detection:0.0.2',
372
372
  ref: '',
373
373
  server: '',
374
374
  role: 'contributor',
@@ -755,7 +755,7 @@ export const MONTH_END_CLOSE_SCENE_0_0_1 = {
755
755
  cast: [
756
756
  {
757
757
  member: 'month-end-close',
758
- app: 'month-end-close:0.0.1',
758
+ app: 'month-end-close:0.0.2',
759
759
  ref: '',
760
760
  server: '',
761
761
  role: 'initiator',
@@ -1912,7 +1912,7 @@ export const SALES_AND_ACCOUNTING_SCENE_0_0_1 = {
1912
1912
  cast: [
1913
1913
  {
1914
1914
  member: 'sales',
1915
- app: 'sales:0.0.2',
1915
+ app: 'sales:0.0.3',
1916
1916
  ref: '',
1917
1917
  server: '',
1918
1918
  role: 'initiator',
@@ -1932,7 +1932,7 @@ export const SALES_AND_ACCOUNTING_SCENE_0_0_1 = {
1932
1932
  },
1933
1933
  {
1934
1934
  member: 'accounting',
1935
- app: 'accounting:0.0.1',
1935
+ app: 'accounting:0.0.2',
1936
1936
  ref: '',
1937
1937
  server: '',
1938
1938
  role: 'contributor',
@@ -727,7 +727,7 @@ export const CROP_MONITORING_TEAM_SPEC_0_0_1 = {
727
727
  supervisor: {
728
728
  name: 'Crop Monitoring',
729
729
  ref: '',
730
- app: 'crop-monitoring:0.0.1',
730
+ app: 'crop-monitoring:0.0.2',
731
731
  model: '',
732
732
  goal: ``,
733
733
  instructions: ``,
@@ -766,7 +766,7 @@ export const CROP_MONITORING_TEAM_SPEC_0_0_1 = {
766
766
  id: 'crop-monitoring',
767
767
  name: '',
768
768
  ref: '',
769
- app: 'crop-monitoring:0.0.1',
769
+ app: 'crop-monitoring:0.0.2',
770
770
  runsIn: 'runtime',
771
771
  role: 'initiator',
772
772
  goal: `Take the person's field and period, search the imagery that covers them, and report the vigour, the growth and the fields to watch.`,
@@ -804,7 +804,7 @@ export const DISASTER_ASSESSMENT_TEAM_SPEC_0_0_1 = {
804
804
  supervisor: {
805
805
  name: 'Event response',
806
806
  ref: '',
807
- app: 'event-response:0.0.2',
807
+ app: 'event-response:0.0.3',
808
808
  model: '',
809
809
  goal: ``,
810
810
  instructions: ``,
@@ -843,7 +843,7 @@ export const DISASTER_ASSESSMENT_TEAM_SPEC_0_0_1 = {
843
843
  id: 'event-response',
844
844
  name: '',
845
845
  ref: '',
846
- app: 'event-response:0.0.2',
846
+ app: 'event-response:0.0.3',
847
847
  runsIn: 'browser',
848
848
  talksTo: [
849
849
  { member: 'disaster-assessment', over: 'a2a' },
@@ -863,7 +863,7 @@ export const DISASTER_ASSESSMENT_TEAM_SPEC_0_0_1 = {
863
863
  id: 'disaster-assessment',
864
864
  name: '',
865
865
  ref: '',
866
- app: 'disaster-assessment:0.0.1',
866
+ app: 'disaster-assessment:0.0.2',
867
867
  runsIn: 'runtime',
868
868
  role: 'contributor',
869
869
  goal: `Estimate the area the event affected and the extent of the damage from the imagery before and after it, over A2A.`,
@@ -879,7 +879,7 @@ export const DISASTER_ASSESSMENT_TEAM_SPEC_0_0_1 = {
879
879
  id: 'change-detection',
880
880
  name: '',
881
881
  ref: '',
882
- app: 'change-detection:0.0.1',
882
+ app: 'change-detection:0.0.2',
883
883
  runsIn: 'runtime',
884
884
  role: 'contributor',
885
885
  goal: `Find what changed on the ground between the two dates from the imagery, over A2A.`,
@@ -1133,7 +1133,7 @@ export const MONTH_END_CLOSE_TEAM_SPEC_0_0_1 = {
1133
1133
  supervisor: {
1134
1134
  name: 'Month-end Close',
1135
1135
  ref: '',
1136
- app: 'month-end-close:0.0.1',
1136
+ app: 'month-end-close:0.0.2',
1137
1137
  model: '',
1138
1138
  goal: ``,
1139
1139
  instructions: ``,
@@ -1169,7 +1169,7 @@ export const MONTH_END_CLOSE_TEAM_SPEC_0_0_1 = {
1169
1169
  id: 'month-end-close',
1170
1170
  name: '',
1171
1171
  ref: '',
1172
- app: 'month-end-close:0.0.1',
1172
+ app: 'month-end-close:0.0.2',
1173
1173
  runsIn: 'runtime',
1174
1174
  role: 'initiator',
1175
1175
  goal: `Take the person's request, read the period's books, and report where the close stands: what is done, what is to book, what is still open.`,
@@ -1735,7 +1735,7 @@ export const SALES_AND_ACCOUNTING_TEAM_SPEC_0_0_1 = {
1735
1735
  supervisor: {
1736
1736
  name: 'Sales',
1737
1737
  ref: '',
1738
- app: 'sales:0.0.2',
1738
+ app: 'sales:0.0.3',
1739
1739
  model: '',
1740
1740
  goal: ``,
1741
1741
  instructions: ``,
@@ -1774,7 +1774,7 @@ export const SALES_AND_ACCOUNTING_TEAM_SPEC_0_0_1 = {
1774
1774
  id: 'sales',
1775
1775
  name: '',
1776
1776
  ref: '',
1777
- app: 'sales:0.0.2',
1777
+ app: 'sales:0.0.3',
1778
1778
  runsIn: 'browser',
1779
1779
  talksTo: [{ member: 'accounting', over: 'a2a' }],
1780
1780
  role: 'initiator',
@@ -1791,7 +1791,7 @@ export const SALES_AND_ACCOUNTING_TEAM_SPEC_0_0_1 = {
1791
1791
  id: 'accounting',
1792
1792
  name: '',
1793
1793
  ref: '',
1794
- app: 'accounting:0.0.1',
1794
+ app: 'accounting:0.0.2',
1795
1795
  runsIn: 'runtime',
1796
1796
  role: 'contributor',
1797
1797
  goal: `Answer report requests from the Odoo books, read only, over A2A.`,
@@ -45,6 +45,8 @@ export interface SpeechModelSpec {
45
45
  id: string;
46
46
  version: string;
47
47
  name: string;
48
+ /** What it is for, in a sentence or two. */
49
+ description: string;
48
50
  task: 'stt' | 'tts' | 'vad';
49
51
  engine: string;
50
52
  dtype: string;
@@ -72,6 +72,7 @@ export const SPEECH_MODEL_CATALOGUE = {
72
72
  id: 'kokoro-82m',
73
73
  version: '0.0.1',
74
74
  name: 'Kokoro 82M',
75
+ description: "Text to speech on Datalayer's servers, on CPU: hexgrad's Kokoro-82M v1.0 exported to ONNX, in full precision, with the voices file that holds its 54 voices, run by kokoro-onnx. Its phonemes come from eSpeak NG (GPL-3.0), which runs on the server and is never sent to a browser. Full precision, not the 8-bit export: on a 16-core CPU the 8-bit one speaks slower than real time (6 s for 3.9 s of speech), this one about four times faster than real time (1 s).",
75
76
  task: 'tts',
76
77
  engine: 'kokoro-onnx',
77
78
  dtype: 'fp32',
@@ -102,6 +103,7 @@ export const SPEECH_MODEL_CATALOGUE = {
102
103
  id: 'moonshine-base-en',
103
104
  version: '0.0.1',
104
105
  name: 'Moonshine Base (English)',
106
+ description: "Speech to text in the browser, in English: Useful Sensors' Moonshine Base (61M parameters), its ONNX export quantized to 8 bits, run by transformers.js. One of the English models whose weights are MIT; the legacy non-English Moonshine models are under a non-commercial licence and are not listed.",
105
107
  task: 'stt',
106
108
  engine: 'transformers.js',
107
109
  dtype: 'q8',
@@ -162,6 +164,7 @@ export const SPEECH_MODEL_CATALOGUE = {
162
164
  id: 'moonshine-tiny-en',
163
165
  version: '0.0.1',
164
166
  name: 'Moonshine Tiny (English)',
167
+ description: "Speech to text in the browser, in English: Useful Sensors' Moonshine Tiny (27M parameters), its ONNX export quantized to 8 bits, run by transformers.js. One of the English models whose weights are MIT; the legacy non-English Moonshine models are under a non-commercial licence and are not listed.",
165
168
  task: 'stt',
166
169
  engine: 'transformers.js',
167
170
  dtype: 'q8',
@@ -222,6 +225,7 @@ export const SPEECH_MODEL_CATALOGUE = {
222
225
  id: 'silero-vad',
223
226
  version: '0.0.1',
224
227
  name: 'Silero VAD',
228
+ description: 'Where speech starts and ends in what the microphone heard, in the browser: Silero VAD (about 2 MB), the build @ricky0123/vad-web 0.0.31 ships and runs on onnxruntime-web. Push-to-talk keeps the speech it finds and drops the rest.',
225
229
  task: 'vad',
226
230
  engine: 'vad-web',
227
231
  dtype: 'fp32',
@@ -247,6 +251,7 @@ export const SPEECH_MODEL_CATALOGUE = {
247
251
  id: 'whisper-base',
248
252
  version: '0.0.1',
249
253
  name: 'Whisper Base',
254
+ description: "Speech to text in the browser for the languages Moonshine's MIT models do not speak, French first: OpenAI's Whisper base (74M parameters, 99 languages), its ONNX export quantized to 8 bits, run by transformers.js. A clip at a time.",
250
255
  task: 'stt',
251
256
  engine: 'transformers.js',
252
257
  dtype: 'q8',
@@ -1483,6 +1483,11 @@ export interface Agentspec {
1483
1483
  parameters?: Record<string, any>;
1484
1484
  /** Subagent delegation configuration. */
1485
1485
  subagents?: SubAgentsConfig;
1486
+ /**
1487
+ * Its voice, for an agent that is not an application (VOICE.md VO-41):
1488
+ * the fields an Appspec says under `interface.voice`; absent when unsaid.
1489
+ */
1490
+ voice?: AppVoiceSpec;
1486
1491
  }
1487
1492
  /**
1488
1493
  * Where a subagent reached over A2A lives, or how to launch it.
@@ -1004,6 +1004,12 @@ export interface ChatBaseProps {
1004
1004
  voiceSpeaking?: boolean;
1005
1005
  /** Stops the agent's voice: the composer's *Stop speaking*, and the microphone opening (VO-13). */
1006
1006
  onStopSpeaking?: () => void;
1007
+ /**
1008
+ * Reads an answer aloud (VOICE.md VO-21): given, each answer the agent has
1009
+ * finished writing has a *Read aloud* under it, which calls it with the
1010
+ * answer's text.
1011
+ */
1012
+ onReadAloud?: (answer: string) => void;
1007
1013
  /**
1008
1014
  * Show the information icon in the header.
1009
1015
  * When clicked, fires onInformationClick.
@@ -59,6 +59,23 @@ export interface ProtocolConfig {
59
59
  * never the bytes. Set for an application's agent.
60
60
  */
61
61
  uiFiles?: string;
62
+ /**
63
+ * The application's sessions (`…/api/v1/apps/sessions`), each AG-UI thread
64
+ * one of them: Stop is its session's (`{appSessions}/{thread}/stop`). Set
65
+ * for an application's agent. The runtime's generic `/ag-ui/terminate`
66
+ * never knew a session's thread, and a deployment's runtime does not
67
+ * answer it (OwnRoutesOnly).
68
+ */
69
+ appSessions?: string;
70
+ /**
71
+ * The runtime answers only the application's own routes (OwnRoutesOnly,
72
+ * PAP_DATALAYER's release gates): it serves a deployment — kept always on,
73
+ * launched by a hosted page for it — or is the visitors' runtime. Nothing
74
+ * outside them is opened: not the monitoring stream (an application's
75
+ * session asks its approvals in the conversation, over `uiSocket`), not
76
+ * the sandbox's socket, nor any runtime-wide setting. Needs `appSessions`.
77
+ */
78
+ ownRoutesOnly?: boolean;
62
79
  /** Additional protocol options */
63
80
  options?: Record<string, unknown>;
64
81
  }
@@ -195,7 +195,14 @@ export function createProtocolAdapter(config) {
195
195
  };
196
196
  switch (config.type) {
197
197
  case 'ag-ui':
198
- return new AGUIAdapter(adapterConfig);
198
+ if (config.ownRoutesOnly && !config.appSessions) {
199
+ // Its runtime answers no generic Stop: an application's own or none.
200
+ throw new Error('A chat whose runtime answers only the application’s own routes is an application’s: it needs its sessions (appSessions).');
201
+ }
202
+ return new AGUIAdapter({
203
+ ...adapterConfig,
204
+ ...(config.appSessions ? { appSessions: config.appSessions } : {}),
205
+ });
199
206
  case 'a2a':
200
207
  return new A2AAdapter(adapterConfig);
201
208
  case 'vercel-ai':
@@ -0,0 +1,35 @@
1
+ /**
2
+ * *Read aloud*, under an answer (VOICE.md VO-21, `on_request`): the answer,
3
+ * read as plain words and cut into sentences, given to the speaker — what it
4
+ * was saying stops first. The press is the gesture a browser plays sound
5
+ * after.
6
+ *
7
+ * @module voice/ReadAloud
8
+ */
9
+ import type { JSX } from 'react';
10
+ import type { SentenceSink } from './useSpokenAnswers';
11
+ /** What *Read aloud* gives an answer to: a sink a press may unlock. */
12
+ export interface ReadingSink extends SentenceSink {
13
+ unlock?: () => void;
14
+ }
15
+ /** An answer read from its start: what was being said stops, its sentences follow. */
16
+ export declare function readAloud(sink: ReadingSink, answer: string): string[];
17
+ /** A message, as far as *Read aloud* reads it. */
18
+ export interface ReadableMessage {
19
+ id: string;
20
+ role: string;
21
+ live?: boolean;
22
+ note?: unknown;
23
+ }
24
+ /**
25
+ * Whether a message has *Read aloud* under it: an answer of the agent with
26
+ * words, finished — not live, and not the one the agent is writing now.
27
+ */
28
+ export declare function readsAloud(message: ReadableMessage, text: string, writingId: string | undefined): boolean;
29
+ export interface ReadAloudProps {
30
+ /** Reads the answer aloud. */
31
+ onRead: () => void;
32
+ }
33
+ /** The button under an answer. */
34
+ export declare function ReadAloud({ onRead }: ReadAloudProps): JSX.Element;
35
+ export default ReadAloud;
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { IconButton, Tooltip } from '@primer/react';
3
+ import { UnmuteIcon } from '@primer/octicons-react';
4
+ import { SentenceCutter } from './sentences';
5
+ /** An answer read from its start: what was being said stops, its sentences follow. */
6
+ export function readAloud(sink, answer) {
7
+ sink.unlock?.();
8
+ sink.stop();
9
+ const cutter = new SentenceCutter();
10
+ const sentences = [...cutter.feed(answer), ...cutter.end(answer)];
11
+ sentences.forEach(sentence => sink.say(sentence));
12
+ return sentences;
13
+ }
14
+ /**
15
+ * Whether a message has *Read aloud* under it: an answer of the agent with
16
+ * words, finished — not live, and not the one the agent is writing now.
17
+ */
18
+ export function readsAloud(message, text, writingId) {
19
+ return (message.role === 'assistant' &&
20
+ !message.live &&
21
+ !message.note &&
22
+ message.id !== writingId &&
23
+ text.trim().length > 0);
24
+ }
25
+ /** The button under an answer. */
26
+ export function ReadAloud({ onRead }) {
27
+ return (_jsx(Tooltip, { text: "Read aloud", direction: "n", children: _jsx(IconButton, { "data-read-aloud": "", icon: UnmuteIcon, "aria-label": "Read aloud", size: "small", variant: "invisible", onClick: onRead }) }));
28
+ }
29
+ export default ReadAloud;
@@ -18,6 +18,8 @@ export * from './consent';
18
18
  export * from './useSpokenAnswers';
19
19
  export { VoiceInput } from './VoiceInput';
20
20
  export type { VoiceInputProps, ListeningState } from './VoiceInput';
21
+ export { ReadAloud, readAloud, readsAloud } from './ReadAloud';
22
+ export type { ReadAloudProps, ReadableMessage, ReadingSink } from './ReadAloud';
21
23
  /**
22
24
  * A chat's voice: what a host gives `ChatBase` and `ChatFloating` to let a
23
25
  * person talk to the agent and hear it — the Appspec's `interface.voice`,
@@ -28,8 +30,11 @@ export interface ChatVoice {
28
30
  language: string;
29
31
  /** `push_to_talk`, or `off`. Hands-free is Phase V3. */
30
32
  input: 'off' | 'push_to_talk';
31
- /** When answers are heard: `always`, or `off`. */
32
- output: 'off' | 'always';
33
+ /**
34
+ * When answers are heard: `always`, as they are written; `on_request`, a
35
+ * *Read aloud* under each answer (VO-21); or `off`.
36
+ */
37
+ output: 'off' | 'on_request' | 'always';
33
38
  /** The voice of the catalogue answers are spoken with. */
34
39
  voice: string;
35
40
  /** Datalayer's origin for the browser's models: the pinned store. */
@@ -11,3 +11,4 @@ export * from './speaker';
11
11
  export * from './consent';
12
12
  export * from './useSpokenAnswers';
13
13
  export { VoiceInput } from './VoiceInput';
14
+ export { ReadAloud, readAloud, readsAloud } from './ReadAloud';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datalayer/agent-runtimes",
3
- "version": "1.5.17",
3
+ "version": "1.5.18",
4
4
  "type": "module",
5
5
  "workspaces": [
6
6
  ".",
@@ -160,7 +160,7 @@
160
160
  "@datalayer/lexical-loro": "^1.0.6",
161
161
  "@datalayer/primer-addons": "^1.0.39",
162
162
  "@datalayer/primer-rjsf": "^1.0.3",
163
- "@datalayer/personal-agent-protocol": "^0.23.0",
163
+ "@datalayer/personal-agent-protocol": "^0.24.0",
164
164
  "@datalayer/reactor": "^1.3.0",
165
165
  "@datalayer/reactor-commands": "^1.0.4",
166
166
  "@datalayer/reactor-manager": "^1.0.4",
@@ -304,9 +304,33 @@ def load_yaml_specs(specs_dir: Path) -> List[tuple[str, Dict[str, Any]]]:
304
304
 
305
305
  check_model_additionals(resolved, load_model_ids(specs_dir))
306
306
  check_protocols(resolved, load_protocol_ids(specs_dir))
307
+ check_voices(resolved)
307
308
  return resolved
308
309
 
309
310
 
311
+ def check_voices(specs: List[tuple[str, Dict[str, Any]]]) -> None:
312
+ """Refuse an agent whose `voice` is not an `interface.voice` block of the voice catalogue (VOICE.md VO-41)."""
313
+ from agentspecs.apps import agent_voice_problems
314
+
315
+ problems = [
316
+ problem
317
+ for _, spec in specs
318
+ if "voice" in spec
319
+ for problem in agent_voice_problems(str(spec.get("id")), spec["voice"])
320
+ ]
321
+ if problems:
322
+ raise SystemExit("\n".join(problems))
323
+
324
+
325
+ def voice_of(spec: Dict[str, Any]) -> Dict[str, Any] | None:
326
+ """An agent's voice with every field said, as the Appspec's block reads it; None when unsaid."""
327
+ if "voice" not in spec:
328
+ return None
329
+ from agentspecs.apps import AppVoice
330
+
331
+ return AppVoice(**spec["voice"]).model_dump(mode="json")
332
+
333
+
310
334
  def load_protocol_ids(specs_dir: Path) -> set[str]:
311
335
  """Every id of the protocols catalogue (`agentspecs/protocols`, AGENT_PROTOCOLS PS-01)."""
312
336
  ids: set[str] = set()
@@ -525,6 +549,10 @@ from agent_runtimes.types import (
525
549
  if model_additionals
526
550
  else ""
527
551
  )
552
+ voice = voice_of(spec)
553
+ voice_py_line = (
554
+ f" voice={_fmt_py_literal(voice)},\n" if voice is not None else ""
555
+ )
528
556
  inference_provider = spec.get("inference_provider")
529
557
  inference_provider_str = (
530
558
  f'"{inference_provider}"' if inference_provider else "None"
@@ -687,7 +715,7 @@ from agent_runtimes.types import (
687
715
  tool_hooks={_fmt_py_literal(tool_hooks_val)},
688
716
  parameters={_fmt_py_literal(parameters_val)},
689
717
  subagents={subagents_str},
690
- )
718
+ {voice_py_line})
691
719
 
692
720
  '''
693
721
 
@@ -1154,6 +1182,10 @@ const FRONTEND_TOOL_MAP: Record<string, any> = {
1154
1182
  if model_additionals
1155
1183
  else ""
1156
1184
  )
1185
+ voice = voice_of(spec)
1186
+ voice_ts_line = (
1187
+ f" voice: {_fmt_ts_literal(voice)},\n" if voice is not None else ""
1188
+ )
1157
1189
  inference_provider = spec.get("inference_provider")
1158
1190
  inference_provider_ts = (
1159
1191
  f"'{inference_provider}'" if inference_provider else "undefined"
@@ -1262,7 +1294,7 @@ const FRONTEND_TOOL_MAP: Record<string, any> = {
1262
1294
  toolHooks: {_fmt_ts_literal(tool_hooks_val)},
1263
1295
  parameters: {_fmt_ts_literal(parameters_val)},
1264
1296
  subagents: {subagents_ts},
1265
- }};
1297
+ {voice_ts_line}}};
1266
1298
 
1267
1299
  """
1268
1300
 
@@ -45,6 +45,7 @@ def _model(model: Any) -> dict[str, Any]:
45
45
  "id": model.id,
46
46
  "version": model.version,
47
47
  "name": model.name,
48
+ "description": " ".join(model.description.split()),
48
49
  "task": model.task,
49
50
  "engine": model.engine,
50
51
  "dtype": model.dtype,
@@ -120,7 +121,8 @@ def generate_python_code(
120
121
  " base = (language or '').strip()",
121
122
  " exact = [v for v in VOICE_CATALOGUE.values() if base in v['languages']]",
122
123
  " near = [v for v in VOICE_CATALOGUE.values() if voice_speaks(v, base.split('-')[0])]",
123
- " return (exact or near or [None])[0]",
124
+ " found = exact or near",
125
+ " return found[0] if found else None",
124
126
  "",
125
127
  ]
126
128
  )
@@ -191,6 +193,8 @@ def generate_typescript_code(
191
193
  " id: string;",
192
194
  " version: string;",
193
195
  " name: string;",
196
+ " /** What it is for, in a sentence or two. */",
197
+ " description: string;",
194
198
  " task: 'stt' | 'tts' | 'vad';",
195
199
  " engine: string;",
196
200
  " dtype: string;",
@@ -1,32 +0,0 @@
1
- import{E as N,eN as uo,r as o,j as t,eO as fo,eP as po,b_ as Cn,B as f,H as ct,T as H,c as G,cu as Pt,eu as Lt,eQ as ae,co as dt,e as mo,eR as go,eS as ho,e3 as bo,eT as xo,aH as So,dX as Un,dV as vo,dY as _t,eU as yo,eV as Co,eW as wo,eX as jo,eY as wn,eZ as ko,e_ as Eo,e$ as Io,d3 as To,a_ as Ro,f0 as Ao,f1 as Po,f2 as Mo,f3 as $o,f4 as Uo,f5 as Oo,x as Mt,f6 as Fo,f7 as Lo,f8 as _o,f9 as zo,fa as No,fb as Bo,fc as Vo,fd as Ho,fe as Wo,ff as Do,fg as Go,fh as Ko,fi as Yo,fj as qo,fk as Jo,fl as Qo,fm as Xo,fn as Zo,fo as es,fp as ts,fq as De,fr as ns,fs as os,ft as ss,fu as as,fv as jn,fw as is,fx as Ae,fy as rs,fz as ls,a$ as ut,fA as cs,fB as ds,fC as kn,fD as us,fE as fs,eC as ps,fF as $t,fG as Se,fH as ms,fI as gs,fJ as En,fK as hs,fL as bs,fM as xs,fN as Ss,fO as vs,fP as ys,fQ as Cs,fR as ws,fS as js,fT as ft,fU as ks,fV as Es,I as Is,fW as Ts,fX as Rs,fY as In,fZ as As,f_ as Ps,f$ as Ms,g0 as zt,g1 as $s,g2 as Us,ek as Ut,g3 as Os,g4 as Fs}from"../datalayer-app-main.js";import{S as Ls,E as _s,a as zs}from"./SignInIcon-4HkE48mS.js";import{F as Ns,a as Bs,b as Vs}from"./LinkedInGreyIcon-BoWXE-HS.js";function On(){const n=N(uo);return o.useMemo(()=>n.map(s=>s.value),[n])}const Ot={github:{name:"github",oauth2CallbackServerRoute:"jupyter_iam/oauth2/callback",oauth2CallbackUIRoute:"/iam/oauth2/github/callback"},google:{name:"google",oauth2CallbackServerRoute:"jupyter_iam/oauth2/callback",oauth2CallbackUIRoute:"/iam/oauth2/google/callback"},linkedin:{name:"linkedin",oauth2CallbackServerRoute:"jupyter_iam/oauth2/callback",oauth2CallbackUIRoute:"/iam/oauth2/linkedin/callback"}},Tn=()=>{if(typeof document>"u")return"";const n=document.getElementById("datalayer-config-data");if(!n?.textContent)return"";try{const s=JSON.parse(n.textContent);return String(s?.iamUrl||"").replace(/\/$/,"")}catch{return""}},Hs=(n,s="Unable to start social sign-in.")=>{if(n instanceof Error&&n.message)return n.message;if(typeof n=="string"&&n.trim())return n;if(n&&typeof n=="object"&&"message"in n){const c=n.message;if(typeof c=="string"&&c.trim())return c}return s},Ws=xo`
2
- .signin-input-theme-scope input:-webkit-autofill,
3
- .signin-input-theme-scope input:-webkit-autofill:hover,
4
- .signin-input-theme-scope input:-webkit-autofill:focus,
5
- .signin-input-theme-scope input:-webkit-autofill:active,
6
- .signin-input-theme-scope input:-webkit-autofill:disabled,
7
- .signin-input-theme-scope textarea:-webkit-autofill,
8
- .signin-input-theme-scope textarea:-webkit-autofill:hover,
9
- .signin-input-theme-scope textarea:-webkit-autofill:focus,
10
- .signin-input-theme-scope textarea:-webkit-autofill:active,
11
- .signin-input-theme-scope textarea:-webkit-autofill:disabled {
12
- -webkit-text-fill-color: var(--fgColor-default) !important;
13
- caret-color: var(--fgColor-default) !important;
14
- -webkit-box-shadow: 0 0 0 1000px var(--bgColor-default) inset !important;
15
- box-shadow: 0 0 0 1000px var(--bgColor-default) inset !important;
16
- background-color: var(--bgColor-default) !important;
17
- transition: background-color 9999s ease-in-out 0s !important;
18
- }
19
-
20
- .signin-input-theme-scope input:disabled,
21
- .signin-input-theme-scope textarea:disabled {
22
- -webkit-text-fill-color: var(--fgColor-muted) !important;
23
- -webkit-box-shadow: 0 0 0 1000px var(--bgColor-default) inset !important;
24
- box-shadow: 0 0 0 1000px var(--bgColor-default) inset !important;
25
- background-color: var(--bgColor-default) !important;
26
- opacity: 1 !important;
27
- }
28
- `,Ds=({onSignIn:n,onApiKeySignIn:s,loginUrl:c,name:a,title:d="Datalayer OTEL",description:b="Sign in to access the observability dashboard.",icon:S,leadingIcon:C=t.jsx(bo,{size:24}),github:p=!1,google:K=!1,linkedin:B=!1,apiKey:Ge=!1,signUp:F=!0,socialSignInNavigationTarget:Z,asDoc:v=!1,fillHeight:I=!0,hideHero:ee=!1,calloutTitle:Pe,calloutDescription:Ke,passwordToggleLabel:ie="Sign in with a password",signUpTitle:Nt="Don't have an account?",signUpDescription:Y="Create a free Datalayer account with your email address.",signUpLabel:pt="Sign up with email",signUpHref:Me="https://datalayer.ai/signup",onSignUp:V,forgotPasswordHref:q="/password",forgotPasswordLabel:$e="Forgot password?",showForgotPassword:mt=!0,socialButtonMarginTop:x=3,actionButtonMaxWidth:J=320})=>{const te=v&&!ee,Ye=a??(v&&d==="Datalayer OTEL"?"Datalayer Sign In":d),gt=S??(v?t.jsx(Ls,{size:24}):C),L=o.useMemo(()=>{if(c)return c;const i=Tn();return i?`${i}/api/iam/v1/login`:"/api/iam/v1/login"},[c]),[W,ve]=o.useState(""),[re,ht]=o.useState(""),[qe,le]=o.useState(!1),[ce,Je]=o.useState(!1),[j,ye]=o.useState(!1),[de,Ce]=o.useState(!1),[Ue,Qe]=o.useState(null),[_,we]=o.useState(null),[ne,Xe]=o.useState(""),[ue,Ze]=o.useState(null),[Oe,M]=o.useState(null),{enqueueToast:fe}=fo(),[pe,E]=o.useState(!1),[Q,oe]=o.useState(""),D=o.useRef(null),Fe=o.useCallback(i=>po()?Cn.URLExt.join(Cn.PageConfig.getBaseUrl(),i.oauth2CallbackServerRoute):`${window.location.protocol}//${window.location.hostname}${window.location.port?`:${window.location.port}`:""}${i.oauth2CallbackUIRoute}`,[]),me=o.useMemo(()=>{if(typeof window>"u")return"/";const i=`${window.location.pathname}${window.location.search}${window.location.hash}`;return i.startsWith("/")?i:"/"},[]),je=o.useCallback(async i=>{if(!de){M(null),Qe(i.name),Ce(!0);try{const g=Tn(),m=new URLSearchParams({provider:i.name,callback_uri:Fe(i)}),R=Z===void 0?void 0:String(Z||"").trim(),y=R===void 0?me&&me!=="/"?me:void 0:R&&R.startsWith("/")&&!R.startsWith("//")?R:void 0;y&&m.set("post_auth_redirect",y);const _e=`${g||""}/api/iam/v1/oauth2/authz/url?${m.toString()}`,k=await fetch(_e),se=await k.json(),ze=se?.autorization_url;if(!k.ok||!ze)throw new Error(se?.message||"Unable to start social sign-in.");window.location.assign(ze)}catch(g){const m=Hs(g);M(m),fe(m,{variant:"error"}),Qe(null),Ce(!1)}}},[Fe,me,fe,de,Z]);o.useEffect(()=>{pe&&D.current?.focus()},[pe]);const $=o.useCallback(()=>{E(!1),oe("")},[]),bt=o.useCallback(()=>{!Q.trim()||!s||(s(Q.trim()),$())},[Q,s,$]),xt=o.useCallback(()=>{if(V){V();return}window.location.assign(Me)},[V,Me]),St=o.useCallback(()=>{if(q){if(q.startsWith("http://")||q.startsWith("https://")){window.open(q,"_blank","noopener,noreferrer");return}window.location.assign(q)}},[q]),Le=o.useCallback(async()=>{if(!(v||!W||!re||j)){ye(!0),M(null);try{const i=await fetch(L,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({handle:W,password:re})});if(!i.ok)throw new Error(`HTTP ${i.status}`);const g=await i.json();if(g.success&&g.token){const m=String(g?.user?.id||g?.user?.uid||"").trim();if(!!g?.user?.mfaUrl&&m){we(m),Ze(g.token),M(null);return}n&&n(g.token,W)}else M(g.message||"Invalid username or password.")}catch(i){M(i instanceof Error?i.message:String(i))}finally{ye(!1)}}},[v,W,re,j,L,n]),ge=o.useCallback(async()=>{if(!(v||j||!_||!ne.trim()||!ue)){ye(!0),M(null);try{const i=new URL(L,window.location.origin),g=i.pathname.endsWith("/api/iam/v1/login")?i.href.replace(/\/api\/iam\/v1\/login$/,""):`${i.origin}`,m=await fetch(`${g}/api/iam/v1/users/${_}/mfa/validate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({userUid:_,code:ne.trim()})}),R=await m.json();if(!m.ok||!R?.success)throw new Error(R?.message||"Failed to validate your MFA code.");n&&n(ue,W)}catch(i){const g=i instanceof Error?i.message:String(i);M(g),fe(g,{variant:"error"})}finally{ye(!1)}}},[v,fe,W,j,L,ne,ue,_,n]),ke=o.useCallback(i=>{i.key==="Enter"&&(_?ge():Le())},[_,Le,ge]),he=de||j||v;return t.jsxs(f,{className:"signin-input-theme-scope",display:"flex",alignItems:ee||te||!I?"flex-start":"center",justifyContent:"center",minHeight:ee||te||!I?"auto":"100vh",bg:ee?"transparent":"canvas.default",color:"fg.default",py:ee?0:te?2:4,children:[t.jsx(Ws,{}),t.jsxs(f,{width:"100%",maxWidth:440,p:0,children:[!ee&&t.jsxs(t.Fragment,{children:[t.jsxs(f,{display:"flex",alignItems:"center",gap:2,mb:te?2:3,justifyContent:"center",children:[gt,t.jsx(ct,{sx:{fontSize:3},children:Ye})]}),t.jsx(H,{as:"p",sx:{fontSize:1,color:"fg.muted",mb:te?2:3,textAlign:"center"},children:b})]}),(Pe||Ke)&&t.jsxs(f,{mb:3,textAlign:"center",children:[Pe&&t.jsx(ct,{as:"h3",sx:{fontSize:2,mb:1},children:Pe}),Ke&&t.jsx(H,{sx:{color:"fg.muted",fontSize:1},children:Ke})]}),!_&&(p||K||B)&&t.jsxs(t.Fragment,{children:[p&&t.jsx(G,{block:!0,size:"large",leadingVisual:Ue==="github"?()=>t.jsx(Pt,{size:"small"}):Ns,disabled:he,onClick:()=>je(Ot.github),sx:{mt:x,maxWidth:J,mx:"auto"},children:"Sign in with GitHub"}),K&&t.jsx(G,{block:!0,size:"large",leadingVisual:Ue==="google"?()=>t.jsx(Pt,{size:"small"}):Bs,disabled:he,onClick:()=>je(Ot.google),sx:{mt:x,maxWidth:J,mx:"auto"},children:"Sign in with Google"}),B&&t.jsx(G,{block:!0,size:"large",leadingVisual:Ue==="linkedin"?()=>t.jsx(Pt,{size:"small"}):Vs,disabled:he,onClick:()=>je(Ot.linkedin),sx:{mt:x,maxWidth:J,mx:"auto"},children:"Sign in with LinkedIn"})]}),!_&&!qe&&t.jsx(f,{mt:3,display:"flex",justifyContent:"center",children:t.jsx(G,{leadingVisual:Lt,size:"large",block:!0,disabled:v||j||de,onClick:()=>le(!0),sx:{maxWidth:J,mx:"auto"},children:ie})}),!_&&qe&&t.jsxs(f,{mt:4,children:[t.jsxs(ae,{required:!0,sx:{mb:3},children:[t.jsx(ae.Label,{children:"Username"}),t.jsx(dt,{autoFocus:!0,block:!0,placeholder:"Your username",value:W,disabled:j||v,onChange:i=>ve(i.target.value),onKeyDown:ke})]}),t.jsxs(ae,{required:!0,sx:{mb:3},children:[t.jsx(ae.Label,{children:"Password"}),t.jsx(dt,{block:!0,placeholder:"Your password",type:ce?"text":"password",value:re,disabled:j||v,onChange:i=>ht(i.target.value),onKeyDown:ke,trailingAction:t.jsx(dt.Action,{onClick:()=>Je(!ce),disabled:j||v,icon:ce?_s:zs,"aria-label":ce?"Hide password":"Show password",sx:{color:"var(--fgColor-muted)"}})})]}),t.jsxs(f,{display:"flex",alignItems:"center",justifyContent:"space-between",mt:3,children:[t.jsx(G,{variant:"primary",disabled:j||v||!W||!re,onClick:Le,children:j?"Signing in…":"Sign In"}),mt&&t.jsx(mo,{as:"button",sx:{fontSize:1,cursor:v?"not-allowed":"pointer",background:"none",border:"none",opacity:v?.6:1},onClick:()=>{v||j||St()},children:$e})]})]}),_&&t.jsxs(t.Fragment,{children:[t.jsxs(ae,{required:!0,sx:{mb:3,mt:2},children:[t.jsx(ae.Label,{children:"MFA Code"}),t.jsx(dt,{autoFocus:!0,block:!0,placeholder:"Your MFA code",value:ne,disabled:j||v,onChange:i=>Xe(i.target.value),onKeyDown:ke})]}),t.jsx(G,{variant:"primary",block:!0,disabled:j||v||!ne.trim(),onClick:ge,sx:{maxWidth:J,mx:"auto"},children:j?"Validating…":"Validate MFA Code"})]}),Oe&&t.jsx(H,{sx:{color:"danger.fg",fontSize:1,mt:3,display:"block"},children:Oe}),F&&t.jsxs(f,{mt:4,pt:4,textAlign:"center",borderTop:"1px solid",borderColor:"border.muted",children:[t.jsx(ct,{as:"h3",sx:{fontSize:2,mb:2},children:Nt}),t.jsx(H,{as:"p",sx:{color:"fg.muted",fontSize:1,mb:3},children:Y}),t.jsx(f,{display:"flex",justifyContent:"center",children:t.jsx(G,{variant:"primary",size:"large",leadingVisual:go,disabled:v||j,onClick:xt,children:pt})})]}),Ge&&s&&t.jsxs(t.Fragment,{children:[t.jsxs(f,{display:"flex",alignItems:"center",gap:2,my:3,children:[t.jsx(f,{flex:1,height:"1px",bg:"border.default"}),t.jsx(H,{sx:{fontSize:0,color:"fg.muted"},children:"or"}),t.jsx(f,{flex:1,height:"1px",bg:"border.default"})]}),t.jsx(G,{block:!0,leadingVisual:Lt,disabled:v||j||de,onClick:()=>E(!0),sx:{maxWidth:J,mx:"auto"},children:"Sign in with an API Key"}),pe&&t.jsx(f,{role:"dialog","aria-modal":"true","aria-labelledby":"signin-api-key-title",onKeyDown:i=>{i.key==="Escape"&&$()},onClick:$,position:"fixed",inset:0,zIndex:200,p:3,bg:"canvas.backdrop",display:"flex",alignItems:"center",justifyContent:"center",children:t.jsxs(f,{as:"form",onClick:i=>i.stopPropagation(),onSubmit:i=>{i.preventDefault(),bt()},width:"min(560px, 100%)",p:3,borderRadius:2,border:"1px solid",borderColor:"border.default",bg:"canvas.overlay",color:"fg.default",boxShadow:"shadow.large",children:[t.jsx(ct,{id:"signin-api-key-title",sx:{fontSize:2,mb:2},children:"Enter your API Key"}),t.jsxs(ae,{required:!0,children:[t.jsx(ae.Label,{children:"API Key"}),t.jsx(ho,{block:!0,required:!0,autoFocus:!0,placeholder:"Paste your API key here",value:Q,onInput:i=>oe(i.currentTarget.value),ref:D})]}),t.jsxs(f,{mt:3,display:"flex",justifyContent:"flex-end",gap:2,children:[t.jsx(G,{type:"button",onClick:$,children:"Cancel"}),t.jsx(G,{type:"submit",variant:"primary",disabled:!Q.trim(),children:"Authenticate"})]})]})})]})]})]})};function Gs(n){const{agentId:s,instructions:c,model:a,frontendTools:d,inference:b,subagents:S,sharing:C,onSubagentEvent:p,modeEffect:K}=n;return{type:"browser-vercel-ai",endpoint:"",agentId:s,enableConfigQuery:!1,options:{instructions:c,model:a,frontendTools:d,inference:b,subagents:S,sharing:C,onSubagentEvent:p,modeEffect:K}}}const Rn=So((n,s)=>({pending:void 0,suggest:(c,a)=>{const d=c.trim();d&&n({pending:{text:d,submit:a?.submit??!1,nonce:(s().pending?.nonce??0)+1}})},consume:()=>n({pending:void 0})}));function Ks({agentName:n,sandboxStillRuns:s=!1,temporary:c=!0,onSignedIn:a,onSignUp:d}){const{configuration:b}=Un(),S=o.useCallback(C=>{vo.getState().checkIAMToken(C),a?.()},[a]);return t.jsx(f,{height:"100%",minHeight:0,overflowY:"auto",bg:"canvas.default",px:4,py:4,children:t.jsxs(f,{maxWidth:440,mx:"auto",children:[t.jsxs(f,{display:"flex",alignItems:"center",justifyContent:"center",gap:2,color:"attention.fg",mb:2,children:[t.jsx(Lt,{size:20}),t.jsx(H,{sx:{fontSize:2,fontWeight:"semibold",color:"fg.default"},children:c?"This demo runs on a shared key":"Your key has expired"})]}),t.jsxs(H,{as:"p",sx:{fontSize:1,color:"fg.muted",textAlign:"center",mb:3},children:[c?`${n??"The agent"} has used the time this key allows. Sign in to point your own agent at it, use your own data, and drop the time limit.`:`${n??"The agent"} stopped because your session ran out.`,s?" Your notebook is still running in this page.":""]}),t.jsx(Ds,{hideHero:!0,fillHeight:!1,calloutTitle:"Sign in to keep going",github:!0,google:!0,linkedin:!0,socialSignInNavigationTarget:typeof window>"u"?void 0:`${window.location.pathname}${window.location.search}`,loginUrl:b?.iamUrl?`${b.iamUrl}/api/iam/v1/login`:void 0,onSignIn:S,onSignUp:d})]})})}const Ys="https://r1.datalayer.run";function qs(n=!0){const{configuration:s}=Un(),c=_t(C=>C.token),a=s?.aiInferenceUrl||Ys,d=yo(a,n&&!c),b=c||d.token,S=o.useMemo(()=>({inferenceUrl:a,token:b||void 0}),[a,b]);return{inference:S,needsSignIn:Co(S),anonymous:d,inferenceUrl:a}}const Js={name:"general-purpose",description:"A capable generalist for a task none of the specialists covers: research, reasoning, drafting, checking.",instructions:"You are a capable general-purpose assistant. Carry out the task you are given completely and report the result plainly, saying what you could not do."};function An(n){const s=n?.subagents;if(!s)return[];const c=(s.subagents??[]).map(a=>{const d=a.ref?wo(a.ref):void 0;return{name:a.name,description:a.description||d?.description||a.name,instructions:a.instructions??d?.systemPrompt,model:a.model??d?.model??s.defaultModel,icon:d?.icon}});return s.includeGeneralPurpose?[...c,Js]:c}function Qs(n){return n.replace(/^datalayer_/,"").replace(/_lexical$/,"")}function Xs(n){const s=Qs(n);return/^executeCodeIn(Notebook|Document)$/.test(s)||/^(read|list)[A-Z]/.test(s)}function Zs(n,s){return n.filter(c=>s?.has(c.name)||Xs(c.name))}function ea(n,s){const c=a=>s&&a.value.id===`${s}-tools`?0:a.value.id==="notebook-tools"?1:2;return n.map((a,d)=>({entry:a,index:d,rank:c(a)})).sort((a,d)=>a.rank-d.rank||a.index-d.index).map(a=>a.entry)}function ta(n,s,c){if(!c||!n.endsWith("-tools"))return!1;const a=n.slice(0,-6);return s.has(a)&&a!==c}const na={type:"object",properties:{}};function oa(n,s){const c=new Set(n.toolset);return n.commands.filter(a=>c.has(a.name)).map(a=>({name:a.name,description:a.description,parameters:a.parameters??na,location:"frontend",handler:async d=>{if(!s)throw new Error(`${a.name}: the ${n.plugin??n.id} plugin is not mounted on this page.`);const b=Object.keys(d??{}).length>0?d:void 0,S=await s.executeCommand(a.command,b);return S===void 0?{ok:!0,command:a.command,argument:b}:S}}))}function Fn(n,s){return n.flatMap(c=>oa(c,s))}function sa(){const n=jo(),s=On();return o.useMemo(()=>Fn(s,n),[s,n])}const Pn={opening:"Opening your conversation…",notOpened:n=>`Your conversation could not be opened, so this is a new one: ${n}`};function aa(n){const s=n?.app_instance;if(!s||typeof s!="object")return"";const c=s.deployment_uid;return typeof c=="string"?c.trim():""}function ia(n,s,c){return n||!s?n:{id:c,messages:[]}}function ra(n){let s;for(const c of n.split(/\r?\n\r?\n/)){const a=c.split(/\r?\n/).filter(d=>d.startsWith("data:")).map(d=>d.slice(5).trim()).join("");if(a)try{const d=JSON.parse(a);d.type==="MESSAGES_SNAPSHOT"&&Array.isArray(d.messages)&&(s=d.messages)}catch{}}return s}async function Mn(n){try{const s=await n.json();if(typeof s.detail=="string"&&s.detail)return s.detail}catch{}return`${n.status}`}async function la({agentBaseUrl:n,agentId:s,uid:c,token:a,fetcher:d=fetch}){const b=`${n.replace(/\/+$/,"")}/api/v1/apps/sessions/${encodeURIComponent(c)}`,S=a?{Authorization:`Bearer ${a}`}:{},C=await d(`${b}/messages`,{headers:S});if(C.ok){const B=await C.json();return wn(B.messages)}if(C.status!==404)throw new Error(await Mn(C));const p=await d(`${b}/resume`,{method:"POST",headers:{"Content-Type":"application/json",...S},body:JSON.stringify({agent:s})});if(!p.ok)throw new Error(await Mn(p));const K=ra(await p.text());if(!K)throw new Error(`The runtime said nothing of session ${c}.`);return wn(K)}const ca="var(--theme-accent)";function Ln({face:n,size:s}){return typeof n=="string"?t.jsx(ko,{emoji:n,size:s,label:""}):t.jsx(t.Fragment,{children:n})}function da({face:n,size:s,state:c}){const a=c==="thinking"||c==="working",d=c==="paused";return t.jsxs(f,{as:"span","aria-hidden":!0,"data-presence":c,position:"relative",display:"inline-flex",alignItems:"center",justifyContent:"center",width:s+8,height:s+8,flexShrink:0,fontSize:s,lineHeight:1,children:[t.jsx(f,{as:"span",position:"absolute",inset:0,borderRadius:"50%",boxShadow:d?"none":`0 0 0 2px ${ca}`,border:d?"2px dashed":"none",borderColor:"border.default",opacity:a||c==="waiting"||d?.9:0,transition:"opacity var(--theme-motion-status, 0ms) var(--theme-motion-easing, ease)",animation:a?"loopPresenceBreath 1.8s ease-in-out infinite":"none",reducedMotion:{animation:"none"},sx:{"@keyframes loopPresenceBreath":{"0%, 100%":{transform:"scale(0.92)",opacity:.35},"50%":{transform:"scale(1.06)",opacity:.9}}}}),t.jsx(f,{as:"span",display:"inline-flex",opacity:d?.55:1,filter:d?"grayscale(0.6)":"none",transition:"opacity var(--theme-motion-status, 0ms) var(--theme-motion-easing, ease)",children:t.jsx(Ln,{face:n,size:s})})]})}function ua({state:n}){return t.jsx(H,{role:"status","aria-live":"polite","data-presence-line":n,sx:{fontSize:0,color:n==="waiting"?"fg.default":"fg.muted",fontWeight:n==="waiting"?"semibold":"normal",whiteSpace:"nowrap",flexShrink:0},children:Eo[n]})}const fa=zt(void 0),pa=zt(""),ma=zt({}),X="",ga=1400,$n=parseInt(Os["--loop-face-large"],10);function va({workspace:n}){const s=Io(),c=To(),a=o.useRef(null),{setViewControls:d}=n,[b,S]=o.useState(null),C=Ro(),p=C.getConfig(Ao),K=p?.placeholder||s.placeholder,B=p?.defaultSurface??"notebook",Ge=C.getConfig(Po),[F,Z]=o.useState(X),v=o.useRef(!1),I=N(Mo),ee=N($o),Pe=N(Uo),ie=N(Oo)[0]?.value,Y=Mt(ie?.promptStance??fa)??ie?.prompt,pt=N(Fo),Me=Lo(pt[0]?.value),V=o.useRef(Me);V.current=Me;const q=o.useRef(""),$e=N(_o),mt=o.useMemo(()=>zo(()=>$e.reduce((e,r)=>({...e,...r.value.extras.value}),{})),[$e]),x=Mt($e.length>0?mt:ma),J=o.useRef(new Set),te=No($s,n),Ye=!te.allowed,gt=Ye?te.reason??"Chat is unavailable for this sandbox":void 0,[L,W]=o.useState(!1),[ve,re]=o.useState(!1),[ht,qe]=o.useState({open:!1,pendingApproval:!1}),le=Bo(L,ht,p?.presence?.paused===!0),ce=p?.presence?.onPresence;o.useEffect(()=>{ce?.(le),V.current?.setPresence(le)},[ce,le]);const Je=o.useRef(p?.presence?.onSaying);Je.current=p?.presence?.onSaying;const j=o.useRef({answering:!1}),ye=o.useCallback(e=>{a.current=e,re(!!e)},[]),de=o.useCallback(e=>{const{open:r,pendingApproval:l}=Vo(e);qe(xe=>xe.open===r&&xe.pendingApproval===l?xe:{open:r,pendingApproval:l});const h={saying:Wo(e),answering:Ho(e)},u=j.current;(u.saying?.id!==h.saying?.id||u.saying?.text!==h.saying?.text||u.answering!==h.answering)&&(j.current=h,Je.current?.(h));const O=V.current;if(!O)return;O.items(e);const P=new Set(["complete","completed","done","error","failed","cancelled","canceled","rejected","denied","stopped"]),A={insertcell:"adding a cell",updatecell:"editing a cell",runcell:"running a cell",deletecells:"removing cells",readallcells:"reading the notebook",readcell:"reading a cell",executecode:"running code",insertblock:"adding a block",updateblock:"editing a block",runblock:"running a block",readdocument:"reading the document"};let w;for(let xe=e.length-1;xe>=0;xe-=1){const lt=e[xe];if(typeof lt.toolName=="string"&&lt.toolCallId){P.has(String(lt.status).toLowerCase())||(w=lt);break}}if(!w){O.activity(void 0);return}const At=w.toolName.toLowerCase().replace(/^datalayer_/,"").replace(/_lexical$/,"").replace(/[^a-z]/g,""),co=A[At]??`using ${w.toolName}`;O.activity(`${q.current||"The agent"} is ${co}…`)},[]),Ce=o.useRef(x);Ce.current=x;const Ue=o.useCallback(e=>{Kn(e),V.current?.usage(e),Ce.current.onUsage?.(e)},[]),Qe=o.useCallback(e=>{W(e),e||V.current?.end("done")},[]),_=o.useCallback(e=>{const r=V.current;if(!r)return;let l=-1;for(let u=e.length-1;u>=0;u-=1)if(e[u].role==="user"){l=u;break}const h=e.slice(l+1).filter(u=>u.role==="assistant").map(Do).filter(u=>u.trim().length>0).join(`
29
-
30
- `);r.assistant(h)},[]),we=o.useRef([]),ne=o.useRef(!1),Xe=o.useRef(void 0),ue=o.useRef(void 0),Ze=N(Go),Oe=o.useRef(Ze);Oe.current=Ze;const M=o.useCallback((e,r)=>{if(ue.current)return ue.current;const l=Ko(Oe.current.map(O=>O.value),r),h=l?.loop;if(ne.current&&h?.files&&h.files.length>0){const O=Xe.current;if(!O)return"A file is given to an application running on a runtime: run it on Datalayer or on your machine to give it one.";let P;try{P=h.files.map(A=>({file:qo(String(A.name??"")),base64:Yo(String(A.data_url??""))}))}catch(A){return A instanceof Error?A.message:String(A)}O.execute(Jo(P)).then(A=>{if(!A.success){S(`The files could not be put in the sandbox: ${A.error??"it failed"}.`);return}M(`${e}
31
-
32
- ${Qo(P.map(w=>w.file))}`,{...l,loop:Object.fromEntries(Object.entries(h).filter(([w])=>w!=="files"))})});return}V.current?.begin(e,a.current?.thread());const u=a.current?.send;if(!u){we.current.push([e,l]);return}u(e,l)},[]);o.useEffect(()=>{d(ve?{busy:L,stop:a.current?.stop,newChat:a.current?.newChat,send:M}:null)},[L,ve,d,M]),o.useEffect(()=>()=>d(null),[d]),o.useEffect(()=>n.prompts.subscribe(M),[n.prompts,M]),o.useEffect(()=>{if(!ve||we.current.length===0)return;const e=we.current.splice(0,we.current.length);for(const[r,l]of e)a.current?.send(r,l)},[ve]);const fe=o.useRef(!1),pe=o.useCallback(async e=>{S(null);const r=await Xo(Ce.current,e);if(r){r.sent?ot(""):S(r.refused);return}fe.current||(fe.current=!0,Ge?.firstPromptHook?.());const l=await n.submit(e);if(!l.handled){S(l.reason??null);return}ot(""),l.result?.content&&S(l.result.content)},[n,Ge?.firstPromptHook]),E=o.useMemo(()=>I.find(e=>e.value.surfaceId===F)?.value,[I,F]),Q=o.useCallback(e=>{v.current=!0,Z(e)},[]);o.useEffect(()=>Zo(Q),[Q]),o.useEffect(()=>{es(I.map(e=>e.value.surfaceId))},[I]),o.useEffect(()=>{ts(F&&F!==X?F:Fs)},[F]);const oe=o.useMemo(()=>B===X||B==="none"?void 0:I.find(e=>e.value.surfaceId===B),[I,B]);o.useEffect(()=>{v.current||!oe||De(oe.value,n)&&Z(B)},[oe,n,B]);const[D,Fe]=o.useState(null),me=o.useRef(null),je=p?.fullScreenTopOffset??0,{fullScreen:$,usingApi:bt,toggle:xt,topOffsetPx:St}=ns(me,{forceOverlay:!!je,topOffset:je}),[Le,ge]=o.useState(!1),ke=o.useRef(!1);o.useEffect(()=>{!L||ke.current||$||(ke.current=!0,ge(!0))},[L,$]),o.useEffect(()=>{$&&ge(!1)},[$]),o.useEffect(()=>{E&&!De(E,n)&&(Fe(E.surfaceId),Z(X))},[E,n]);const he=o.useMemo(()=>{if(D)return I.find(e=>e.value.surfaceId===D)?.value;if(!v.current&&F===X)return oe?.value},[I,D,F,oe]);o.useEffect(()=>{if(!D||F!==X)return;const e=I.find(r=>r.value.surfaceId===D);e&&De(e.value,n)&&(Fe(null),Z(D))},[I,F,D,n]);const i=n.agentId?.trim()||"default",g=os(n.sandbox.target??"local");ne.current=g;const m=ss(),R=Mt(m?.selected??pa),y=m?.members.find(e=>e.id===R),vt=N(as)[0]?.value,_e=vt?.specId,k=jn(y?.specId??i)??(_e?jn(_e):void 0),se=y?void 0:vt,ze=g&&!y?Ms(_e,k):void 0;q.current=y?.name??k?.name??i;const Bt=N(is),Vt=x.hiddenOpeners,Ht=x.hideOpeners,yt=x.openers,Ct=o.useMemo(()=>{if(Ht)return[];const e=new Set(Vt??[]),r=w=>e.size===0?w:w.filter(At=>!e.has(At.text));if(yt)return r(yt);const l=Bt.flatMap(w=>w.value.suggestions);if(l.length>0)return r(l);const h=r(k?.suggestions??[]),u=r(m?.team.suggestions??[]);if(u.length===0)return h;const O=new Set(u.map(w=>w.text)),P=m?.team.name??"Team",A=y?.name??k?.name??i;return[...u.map(w=>({...w,group:P})),...h.filter(w=>!O.has(w.text)).map(w=>({...w,group:A}))]},[Bt,m,k,y,i,Vt,Ht,yt]),et=o.useMemo(()=>Ct.map(e=>({title:e.summary??e.text,message:e.message??e.text,group:e.group})),[Ct]),wt=Ae(k?.icon),z=p?.presence,_n=Ae(m?.team.icon),Wt=N(rs),tt=o.useMemo(()=>{const e=[],r=new Map,l=new Set,h=new Set(I.map(u=>u.value.surfaceId));for(const u of ea(Wt,E?.surfaceId)){if(ta(u.value.id,h,E?.surfaceId))continue;let O;try{O=u.value.tools(n)}catch(P){console.warn(`[loop] frontend tools from '${u.plugin}' failed:`,P);continue}for(const P of O){const A=r.get(P.name);if(A){console.warn(`[loop] frontend tool '${P.name}' from '${u.plugin}' is shadowed by the one from '${A}'.`);continue}r.set(P.name,u.plugin),e.push(P),u.value.chatView&&l.add(P.name)}}for(const u of x.frontendTools??[])r.has(u.name)||(r.set(u.name,"chat-extras"),e.push(u),l.add(u.name));return E?e:Zs(e,l)},[Wt,n.surfaceId,n.agentId,x.frontendTools,E?.surfaceId,I]),jt=sa(),Ne=o.useMemo(()=>{if(jt.length===0)return tt;const e=new Set(tt.map(r=>r.name));return[...tt,...jt.filter(r=>!e.has(r.name))]},[tt,jt]),Dt=On(),kt=x.agentToolBundles,zn=o.useMemo(()=>{const e=x.frontendTools??[];if(!kt?.length)return x.frontendTools;const r=Fn(Dt.filter(h=>kt.includes(h.id)),C),l=new Set(e.map(h=>h.name));return[...e,...r.filter(h=>!l.has(h.name))]},[x.frontendTools,kt,Dt,C]);Xe.current=g&&Ne.some(e=>e.name===ls)?C.getOutput(ut)?.sandbox:void 0;const T=cs(n.sandbox,n.serverUrl),Gt=N(ds),Nn=o.useMemo(()=>Gt.filter(e=>e.value.composer).map(e=>({name:e.value.name,description:e.value.description})),[Gt]),Bn=o.useMemo(()=>{if(!m||!y)return An(k).map(l=>({name:l.name,description:l.description,icon:Ae(l.icon)}));const e=m.members.map(l=>({name:l.name,description:l.description,emoji:l.emoji,icon:Ae(l.icon),disabled:l.id===y.id,disabledReason:l.id===y.id?`You are already talking to ${l.name}`:void 0})),r=kn(m.team,y.id).filter(l=>!m.members.some(h=>h.name===l.name)).map(l=>({name:l.name,description:l.description,icon:Ae(l.icon)}));return[...e,...r]},[m,y,k]),{inference:Kt,anonymous:Vn}=qs(g),Hn=_t(e=>e.user),Et=g&&Vn.status==="expired",Yt=!Hn,Be=us();ue.current=Be.disabled?Be.disableReason||"This conversation is closed here.":void 0;const It=T===void 0?fs(n.sandbox,s):void 0,nt=Ye||Et||!!ze||!!It||Be.disabled,qt=Et?Yt?s.demoKeyExpired:s.keyExpired:ze??It??gt??(Be.disabled?Be.disableReason:void 0),[Jt,ot]=o.useState(""),[Wn,Qt]=o.useState(),st=Wn??se?.model??k?.model??n.model??"",Ee=ps(),Xt=o.useRef(Ee),Zt=o.useRef(R),en=o.useRef(Ee);en.current=Ee,o.useEffect(()=>{Zt.current!==R&&(Zt.current=R,Xt.current=en.current,Qt(void 0))},[R]);const Dn=Ee&&Ee!==Xt.current?Ee:null,[Gn,Kn]=o.useState(),Yn=Dn??Gn??null,qn=$t(Se.inpromptMenu),Jn=$t(Se.promptAction),tn=$t(Se.chatHeader),Qn=o.useMemo(()=>m?.members.map(e=>({id:e.id,name:e.name,description:e.description,icon:Ae(e.icon)}))??[],[m]),be=Rn(e=>e.pending),[nn,Xn]=o.useState(0);o.useEffect(()=>ms(()=>Xn(e=>e+1)),[]),o.useEffect(()=>{be&&(ot(be.text),Rn.getState().consume(),be.submit&&pe(be.text))},[be]);const on=C.getConfig(ut)?.datalayerCreatePayload,Ie=!!(se?.createPayload?.app_spec||on?.app_spec),sn=aa(on),Zn=_t(e=>e.token),an=C.getConfig(ut)?.datalayerVisitors,eo=gs(an),to=C.getConfig(ut)?.embedToken,Ve=an?eo.token:to||Zn,[rn]=o.useState(En),U=o.useMemo(()=>ia(p?.thread,sn,rn),[p?.thread,sn,rn]),[Te,ln]=o.useState(null),no=!!(U?.fromRuntime&&Te?.given!==U.id);o.useEffect(()=>{if(!U?.fromRuntime||!Ie||!T)return;let e=!0;return(async()=>{let r="";for(let l=0;l<4&&e;l+=1)try{const h=await la({agentBaseUrl:T,agentId:i,uid:U.id,token:Ve});e&&ln({given:U.id,thread:{...U,fromRuntime:!1,messages:h}});return}catch(h){r=h instanceof Error?h.message:String(h),await new Promise(u=>setTimeout(u,1500))}e&&ln({given:U.id,thread:{id:En(),messages:[],onStarted:U.onStarted},said:Pn.notOpened(r)})})(),()=>{e=!1}},[U?.id,U?.fromRuntime,Ie,T,i,Ve]);const cn=U?.fromRuntime?Te?.given===U.id?Te.thread:void 0:U,Tt=o.useMemo(()=>g?Gs({agentId:y?.specId??i,instructions:hs(k,se?.instructions),model:st||void 0,inference:Kt,frontendTools:Ne,subagents:m&&y?kn(m.team,y.id):An(k),sharing:m?.sharing,onSubagentEvent:e=>Us.getState().appendSubagentEvent(e),modeEffect:se?.modeEffect}):T!==void 0?{type:"ag-ui",endpoint:Ie?`${T}/api/v1/apps/agents/${encodeURIComponent(i)}/ag-ui/`:`${T}/api/v1/ag-ui/${i}/`,...Ie&&Ve?{authToken:Ve}:{},...Ie?{uiSocket:`${T.replace(/^http/,"ws")}/api/v1/apps/ui`,uiFiles:`${T}/api/v1/apps/agents/${encodeURIComponent(i)}/files`}:{},agentId:i,configEndpoint:`${T}/api/v1/configure`,enableConfigQuery:!0}:void 0,[i,g,Kt,y,Ne,m,k,se,st,T,Ie,Ve]),at=bs(!g,Tt?.type==="ag-ui"?Tt.configEndpoint:void 0,void 0,i),He=xs(),it=Ss(i),[dn,un]=o.useState(void 0),[oo,so]=o.useState(void 0);o.useEffect(()=>{if(g||T===void 0)return;let e=!1;return fetch(`${T}/api/v1/configure/models?agent_id=${encodeURIComponent(i)}`).then(r=>r.ok?r.json():null).then(r=>{e||(un(r?vs(r):[]),so(r?ys(r):void 0))}).catch(()=>{e||un([])}),()=>{e=!0}},[T,i,g]);const ao=o.useMemo(()=>Cs(dn,()=>Object.values(ws).filter(e=>e.available&&js(e)).map(e=>({id:e.id,name:e.name,provider:e.provider}))),[dn]),fn=o.useMemo(()=>{const e=at.data?.builtinTools??[],r=new Set(e.map(l=>l.name));return{runtime:e,frontend:Ne.filter(l=>!r.has(l.name)).map(l=>({id:l.name,name:l.name}))}},[at.data?.builtinTools,Ne]),pn=o.useMemo(()=>new Set((He.data?.skills??[]).filter(e=>e.status==="enabled"||e.status==="loaded").map(e=>e.id)),[He.data]),io=o.useCallback(async e=>{Qt(e),!(g||T===void 0)&&await fetch(`${T}/api/v1/configure/inference/provider`,{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({model:e})}).catch(()=>{})},[T,g]),mn=p?.promptPlacement==="bottom-chat",ro=p?.promptPlacement==="floating",Re=p?.promptPlacement==="top",We=p?.hidePrompt===!0||x.hidePrompt===!0,lo={onSend:()=>{pe(Jt)},input:Jt,setInput:ot,focusTrigger:be||nn?(be?.nonce??0)+nn:void 0,placement:ro||Y==="floating"||Y==="floating-top"||Y==="floating-bottom"?"floating":"docked",floatingAnchor:Y==="floating-top"?"top":"bottom",isLoading:L,onStop:()=>n.viewControls.stop?.(),placeholder:qt??x.sendInstead?.says??K,typingSuggestions:Ct.map(e=>e.text),suggestions:et,disableInputPrompt:nt,connectionConfirmed:!nt,padding:Re||Y==="floating-top"||Y==="floating-bottom"||Y==="docked-top"?2:3,promptVariant:"lexical",autoFocus:p?.autoFocusPrompt??!0,mentionableAgents:Bn,promptCommands:Nn,headerContent:qn.length>0?t.jsx(ft,{slot:Se.inpromptMenu,props:{workspace:n}}):void 0,footerExtras:Jn.length>0?t.jsx(ft,{slot:Se.promptAction,props:{workspace:n}}):void 0,showAgentsMenu:!z,showInlineAgentsMenu:!1,agents:Qn,selectedAgentId:R,onSelectAgent:e=>m?.select(e),showTokenUsage:x.showTokenUsage??p?.showTokenUsage??!0,showContextRing:!0,agentUsage:Yn??void 0,showModelSelector:!z,models:ao,decisions:oo,selectedModel:st,onModelSelect:e=>{io(e)},showToolsMenu:!z,availableTools:fn.runtime,availableFrontendTools:fn.frontend,mcpServers:at.data?.mcpServers??[],mcpStatusData:x.mcpStatusData??void 0,showSkillsMenu:!z,skills:He.data?.skills??[],skillsLoading:He.isLoading,enabledSkills:pn,onToggleSkill:e=>pn.has(e)?it.disableSkill(e):it.enableSkill(e),onToggleAllSkills:(e,r)=>e.forEach(l=>r?it.enableSkill(l):it.disableSkill(l)),codemodeEnabled:x.codemodeEnabled??!1,onToggleCodemode:x.onToggleCodemode,isA2AProtocol:!1,hasConfigData:!!at.data,hasSkillsData:!!He.data},gn=ee[0]?.value.Component,Rt=Pe[0]?.value.Component,hn=!p?.hideHeader&&!!Rt,rt=gn?t.jsx(gn,{workspace:n,composer:lo}):null,bn=I.length>0&&p?.showSurfaceSelector!==!1?t.jsx(ha,{surfaces:I.map(e=>e.value),active:E?.surfaceId??he?.surfaceId??X,onChange:Q,workspace:n}):null,xn=t.jsxs(t.Fragment,{children:[I.map(e=>{const r=e.value,l=E?.surfaceId===r.surfaceId;return l||J.current.has(r.surfaceId)||De(r,n)?(J.current.add(r.surfaceId),t.jsx(f,{sx:l?{flex:"1 1 0",minWidth:0,minHeight:0}:{position:"absolute",inset:0,visibility:"hidden",pointerEvents:"none",zIndex:-1},children:t.jsx(ks,{load:r.load,props:{surfaceId:r.surfaceId,workspace:n},fallback:t.jsxs(Ft,{children:["Loading ",r.title,"…"]}),errorFallback:u=>t.jsxs(Ft,{children:[r.title," failed to load: ",u.message]})})},r.surfaceId)):null}),!E&&he?t.jsx(f,{flex:"1 1 0",minWidth:0,minHeight:0,children:t.jsxs(Ft,{children:["Starting ",he.title,"…"]})}):null]}),Sn=t.jsx(t.Fragment,{children:t.jsxs(f,{flex:Re&&E?"0 0 34%":"1 1 0",maxWidth:Re&&E?460:void 0,minWidth:0,minHeight:0,display:"flex",flexDirection:"column",borderLeft:E?"1px solid":void 0,borderColor:"border.default",position:"relative",children:[x.errorBanner?t.jsx(f,{flexShrink:0,px:3,py:2,fontSize:1,borderBottom:"1px solid",bg:x.errorBanner.variant==="warning"?"attention.subtle":"danger.subtle",color:x.errorBanner.variant==="warning"?"attention.fg":"danger.fg",borderColor:x.errorBanner.variant==="warning"?"attention.muted":"danger.muted",children:x.errorBanner.message}):null,Te?.said&&Te.given===U?.id?t.jsx(H,{as:"p",role:"status",sx:{m:0,px:3,py:2,fontSize:1,color:"fg.muted"},children:Te.said}):null,t.jsx(f,{flex:"1 1 auto",minHeight:0,display:"flex",children:no?t.jsx(H,{as:"p",role:"status",sx:{m:0,p:3,fontSize:1,color:"fg.muted"},children:Pn.opening}):t.jsx(Es,{themeVariant:p?.themeVariant,themeOverrides:p?.themeOverrides,colorMode:p?.colorMode,thread:cn,disabled:nt,disableReason:qt,protocol:Tt,frontendTools:g?void 0:zn,initialModel:st||void 0,title:z?.name??y?.name??k?.name??i,description:z?.welcome??k?.description,brandIcon:z?.face?t.jsx(da,{face:z.face,size:20,state:le}):t.jsx(wt,{size:20}),headerContent:z&&!It?t.jsx(ua,{state:le}):void 0,emptyState:{icon:z?.face?t.jsx("span",{"aria-hidden":!0,style:{fontSize:$n,lineHeight:1},children:t.jsx(Ln,{face:z.face,size:$n})}):t.jsx(wt,{size:48}),title:z?.name??y?.name??k?.name??i,...m&&y?{sections:[{group:m.team.name,icon:t.jsx(_n,{size:48}),title:m.team.name,subtitle:m.team.description},{group:y.name,icon:t.jsx(wt,{size:32}),title:y.name,subtitle:k?.description}]}:null},suggestions:Re||ie||p?.suggestionLabels===!1?[]:et,showHeader:hn,headerButtons:{showNewChat:p?.headerButtons?.newChat??!1,showClear:p?.headerButtons?.clear??!1},renderHeader:Rt?e=>t.jsx(Rt,{workspace:n,header:n.chatViewModes?{...e,chatViewMode:n.chatViewModes.value,onChatViewModeChange:n.chatViewModes.onChange,offeredViewModes:n.chatViewModes.offered}:e}):void 0,showInformation:!0,headerActions:t.jsxs(f,{display:"inline-flex",alignItems:"center",gap:2,children:[n.chatHeaderActions,tn.length>0?t.jsx(ft,{slot:Se.chatHeader,props:{workspace:n}}):null,t.jsx(Is,{icon:$?Ts:Rs,"aria-label":$?"Exit full screen":"Enter full screen",variant:"invisible",size:"small",onClick:()=>{ge(!1),xt()},sx:Le?{"@keyframes dla-fullscreen-hint":{"0%, 100%":{opacity:1},"50%":{opacity:.4}},"&&":{bg:`color-mix(in srgb, ${c.primary} 16%, transparent)`,boxShadow:`inset 0 0 0 1.5px ${c.primary}`,animation:`dla-fullscreen-hint ${ga}ms ease-in-out infinite`},"@media (prefers-reduced-motion: reduce)":{"&&":{animation:"none"}}}:void 0})]}),showInput:!1,onSendReady:ye,notebookToolSurfacesId:E?void 0:n.surfaceId,showTurnFooter:x.showTokenUsage??p?.showTokenUsage??!0,onContextSnapshot:Ue,onLoadingChange:Qe,onItemsChange:_,onDisplayItemsChange:de,enableStreaming:!0},cn?.id)}),!hn&&tn.length>0?t.jsx(f,{hidden:!0,children:t.jsx(ft,{slot:Se.chatHeader,props:{workspace:n}})}):null,mn&&!We?rt:null]})}),vn=p?.suggestionLabels!==!1&&et.length>0?t.jsx(f,{"aria-label":s.suggestedPrompts,display:"flex",flexWrap:"wrap",gap:2,px:2,pb:"6px",children:et.map(e=>t.jsx(f,{as:"button",type:"button",title:e.message,disabled:L||nt,onClick:()=>{pe(e.message)},appearance:"none",font:"inherit",fontSize:0,fontWeight:"semibold",lineHeight:1.25,px:"10px",py:"5px",width:In,flex:`0 0 ${In}px`,borderRadius:"999px",border:"1px solid",bg:"canvas.subtle",whiteSpace:"nowrap",sx:{borderColor:"border.default",color:"fg.default",cursor:"pointer","&:hover:not(:disabled)":{borderColor:"accent.fg",color:"accent.fg"},"&:disabled":{opacity:.5,cursor:"default"}},children:t.jsx(As,{title:e.title,maxWidth:"100%",sx:{minWidth:0},children:e.title})},e.title))}):null,yn=b?t.jsx(f,{flex:"0 0 auto",px:3,py:2,borderTop:"1px solid",borderColor:"border.default",bg:"canvas.subtle",fontSize:1,maxHeight:"40%",overflowY:"auto",children:b}):null;return t.jsxs(f,{ref:me,sx:{height:"100%",minHeight:0,display:"flex",flexDirection:"column",position:"relative",...$?{bg:"canvas.default"}:null,...$&&!bt.current?{position:"fixed",top:St,right:0,bottom:0,left:0,height:"auto",zIndex:1e3}:null},children:[ie?t.jsx(ie.Component,{workspace:n,editors:xn,hasEditor:!!E,transcript:Sn,prompt:We?null:rt,chips:We?null:vn,picker:bn,transient:yn}):t.jsxs(t.Fragment,{children:[Re&&!We?t.jsxs(f,{flex:"0 0 auto",borderBottom:"1px solid",borderColor:"border.default",children:[rt,vn]}):null,bn,t.jsxs(f,{flex:"1 1 auto",minHeight:0,display:"flex",position:"relative",children:[xn,Sn]}),yn,mn||We||Re?null:rt]}),Et?t.jsx(f,{position:"absolute",inset:0,zIndex:5,bg:"canvas.default",display:"flex",flexDirection:"column",minHeight:0,children:t.jsx(Ks,{agentName:y?.name??k?.name,sandboxStillRuns:g,temporary:Yt,onSignedIn:()=>Ps.getState().clear()})}):null]})}function ha({surfaces:n,active:s,onChange:c,workspace:a}){const d=[...n].sort((b,S)=>(b.order??100)-(S.order??100));return t.jsxs(f,{flex:"0 0 auto",display:"flex",alignItems:"center",gap:2,px:3,py:2,borderBottom:"1px solid",borderColor:"border.default",children:[t.jsx(H,{sx:{fontSize:0,color:"fg.muted"},children:"Beside the chat"}),t.jsxs(Ut,{"aria-label":"Editor beside the chat",size:"small",children:[t.jsx(Ut.Button,{selected:s===X,onClick:()=>c(X),children:"Chat"}),d.map(b=>{const S=De(b,a),C=S?void 0:b.unavailableReason?.(a)??"Not available right now";return t.jsx(Ut.Button,{selected:s===b.surfaceId,"aria-disabled":!S,title:C??b.title,leadingIcon:b.icon,onClick:()=>{S&&c(b.surfaceId)},children:b.title},b.surfaceId)})]})]})}function Ft({children:n}){return t.jsx(f,{height:"100%",display:"flex",alignItems:"center",justifyContent:"center",color:"fg.muted",fontSize:1,px:3,textAlign:"center",children:n})}export{va as default};