@datalayer/agent-runtimes 1.3.55 → 1.3.56

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 (39) hide show
  1. package/lib/chat/base/ChatBase.js +8 -3
  2. package/lib/chat/index.d.ts +1 -0
  3. package/lib/chat/index.js +3 -0
  4. package/lib/chat/marks/SpecMark.d.ts +46 -0
  5. package/lib/chat/marks/SpecMark.js +90 -0
  6. package/lib/chat/marks/iconRef.d.ts +29 -0
  7. package/lib/chat/marks/iconRef.js +40 -0
  8. package/lib/chat/marks/index.d.ts +8 -0
  9. package/lib/chat/marks/index.js +12 -0
  10. package/lib/chat/marks/toolMarks.d.ts +43 -0
  11. package/lib/chat/marks/toolMarks.js +110 -0
  12. package/lib/chat/messages/ChatMessageList.d.ts +8 -1
  13. package/lib/chat/messages/ChatMessageList.js +11 -18
  14. package/lib/chat/parts/ToolPart.js +6 -1
  15. package/lib/chat/prompt/InputPrompt.d.ts +4 -1
  16. package/lib/chat/prompt/InputPrompt.js +2 -2
  17. package/lib/chat/prompt/menus/SkillsMenu.js +2 -1
  18. package/lib/chat/prompt/menus/ToolsMenu.d.ts +3 -1
  19. package/lib/chat/prompt/menus/ToolsMenu.js +25 -9
  20. package/lib/chat/tools/ToolCallDisplay.d.ts +8 -1
  21. package/lib/chat/tools/ToolCallDisplay.js +3 -2
  22. package/lib/loop/plugins/chat/ChatView.js +7 -5
  23. package/lib/specs/actions.js +56 -0
  24. package/lib/specs/frontendTools.js +6 -6
  25. package/lib/specs/mcpServers.d.ts +1 -0
  26. package/lib/specs/mcpServers.js +39 -16
  27. package/lib/specs/skills.js +7 -7
  28. package/lib/specs/tools.js +21 -21
  29. package/lib/types/chat.d.ts +4 -0
  30. package/lib/types/mcp.d.ts +2 -2
  31. package/lib/types/skills.d.ts +2 -2
  32. package/lib/types/tools.d.ts +4 -4
  33. package/package.json +1 -1
  34. package/scripts/codegen/agentspecs_clone.py +5 -3
  35. package/scripts/codegen/generate_frontend_tools.py +2 -0
  36. package/scripts/codegen/generate_mcp_servers.py +2 -0
  37. package/scripts/codegen/generate_skills.py +2 -0
  38. package/scripts/codegen/generate_tools.py +2 -0
  39. package/scripts/codegen/marks.py +33 -0
@@ -20,7 +20,7 @@ export const CREATE_PLAN_TOOL_SPEC_0_0_1 = {
20
20
  package: 'agent_runtimes.examples.tools.ag_ui',
21
21
  method: 'create_plan',
22
22
  },
23
- icon: 'list-unordered',
23
+ icon: '@primer/octicons-react:list-unordered',
24
24
  emoji: '📋',
25
25
  };
26
26
  export const CURRENT_TIME_TOOL_SPEC_0_0_1 = {
@@ -38,7 +38,7 @@ export const CURRENT_TIME_TOOL_SPEC_0_0_1 = {
38
38
  package: 'agent_runtimes.examples.tools.ag_ui',
39
39
  method: 'current_time',
40
40
  },
41
- icon: 'clock',
41
+ icon: '@primer/octicons-react:clock',
42
42
  emoji: '🕒',
43
43
  };
44
44
  export const DECIDE_TOOL_SPEC_0_0_1 = {
@@ -56,7 +56,7 @@ export const DECIDE_TOOL_SPEC_0_0_1 = {
56
56
  package: 'agent_runtimes.tools.decisions',
57
57
  method: 'decide',
58
58
  },
59
- icon: 'law',
59
+ icon: '@primer/octicons-react:law',
60
60
  emoji: '⚖️',
61
61
  };
62
62
  export const DISPLAY_RECIPE_TOOL_SPEC_0_0_1 = {
@@ -74,7 +74,7 @@ export const DISPLAY_RECIPE_TOOL_SPEC_0_0_1 = {
74
74
  package: 'agent_runtimes.examples.tools.ag_ui',
75
75
  method: 'display_recipe',
76
76
  },
77
- icon: 'book',
77
+ icon: '@primer/octicons-react:book',
78
78
  emoji: '🍳',
79
79
  };
80
80
  export const EXAMPLE_CREATE_PLAN_TOOL_SPEC_0_0_1 = {
@@ -92,7 +92,7 @@ export const EXAMPLE_CREATE_PLAN_TOOL_SPEC_0_0_1 = {
92
92
  package: 'agent_runtimes.examples.tools.ag_ui',
93
93
  method: 'create_plan',
94
94
  },
95
- icon: 'list-unordered',
95
+ icon: '@primer/octicons-react:list-unordered',
96
96
  emoji: '📋',
97
97
  };
98
98
  export const EXAMPLE_CURRENT_TIME_TOOL_SPEC_0_0_1 = {
@@ -110,7 +110,7 @@ export const EXAMPLE_CURRENT_TIME_TOOL_SPEC_0_0_1 = {
110
110
  package: 'agent_runtimes.examples.tools.ag_ui',
111
111
  method: 'current_time',
112
112
  },
113
- icon: 'clock',
113
+ icon: '@primer/octicons-react:clock',
114
114
  emoji: '🕒',
115
115
  };
116
116
  export const EXAMPLE_DISPLAY_RECIPE_TOOL_SPEC_0_0_1 = {
@@ -128,7 +128,7 @@ export const EXAMPLE_DISPLAY_RECIPE_TOOL_SPEC_0_0_1 = {
128
128
  package: 'agent_runtimes.examples.tools.ag_ui',
129
129
  method: 'display_recipe',
130
130
  },
131
- icon: 'book',
131
+ icon: '@primer/octicons-react:book',
132
132
  emoji: '🍳',
133
133
  };
134
134
  export const EXAMPLE_GENERATE_HAIKU_TOOL_SPEC_0_0_1 = {
@@ -146,7 +146,7 @@ export const EXAMPLE_GENERATE_HAIKU_TOOL_SPEC_0_0_1 = {
146
146
  package: 'agent_runtimes.examples.tools.ag_ui',
147
147
  method: 'generate_haiku',
148
148
  },
149
- icon: 'pencil',
149
+ icon: '@primer/octicons-react:pencil',
150
150
  emoji: '🖋️',
151
151
  };
152
152
  export const EXAMPLE_GENERATE_TASK_STEPS_TOOL_SPEC_0_0_1 = {
@@ -164,8 +164,8 @@ export const EXAMPLE_GENERATE_TASK_STEPS_TOOL_SPEC_0_0_1 = {
164
164
  package: 'agent_runtimes.examples.tools.ag_ui',
165
165
  method: 'generate_task_steps',
166
166
  },
167
- icon: 'tasklist',
168
- emoji: '🧑‍⚖️',
167
+ icon: '@primer/octicons-react:tasklist',
168
+ emoji: '🙋',
169
169
  };
170
170
  export const EXAMPLE_GET_WEATHER_TOOL_SPEC_0_0_1 = {
171
171
  id: 'example-get-weather',
@@ -182,7 +182,7 @@ export const EXAMPLE_GET_WEATHER_TOOL_SPEC_0_0_1 = {
182
182
  package: 'agent_runtimes.examples.tools.ag_ui',
183
183
  method: 'get_weather',
184
184
  },
185
- icon: 'sun',
185
+ icon: '@primer/octicons-react:sun',
186
186
  emoji: '🌤️',
187
187
  };
188
188
  export const EXAMPLE_RENDER_A2UI_SURFACE_TOOL_SPEC_0_0_1 = {
@@ -200,7 +200,7 @@ export const EXAMPLE_RENDER_A2UI_SURFACE_TOOL_SPEC_0_0_1 = {
200
200
  package: 'agent_runtimes.examples.tools.a2ui',
201
201
  method: 'render_a2ui_surface',
202
202
  },
203
- icon: 'browser',
203
+ icon: '@primer/octicons-react:browser',
204
204
  emoji: '🎛️',
205
205
  };
206
206
  export const EXAMPLE_UPDATE_PLAN_STEP_TOOL_SPEC_0_0_1 = {
@@ -218,7 +218,7 @@ export const EXAMPLE_UPDATE_PLAN_STEP_TOOL_SPEC_0_0_1 = {
218
218
  package: 'agent_runtimes.examples.tools.ag_ui',
219
219
  method: 'update_plan_step',
220
220
  },
221
- icon: 'checklist',
221
+ icon: '@primer/octicons-react:checklist',
222
222
  emoji: '✅',
223
223
  };
224
224
  export const GENERATE_HAIKU_TOOL_SPEC_0_0_1 = {
@@ -236,7 +236,7 @@ export const GENERATE_HAIKU_TOOL_SPEC_0_0_1 = {
236
236
  package: 'agent_runtimes.examples.tools.ag_ui',
237
237
  method: 'generate_haiku',
238
238
  },
239
- icon: 'pencil',
239
+ icon: '@primer/octicons-react:pencil',
240
240
  emoji: '🖋️',
241
241
  };
242
242
  export const GENERATE_TASK_STEPS_TOOL_SPEC_0_0_1 = {
@@ -254,8 +254,8 @@ export const GENERATE_TASK_STEPS_TOOL_SPEC_0_0_1 = {
254
254
  package: 'agent_runtimes.examples.tools.ag_ui',
255
255
  method: 'generate_task_steps',
256
256
  },
257
- icon: 'tasklist',
258
- emoji: '🧑‍⚖️',
257
+ icon: '@primer/octicons-react:tasklist',
258
+ emoji: '🙋',
259
259
  };
260
260
  export const GET_WEATHER_TOOL_SPEC_0_0_1 = {
261
261
  id: 'get-weather',
@@ -272,7 +272,7 @@ export const GET_WEATHER_TOOL_SPEC_0_0_1 = {
272
272
  package: 'agent_runtimes.examples.tools.ag_ui',
273
273
  method: 'get_weather',
274
274
  },
275
- icon: 'sun',
275
+ icon: '@primer/octicons-react:sun',
276
276
  emoji: '🌤️',
277
277
  };
278
278
  export const RUNTIME_ECHO_TOOL_SPEC_0_0_1 = {
@@ -290,7 +290,7 @@ export const RUNTIME_ECHO_TOOL_SPEC_0_0_1 = {
290
290
  package: 'agent_runtimes.examples.tools',
291
291
  method: 'runtime_echo',
292
292
  },
293
- icon: 'comment',
293
+ icon: '@primer/octicons-react:comment',
294
294
  emoji: '💬',
295
295
  };
296
296
  export const RUNTIME_SEND_MAIL_TOOL_SPEC_0_0_1 = {
@@ -308,7 +308,7 @@ export const RUNTIME_SEND_MAIL_TOOL_SPEC_0_0_1 = {
308
308
  package: 'agent_runtimes.examples.tools',
309
309
  method: 'runtime_send_mail',
310
310
  },
311
- icon: 'mail',
311
+ icon: '@primer/octicons-react:mail',
312
312
  emoji: '📧',
313
313
  };
314
314
  export const RUNTIME_SENSITIVE_ECHO_TOOL_SPEC_0_0_1 = {
@@ -326,7 +326,7 @@ export const RUNTIME_SENSITIVE_ECHO_TOOL_SPEC_0_0_1 = {
326
326
  package: 'agent_runtimes.examples.tools',
327
327
  method: 'runtime_sensitive_echo',
328
328
  },
329
- icon: 'shield',
329
+ icon: '@primer/octicons-react:shield',
330
330
  emoji: '🛡️',
331
331
  };
332
332
  export const UPDATE_PLAN_STEP_TOOL_SPEC_0_0_1 = {
@@ -344,7 +344,7 @@ export const UPDATE_PLAN_STEP_TOOL_SPEC_0_0_1 = {
344
344
  package: 'agent_runtimes.examples.tools.ag_ui',
345
345
  method: 'update_plan_step',
346
346
  },
347
- icon: 'checklist',
347
+ icon: '@primer/octicons-react:checklist',
348
348
  emoji: '✅',
349
349
  };
350
350
  // ============================================================================
@@ -276,6 +276,10 @@ export interface MCPServerConfig {
276
276
  transport?: string;
277
277
  isConfig?: boolean;
278
278
  isRunning?: boolean;
279
+ /** The icon, `<package>:<name>` (agentspecs.marks), as the runtime's catalogue says it. */
280
+ icon?: string;
281
+ /** Drawn where there is no icon. */
282
+ emoji?: string;
279
283
  }
280
284
  /**
281
285
  * Common props shared by all Chat wrapper components
@@ -39,9 +39,9 @@ export interface MCPServer {
39
39
  transport: 'stdio' | 'http';
40
40
  /** Environment variables required by this server (e.g., API keys) */
41
41
  requiredEnvVars?: string[];
42
- /** Icon identifier for the server */
42
+ /** The icon, `<package>:<name>` — `@datalayer/icons-react:odoo` (agentspecs.marks; see `SpecMark`) */
43
43
  icon?: string;
44
- /** Emoji identifier for the server */
44
+ /** Drawn where there is no icon */
45
45
  emoji?: string;
46
46
  }
47
47
  /**
@@ -107,9 +107,9 @@ export interface SkillSpec {
107
107
  dependencies?: string[];
108
108
  /** Tags for categorization */
109
109
  tags: string[];
110
- /** Icon identifier */
110
+ /** The icon, `<package>:<name>` — `@datalayer/icons-react:odoo` (agentspecs.marks; see `SpecMark`) */
111
111
  icon?: string;
112
- /** Emoji identifier */
112
+ /** Drawn where there is no icon */
113
113
  emoji?: string;
114
114
  /** Whether the skill is enabled */
115
115
  enabled: boolean;
@@ -33,9 +33,9 @@ export interface ToolSpec {
33
33
  requiresApproval?: boolean;
34
34
  /** Runtime binding metadata */
35
35
  runtime: ToolRuntimeSpec;
36
- /** Icon identifier */
36
+ /** The icon, `<package>:<name>` — `@datalayer/icons-react:odoo` (agentspecs.marks; see `SpecMark`) */
37
37
  icon?: string;
38
- /** Emoji identifier */
38
+ /** Drawn where there is no icon */
39
39
  emoji?: string;
40
40
  }
41
41
  /**
@@ -78,9 +78,9 @@ export interface FrontendToolSpec {
78
78
  * read and edit a notebook but must never delete from it.
79
79
  */
80
80
  toolset: string | string[];
81
- /** Icon identifier */
81
+ /** The icon, `<package>:<name>` — `@datalayer/icons-react:odoo` (agentspecs.marks; see `SpecMark`) */
82
82
  icon?: string;
83
- /** Emoji identifier */
83
+ /** Drawn where there is no icon */
84
84
  emoji?: string;
85
85
  }
86
86
  import type { ReactNode } from 'react';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datalayer/agent-runtimes",
3
- "version": "1.3.55",
3
+ "version": "1.3.56",
4
4
  "type": "module",
5
5
  "workspaces": [
6
6
  ".",
@@ -29,10 +29,12 @@ def package_root(specs_dir: Path) -> Path:
29
29
  def import_from_clone(specs_dir: Path, module: str) -> ModuleType:
30
30
  """Import `agentspecs.<module>` from the clone `specs_dir` belongs to."""
31
31
  root = package_root(specs_dir)
32
- if not (root / "agentspecs" / module).exists():
32
+ package = root / "agentspecs"
33
+ if not (package / module).exists() and not (package / f"{module}.py").exists():
33
34
  raise SystemExit(
34
- f"Error: {root / 'agentspecs' / module} not found — Frames and Cogs "
35
- "need agentspecs >= 0.0.12"
35
+ f"Error: agentspecs.{module} not found in {package} — the clone is "
36
+ "older than the generators (Frames and Cogs need agentspecs >= 0.0.12, "
37
+ "the marks of the catalogues >= 0.0.31)"
36
38
  )
37
39
  for name in [
38
40
  name
@@ -13,6 +13,7 @@ from pathlib import Path
13
13
  from typing import Any
14
14
 
15
15
  import yaml
16
+ from marks import check_marks
16
17
  from versioning import ensure_spec_version, version_suffix
17
18
 
18
19
 
@@ -274,6 +275,7 @@ def main() -> None:
274
275
 
275
276
  print(f"Loading frontend tool specs from {args.specs_dir}...")
276
277
  specs = load_frontend_tool_specs(args.specs_dir)
278
+ check_marks(specs, args.specs_dir)
277
279
  print(f"Loaded {len(specs)} frontend tool specifications")
278
280
 
279
281
  # Generate Python code
@@ -18,6 +18,7 @@ from pathlib import Path
18
18
  from typing import Any
19
19
 
20
20
  import yaml
21
+ from marks import check_marks
21
22
  from versioning import ensure_spec_version, version_suffix
22
23
 
23
24
 
@@ -434,6 +435,7 @@ def main():
434
435
  # Load specifications
435
436
  print(f"Loading MCP server specs from {args.specs_dir}...")
436
437
  specs = load_mcp_specs(args.specs_dir)
438
+ check_marks(specs, args.specs_dir)
437
439
  print(f"Loaded {len(specs)} MCP server specifications")
438
440
 
439
441
  # Generate Python code
@@ -18,6 +18,7 @@ from pathlib import Path
18
18
  from typing import Any
19
19
 
20
20
  import yaml
21
+ from marks import check_marks
21
22
  from versioning import ensure_spec_version, version_suffix
22
23
 
23
24
 
@@ -368,6 +369,7 @@ def main():
368
369
  # Load specifications
369
370
  print(f"Loading skill specs from {args.specs_dir}...")
370
371
  specs = load_skill_specs(args.specs_dir)
372
+ check_marks(specs, args.specs_dir)
371
373
  print(f"Loaded {len(specs)} skill specifications")
372
374
 
373
375
  # Generate Python code
@@ -14,6 +14,7 @@ from pathlib import Path
14
14
  from typing import Any
15
15
 
16
16
  import yaml
17
+ from marks import check_marks
17
18
  from versioning import ensure_spec_version, version_suffix
18
19
 
19
20
 
@@ -327,6 +328,7 @@ def main() -> None:
327
328
 
328
329
  print(f"Loading tool specs from {args.specs_dir}...")
329
330
  specs = load_tool_specs(args.specs_dir)
331
+ check_marks(specs, args.specs_dir)
330
332
  print(f"Loaded {len(specs)} tool specifications")
331
333
 
332
334
  print("Generating Python code...")
@@ -0,0 +1,33 @@
1
+ # Copyright (c) 2025-2026 Datalayer, Inc.
2
+ # Distributed under the terms of the Modified BSD License.
3
+
4
+ """The marks of a catalogue entry, checked before anything is generated from it.
5
+
6
+ An MCP server, a skill, a tool and a frontend tool set each have an icon and an
7
+ emoji. The icon says its package (`@datalayer/icons-react:odoo`,
8
+ `@primer/octicons-react:mark-github`), so the chat loads it from the right one.
9
+ The rule is `agentspecs.marks`, imported from the clone the specs are read
10
+ from; an entry that breaks it stops the generator, naming the entry.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from pathlib import Path
16
+ from typing import Any
17
+
18
+ from agentspecs_clone import import_from_clone
19
+
20
+
21
+ def check_marks(specs: list[dict[str, Any]], specs_dir: Path) -> None:
22
+ """Refuse a catalogue with an entry whose marks are missing or malformed."""
23
+ marks = import_from_clone(specs_dir, "marks")
24
+ problems = [
25
+ f" {spec.get('id', '?')}: {problem}"
26
+ for spec in specs
27
+ for problem in marks.marks_problems(spec)
28
+ ]
29
+ if problems:
30
+ raise SystemExit(
31
+ f"Error: the marks of {specs_dir.name} are not what agentspecs.marks says:\n"
32
+ + "\n".join(problems)
33
+ )