@datalayer/agent-runtimes 1.0.5 → 1.0.6

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 (111) hide show
  1. package/README.md +157 -10
  2. package/lib/AgentNode.d.ts +3 -0
  3. package/lib/AgentNode.js +676 -0
  4. package/lib/agent-node/themeStore.d.ts +3 -0
  5. package/lib/agent-node/themeStore.js +156 -0
  6. package/lib/agent-node-main.d.ts +1 -0
  7. package/lib/agent-node-main.js +14 -0
  8. package/lib/chat/Chat.js +16 -10
  9. package/lib/chat/ChatFloating.js +1 -1
  10. package/lib/chat/ChatSidebar.js +81 -49
  11. package/lib/chat/base/ChatBase.js +388 -74
  12. package/lib/chat/display/FloatingBrandButton.js +8 -1
  13. package/lib/chat/header/ChatHeader.d.ts +3 -1
  14. package/lib/chat/header/ChatHeader.js +15 -12
  15. package/lib/chat/header/ChatHeaderBase.d.ts +29 -9
  16. package/lib/chat/header/ChatHeaderBase.js +26 -3
  17. package/lib/chat/indicators/SandboxStatusIndicator.js +82 -47
  18. package/lib/chat/messages/ChatMessageList.js +46 -1
  19. package/lib/chat/messages/ChatMessages.js +6 -2
  20. package/lib/chat/prompt/InputFooter.d.ts +3 -1
  21. package/lib/chat/prompt/InputFooter.js +8 -5
  22. package/lib/chat/prompt/InputPrompt.d.ts +3 -1
  23. package/lib/chat/prompt/InputPrompt.js +2 -2
  24. package/lib/chat/prompt/InputPromptFooter.d.ts +3 -1
  25. package/lib/chat/prompt/InputPromptFooter.js +3 -3
  26. package/lib/client/AgentsMixin.js +14 -0
  27. package/lib/config/AgentConfiguration.d.ts +22 -0
  28. package/lib/config/AgentConfiguration.js +319 -64
  29. package/lib/examples/AgUiSharedStateExample.js +2 -1
  30. package/lib/examples/AgentCheckpointsExample.js +3 -3
  31. package/lib/examples/AgentCodemodeExample.d.ts +3 -3
  32. package/lib/examples/AgentCodemodeExample.js +24 -12
  33. package/lib/examples/AgentEvalsExample.js +330 -40
  34. package/lib/examples/AgentGuardrailsExample.js +16 -5
  35. package/lib/examples/AgentHooksExample.js +27 -9
  36. package/lib/examples/AgentInferenceProviderExample.d.ts +3 -0
  37. package/lib/examples/AgentInferenceProviderExample.js +329 -0
  38. package/lib/examples/AgentMCPExample.js +6 -5
  39. package/lib/examples/AgentMemoryExample.d.ts +1 -2
  40. package/lib/examples/AgentMemoryExample.js +71 -22
  41. package/lib/examples/AgentMonitoringExample.js +5 -5
  42. package/lib/examples/AgentNotificationsExample.d.ts +1 -2
  43. package/lib/examples/AgentNotificationsExample.js +71 -22
  44. package/lib/examples/AgentOtelExample.js +31 -40
  45. package/lib/examples/AgentOutputsExample.d.ts +1 -1
  46. package/lib/examples/AgentOutputsExample.js +67 -16
  47. package/lib/examples/AgentParametersExample.js +10 -8
  48. package/lib/examples/AgentSandboxExample.d.ts +1 -1
  49. package/lib/examples/AgentSandboxExample.js +7 -6
  50. package/lib/examples/AgentSkillsExample.js +6 -6
  51. package/lib/examples/AgentSubagentsExample.d.ts +1 -1
  52. package/lib/examples/AgentSubagentsExample.js +6 -6
  53. package/lib/examples/AgentToolApprovalsExample.js +27 -11
  54. package/lib/examples/AgentTriggersExample.js +5 -5
  55. package/lib/examples/{AgentSpecsExample.d.ts → AgentspecsExample.d.ts} +2 -2
  56. package/lib/examples/AgentspecsExample.js +1096 -0
  57. package/lib/examples/ChatCustomExample.js +6 -5
  58. package/lib/examples/ChatExample.js +6 -5
  59. package/lib/examples/Lexical2Example.js +1 -1
  60. package/lib/examples/LexicalAgentExample.js +1 -1
  61. package/lib/examples/NotebookAgentExample.js +3 -3
  62. package/lib/examples/components/ExampleWrapper.d.ts +6 -7
  63. package/lib/examples/components/ExampleWrapper.js +27 -10
  64. package/lib/examples/example-selector.js +2 -1
  65. package/lib/examples/index.d.ts +2 -1
  66. package/lib/examples/index.js +2 -1
  67. package/lib/examples/lexical/initial-content.json +6 -6
  68. package/lib/examples/main.js +56 -16
  69. package/lib/examples/utils/agentId.d.ts +1 -1
  70. package/lib/examples/utils/agentId.js +1 -1
  71. package/lib/examples/utils/useExampleAgentRuntimesUrl.d.ts +5 -0
  72. package/lib/examples/utils/useExampleAgentRuntimesUrl.js +19 -0
  73. package/lib/hooks/useAIAgentsWebSocket.js +35 -0
  74. package/lib/hooks/useAgentRuntimes.d.ts +32 -3
  75. package/lib/hooks/useAgentRuntimes.js +114 -19
  76. package/lib/index.d.ts +1 -1
  77. package/lib/specs/agents/agents.d.ts +20 -13
  78. package/lib/specs/agents/agents.js +1267 -581
  79. package/lib/specs/benchmarks.d.ts +20 -0
  80. package/lib/specs/benchmarks.js +205 -0
  81. package/lib/specs/envvars.d.ts +0 -1
  82. package/lib/specs/envvars.js +0 -11
  83. package/lib/specs/evals.d.ts +10 -9
  84. package/lib/specs/evals.js +128 -88
  85. package/lib/specs/index.d.ts +0 -1
  86. package/lib/specs/index.js +0 -1
  87. package/lib/specs/models.d.ts +0 -2
  88. package/lib/specs/models.js +0 -15
  89. package/lib/specs/skills.d.ts +0 -1
  90. package/lib/specs/skills.js +0 -18
  91. package/lib/stores/agentRuntimeStore.d.ts +5 -1
  92. package/lib/stores/agentRuntimeStore.js +22 -8
  93. package/lib/stores/conversationStore.js +2 -2
  94. package/lib/types/agents-lifecycle.d.ts +18 -0
  95. package/lib/types/agents.d.ts +6 -0
  96. package/lib/types/agentspecs.d.ts +4 -0
  97. package/lib/types/benchmarks.d.ts +43 -0
  98. package/lib/types/benchmarks.js +5 -0
  99. package/lib/types/chat.d.ts +16 -0
  100. package/lib/types/evals.d.ts +26 -17
  101. package/lib/types/index.d.ts +1 -0
  102. package/lib/types/index.js +1 -0
  103. package/package.json +9 -5
  104. package/scripts/codegen/__pycache__/generate_agents.cpython-313.pyc +0 -0
  105. package/scripts/codegen/__pycache__/generate_benchmarks.cpython-313.pyc +0 -0
  106. package/scripts/codegen/__pycache__/generate_evals.cpython-313.pyc +0 -0
  107. package/scripts/codegen/generate_agents.py +89 -43
  108. package/scripts/codegen/generate_benchmarks.py +441 -0
  109. package/scripts/codegen/generate_evals.py +94 -16
  110. package/scripts/codegen/generate_events.py +0 -1
  111. package/lib/examples/AgentSpecsExample.js +0 -694
@@ -75,7 +75,7 @@ export interface AgentRuntimeStoreActions {
75
75
  setLoadedSkillsForAgent: (agentId: string, skills: LoadedSkillInfo[]) => void;
76
76
  getLoadedSkillsForAgent: (agentId: string) => LoadedSkillInfo[];
77
77
  clearLoadedSkillsForAgent: (agentId: string) => void;
78
- launchAgent: (options: IRuntimeOptions) => Promise<AgentConnection>;
78
+ launchAgent: (options: LaunchAgentOptions) => Promise<AgentConnection>;
79
79
  connectAgent: (connection: {
80
80
  podName: string;
81
81
  environmentName: string;
@@ -134,6 +134,10 @@ export interface AgentRuntimeStoreActions {
134
134
  resetWs: () => void;
135
135
  }
136
136
  export type AgentRuntimeStore = AgentRuntimeStoreState & AgentRuntimeStoreActions;
137
+ export interface LaunchAgentOptions extends IRuntimeOptions {
138
+ /** Optional runtimes API base URL override for runtime creation. */
139
+ runtimesRunUrl?: string;
140
+ }
137
141
  export declare const agentRuntimeStore: Omit<Omit<import("zustand").StoreApi<AgentRuntimeStore>, "subscribe"> & {
138
142
  subscribe: {
139
143
  (listener: (selectedState: AgentRuntimeStore, previousSelectedState: AgentRuntimeStore) => void): () => void;
@@ -89,6 +89,7 @@ const initialWsState = {
89
89
  monitoringCache: {},
90
90
  loadedSkillsByAgentId: {},
91
91
  };
92
+ const countPendingApprovals = (approvals) => approvals.filter(approval => approval.status === 'pending').length;
92
93
  // ---------------------------------------------------------------------------
93
94
  // Store
94
95
  // ---------------------------------------------------------------------------
@@ -233,13 +234,20 @@ export const agentRuntimeStore = createStore()(subscribeWithSelector(persist((se
233
234
  set({ status: 'launching', error: null, isLaunching: true });
234
235
  try {
235
236
  const { createRuntime } = await import('@datalayer/core/lib/api');
237
+ const { runtimesStore } = await import('@datalayer/core/lib/state');
238
+ if (config.runtimesRunUrl) {
239
+ runtimesStore.setState({
240
+ runtimesRunUrl: config.runtimesRunUrl,
241
+ });
242
+ }
243
+ const { runtimesRunUrl: _runtimesRunUrl, ...runtimeOptions } = config;
236
244
  const runtimePod = await createRuntime({
237
- environmentName: config.environmentName,
238
- creditsLimit: config.creditsLimit,
239
- type: config.type || 'notebook',
240
- givenName: config.givenName,
241
- capabilities: config.capabilities,
242
- snapshot: config.snapshot,
245
+ environmentName: runtimeOptions.environmentName,
246
+ creditsLimit: runtimeOptions.creditsLimit,
247
+ type: runtimeOptions.type || 'notebook',
248
+ givenName: runtimeOptions.givenName,
249
+ capabilities: runtimeOptions.capabilities,
250
+ snapshot: runtimeOptions.snapshot,
243
251
  });
244
252
  set({ status: 'connecting' });
245
253
  const jupyterBaseUrl = runtimePod.ingress;
@@ -316,11 +324,17 @@ export const agentRuntimeStore = createStore()(subscribeWithSelector(persist((se
316
324
  upsertApproval: approval => set(state => {
317
325
  const filtered = state.approvals.filter(a => a.id !== approval.id);
318
326
  const approvals = [approval, ...filtered];
319
- return { approvals, pendingApprovalCount: approvals.length };
327
+ return {
328
+ approvals,
329
+ pendingApprovalCount: countPendingApprovals(approvals),
330
+ };
320
331
  }),
321
332
  removeApproval: approvalId => set(state => {
322
333
  const approvals = state.approvals.filter(a => a.id !== approvalId);
323
- return { approvals, pendingApprovalCount: approvals.length };
334
+ return {
335
+ approvals,
336
+ pendingApprovalCount: countPendingApprovals(approvals),
337
+ };
324
338
  }),
325
339
  sendDecision: (approvalId, approved, note, toolCallId, agentId) => {
326
340
  const targetWs = _resolveWs(agentId);
@@ -8,8 +8,8 @@
8
8
  *
9
9
  * Key features:
10
10
  * - Messages are stored per runtime ID in memory
11
- * - On page reload, messages are fetched from the server API
12
- * - No browser storage persistence - server is the source of truth
11
+ * - On page reload, messages are synchronized from the runtime via websocket
12
+ * - No browser storage persistence - runtime is the source of truth
13
13
  *
14
14
  * @module store/conversationStore
15
15
  */
@@ -18,6 +18,24 @@ export type CreateAgentRuntimeRequest = {
18
18
  agentSpecId?: string;
19
19
  /** Full agent spec payload to propagate to backend services */
20
20
  agentSpec?: Record<string, any>;
21
+ /** Account UID (user or organization) charged for runtime costs */
22
+ billableAccountUid?: string;
23
+ /** User account handle used for user home mount path. */
24
+ userAccountHandle?: string;
25
+ /** Account kind charged for runtime costs. */
26
+ billableAccountType?: 'user' | 'organization' | 'team';
27
+ /** Account handle charged for runtime costs. */
28
+ billableAccountHandle?: string;
29
+ /** Source organization UID for team-billed runtimes. */
30
+ billableSourceOrganizationUid?: string;
31
+ /** Source organization handle for team-billed runtimes. */
32
+ billableSourceOrganizationHandle?: string;
33
+ /** Mount account home folder into runtime. */
34
+ mountHomeFolder?: boolean;
35
+ /** Optional volume UID to mount into runtime. */
36
+ volumeUid?: string;
37
+ /** Optional volume UIDs to mount into runtime. */
38
+ volumeUids?: string[];
21
39
  };
22
40
  export type CreateRuntimeApiResponse = {
23
41
  success?: boolean;
@@ -53,6 +53,12 @@ export type AgentRuntimeData = {
53
53
  token?: string;
54
54
  agentSpec?: AgentSpec;
55
55
  agent_spec_id?: string;
56
+ billable_account_uid?: string;
57
+ billable_account_type?: 'user' | 'organization' | 'team';
58
+ billable_account_handle?: string;
59
+ mount_home_folder?: boolean;
60
+ volume_uid?: string;
61
+ volume_uids?: string[];
56
62
  };
57
63
  export interface RunningAgent {
58
64
  /** Unique agent ID within the runtime */
@@ -33,6 +33,8 @@ export interface AgentSpec {
33
33
  enabled: boolean;
34
34
  /** AI model identifier to use for this agent */
35
35
  model?: string;
36
+ /** Inference provider routing strategy */
37
+ inferenceProvider?: 'local' | 'datalayer';
36
38
  /** MCP servers used by this agent */
37
39
  mcpServers: MCPServer[];
38
40
  /** Skills available to this agent */
@@ -96,6 +98,8 @@ export interface AgentSpec {
96
98
  postHooks?: {
97
99
  sandbox?: string | string[];
98
100
  };
101
+ /** Per-tool-call hooks (authorization/audit integration). */
102
+ toolHooks?: Record<string, any>;
99
103
  /** JSON schema for launch-time parameter values. */
100
104
  parameters?: Record<string, any>;
101
105
  /** Subagent delegation configuration. */
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Evaluation benchmark specification.
3
+ */
4
+ export interface BenchmarkSpec {
5
+ /** Unique benchmark identifier */
6
+ id: string;
7
+ /** Version */
8
+ version?: string;
9
+ /** Display name */
10
+ name: string;
11
+ /** Description of the benchmark */
12
+ description: string;
13
+ /** Category: Coding, Knowledge, Reasoning, Agentic, or Safety */
14
+ category: 'Coding' | 'Knowledge' | 'Reasoning' | 'Agentic' | 'Safety';
15
+ /** Number of tasks in the benchmark */
16
+ task_count: number;
17
+ /** Primary metric (e.g., 'pass@1', 'accuracy', 'success_rate') */
18
+ metric: string;
19
+ /** Source URL or repository */
20
+ source: string;
21
+ /** Difficulty level */
22
+ difficulty: 'easy' | 'medium' | 'hard' | 'expert';
23
+ /** Relevant languages */
24
+ languages: string[];
25
+ /** Dataset source mode used by this benchmark */
26
+ dataset_source?: 'hosted' | 'local' | 'hybrid';
27
+ /** Whether this benchmark can be tracked in live monitoring */
28
+ supports_live_monitoring?: boolean;
29
+ /** Whether this benchmark supports side-by-side run comparison */
30
+ supports_experiment_comparison?: boolean;
31
+ /** Shapes emitted by evaluators (pass_rate, numeric, categorical, error_only) */
32
+ evaluator_shapes?: Array<'pass_rate' | 'numeric' | 'categorical' | 'error_only'>;
33
+ /** Evaluator IDs (optionally versioned) used to score this benchmark */
34
+ evaluators: string[];
35
+ /** Suggested time windows for monitoring UIs */
36
+ recommended_windows?: string[];
37
+ /** Whether traces include links from results to execution spans */
38
+ trace_integration?: boolean;
39
+ /** Whether cases are editable in hosted UI */
40
+ dataset_editability?: 'read-only' | 'editable';
41
+ /** SDK maturity level for this benchmark */
42
+ sdk_support?: 'none' | 'experimental' | 'stable';
43
+ }
@@ -0,0 +1,5 @@
1
+ /*
2
+ * Copyright (c) 2025-2026 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ export {};
@@ -462,6 +462,22 @@ export interface ChatBaseProps {
462
462
  loadingState?: React.ReactNode;
463
463
  /** Header actions */
464
464
  headerActions?: React.ReactNode;
465
+ /** Notebook kernel indicator state override for the chat header. */
466
+ kernelIndicatorState?: import('@datalayer/jupyter-react').ExecutionState;
467
+ /**
468
+ * Live notebook kernel connection. When provided, the chat header
469
+ * renders the same `<KernelIndicator>` as the notebook toolbar so
470
+ * the colour and tooltip remain in sync with the notebook runtime.
471
+ */
472
+ kernel?: import('@jupyterlab/services/lib/kernel/kernel').IKernelConnection | null;
473
+ /** Optional environment name displayed in kernel indicator details. */
474
+ kernelEnvironmentName?: string;
475
+ /** Optional CPU info displayed in kernel indicator details. */
476
+ kernelCpu?: string;
477
+ /** Optional memory info displayed in kernel indicator details. */
478
+ kernelMemory?: string;
479
+ /** Optional GPU info displayed in kernel indicator details. */
480
+ kernelGpu?: string;
465
481
  /**
466
482
  * Current chat view mode.
467
483
  * When provided, a segmented view-mode toggle is rendered in the header
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Evaluation benchmark specification.
2
+ * Built-in evaluator specification.
3
3
  */
4
4
  export interface EvalSpec {
5
5
  /** Unique eval identifier */
@@ -8,20 +8,26 @@ export interface EvalSpec {
8
8
  version?: string;
9
9
  /** Display name */
10
10
  name: string;
11
- /** Description of the evaluation */
11
+ /** Description of the evaluator */
12
12
  description: string;
13
- /** Category: Coding, Knowledge, Reasoning, Agentic, or Safety */
14
- category: 'Coding' | 'Knowledge' | 'Reasoning' | 'Agentic' | 'Safety';
15
- /** Number of tasks in the benchmark */
16
- task_count: number;
17
- /** Primary metric (e.g., 'pass@1', 'accuracy', 'success_rate') */
18
- metric: string;
19
- /** Source URL or repository */
13
+ /** Evaluator family */
14
+ category: 'Comparison' | 'Type Validation' | 'Performance' | 'LLM-as-a-Judge' | 'Span-Based' | 'Report';
15
+ /** Case-level or report-level evaluator */
16
+ evaluator_type: 'case' | 'report';
17
+ /** Pydantic evaluator class name */
18
+ pydantic_class: string;
19
+ /** Primary output shape */
20
+ output_kind: 'boolean' | 'boolean_with_reason' | 'score' | 'score_and_assertion' | 'report_table' | 'report_curve';
21
+ /** Cost tier for running this evaluator */
22
+ cost_tier: 'free' | 'llm';
23
+ /** Expected latency profile */
24
+ latency: 'instant' | 'fast' | 'slow';
25
+ /** Runtime requirements (e.g. expected_output, logfire, model) */
26
+ requires?: string[];
27
+ /** Source documentation URL */
20
28
  source: string;
21
- /** Difficulty level */
22
- difficulty: 'easy' | 'medium' | 'hard' | 'expert';
23
- /** Relevant languages */
24
- languages: string[];
29
+ /** Suggested baseline configuration */
30
+ default_config?: Record<string, unknown>;
25
31
  }
26
32
  /**
27
33
  * Eval configuration for an agent spec.
@@ -31,11 +37,14 @@ export interface AgentEvalConfig {
31
37
  name?: string;
32
38
  description?: string;
33
39
  category?: string;
34
- task_count?: number;
35
- metric?: string;
40
+ evaluator_type?: string;
41
+ pydantic_class?: string;
42
+ output_kind?: string;
43
+ cost_tier?: string;
44
+ latency?: string;
45
+ requires?: string[];
36
46
  source?: string;
37
- difficulty?: string;
38
- languages?: string[];
47
+ default_config?: Record<string, unknown>;
39
48
  [key: string]: unknown;
40
49
  }
41
50
  export interface EvalReport {
@@ -4,6 +4,7 @@ export * from './ag-ui';
4
4
  export * from './agents';
5
5
  export * from './agents-lifecycle';
6
6
  export * from './agentspecs';
7
+ export * from './benchmarks';
7
8
  export * from './chat';
8
9
  export * from './checkpoints';
9
10
  export * from './config';
@@ -8,6 +8,7 @@ export * from './ag-ui';
8
8
  export * from './agents';
9
9
  export * from './agents-lifecycle';
10
10
  export * from './agentspecs';
11
+ export * from './benchmarks';
11
12
  export * from './chat';
12
13
  export * from './checkpoints';
13
14
  export * from './config';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datalayer/agent-runtimes",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "type": "module",
5
5
  "workspaces": [
6
6
  ".",
@@ -68,10 +68,11 @@
68
68
  "clean:lib": "rimraf lib tsconfig.tsbuildinfo",
69
69
  "create:patches": "bash scripts/create-patches.sh",
70
70
  "examples": "run-p server:start server:start:codemode jupyter:start examples:vite",
71
+ "examples:proxy": "make examples:proxy",
71
72
  "examples:fresh": "npm run clean:cache && npm run examples",
72
73
  "examples:jupyter": "run-p jupyter:start server:start server:start:codemode examples:vite",
73
74
  "examples:nextjs": "npm run dev --workspace=nextjs-notebook-example",
74
- "examples:vite": "VITE_APP_TARGET=examples VITE_DATALAYER_RUN_URL=http://localhost:8888 vite",
75
+ "examples:vite": "VITE_DATALAYER_RUN_URL=${VITE_DATALAYER_RUN_URL:-https://prod1.datalayer.run} VITE_DATALAYER_RUNTIMES_URL=${VITE_DATALAYER_RUNTIMES_URL:-https://r1.datalayer.run} VITE_DATALAYER_AGENT_RUNTIMES_URL=${VITE_DATALAYER_AGENT_RUNTIMES_URL:-https://r1.datalayer.run} VITE_APP_TARGET=examples vite",
75
76
  "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css,json,md}\" \"examples/**/*.{js,jsx,ts,tsx,css,json,md,mjs}\"",
76
77
  "format:all": "npm run format && npm run format --workspaces --if-present",
77
78
  "format:check": "prettier --check \"src/**/*.{js,jsx,ts,tsx,css,json,md}\" \"examples/**/*.{js,jsx,ts,tsx,css,json,md,mjs}\"",
@@ -89,8 +90,9 @@
89
90
  "preview": "vite preview",
90
91
  "rebuild:fresh": "npm run create:patches && npm install && npm run build && npm run clean:cache",
91
92
  "server": "python -m agent_runtimes serve",
92
- "server:start": "PYTHONIOENCODING=utf-8 AGENT_RUNTIMES_DEBUG=false AGENT_RUNTIMES_LOG_LEVEL=info python -m agent_runtimes serve --port 8765 --log-level info",
93
- "server:start:codemode": "PYTHONIOENCODING=utf-8 AGENT_RUNTIMES_DEBUG=false AGENT_RUNTIMES_LOG_LEVEL=info python -m agent_runtimes serve --port 8766 --log-level info",
93
+ "server:start": "PYTHONIOENCODING=utf-8 AGENT_RUNTIMES_DEBUG=false AGENT_RUNTIMES_LOG_LEVEL=info DATALAYER_EVALS_MODE=interactive DATALAYER_EVALS_EMIT_LIVE_EVENTS=true python -m agent_runtimes serve --port 8765 --log-level info",
94
+ "server:start:agent-node": "PYTHONIOENCODING=utf-8 AGENT_RUNTIMES_DEBUG=false AGENT_RUNTIMES_LOG_LEVEL=info DATALAYER_EVALS_MODE=interactive DATALAYER_EVALS_EMIT_LIVE_EVENTS=true AGENT_RUNTIMES_INFERENCE_PROVIDER_OVERRIDE=${AGENT_RUNTIMES_INFERENCE_PROVIDER_OVERRIDE:-datalayer} python -m agent_runtimes serve --node --port 8765 --log-level info",
95
+ "server:start:codemode": "PYTHONIOENCODING=utf-8 AGENT_RUNTIMES_DEBUG=false AGENT_RUNTIMES_LOG_LEVEL=info DATALAYER_EVALS_MODE=interactive DATALAYER_EVALS_EMIT_LIVE_EVENTS=true python -m agent_runtimes serve --port 8766 --log-level info",
94
96
  "examples:codemode": "run-p server:start server:start:codemode examples:vite",
95
97
  "start": "vite",
96
98
  "start:acp": "run-p server:start start:acp:vite",
@@ -98,6 +100,8 @@
98
100
  "start:acp:vite": "VITE_ACP_WS_URL=ws://localhost:8765/api/v1/acp/ws vite",
99
101
  "start:agent": "run-p server:start start:agent:vite",
100
102
  "start:agent:vite": "vite --open /html/agent.html",
103
+ "start:agent-node": "run-p server:start:agent-node start:agent-node:vite",
104
+ "start:agent-node:vite": "vite --open /html/agent-node.html",
101
105
  "start:agent-notebook": "run-p server:start jupyter:start start:agent-notebook:vite",
102
106
  "start:agent-notebook:vite": "vite --open /html/agent-notebook.html",
103
107
  "start:agent-lexical": "run-p server:start jupyter:start start:agent-lexical:vite",
@@ -130,7 +134,7 @@
130
134
  "@agentclientprotocol/sdk": "^0.8.0",
131
135
  "@ai-sdk/react": "^4.0.0-beta.33",
132
136
  "@anthropic-ai/sdk": "^0.52.0",
133
- "@datalayer/core": "^1.0.20",
137
+ "@datalayer/core": "^1.0.22",
134
138
  "@datalayer/icons-react": "^1.0.7",
135
139
  "@datalayer/jupyter-lexical": "^1.0.16",
136
140
  "@datalayer/jupyter-react": "^2.0.7",
@@ -11,6 +11,7 @@ Generates Python and TypeScript code from YAML agent specifications.
11
11
  import argparse
12
12
  import json
13
13
  import sys
14
+ from copy import deepcopy
14
15
  from pathlib import Path
15
16
  from typing import Any, Dict, List
16
17
 
@@ -82,6 +83,30 @@ def _normalize_subagents_for_typescript(value: Any) -> Any:
82
83
  return normalized
83
84
 
84
85
 
86
+ def _sanitize_tool_hooks_for_codegen(value: Any) -> Any:
87
+ """Normalize tool hook paths that would trigger bandit in generated code."""
88
+ if not isinstance(value, dict):
89
+ return value
90
+
91
+ tool_hooks = deepcopy(value)
92
+ for key in ("audit_log_path", "auditLogPath"):
93
+ raw_path = tool_hooks.get(key)
94
+ if isinstance(raw_path, str):
95
+ raw_parts = Path(raw_path).parts
96
+ if len(raw_parts) >= 3 and raw_parts[0] == "/" and raw_parts[1] == "tmp":
97
+ tool_hooks[key] = Path(raw_path).name
98
+ return tool_hooks
99
+
100
+
101
+ def _sanitize_spec_for_codegen(spec: Dict[str, Any]) -> Dict[str, Any]:
102
+ """Return a spec copy sanitized for generated Python/TypeScript outputs."""
103
+ sanitized = deepcopy(spec)
104
+ sanitized["tool_hooks"] = _sanitize_tool_hooks_for_codegen(
105
+ sanitized.get("tool_hooks")
106
+ )
107
+ return sanitized
108
+
109
+
85
110
  def load_yaml_specs(specs_dir: Path) -> List[tuple[str, Dict[str, Any]]]:
86
111
  """
87
112
  Load all YAML agent specifications from directory and subdirectories.
@@ -161,6 +186,7 @@ from agent_runtimes.types import AgentSpec, SubAgentSpecConfig, SubAgentsConfig
161
186
  code += f"# {'=' * 76}\n\n"
162
187
 
163
188
  for spec in folder_specs:
189
+ spec = _sanitize_spec_for_codegen(spec)
164
190
  agent_id = spec["id"]
165
191
  version = spec["version"]
166
192
  # Prefix agent ID with folder name for uniqueness
@@ -248,6 +274,10 @@ from agent_runtimes.types import AgentSpec, SubAgentSpecConfig, SubAgentsConfig
248
274
  # Model field
249
275
  model_id = spec.get("model")
250
276
  model_str = f'"{model_id}"' if model_id else "None"
277
+ inference_provider = spec.get("inference_provider")
278
+ inference_provider_str = (
279
+ f'"{inference_provider}"' if inference_provider else "None"
280
+ )
251
281
 
252
282
  # Sandbox variant field
253
283
  sandbox_variant = spec.get("sandbox_variant")
@@ -280,6 +310,7 @@ from agent_runtimes.types import AgentSpec, SubAgentSpecConfig, SubAgentsConfig
280
310
  memory_str = f'"{memory_val}"' if memory_val else "None"
281
311
  pre_hooks_val = spec.get("pre_hooks")
282
312
  post_hooks_val = spec.get("post_hooks")
313
+ tool_hooks_val = spec.get("tool_hooks")
283
314
  parameters_val = spec.get("parameters")
284
315
  subagents_val = spec.get("subagents")
285
316
 
@@ -329,6 +360,7 @@ from agent_runtimes.types import AgentSpec, SubAgentSpecConfig, SubAgentsConfig
329
360
  tags={_fmt_list(spec.get("tags", []))},
330
361
  enabled={spec.get("enabled", True)},
331
362
  model={model_str},
363
+ inference_provider={inference_provider_str},
332
364
  mcp_servers=[{mcp_servers_str}],
333
365
  skills={_fmt_list(skill_refs)},
334
366
  tools={_fmt_list(tool_refs)},
@@ -360,6 +392,7 @@ from agent_runtimes.types import AgentSpec, SubAgentSpecConfig, SubAgentsConfig
360
392
  memory={memory_str},
361
393
  pre_hooks={_fmt_py_literal(pre_hooks_val)},
362
394
  post_hooks={_fmt_py_literal(post_hooks_val)},
395
+ tool_hooks={_fmt_py_literal(tool_hooks_val)},
363
396
  parameters={_fmt_py_literal(parameters_val)},
364
397
  subagents={subagents_str},
365
398
  )
@@ -649,15 +682,15 @@ const SKILL_MAP: Record<string, any> = {
649
682
  code += "};\n"
650
683
  code += """
651
684
  function toAgentSkillSpec(skill: SkillSpec) {
652
- return {
653
- id: skill.id,
654
- name: skill.name,
655
- description: skill.description,
685
+ return {
686
+ id: skill.id,
687
+ name: skill.name,
688
+ description: skill.description,
656
689
  version: skill.version ?? '0.0.1',
657
- tags: skill.tags,
658
- enabled: skill.enabled,
659
- requiredEnvVars: skill.requiredEnvVars,
660
- };
690
+ tags: skill.tags,
691
+ enabled: skill.enabled,
692
+ requiredEnvVars: skill.requiredEnvVars,
693
+ };
661
694
  }
662
695
  """
663
696
 
@@ -714,6 +747,7 @@ const FRONTEND_TOOL_MAP: Record<string, any> = {
714
747
  code += f"// {'=' * 76}\n\n"
715
748
 
716
749
  for spec in folder_specs:
750
+ spec = _sanitize_spec_for_codegen(spec)
717
751
  agent_id = spec["id"]
718
752
  version = spec["version"]
719
753
  # Prefix agent ID with folder name for uniqueness
@@ -748,7 +782,8 @@ const FRONTEND_TOOL_MAP: Record<string, any> = {
748
782
  ]
749
783
  if has_skills and skill_ids_list:
750
784
  skills_str = ", ".join(
751
- f"toAgentSkillSpec(SKILL_MAP['{sid}'])" for sid in skill_ids_list
785
+ f"(SKILL_MAP['{sid}'] ? toAgentSkillSpec(SKILL_MAP['{sid}']) : undefined)"
786
+ for sid in skill_ids_list
752
787
  )
753
788
  else:
754
789
  skills_str = ""
@@ -816,6 +851,10 @@ const FRONTEND_TOOL_MAP: Record<string, any> = {
816
851
  # Model field
817
852
  model_id = spec.get("model")
818
853
  model_ts = f"'{model_id}'" if model_id else "undefined"
854
+ inference_provider = spec.get("inference_provider")
855
+ inference_provider_ts = (
856
+ f"'{inference_provider}'" if inference_provider else "undefined"
857
+ )
819
858
 
820
859
  # Sandbox variant field
821
860
  sandbox_variant = spec.get("sandbox_variant")
@@ -851,53 +890,60 @@ const FRONTEND_TOOL_MAP: Record<string, any> = {
851
890
  memory_ts = f"'{memory_val}'" if memory_val else "undefined"
852
891
  pre_hooks_val = spec.get("pre_hooks")
853
892
  post_hooks_val = spec.get("post_hooks")
893
+ tool_hooks_val = spec.get("tool_hooks")
854
894
  parameters_val = spec.get("parameters")
855
895
  subagents_val = spec.get("subagents")
856
896
  subagents_ts = _fmt_ts_literal(
857
897
  _normalize_subagents_for_typescript(subagents_val)
858
898
  )
899
+ inference_provider_line = (
900
+ f" inferenceProvider: {inference_provider_ts},\n"
901
+ if inference_provider
902
+ else ""
903
+ )
859
904
 
860
905
  code += f"""export const {const_name}: AgentSpec = {{
861
- id: '{full_agent_id}',
906
+ id: '{full_agent_id}',
862
907
  version: '{version}',
863
- name: '{spec["name"]}',
864
- description: `{description}`,
865
- tags: {tags_str},
866
- enabled: {str(spec.get("enabled", True)).lower()},
867
- model: {model_ts},
868
- mcpServers: [{mcp_servers_str}],
869
- skills: [{skills_str}],
908
+ name: '{spec["name"]}',
909
+ description: `{description}`,
910
+ tags: {tags_str},
911
+ enabled: {str(spec.get("enabled", True)).lower()},
912
+ model: {model_ts},
913
+ {inference_provider_line} mcpServers: [{mcp_servers_str}],
914
+ skills: [{skills_str}].filter(Boolean) as SkillSpec[],
870
915
  tools: [{tools_str}],
871
916
  frontendTools: [{frontend_tools_str}],
872
- environmentName: '{spec.get("environment_name", "ai-agents-env")}',
873
- icon: {icon},
874
- emoji: {emoji},
875
- color: {color},
876
- suggestions: {suggestions_str},
917
+ environmentName: '{spec.get("environment_name", "ai-agents-env")}',
918
+ icon: {icon},
919
+ emoji: {emoji},
920
+ color: {color},
921
+ suggestions: {suggestions_str},
877
922
  welcomeMessage: {_fmt_ts_literal(welcome_message)},
878
923
  welcomeNotebook: {_fmt_ts_literal(welcome_notebook)},
879
924
  welcomeDocument: {_fmt_ts_literal(welcome_document)},
880
- sandboxVariant: {sandbox_variant_ts},
881
- systemPrompt: {f"`{system_prompt}`" if system_prompt else "undefined"},
882
- systemPromptCodemodeAddons: {f"`{system_prompt_codemode_addons}`" if system_prompt_codemode_addons else "undefined"},
883
- goal: {goal_ts},
884
- protocol: {protocol_ts},
885
- uiExtension: {ui_ext_ts},
886
- trigger: {_fmt_ts_literal(trigger_val)},
887
- modelConfig: {_fmt_ts_literal(model_cfg)},
888
- mcpServerTools: {_fmt_ts_literal(mcp_srv_tools)},
889
- guardrails: {_fmt_ts_literal(guardrails_val)},
890
- evals: {_fmt_ts_literal(evals_val)},
891
- codemode: {_fmt_ts_literal(codemode_val)},
892
- output: {_fmt_ts_literal(output_val)},
893
- advanced: {_fmt_ts_literal(advanced_val)},
894
- authorizationPolicy: {auth_policy_ts},
895
- notifications: {_fmt_ts_literal(notifs)},
896
- memory: {memory_ts},
897
- preHooks: {_fmt_ts_literal(pre_hooks_val)},
898
- postHooks: {_fmt_ts_literal(post_hooks_val)},
899
- parameters: {_fmt_ts_literal(parameters_val)},
900
- subagents: {subagents_ts},
925
+ sandboxVariant: {sandbox_variant_ts},
926
+ systemPrompt: {f"`{system_prompt}`" if system_prompt else "undefined"},
927
+ systemPromptCodemodeAddons: {f"`{system_prompt_codemode_addons}`" if system_prompt_codemode_addons else "undefined"},
928
+ goal: {goal_ts},
929
+ protocol: {protocol_ts},
930
+ uiExtension: {ui_ext_ts},
931
+ trigger: {_fmt_ts_literal(trigger_val)},
932
+ modelConfig: {_fmt_ts_literal(model_cfg)},
933
+ mcpServerTools: {_fmt_ts_literal(mcp_srv_tools)},
934
+ guardrails: {_fmt_ts_literal(guardrails_val)},
935
+ evals: {_fmt_ts_literal(evals_val)},
936
+ codemode: {_fmt_ts_literal(codemode_val)},
937
+ output: {_fmt_ts_literal(output_val)},
938
+ advanced: {_fmt_ts_literal(advanced_val)},
939
+ authorizationPolicy: {auth_policy_ts},
940
+ notifications: {_fmt_ts_literal(notifs)},
941
+ memory: {memory_ts},
942
+ preHooks: {_fmt_ts_literal(pre_hooks_val)},
943
+ postHooks: {_fmt_ts_literal(post_hooks_val)},
944
+ toolHooks: {_fmt_ts_literal(tool_hooks_val)},
945
+ parameters: {_fmt_ts_literal(parameters_val)},
946
+ subagents: {subagents_ts},
901
947
  }};
902
948
 
903
949
  """