@datalayer/agent-runtimes 1.3.80 → 1.3.82

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 (97) hide show
  1. package/lib/chat/assistant/AssistantStage.d.ts +9 -4
  2. package/lib/chat/assistant/AssistantStage.js +18 -6
  3. package/lib/chat/assistant/SpeechBalloon.js +16 -1
  4. package/lib/chat/assistant/SpriteCharacter.d.ts +25 -3
  5. package/lib/chat/assistant/SpriteCharacter.js +68 -3
  6. package/lib/chat/assistant/formats/acf.d.ts +56 -0
  7. package/lib/chat/assistant/formats/acf.js +317 -0
  8. package/lib/chat/assistant/formats/acs.d.ts +85 -7
  9. package/lib/chat/assistant/formats/acs.js +111 -39
  10. package/lib/chat/assistant/formats/files.d.ts +6 -2
  11. package/lib/chat/assistant/formats/files.js +18 -4
  12. package/lib/chat/assistant/formats/index.d.ts +6 -3
  13. package/lib/chat/assistant/formats/index.js +4 -2
  14. package/lib/chat/assistant/formats/types.d.ts +14 -0
  15. package/lib/chat/assistant/state.d.ts +2 -0
  16. package/lib/chat/assistant/state.js +9 -0
  17. package/lib/chat/base/ChatBase.js +47 -4
  18. package/lib/chat/base/loopStep.d.ts +40 -0
  19. package/lib/chat/base/loopStep.js +73 -0
  20. package/lib/chat/indicators/McpStatusIndicator.d.ts +1 -1
  21. package/lib/chat/indicators/McpStatusIndicator.js +13 -6
  22. package/lib/chat/indicators/SkillsStatusIndicator.d.ts +1 -1
  23. package/lib/chat/indicators/SkillsStatusIndicator.js +7 -3
  24. package/lib/chat/prompt/InputPrompt.d.ts +4 -1
  25. package/lib/chat/prompt/InputPrompt.js +2 -2
  26. package/lib/chat/prompt/InputPromptBase.d.ts +4 -1
  27. package/lib/chat/prompt/InputPromptBase.js +2 -2
  28. package/lib/chat/prompt/InputPromptLexical.d.ts +7 -1
  29. package/lib/chat/prompt/InputPromptLexical.js +5 -3
  30. package/lib/components/teams/index.d.ts +1 -0
  31. package/lib/components/teams/index.js +1 -0
  32. package/lib/components/teams/usePeerSandbox.d.ts +13 -0
  33. package/lib/components/teams/usePeerSandbox.js +59 -0
  34. package/lib/examples/AgentA2ATeamExample.js +7 -2
  35. package/lib/loop/apps/AppComposer.d.ts +31 -0
  36. package/lib/loop/apps/AppComposer.js +67 -0
  37. package/lib/loop/apps/AppRenderer.d.ts +16 -5
  38. package/lib/loop/apps/AppRenderer.js +49 -16
  39. package/lib/loop/apps/appspec.d.ts +8 -1
  40. package/lib/loop/apps/appspec.js +119 -2
  41. package/lib/loop/apps/checks.js +161 -1
  42. package/lib/loop/apps/composer.d.ts +37 -0
  43. package/lib/loop/apps/composer.js +61 -0
  44. package/lib/loop/apps/hostTools.d.ts +17 -0
  45. package/lib/loop/apps/hostTools.js +20 -0
  46. package/lib/loop/apps/index.d.ts +2 -0
  47. package/lib/loop/apps/index.js +2 -0
  48. package/lib/loop/apps/rules.d.ts +22 -1
  49. package/lib/loop/apps/rules.js +49 -1
  50. package/lib/loop/core/index.d.ts +31 -0
  51. package/lib/loop/core/index.js +22 -0
  52. package/lib/loop/embed/AppEmbed.d.ts +100 -6
  53. package/lib/loop/embed/AppEmbed.js +172 -27
  54. package/lib/loop/embed/LoopEmbed.js +2 -0
  55. package/lib/loop/embed/element.js +58 -5
  56. package/lib/loop/embed/embedConfig.d.ts +10 -1
  57. package/lib/loop/embed/embedConfig.js +12 -1
  58. package/lib/loop/embed/embedSession.d.ts +79 -0
  59. package/lib/loop/embed/embedSession.js +136 -0
  60. package/lib/loop/embed/embedTheme.d.ts +12 -9
  61. package/lib/loop/embed/embedTheme.js +32 -22
  62. package/lib/loop/embed/hostBridge.d.ts +79 -0
  63. package/lib/loop/embed/hostBridge.js +104 -0
  64. package/lib/loop/index.d.ts +5 -3
  65. package/lib/loop/index.js +6 -3
  66. package/lib/loop/plugins/a2ui-surface/SurfaceToolResult.d.ts +5 -2
  67. package/lib/loop/plugins/a2ui-surface/SurfaceToolResult.js +7 -1
  68. package/lib/loop/plugins/a2ui-surface/index.d.ts +1 -1
  69. package/lib/loop/plugins/a2ui-surface/index.js +4 -4
  70. package/lib/loop/plugins/a2ui-surface/toolResult.d.ts +27 -0
  71. package/lib/loop/plugins/a2ui-surface/toolResult.js +22 -0
  72. package/lib/loop/plugins/agent-capacity/index.d.ts +3 -1
  73. package/lib/loop/plugins/agent-capacity/index.js +2 -1
  74. package/lib/loop/plugins/chat/ChatView.js +31 -4
  75. package/lib/loop/plugins/chat/index.d.ts +6 -1
  76. package/lib/loop/presets.d.ts +3 -1
  77. package/lib/loop/presets.js +2 -1
  78. package/lib/loop/shell/LoopWorkspace.js +3 -0
  79. package/lib/protocols/BrowserAgentAdapter.d.ts +18 -0
  80. package/lib/protocols/BrowserAgentAdapter.js +35 -2
  81. package/lib/runtimes/__tests__/fixtures/accounting-agent-card.json +8 -0
  82. package/lib/runtimes/browser/a2aPeer.d.ts +11 -0
  83. package/lib/runtimes/browser/a2aPeer.js +15 -1
  84. package/lib/runtimes/browser/protocol.d.ts +3 -0
  85. package/lib/runtimes/browser/protocol.js +2 -1
  86. package/lib/specs/agents/agents.js +6 -25
  87. package/lib/specs/apps.js +50 -8
  88. package/lib/specs/appspecSchema.js +258 -0
  89. package/lib/types/agentspecs.d.ts +86 -0
  90. package/lib/types/chat.d.ts +29 -1
  91. package/package.json +1 -1
  92. package/scripts/codegen/generate_agents.py +4 -2
  93. package/scripts/codegen/generate_apps.py +7 -0
  94. package/scripts/codegen/generate_backend_tools.py +4 -12
  95. package/scripts/codegen/generate_cogs.py +3 -1
  96. package/scripts/codegen/generate_ui_plugins.py +22 -9
  97. package/scripts/voice/transcribe.mjs +29 -21
@@ -15,6 +15,7 @@ import type { AgentRuntimeConfig } from './config';
15
15
  import type { ContextSnapshotData } from './context';
16
16
  import type { InputPromptVariant } from '../chat/prompt/InputPromptBase';
17
17
  import type { MentionableAgent } from '../chat/prompt/plugins/AgentMentionPlugin';
18
+ import type { PromptCommand } from '../chat/prompt/plugins/CommandPlugin';
18
19
  import type { Icon } from '@primer/octicons-react';
19
20
  /** One agent a chat may address, as its controls need it. */
20
21
  export interface FooterAgent {
@@ -652,6 +653,21 @@ export type ThemeOverrides = {
652
653
  light?: Record<string, string>;
653
654
  dark?: Record<string, string>;
654
655
  };
656
+ /**
657
+ * A conversation the chat goes on with (LOOP D-13): an embedded
658
+ * application's session, reattached after its page reloaded.
659
+ */
660
+ export type ResumedThread = {
661
+ /** Its id, AG-UI's `threadId`: the session's uid. */
662
+ id: string;
663
+ /** What it holds already; none for a new one. */
664
+ messages: ChatMessage[];
665
+ /**
666
+ * Told the thread a message is first sent on — this one, or a new one
667
+ * after the header's + — so that its host keeps it. A stable function.
668
+ */
669
+ onStarted?: (threadId: string) => void;
670
+ };
655
671
  export interface ChatBaseProps {
656
672
  /**
657
673
  * Hands an imperative send function to the host, once the chat is able to
@@ -722,7 +738,7 @@ export interface ChatBaseProps {
722
738
  /**
723
739
  * External MCP toolsets status data for the MCP indicator.
724
740
  * When provided, the data is forwarded to the McpStatusIndicator
725
- * so it shows live status instead of "No MCP Server defined".
741
+ * so it shows their live status; with none, it is not drawn.
726
742
  */
727
743
  mcpStatusData?: import('./mcp').McpToolsetsStatusResponse | null;
728
744
  /**
@@ -755,6 +771,11 @@ export interface ChatBaseProps {
755
771
  promptVariant?: InputPromptVariant;
756
772
  /** Agents the prompt may address by typing `@`. Lexical only. */
757
773
  mentionableAgents?: MentionableAgent[];
774
+ /**
775
+ * Commands the prompt lists while `/` is typed, before its own: an
776
+ * application's (LOOP P-19). Picking one writes `/<name> `. Lexical only.
777
+ */
778
+ promptCommands?: PromptCommand[];
758
779
  /**
759
780
  * Whether the prompt offers a chooser for who answers.
760
781
  *
@@ -1190,6 +1211,13 @@ export interface ChatBaseProps {
1190
1211
  userId?: string;
1191
1212
  accessToken?: string;
1192
1213
  }>;
1214
+ /**
1215
+ * The conversation to go on with (LOOP D-13): its AG-UI thread — an
1216
+ * application's session — and what it holds, drawn in place of the
1217
+ * runtime's history, which is its agent's and not one session's. Read
1218
+ * when the chat mounts; a new thread (the header's +) is the chat's own.
1219
+ */
1220
+ thread?: ResumedThread;
1193
1221
  /**
1194
1222
  * Runtime ID for conversation persistence.
1195
1223
  * When provided, messages are restored from websocket snapshot data on
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datalayer/agent-runtimes",
3
- "version": "1.3.80",
3
+ "version": "1.3.82",
4
4
  "type": "module",
5
5
  "workspaces": [
6
6
  ".",
@@ -410,7 +410,8 @@ from agent_runtimes.types import (
410
410
  for skill in spec.get("skills", [])
411
411
  ]
412
412
  tool_refs = [
413
- versioned_ref(*split_spec_ref(tool)) for tool in spec.get("backend_tools", [])
413
+ versioned_ref(*split_spec_ref(tool))
414
+ for tool in spec.get("backend_tools", [])
414
415
  ]
415
416
  frontend_tool_refs = [
416
417
  versioned_ref(*split_spec_ref(ft))
@@ -1032,7 +1033,8 @@ const FRONTEND_TOOL_MAP: Record<string, any> = {
1032
1033
 
1033
1034
  # Get backend tools - resolve to BackendToolSpec via TOOL_MAP
1034
1035
  tool_ids_list = [
1035
- versioned_ref(*split_spec_ref(sid)) for sid in spec.get("backend_tools", [])
1036
+ versioned_ref(*split_spec_ref(sid))
1037
+ for sid in spec.get("backend_tools", [])
1036
1038
  ]
1037
1039
  if has_tools and tool_ids_list:
1038
1040
  tools_str = ", ".join(f"TOOL_MAP['{tid}']" for tid in tool_ids_list)
@@ -53,6 +53,7 @@ CAMEL = {
53
53
  "min_confidence": "minConfidence",
54
54
  "decision_model": "decisionModel",
55
55
  "backend_tools": "backendTools",
56
+ "character_alone": "characterAlone",
56
57
  }
57
58
 
58
59
  #: The keys whose value is carried as it is written: a component tree, weights by name.
@@ -90,6 +91,12 @@ def load_specs(specs_dir: Path) -> tuple[list[dict[str, Any]], dict[str, Any]]:
90
91
  spec["interface"]["layout"] = app.layout.value
91
92
  spec["record"]["retention_days"] = app.record.retention_days
92
93
  spec["setup"] = apps_module.app_setup(app)
94
+ # What TypeScript reads only when it is said: off, or none.
95
+ deployment = spec.get("deployment") or {}
96
+ if (deployment.get("hosted") or {}).get("character_alone") is False:
97
+ del deployment["hosted"]["character_alone"]
98
+ if deployment.get("embedded") and deployment["embedded"].get("host") is None:
99
+ del deployment["embedded"]["host"]
93
100
  behaviours[identity] = {
94
101
  tool: behaviour.value
95
102
  for tool, behaviour in sorted(apps_module.tool_behaviours(app).items())
@@ -110,9 +110,7 @@ def generate_python_code(specs: list[dict[str, Any]]) -> str:
110
110
  for spec in specs:
111
111
  tool_id = spec["id"]
112
112
  version = spec["version"]
113
- const_name = (
114
- f"{tool_id.upper().replace('-', '_')}_BACKEND_TOOL_SPEC{version_suffix(version)}"
115
- )
113
+ const_name = f"{tool_id.upper().replace('-', '_')}_BACKEND_TOOL_SPEC{version_suffix(version)}"
116
114
  runtime = _require_runtime(spec)
117
115
  requires_approval = _requires_approval(spec)
118
116
  timeout = _timeout_hms(spec)
@@ -157,9 +155,7 @@ def generate_python_code(specs: list[dict[str, Any]]) -> str:
157
155
  for spec in specs:
158
156
  tool_id = spec["id"]
159
157
  version = spec["version"]
160
- const_name = (
161
- f"{tool_id.upper().replace('-', '_')}_BACKEND_TOOL_SPEC{version_suffix(version)}"
162
- )
158
+ const_name = f"{tool_id.upper().replace('-', '_')}_BACKEND_TOOL_SPEC{version_suffix(version)}"
163
159
  lines.append(f' "{tool_id}": {const_name},')
164
160
 
165
161
  lines.extend(
@@ -215,9 +211,7 @@ def generate_typescript_code(specs: list[dict[str, Any]]) -> str:
215
211
  for spec in specs:
216
212
  tool_id = spec["id"]
217
213
  version = spec["version"]
218
- const_name = (
219
- f"{tool_id.upper().replace('-', '_')}_BACKEND_TOOL_SPEC{version_suffix(version)}"
220
- )
214
+ const_name = f"{tool_id.upper().replace('-', '_')}_BACKEND_TOOL_SPEC{version_suffix(version)}"
221
215
  runtime = _require_runtime(spec)
222
216
  requires_approval = _requires_approval(spec)
223
217
  timeout = _timeout_hms(spec)
@@ -264,9 +258,7 @@ def generate_typescript_code(specs: list[dict[str, Any]]) -> str:
264
258
  for spec in specs:
265
259
  tool_id = spec["id"]
266
260
  version = spec["version"]
267
- const_name = (
268
- f"{tool_id.upper().replace('-', '_')}_BACKEND_TOOL_SPEC{version_suffix(version)}"
269
- )
261
+ const_name = f"{tool_id.upper().replace('-', '_')}_BACKEND_TOOL_SPEC{version_suffix(version)}"
270
262
  lines.append(f" '{tool_id}': {const_name},")
271
263
 
272
264
  lines.extend(
@@ -208,7 +208,9 @@ def generate_typescript_code(specs: list[dict[str, Any]], specs_dir: Path) -> st
208
208
  # is one directory up, beside the catalogues it imports.
209
209
  head = head.replace("from '../../types'", "from '../types'")
210
210
  head = re.sub(
211
- r"from '\.\./(mcpServers|skills|backendTools|frontendTools)'", r"from './\1'", head
211
+ r"from '\.\./(mcpServers|skills|backendTools|frontendTools)'",
212
+ r"from './\1'",
213
+ head,
212
214
  )
213
215
 
214
216
  lines = [
@@ -104,18 +104,18 @@ def _py_calls(specs: list[dict[str, Any]]) -> list[str]:
104
104
  "# The components as typed calls (LOOP C-15)",
105
105
  "# " + "=" * 76,
106
106
  "",
107
- "#: A property bound to what the application publishes or takes: ``{\"path\": \"/runs\"}``.",
107
+ '#: A property bound to what the application publishes or takes: ``{"path": "/runs"}``.',
108
108
  "Bound = Mapping[str, str]",
109
109
  "",
110
110
  "",
111
111
  "class SurfaceComponents:",
112
- ' """Every component of the catalog as a typed call: ``app.ui.table(\"runs\", columns=[...])``.',
112
+ ' """Every component of the catalog as a typed call: ``app.ui.table("runs", columns=[...])``.',
113
113
  "",
114
114
  " Each places the node the Canvas and the YAML write, through",
115
115
  " `Application.component`, which checks it against the same JSON Schema; an",
116
116
  " IDE completes its properties, and a type checker refuses a wrong value",
117
117
  " before the application runs. A property may be bound instead",
118
- ' (``{\"path\": ...}``); a property left as ``None`` is not written.',
118
+ ' (``{"path": ...}``); a property left as ``None`` is not written.',
119
119
  ' """',
120
120
  "",
121
121
  " def __init__(self, place: Callable[..., Dict[str, Any]]) -> None:",
@@ -131,15 +131,21 @@ def _py_calls(specs: list[dict[str, Any]]) -> list[str]:
131
131
  bindings = component.get("bindings") or {}
132
132
  extra = [
133
133
  name
134
- for name in dict.fromkeys([*(bindings.get("shows") or []), *(bindings.get("sends") or [])])
134
+ for name in dict.fromkeys(
135
+ [*(bindings.get("shows") or []), *(bindings.get("sends") or [])]
136
+ )
135
137
  if name not in fields
136
138
  ]
137
139
  params = [" self,", " id: str,", " *,"]
138
- ordered = [n for n in fields if n in required] + [n for n in fields if n not in required]
140
+ ordered = [n for n in fields if n in required] + [
141
+ n for n in fields if n not in required
142
+ ]
139
143
  for name in ordered:
140
144
  kind = f"Union[{_py_type(fields[name])}, Bound]"
141
145
  params.append(
142
- f" {name}: {kind}," if name in required else f" {name}: Optional[{kind}] = None,"
146
+ f" {name}: {kind},"
147
+ if name in required
148
+ else f" {name}: Optional[{kind}] = None,"
143
149
  )
144
150
  for name in extra:
145
151
  params.append(f" {name}: Optional[Bound] = None,")
@@ -157,9 +163,16 @@ def _py_calls(specs: list[dict[str, Any]]) -> list[str]:
157
163
  ]
158
164
  for name in ordered:
159
165
  field = fields[name]
160
- doc += [f" {name} : {_py_type(field)} or Bound", f" {field.get('title', name)}: {field.get('description', '')}"]
166
+ doc += [
167
+ f" {name} : {_py_type(field)} or Bound",
168
+ f" {field.get('title', name)}: {field.get('description', '')}",
169
+ ]
161
170
  for name in extra:
162
- said = "What it shows" if name in (bindings.get("shows") or []) else "Where what a person does is written"
171
+ said = (
172
+ "What it shows"
173
+ if name in (bindings.get("shows") or [])
174
+ else "Where what a person does is written"
175
+ )
163
176
  doc += [f" {name} : Bound", f" {said}."]
164
177
  doc += [' """']
165
178
  names = [*ordered, *extra]
@@ -171,7 +184,7 @@ def _py_calls(specs: list[dict[str, Any]]) -> list[str]:
171
184
  f" def {call_name(component['id'])}(",
172
185
  *params,
173
186
  " ) -> Dict[str, Any]:",
174
- *[d.replace('\\', '\\\\') for d in doc],
187
+ *[d.replace("\\", "\\\\") for d in doc],
175
188
  " given = {",
176
189
  *[f" {json.dumps(name)}: {name}," for name in names],
177
190
  " }",
@@ -33,26 +33,34 @@ function readWav(path) {
33
33
  return samples;
34
34
  }
35
35
 
36
- const loading = performance.now();
37
- const transcribe = await pipeline('automatic-speech-recognition', model, {
38
- dtype: 'q8',
39
- device: 'cpu',
40
- });
41
- const loadMs = Math.round(performance.now() - loading);
42
- // Whisper is told the language; Moonshine hears English only.
43
- const options = model.startsWith('whisper')
44
- ? { language: language === 'fr' ? 'french' : 'english', task: 'transcribe' }
45
- : {};
46
- const results = [];
47
- for (const file of files) {
48
- const audio = readWav(file);
49
- const started = performance.now();
50
- const output = await transcribe(audio, options);
51
- results.push({
52
- file: file.split('/').pop(),
53
- text: output.text.trim(),
54
- ms: Math.round(performance.now() - started),
55
- audio_s: Math.round((audio.length / 16000) * 100) / 100,
36
+ /** Load the model, transcribe each file, print the JSON line. */
37
+ async function main() {
38
+ const loading = performance.now();
39
+ const transcribe = await pipeline('automatic-speech-recognition', model, {
40
+ dtype: 'q8',
41
+ device: 'cpu',
56
42
  });
43
+ const loadMs = Math.round(performance.now() - loading);
44
+ // Whisper is told the language; Moonshine hears English only.
45
+ const options = model.startsWith('whisper')
46
+ ? { language: language === 'fr' ? 'french' : 'english', task: 'transcribe' }
47
+ : {};
48
+ const results = [];
49
+ for (const file of files) {
50
+ const audio = readWav(file);
51
+ const started = performance.now();
52
+ const output = await transcribe(audio, options);
53
+ results.push({
54
+ file: file.split('/').pop(),
55
+ text: output.text.trim(),
56
+ ms: Math.round(performance.now() - started),
57
+ audio_s: Math.round((audio.length / 16000) * 100) / 100,
58
+ });
59
+ }
60
+ console.log(JSON.stringify({ model, language, load_ms: loadMs, results }));
57
61
  }
58
- console.log(JSON.stringify({ model, language, load_ms: loadMs, results }));
62
+
63
+ main().catch(error => {
64
+ console.error(error);
65
+ process.exit(1);
66
+ });