@datalayer/agent-runtimes 1.0.4 → 1.0.5
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.
- package/README.md +34 -0
- package/lib/App.js +1 -1
- package/lib/agents/AgentDetails.d.ts +22 -1
- package/lib/agents/AgentDetails.js +34 -47
- package/lib/api/index.d.ts +0 -1
- package/lib/api/index.js +4 -2
- package/lib/chat/Chat.d.ts +5 -106
- package/lib/chat/Chat.js +4 -4
- package/lib/chat/ChatFloating.d.ts +7 -140
- package/lib/chat/ChatFloating.js +2 -2
- package/lib/chat/ChatPopupStandalone.d.ts +8 -47
- package/lib/chat/ChatPopupStandalone.js +3 -3
- package/lib/chat/ChatSidebar.d.ts +4 -69
- package/lib/chat/ChatSidebar.js +2 -2
- package/lib/chat/ChatStandalone.d.ts +4 -54
- package/lib/chat/ChatStandalone.js +3 -3
- package/lib/chat/base/ChatBase.js +1083 -157
- package/lib/chat/header/ChatHeaderBase.d.ts +11 -6
- package/lib/chat/header/ChatHeaderBase.js +18 -16
- package/lib/chat/indicators/McpStatusIndicator.d.ts +7 -4
- package/lib/chat/indicators/McpStatusIndicator.js +7 -32
- package/lib/chat/indicators/SandboxStatusIndicator.d.ts +4 -1
- package/lib/chat/indicators/SandboxStatusIndicator.js +9 -9
- package/lib/chat/indicators/SkillsStatusIndicator.d.ts +7 -0
- package/lib/chat/indicators/SkillsStatusIndicator.js +88 -0
- package/lib/chat/indicators/index.d.ts +1 -0
- package/lib/chat/indicators/index.js +1 -0
- package/lib/chat/messages/ChatMessageList.d.ts +1 -1
- package/lib/chat/messages/ChatMessageList.js +108 -113
- package/lib/chat/prompt/InputFooter.d.ts +19 -6
- package/lib/chat/prompt/InputFooter.js +71 -18
- package/lib/chat/prompt/InputPrompt.d.ts +3 -1
- package/lib/chat/prompt/InputPrompt.js +4 -4
- package/lib/chat/prompt/InputPromptFooter.js +1 -1
- package/lib/chat/prompt/InputPromptLexical.d.ts +3 -1
- package/lib/chat/prompt/InputPromptLexical.js +12 -5
- package/lib/chat/prompt/InputPromptText.d.ts +3 -1
- package/lib/chat/prompt/InputPromptText.js +2 -2
- package/lib/chat/tools/ToolApprovalBanner.js +1 -1
- package/lib/chat/tools/ToolCallDisplay.d.ts +3 -1
- package/lib/chat/tools/ToolCallDisplay.js +2 -2
- package/lib/chat/usage/TokenUsageBar.js +20 -2
- package/lib/client/AgentRuntimesClientContext.d.ts +53 -0
- package/lib/client/AgentRuntimesClientContext.js +55 -0
- package/lib/client/AgentsMixin.d.ts +0 -18
- package/lib/client/AgentsMixin.js +6 -30
- package/lib/client/IAgentRuntimesClient.d.ts +215 -0
- package/lib/client/IAgentRuntimesClient.js +5 -0
- package/lib/client/SdkAgentRuntimesClient.d.ts +151 -0
- package/lib/client/SdkAgentRuntimesClient.js +134 -0
- package/lib/client/index.d.ts +4 -1
- package/lib/client/index.js +3 -1
- package/lib/components/NotificationEventCard.js +5 -1
- package/lib/config/AgentConfiguration.js +3 -3
- package/lib/context/ContextDistribution.d.ts +3 -1
- package/lib/context/ContextDistribution.js +8 -27
- package/lib/context/ContextInspector.d.ts +3 -1
- package/lib/context/ContextInspector.js +19 -67
- package/lib/context/ContextPanel.d.ts +3 -1
- package/lib/context/ContextPanel.js +104 -64
- package/lib/context/ContextUsage.d.ts +3 -1
- package/lib/context/ContextUsage.js +3 -3
- package/lib/context/CostTracker.d.ts +9 -3
- package/lib/context/CostTracker.js +26 -47
- package/lib/context/CostUsageChart.d.ts +12 -0
- package/lib/context/CostUsageChart.js +378 -0
- package/lib/context/GraphFlowChart.d.ts +16 -0
- package/lib/context/GraphFlowChart.js +182 -0
- package/lib/context/TokenUsageChart.d.ts +8 -1
- package/lib/context/TokenUsageChart.js +349 -211
- package/lib/context/TurnGraphChart.d.ts +39 -0
- package/lib/context/TurnGraphChart.js +538 -0
- package/lib/context/otelWsPool.d.ts +20 -0
- package/lib/context/otelWsPool.js +69 -0
- package/lib/examples/A2UiComponentGalleryExample.d.ts +0 -17
- package/lib/examples/A2UiComponentGalleryExample.js +315 -522
- package/lib/examples/A2UiContactCardExample.d.ts +0 -18
- package/lib/examples/A2UiContactCardExample.js +154 -411
- package/lib/examples/A2UiRestaurantExample.d.ts +0 -30
- package/lib/examples/A2UiRestaurantExample.js +114 -212
- package/lib/examples/A2UiViewerExample.d.ts +0 -18
- package/lib/examples/A2UiViewerExample.js +283 -532
- package/lib/examples/AgUiBackendToolRenderingExample.js +1 -1
- package/lib/examples/AgUiHaikuGenUiExample.d.ts +1 -1
- package/lib/examples/AgUiHaikuGenUiExample.js +1 -1
- package/lib/examples/AgentCheckpointsExample.js +13 -27
- package/lib/examples/AgentCodemodeExample.d.ts +4 -6
- package/lib/examples/AgentCodemodeExample.js +591 -169
- package/lib/examples/AgentEvalsExample.js +12 -16
- package/lib/examples/AgentGuardrailsExample.js +370 -64
- package/lib/examples/AgentHooksExample.d.ts +3 -0
- package/lib/examples/AgentHooksExample.js +104 -0
- package/lib/examples/AgentMCPExample.d.ts +3 -0
- package/lib/examples/AgentMCPExample.js +480 -0
- package/lib/examples/AgentMemoryExample.js +13 -17
- package/lib/examples/AgentMonitoringExample.js +260 -199
- package/lib/examples/AgentNotificationsExample.js +49 -17
- package/lib/examples/AgentOtelExample.js +2 -3
- package/lib/examples/AgentOutputsExample.d.ts +11 -6
- package/lib/examples/AgentOutputsExample.js +382 -81
- package/lib/examples/AgentParametersExample.d.ts +3 -0
- package/lib/examples/AgentParametersExample.js +246 -0
- package/lib/examples/AgentSandboxExample.d.ts +2 -2
- package/lib/examples/AgentSandboxExample.js +68 -40
- package/lib/examples/AgentSkillsExample.js +91 -99
- package/lib/examples/{AgentspecExample.js → AgentSpecsExample.js} +10 -21
- package/lib/examples/AgentSubagentsExample.d.ts +14 -0
- package/lib/examples/AgentSubagentsExample.js +228 -0
- package/lib/examples/AgentToolApprovalsExample.js +29 -557
- package/lib/examples/AgentTriggersExample.js +819 -565
- package/lib/examples/ChatCustomExample.js +11 -24
- package/lib/examples/ChatExample.js +7 -24
- package/lib/examples/CopilotKitLexicalExample.js +2 -1
- package/lib/examples/CopilotKitNotebookExample.js +2 -1
- package/lib/examples/HomeExample.d.ts +15 -0
- package/lib/examples/HomeExample.js +77 -0
- package/lib/examples/Lexical2Example.js +4 -2
- package/lib/examples/{LexicalExample.d.ts → LexicalAgentExample.d.ts} +4 -4
- package/lib/examples/{LexicalExample.js → LexicalAgentExample.js} +65 -16
- package/lib/examples/{LexicalSidebarExample.d.ts → LexicalAgentSidebarExample.d.ts} +5 -5
- package/lib/examples/LexicalAgentSidebarExample.js +261 -0
- package/lib/examples/NotebookAgentExample.d.ts +9 -0
- package/lib/examples/NotebookAgentExample.js +192 -0
- package/lib/examples/{NotebookSidebarExample.d.ts → NotebookAgentSidebarExample.d.ts} +2 -2
- package/lib/examples/NotebookAgentSidebarExample.js +221 -0
- package/lib/examples/{DatalayerNotebookExample.d.ts → NotebookCollaborationExample.d.ts} +4 -4
- package/lib/examples/{DatalayerNotebookExample.js → NotebookCollaborationExample.js} +3 -3
- package/lib/examples/NotebookExample.d.ts +4 -7
- package/lib/examples/NotebookExample.js +14 -146
- package/lib/examples/components/AuthRequiredView.d.ts +6 -0
- package/lib/examples/components/AuthRequiredView.js +33 -0
- package/lib/examples/components/ExampleWrapper.d.ts +7 -0
- package/lib/examples/components/ExampleWrapper.js +25 -6
- package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.js +1 -1
- package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.js +1 -1
- package/lib/examples/{ag-ui → components}/haiku/index.d.ts +1 -1
- package/lib/examples/{ag-ui → components}/haiku/index.js +1 -1
- package/lib/examples/components/index.d.ts +3 -0
- package/lib/examples/components/index.js +4 -0
- package/lib/examples/{ag-ui → components}/weather/index.d.ts +1 -1
- package/lib/examples/{ag-ui → components}/weather/index.js +1 -1
- package/lib/examples/example-selector.d.ts +17 -4
- package/lib/examples/example-selector.js +107 -41
- package/lib/examples/index.d.ts +9 -6
- package/lib/examples/index.js +9 -6
- package/lib/examples/main.js +217 -27
- package/lib/examples/utils/a2ui.d.ts +18 -0
- package/lib/examples/utils/a2ui.js +69 -0
- package/lib/examples/utils/a2uiMarkdownProvider.d.ts +7 -0
- package/lib/examples/utils/a2uiMarkdownProvider.js +9 -0
- package/lib/examples/utils/agentId.d.ts +18 -0
- package/lib/examples/utils/agentId.js +54 -0
- package/lib/examples/utils/agents/earthquake-detector.json +11 -11
- package/lib/examples/utils/agents/sales-forecaster.json +11 -11
- package/lib/examples/utils/agents/social-post-generator.json +11 -11
- package/lib/examples/utils/agents/stock-market.json +11 -11
- package/lib/examples/utils/examplesStore.js +82 -27
- package/lib/hooks/index.d.ts +8 -8
- package/lib/hooks/index.js +7 -7
- package/lib/hooks/useA2A.d.ts +2 -3
- package/lib/hooks/useAIAgentsWebSocket.d.ts +43 -4
- package/lib/hooks/useAIAgentsWebSocket.js +118 -12
- package/lib/hooks/useAcp.d.ts +1 -2
- package/lib/hooks/useAgUi.d.ts +1 -1
- package/lib/hooks/{useAgents.d.ts → useAgentRuntimes.d.ts} +39 -2
- package/lib/hooks/{useAgents.js → useAgentRuntimes.js} +125 -15
- package/lib/hooks/useAgentsCatalog.js +1 -1
- package/lib/hooks/useAgentsService.d.ts +2 -2
- package/lib/hooks/useAgentsService.js +7 -7
- package/lib/hooks/useCheckpoints.js +1 -1
- package/lib/hooks/useConfig.d.ts +4 -1
- package/lib/hooks/useConfig.js +10 -3
- package/lib/hooks/useContextSnapshot.d.ts +9 -4
- package/lib/hooks/useContextSnapshot.js +9 -37
- package/lib/hooks/useMonitoring.js +3 -0
- package/lib/hooks/useSandbox.d.ts +20 -8
- package/lib/hooks/useSandbox.js +105 -40
- package/lib/hooks/useSkills.d.ts +23 -5
- package/lib/hooks/useSkills.js +94 -39
- package/lib/hooks/useToolApprovals.d.ts +60 -36
- package/lib/hooks/useToolApprovals.js +318 -69
- package/lib/hooks/useVercelAI.d.ts +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +1 -0
- package/lib/inference/index.d.ts +0 -1
- package/lib/middleware/index.d.ts +0 -1
- package/lib/protocols/AGUIAdapter.js +6 -0
- package/lib/protocols/VercelAIAdapter.d.ts +7 -0
- package/lib/protocols/VercelAIAdapter.js +59 -7
- package/lib/specs/agents/agents.d.ts +10 -0
- package/lib/specs/agents/agents.js +2139 -262
- package/lib/specs/agents/index.js +3 -1
- package/lib/specs/envvars.d.ts +1 -0
- package/lib/specs/envvars.js +38 -20
- package/lib/specs/evals.js +6 -6
- package/lib/specs/events.d.ts +3 -10
- package/lib/specs/events.js +127 -84
- package/lib/specs/frontendTools.js +2 -2
- package/lib/specs/guardrails.d.ts +0 -7
- package/lib/specs/guardrails.js +240 -159
- package/lib/specs/index.d.ts +1 -0
- package/lib/specs/index.js +1 -0
- package/lib/specs/mcpServers.js +35 -6
- package/lib/specs/memory.d.ts +0 -2
- package/lib/specs/memory.js +4 -17
- package/lib/specs/models.js +25 -5
- package/lib/specs/notifications.js +102 -18
- package/lib/specs/outputs.js +15 -9
- package/lib/specs/personas.d.ts +41 -0
- package/lib/specs/personas.js +168 -0
- package/lib/specs/skills.d.ts +2 -1
- package/lib/specs/skills.js +41 -23
- package/lib/specs/teams/index.js +3 -1
- package/lib/specs/teams/teams.js +468 -348
- package/lib/specs/tools.js +4 -4
- package/lib/specs/triggers.js +61 -11
- package/lib/stores/agentRuntimeStore.d.ts +204 -0
- package/lib/stores/agentRuntimeStore.js +636 -0
- package/lib/stores/index.d.ts +1 -1
- package/lib/stores/index.js +1 -1
- package/lib/tools/adapters/copilotkit/lexicalHooks.d.ts +1 -2
- package/lib/tools/adapters/copilotkit/lexicalHooks.js +1 -3
- package/lib/tools/adapters/copilotkit/notebookHooks.d.ts +1 -2
- package/lib/tools/adapters/copilotkit/notebookHooks.js +1 -3
- package/lib/tools/index.d.ts +0 -2
- package/lib/tools/index.js +0 -1
- package/lib/types/agentspecs.d.ts +50 -1
- package/lib/types/chat.d.ts +309 -8
- package/lib/types/context.d.ts +27 -0
- package/lib/types/cost.d.ts +2 -2
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.js +2 -0
- package/lib/types/mcp.d.ts +8 -0
- package/lib/types/models.d.ts +2 -2
- package/lib/types/personas.d.ts +25 -0
- package/lib/types/personas.js +5 -0
- package/lib/types/skills.d.ts +43 -1
- package/lib/types/stream.d.ts +110 -0
- package/lib/types/stream.js +36 -0
- package/lib/utils/utils.d.ts +9 -5
- package/lib/utils/utils.js +9 -5
- package/package.json +13 -9
- package/scripts/codegen/__pycache__/generate_agents.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/generate_events.cpython-313.pyc +0 -0
- package/scripts/codegen/__pycache__/versioning.cpython-313.pyc +0 -0
- package/scripts/codegen/generate_agents.py +102 -6
- package/scripts/codegen/generate_events.py +35 -13
- package/scripts/codegen/generate_personas.py +319 -0
- package/scripts/codegen/generate_skills.py +9 -9
- package/scripts/sync-jupyter.sh +26 -7
- package/lib/api/tool-approvals.d.ts +0 -62
- package/lib/api/tool-approvals.js +0 -145
- package/lib/examples/LexicalSidebarExample.js +0 -163
- package/lib/examples/NotebookSidebarExample.js +0 -119
- package/lib/examples/NotebookSimpleExample.d.ts +0 -6
- package/lib/examples/NotebookSimpleExample.js +0 -22
- package/lib/examples/ag-ui/index.d.ts +0 -10
- package/lib/examples/ag-ui/index.js +0 -16
- package/lib/hooks/useAgentsRegistry.d.ts +0 -10
- package/lib/hooks/useAgentsRegistry.js +0 -20
- package/lib/stores/agentsStore.d.ts +0 -123
- package/lib/stores/agentsStore.js +0 -270
- /package/lib/examples/{AgentspecExample.d.ts → AgentSpecsExample.d.ts} +0 -0
- /package/lib/examples/{ag-ui → components}/haiku/HaikuDisplay.d.ts +0 -0
- /package/lib/examples/{ag-ui → components}/haiku/InlineHaikuCard.d.ts +0 -0
- /package/lib/examples/{ag-ui → components}/weather/InlineWeatherCard.d.ts +0 -0
- /package/lib/examples/{ag-ui → components}/weather/InlineWeatherCard.js +0 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { ContextSnapshotData } from './context';
|
|
2
|
+
import type { McpToolsetsStatusResponse } from './mcp';
|
|
3
|
+
import type { SkillStatus } from './skills';
|
|
4
|
+
export type AgentStreamEventType = 'agent.snapshot' | 'tool_approval_created' | 'tool_approval_approved' | 'tool_approval_rejected';
|
|
5
|
+
export interface AgentStreamMessage<TPayload = Record<string, unknown>> {
|
|
6
|
+
version: string;
|
|
7
|
+
type: AgentStreamEventType | string;
|
|
8
|
+
agentId?: string;
|
|
9
|
+
timestamp: string;
|
|
10
|
+
payload: TPayload;
|
|
11
|
+
event?: string;
|
|
12
|
+
data?: unknown;
|
|
13
|
+
}
|
|
14
|
+
export interface AgentStreamToolApprovalPayload {
|
|
15
|
+
id: string;
|
|
16
|
+
agent_id?: string;
|
|
17
|
+
pod_name?: string;
|
|
18
|
+
tool_name: string;
|
|
19
|
+
tool_call_id?: string;
|
|
20
|
+
tool_args?: Record<string, unknown>;
|
|
21
|
+
status?: string;
|
|
22
|
+
note?: string | null;
|
|
23
|
+
created_at?: string;
|
|
24
|
+
updated_at?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface AgentStreamSnapshotPayload {
|
|
27
|
+
agentId?: string;
|
|
28
|
+
approvals: AgentStreamToolApprovalPayload[];
|
|
29
|
+
pendingApprovalCount: number;
|
|
30
|
+
contextSnapshot?: ContextSnapshotData | null;
|
|
31
|
+
costUsage?: ContextSnapshotData['costUsage'];
|
|
32
|
+
mcpStatus?: McpToolsetsStatusResponse | null;
|
|
33
|
+
codemodeStatus?: CodemodeStatusData | null;
|
|
34
|
+
fullContext?: Record<string, unknown> | null;
|
|
35
|
+
graphTelemetry?: GraphTelemetryData | null;
|
|
36
|
+
}
|
|
37
|
+
/** Graph-level telemetry data from pydantic-graph execution. */
|
|
38
|
+
export interface GraphTelemetryData {
|
|
39
|
+
agentId?: string;
|
|
40
|
+
graphName?: string | null;
|
|
41
|
+
/** Static topology: graph node definitions. */
|
|
42
|
+
nodes: GraphTelemetryNode[];
|
|
43
|
+
/** Static topology: edges between nodes. */
|
|
44
|
+
edges: GraphTelemetryEdge[];
|
|
45
|
+
/** Dynamic execution trace: per-node events. */
|
|
46
|
+
events: GraphNodeEvent[];
|
|
47
|
+
totalNodesExecuted: number;
|
|
48
|
+
totalDurationMs: number;
|
|
49
|
+
lastRunStartMs: number;
|
|
50
|
+
lastRunEndMs: number;
|
|
51
|
+
runCount: number;
|
|
52
|
+
}
|
|
53
|
+
export interface GraphTelemetryNode {
|
|
54
|
+
id: string;
|
|
55
|
+
name: string;
|
|
56
|
+
category: string;
|
|
57
|
+
}
|
|
58
|
+
export interface GraphTelemetryEdge {
|
|
59
|
+
source: string;
|
|
60
|
+
target: string;
|
|
61
|
+
label?: string | null;
|
|
62
|
+
edgeType: string;
|
|
63
|
+
}
|
|
64
|
+
export interface GraphNodeEvent {
|
|
65
|
+
nodeId: string;
|
|
66
|
+
nodeType: string;
|
|
67
|
+
status: string;
|
|
68
|
+
timestampMs: number;
|
|
69
|
+
durationMs?: number | null;
|
|
70
|
+
parentNodeId?: string | null;
|
|
71
|
+
error?: string | null;
|
|
72
|
+
}
|
|
73
|
+
/** Codemode status as pushed via the monitoring WebSocket. */
|
|
74
|
+
export interface CodemodeStatusData {
|
|
75
|
+
enabled: boolean;
|
|
76
|
+
skills: Array<{
|
|
77
|
+
id?: string;
|
|
78
|
+
name: string;
|
|
79
|
+
description?: string;
|
|
80
|
+
tags?: string[];
|
|
81
|
+
has_scripts?: boolean;
|
|
82
|
+
has_resources?: boolean;
|
|
83
|
+
status?: SkillStatus;
|
|
84
|
+
approved?: boolean;
|
|
85
|
+
skill_definition?: string | null;
|
|
86
|
+
source_variant?: 'module' | 'package' | 'path' | 'unknown';
|
|
87
|
+
module?: string;
|
|
88
|
+
package?: string;
|
|
89
|
+
method?: string;
|
|
90
|
+
path?: string;
|
|
91
|
+
}>;
|
|
92
|
+
available_skills: Array<{
|
|
93
|
+
id?: string;
|
|
94
|
+
name: string;
|
|
95
|
+
description?: string;
|
|
96
|
+
tags?: string[];
|
|
97
|
+
has_scripts?: boolean;
|
|
98
|
+
has_resources?: boolean;
|
|
99
|
+
status?: SkillStatus;
|
|
100
|
+
approved?: boolean;
|
|
101
|
+
skill_definition?: string | null;
|
|
102
|
+
source_variant?: 'module' | 'package' | 'path' | 'unknown';
|
|
103
|
+
module?: string;
|
|
104
|
+
package?: string;
|
|
105
|
+
method?: string;
|
|
106
|
+
path?: string;
|
|
107
|
+
}>;
|
|
108
|
+
sandbox?: Record<string, unknown> | null;
|
|
109
|
+
}
|
|
110
|
+
export declare function parseAgentStreamMessage(raw: unknown): AgentStreamMessage | null;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025-2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
const isObject = (value) => !!value && typeof value === 'object';
|
|
6
|
+
export function parseAgentStreamMessage(raw) {
|
|
7
|
+
if (!isObject(raw)) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
// New envelope format.
|
|
11
|
+
if (typeof raw.type === 'string' && isObject(raw.payload)) {
|
|
12
|
+
return {
|
|
13
|
+
version: typeof raw.version === 'string' ? raw.version : '1.0',
|
|
14
|
+
type: raw.type,
|
|
15
|
+
agentId: typeof raw.agentId === 'string' ? raw.agentId : undefined,
|
|
16
|
+
timestamp: typeof raw.timestamp === 'string'
|
|
17
|
+
? raw.timestamp
|
|
18
|
+
: new Date().toISOString(),
|
|
19
|
+
payload: raw.payload,
|
|
20
|
+
event: typeof raw.event === 'string' ? raw.event : undefined,
|
|
21
|
+
data: raw.data,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
// Legacy event/data format.
|
|
25
|
+
if (typeof raw.event === 'string' && isObject(raw.data)) {
|
|
26
|
+
return {
|
|
27
|
+
version: '1.0',
|
|
28
|
+
type: raw.event,
|
|
29
|
+
timestamp: new Date().toISOString(),
|
|
30
|
+
payload: raw.data,
|
|
31
|
+
event: raw.event,
|
|
32
|
+
data: raw.data,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
package/lib/utils/utils.d.ts
CHANGED
|
@@ -47,11 +47,15 @@ export declare function convertHistoryToDisplayItems(messages: ChatMessage[]): D
|
|
|
47
47
|
*/
|
|
48
48
|
export declare function formatTokenCount(tokens: number): string;
|
|
49
49
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
50
|
+
* Derives the API base URL from a config endpoint URL.
|
|
51
|
+
*
|
|
52
|
+
* The config endpoint may be `{base}/api/v1/config` (from agentRuntimeConfig)
|
|
53
|
+
* or `{base}/api/v1/configure` (from the Chat component). This function
|
|
54
|
+
* strips the trailing path segment to yield `{base}/api/v1`.
|
|
55
|
+
*
|
|
56
|
+
* @param configEndpoint - Full config endpoint URL.
|
|
57
|
+
*
|
|
58
|
+
* @returns The API base URL without the trailing config segment.
|
|
55
59
|
*/
|
|
56
60
|
export declare function getApiBaseFromConfig(configEndpoint: string): string;
|
|
57
61
|
/**
|
package/lib/utils/utils.js
CHANGED
|
@@ -166,11 +166,15 @@ export function formatTokenCount(tokens) {
|
|
|
166
166
|
return tokens.toString();
|
|
167
167
|
}
|
|
168
168
|
/**
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
169
|
+
* Derives the API base URL from a config endpoint URL.
|
|
170
|
+
*
|
|
171
|
+
* The config endpoint may be `{base}/api/v1/config` (from agentRuntimeConfig)
|
|
172
|
+
* or `{base}/api/v1/configure` (from the Chat component). This function
|
|
173
|
+
* strips the trailing path segment to yield `{base}/api/v1`.
|
|
174
|
+
*
|
|
175
|
+
* @param configEndpoint - Full config endpoint URL.
|
|
176
|
+
*
|
|
177
|
+
* @returns The API base URL without the trailing config segment.
|
|
174
178
|
*/
|
|
175
179
|
export function getApiBaseFromConfig(configEndpoint) {
|
|
176
180
|
return configEndpoint.replace(/\/(config|configure)\/?$/, '');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datalayer/agent-runtimes",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"workspaces": [
|
|
6
6
|
".",
|
|
@@ -60,16 +60,16 @@
|
|
|
60
60
|
"build:lib": "npm run clean:lib && gulp resources-to-lib && tsc -b",
|
|
61
61
|
"build:nextjs": "npm run build --workspace=nextjs-notebook-example",
|
|
62
62
|
"build:types": "npm run clean:lib && tsc -b",
|
|
63
|
-
"check": "npm run format:check && npm run lint:all && npm run type-check:all",
|
|
63
|
+
"check": "npm run format:check && npm run lint:all && npm run type-check:all && npm run typedoc",
|
|
64
64
|
"check:fix": "npm run format:all && npm run lint:fix && npm run type-check:all",
|
|
65
65
|
"clean": "rimraf lib dist build tsconfig.tsbuildinfo",
|
|
66
66
|
"clean:cache": "rimraf node_modules/.vite",
|
|
67
67
|
"clean:dist": "rimraf dist",
|
|
68
68
|
"clean:lib": "rimraf lib tsconfig.tsbuildinfo",
|
|
69
69
|
"create:patches": "bash scripts/create-patches.sh",
|
|
70
|
-
"examples": "run-p server:start jupyter:start examples:vite",
|
|
70
|
+
"examples": "run-p server:start server:start:codemode jupyter:start examples:vite",
|
|
71
71
|
"examples:fresh": "npm run clean:cache && npm run examples",
|
|
72
|
-
"examples:jupyter": "run-p jupyter:start server:start examples:vite",
|
|
72
|
+
"examples:jupyter": "run-p jupyter:start server:start server:start:codemode examples:vite",
|
|
73
73
|
"examples:nextjs": "npm run dev --workspace=nextjs-notebook-example",
|
|
74
74
|
"examples:vite": "VITE_APP_TARGET=examples VITE_DATALAYER_RUN_URL=http://localhost:8888 vite",
|
|
75
75
|
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css,json,md}\" \"examples/**/*.{js,jsx,ts,tsx,css,json,md,mjs}\"",
|
|
@@ -90,6 +90,8 @@
|
|
|
90
90
|
"rebuild:fresh": "npm run create:patches && npm install && npm run build && npm run clean:cache",
|
|
91
91
|
"server": "python -m agent_runtimes serve",
|
|
92
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",
|
|
94
|
+
"examples:codemode": "run-p server:start server:start:codemode examples:vite",
|
|
93
95
|
"start": "vite",
|
|
94
96
|
"start:acp": "run-p server:start start:acp:vite",
|
|
95
97
|
"start:acp:prod": "run-p server start:acp:vite",
|
|
@@ -120,7 +122,7 @@
|
|
|
120
122
|
},
|
|
121
123
|
"dependencies": {
|
|
122
124
|
"@a2a-js/sdk": "^0.3.6",
|
|
123
|
-
"@a2ui/react": "^0.
|
|
125
|
+
"@a2ui/react": "^0.9.1",
|
|
124
126
|
"@ag-ui/client": "^0.0.42",
|
|
125
127
|
"@ag-ui/core": "^0.0.42",
|
|
126
128
|
"@ag-ui/encoder": "^0.0.42",
|
|
@@ -128,12 +130,12 @@
|
|
|
128
130
|
"@agentclientprotocol/sdk": "^0.8.0",
|
|
129
131
|
"@ai-sdk/react": "^4.0.0-beta.33",
|
|
130
132
|
"@anthropic-ai/sdk": "^0.52.0",
|
|
131
|
-
"@datalayer/core": "^1.0.
|
|
132
|
-
"@datalayer/icons-react": "^1.0.
|
|
133
|
+
"@datalayer/core": "^1.0.20",
|
|
134
|
+
"@datalayer/icons-react": "^1.0.7",
|
|
133
135
|
"@datalayer/jupyter-lexical": "^1.0.16",
|
|
134
136
|
"@datalayer/jupyter-react": "^2.0.7",
|
|
135
|
-
"@datalayer/primer-addons": "^1.0.
|
|
136
|
-
"@datalayer/primer-rjsf": "^1.0.
|
|
137
|
+
"@datalayer/primer-addons": "^1.0.15",
|
|
138
|
+
"@datalayer/primer-rjsf": "^1.0.3",
|
|
137
139
|
"@excalidraw/excalidraw": "^0.18.0",
|
|
138
140
|
"@jupyter-widgets/base-manager": "^1.0.12",
|
|
139
141
|
"@jupyter-widgets/schema": "^0.5.6",
|
|
@@ -301,6 +303,7 @@
|
|
|
301
303
|
"vitest": "^3.2.4"
|
|
302
304
|
},
|
|
303
305
|
"resolutions": {
|
|
306
|
+
"@langchain/core": "^0.3.80",
|
|
304
307
|
"@ai-sdk/react": "^4.0.0-beta.33",
|
|
305
308
|
"@microsoft/fast-colors": "5.3.1",
|
|
306
309
|
"@microsoft/fast-components": "2.30.6",
|
|
@@ -318,6 +321,7 @@
|
|
|
318
321
|
"typescript": "^5.8.3"
|
|
319
322
|
},
|
|
320
323
|
"overrides": {
|
|
324
|
+
"@langchain/core": "^0.3.80",
|
|
321
325
|
"@ai-sdk/react": "^4.0.0-beta.33",
|
|
322
326
|
"@microsoft/fast-colors": "5.3.1",
|
|
323
327
|
"@microsoft/fast-components": "2.30.6",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -27,7 +27,7 @@ def _fmt_list(items: list[str]) -> str:
|
|
|
27
27
|
"""Format a list of strings with double quotes for ruff compliance."""
|
|
28
28
|
if not items:
|
|
29
29
|
return "[]"
|
|
30
|
-
return "[" + ", ".join(
|
|
30
|
+
return "[" + ", ".join(_fmt_py_literal(item) for item in items) + "]"
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def _fmt_py_literal(value: Any) -> str:
|
|
@@ -44,6 +44,44 @@ def _fmt_ts_literal(value: Any) -> str:
|
|
|
44
44
|
return json.dumps(value, ensure_ascii=False)
|
|
45
45
|
|
|
46
46
|
|
|
47
|
+
def _normalize_subagents_for_typescript(value: Any) -> Any:
|
|
48
|
+
"""Convert subagents config keys from YAML snake_case to TS camelCase."""
|
|
49
|
+
if not isinstance(value, dict):
|
|
50
|
+
return value
|
|
51
|
+
|
|
52
|
+
top_level_map = {
|
|
53
|
+
"default_model": "defaultModel",
|
|
54
|
+
"include_general_purpose": "includeGeneralPurpose",
|
|
55
|
+
"max_nesting_depth": "maxNestingDepth",
|
|
56
|
+
}
|
|
57
|
+
subagent_map = {
|
|
58
|
+
"can_ask_questions": "canAskQuestions",
|
|
59
|
+
"max_questions": "maxQuestions",
|
|
60
|
+
"preferred_mode": "preferredMode",
|
|
61
|
+
"typical_complexity": "typicalComplexity",
|
|
62
|
+
"typically_needs_context": "typicallyNeedsContext",
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
normalized: dict[str, Any] = {}
|
|
66
|
+
for key, raw_val in value.items():
|
|
67
|
+
mapped_key = top_level_map.get(key, key)
|
|
68
|
+
if mapped_key == "subagents" and isinstance(raw_val, list):
|
|
69
|
+
normalized_subagents: list[Any] = []
|
|
70
|
+
for subagent in raw_val:
|
|
71
|
+
if isinstance(subagent, dict):
|
|
72
|
+
normalized_subagent: dict[str, Any] = {}
|
|
73
|
+
for sa_key, sa_val in subagent.items():
|
|
74
|
+
normalized_subagent[subagent_map.get(sa_key, sa_key)] = sa_val
|
|
75
|
+
normalized_subagents.append(normalized_subagent)
|
|
76
|
+
else:
|
|
77
|
+
normalized_subagents.append(subagent)
|
|
78
|
+
normalized[mapped_key] = normalized_subagents
|
|
79
|
+
else:
|
|
80
|
+
normalized[mapped_key] = raw_val
|
|
81
|
+
|
|
82
|
+
return normalized
|
|
83
|
+
|
|
84
|
+
|
|
47
85
|
def load_yaml_specs(specs_dir: Path) -> List[tuple[str, Dict[str, Any]]]:
|
|
48
86
|
"""
|
|
49
87
|
Load all YAML agent specifications from directory and subdirectories.
|
|
@@ -91,7 +129,7 @@ Generated from YAML specifications in specs/agents/
|
|
|
91
129
|
from typing import Dict
|
|
92
130
|
|
|
93
131
|
from agent_runtimes.mcp.catalog_mcp_servers import MCP_SERVER_CATALOG
|
|
94
|
-
from agent_runtimes.types import AgentSpec
|
|
132
|
+
from agent_runtimes.types import AgentSpec, SubAgentSpecConfig, SubAgentsConfig
|
|
95
133
|
|
|
96
134
|
# ============================================================================
|
|
97
135
|
# Agent Specs
|
|
@@ -166,7 +204,7 @@ from agent_runtimes.types import AgentSpec
|
|
|
166
204
|
suggestions = spec.get("suggestions", [])
|
|
167
205
|
suggestions_str = (
|
|
168
206
|
"[\n "
|
|
169
|
-
+ ",\n ".join(
|
|
207
|
+
+ ",\n ".join(_fmt_py_literal(s) for s in suggestions)
|
|
170
208
|
+ ",\n ]"
|
|
171
209
|
if suggestions
|
|
172
210
|
else "[]"
|
|
@@ -217,11 +255,12 @@ from agent_runtimes.types import AgentSpec
|
|
|
217
255
|
|
|
218
256
|
# New flow-level fields
|
|
219
257
|
goal_raw = spec.get("goal")
|
|
220
|
-
|
|
221
|
-
|
|
258
|
+
goal_clean = (
|
|
259
|
+
goal_raw.replace(chr(10), " ").replace(" ", " ").strip()
|
|
222
260
|
if goal_raw
|
|
223
|
-
else
|
|
261
|
+
else None
|
|
224
262
|
)
|
|
263
|
+
goal_str = _fmt_py_literal(goal_clean)
|
|
225
264
|
protocol_val = spec.get("protocol")
|
|
226
265
|
protocol_str = f'"{protocol_val}"' if protocol_val else "None"
|
|
227
266
|
ui_ext = spec.get("ui_extension")
|
|
@@ -239,6 +278,48 @@ from agent_runtimes.types import AgentSpec
|
|
|
239
278
|
notifs = spec.get("notifications")
|
|
240
279
|
memory_val = spec.get("memory")
|
|
241
280
|
memory_str = f'"{memory_val}"' if memory_val else "None"
|
|
281
|
+
pre_hooks_val = spec.get("pre_hooks")
|
|
282
|
+
post_hooks_val = spec.get("post_hooks")
|
|
283
|
+
parameters_val = spec.get("parameters")
|
|
284
|
+
subagents_val = spec.get("subagents")
|
|
285
|
+
|
|
286
|
+
# Build subagents code if present
|
|
287
|
+
subagents_str = "None"
|
|
288
|
+
if isinstance(subagents_val, dict) and subagents_val.get("subagents"):
|
|
289
|
+
sa_items = []
|
|
290
|
+
for sa in subagents_val["subagents"]:
|
|
291
|
+
sa_fields = [
|
|
292
|
+
f"name={_fmt_py_literal(sa['name'])}",
|
|
293
|
+
f"description={_fmt_py_literal(sa['description'])}",
|
|
294
|
+
f"instructions={_fmt_py_literal(sa['instructions'])}",
|
|
295
|
+
]
|
|
296
|
+
for opt_key in (
|
|
297
|
+
"model",
|
|
298
|
+
"can_ask_questions",
|
|
299
|
+
"max_questions",
|
|
300
|
+
"preferred_mode",
|
|
301
|
+
"typical_complexity",
|
|
302
|
+
"typically_needs_context",
|
|
303
|
+
):
|
|
304
|
+
opt_val = sa.get(opt_key)
|
|
305
|
+
if opt_val is not None:
|
|
306
|
+
sa_fields.append(f"{opt_key}={_fmt_py_literal(opt_val)}")
|
|
307
|
+
sa_items.append("SubAgentSpecConfig(" + ", ".join(sa_fields) + ")")
|
|
308
|
+
sa_list_str = "[" + ", ".join(sa_items) + "]"
|
|
309
|
+
cfg_parts = [f"subagents={sa_list_str}"]
|
|
310
|
+
if subagents_val.get("default_model") is not None:
|
|
311
|
+
cfg_parts.append(
|
|
312
|
+
f"default_model={_fmt_py_literal(subagents_val['default_model'])}"
|
|
313
|
+
)
|
|
314
|
+
if subagents_val.get("include_general_purpose") is not None:
|
|
315
|
+
cfg_parts.append(
|
|
316
|
+
f"include_general_purpose={_fmt_py_literal(subagents_val['include_general_purpose'])}"
|
|
317
|
+
)
|
|
318
|
+
if subagents_val.get("max_nesting_depth") is not None:
|
|
319
|
+
cfg_parts.append(
|
|
320
|
+
f"max_nesting_depth={_fmt_py_literal(subagents_val['max_nesting_depth'])}"
|
|
321
|
+
)
|
|
322
|
+
subagents_str = "SubAgentsConfig(" + ", ".join(cfg_parts) + ")"
|
|
242
323
|
|
|
243
324
|
code += f'''{const_name} = AgentSpec(
|
|
244
325
|
id="{full_agent_id}",
|
|
@@ -277,6 +358,10 @@ from agent_runtimes.types import AgentSpec
|
|
|
277
358
|
authorization_policy={auth_policy_str},
|
|
278
359
|
notifications={_fmt_py_literal(notifs)},
|
|
279
360
|
memory={memory_str},
|
|
361
|
+
pre_hooks={_fmt_py_literal(pre_hooks_val)},
|
|
362
|
+
post_hooks={_fmt_py_literal(post_hooks_val)},
|
|
363
|
+
parameters={_fmt_py_literal(parameters_val)},
|
|
364
|
+
subagents={subagents_str},
|
|
280
365
|
)
|
|
281
366
|
|
|
282
367
|
'''
|
|
@@ -764,6 +849,13 @@ const FRONTEND_TOOL_MAP: Record<string, any> = {
|
|
|
764
849
|
notifs = spec.get("notifications")
|
|
765
850
|
memory_val = spec.get("memory")
|
|
766
851
|
memory_ts = f"'{memory_val}'" if memory_val else "undefined"
|
|
852
|
+
pre_hooks_val = spec.get("pre_hooks")
|
|
853
|
+
post_hooks_val = spec.get("post_hooks")
|
|
854
|
+
parameters_val = spec.get("parameters")
|
|
855
|
+
subagents_val = spec.get("subagents")
|
|
856
|
+
subagents_ts = _fmt_ts_literal(
|
|
857
|
+
_normalize_subagents_for_typescript(subagents_val)
|
|
858
|
+
)
|
|
767
859
|
|
|
768
860
|
code += f"""export const {const_name}: AgentSpec = {{
|
|
769
861
|
id: '{full_agent_id}',
|
|
@@ -802,6 +894,10 @@ const FRONTEND_TOOL_MAP: Record<string, any> = {
|
|
|
802
894
|
authorizationPolicy: {auth_policy_ts},
|
|
803
895
|
notifications: {_fmt_ts_literal(notifs)},
|
|
804
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},
|
|
805
901
|
}};
|
|
806
902
|
|
|
807
903
|
"""
|
|
@@ -43,18 +43,22 @@ def load_specs(specs_dir: Path) -> list[dict[str, Any]]:
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
def _py_field(f: dict[str, Any]) -> str:
|
|
46
|
-
"""Format an EventField
|
|
46
|
+
"""Format an EventField dict body.
|
|
47
|
+
|
|
48
|
+
Returns the lines inside ``EventField(\n **{\n ...\n }\n)``
|
|
49
|
+
so that the generated output matches ``ruff format`` exactly.
|
|
50
|
+
"""
|
|
47
51
|
parts = [
|
|
48
|
-
f'"name": "{f["name"]}"',
|
|
49
|
-
f'"label": "{f["label"]}"',
|
|
50
|
-
f'"type": "{f["type"]}"',
|
|
51
|
-
f'"required": {str(f["required"])}',
|
|
52
|
+
f' "name": "{f["name"]}"',
|
|
53
|
+
f' "label": "{f["label"]}"',
|
|
54
|
+
f' "type": "{f["type"]}"',
|
|
55
|
+
f' "required": {str(f["required"])}',
|
|
52
56
|
]
|
|
53
57
|
if "description" in f:
|
|
54
|
-
parts.append(f'"description": "{_esc_dq(f["description"])}"')
|
|
58
|
+
parts.append(f' "description": "{_esc_dq(f["description"])}"')
|
|
55
59
|
if "placeholder" in f:
|
|
56
|
-
parts.append(f'"placeholder": "{_esc_dq(f["placeholder"])}"')
|
|
57
|
-
return "
|
|
60
|
+
parts.append(f' "placeholder": "{_esc_dq(f["placeholder"])}"')
|
|
61
|
+
return ",\n".join(parts)
|
|
58
62
|
|
|
59
63
|
|
|
60
64
|
def _ts_field(f: dict[str, Any]) -> str:
|
|
@@ -118,10 +122,18 @@ def generate_python_code(specs: list[dict[str, Any]]) -> str:
|
|
|
118
122
|
]
|
|
119
123
|
)
|
|
120
124
|
if fields:
|
|
121
|
-
field_strs = [_py_field(f) for f in fields]
|
|
122
125
|
lines.append(" fields=[")
|
|
123
|
-
for
|
|
124
|
-
|
|
126
|
+
for f in fields:
|
|
127
|
+
field_body = _py_field(f)
|
|
128
|
+
lines.extend(
|
|
129
|
+
[
|
|
130
|
+
" EventField(",
|
|
131
|
+
" **{",
|
|
132
|
+
field_body + ",",
|
|
133
|
+
" }",
|
|
134
|
+
" ),",
|
|
135
|
+
]
|
|
136
|
+
)
|
|
125
137
|
lines.append(" ],")
|
|
126
138
|
lines.extend([")", ""])
|
|
127
139
|
|
|
@@ -149,10 +161,17 @@ def generate_python_code(specs: list[dict[str, Any]]) -> str:
|
|
|
149
161
|
"# Event kind constants for programmatic use",
|
|
150
162
|
]
|
|
151
163
|
)
|
|
164
|
+
|
|
165
|
+
spec_kinds = {spec.get("kind", spec["id"]) for spec in specs}
|
|
166
|
+
|
|
152
167
|
for spec in specs:
|
|
153
168
|
kind = spec.get("kind", spec["id"])
|
|
154
169
|
const = kind.upper().replace("-", "_")
|
|
155
170
|
lines.append(f'EVENT_KIND_{const} = "{kind}"')
|
|
171
|
+
|
|
172
|
+
# Backward-compat constants used by older runtime code paths.
|
|
173
|
+
if "agent-assigned" not in spec_kinds:
|
|
174
|
+
lines.append('EVENT_KIND_AGENT_ASSIGNED = "agent-assigned"')
|
|
156
175
|
lines.extend(
|
|
157
176
|
[
|
|
158
177
|
"",
|
|
@@ -162,8 +181,8 @@ def generate_python_code(specs: list[dict[str, Any]]) -> str:
|
|
|
162
181
|
" spec = EVENT_CATALOG.get(event_id)",
|
|
163
182
|
" if spec is not None:",
|
|
164
183
|
" return spec",
|
|
165
|
-
|
|
166
|
-
|
|
184
|
+
' base, _, ver = event_id.rpartition(":")',
|
|
185
|
+
' if base and "." in ver:',
|
|
167
186
|
" return EVENT_CATALOG.get(base)",
|
|
168
187
|
" return None",
|
|
169
188
|
"",
|
|
@@ -233,11 +252,14 @@ def generate_typescript_code(specs: list[dict[str, Any]]) -> str:
|
|
|
233
252
|
lines.extend(["};", ""])
|
|
234
253
|
|
|
235
254
|
# Event kind constants
|
|
255
|
+
spec_kinds = {spec.get("kind", spec["id"]) for spec in specs}
|
|
236
256
|
lines.append("// Event kind constants for programmatic use")
|
|
237
257
|
for spec in specs:
|
|
238
258
|
kind = spec.get("kind", spec["id"])
|
|
239
259
|
const = kind.upper().replace("-", "_")
|
|
240
260
|
lines.append(f"export const EVENT_KIND_{const} = '{kind}';")
|
|
261
|
+
if "agent-assigned" not in spec_kinds:
|
|
262
|
+
lines.append("export const EVENT_KIND_AGENT_ASSIGNED = 'agent-assigned';")
|
|
241
263
|
lines.append("")
|
|
242
264
|
|
|
243
265
|
lines.extend(
|