aethergraph 0.1.0a3__py3-none-any.whl → 0.1.0a4__py3-none-any.whl
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.
- aethergraph/api/v1/artifacts.py +23 -4
- aethergraph/api/v1/schemas.py +7 -0
- aethergraph/api/v1/session.py +123 -4
- aethergraph/config/config.py +2 -0
- aethergraph/config/search.py +49 -0
- aethergraph/contracts/services/channel.py +18 -1
- aethergraph/contracts/services/execution.py +58 -0
- aethergraph/contracts/services/llm.py +26 -0
- aethergraph/contracts/services/memory.py +10 -4
- aethergraph/contracts/services/planning.py +53 -0
- aethergraph/contracts/storage/event_log.py +8 -0
- aethergraph/contracts/storage/search_backend.py +47 -0
- aethergraph/contracts/storage/vector_index.py +73 -0
- aethergraph/core/graph/action_spec.py +76 -0
- aethergraph/core/graph/graph_fn.py +75 -2
- aethergraph/core/graph/graphify.py +74 -2
- aethergraph/core/runtime/graph_runner.py +2 -1
- aethergraph/core/runtime/node_context.py +66 -3
- aethergraph/core/runtime/node_services.py +8 -0
- aethergraph/core/runtime/run_manager.py +263 -271
- aethergraph/core/runtime/run_types.py +54 -1
- aethergraph/core/runtime/runtime_env.py +35 -14
- aethergraph/core/runtime/runtime_services.py +308 -18
- aethergraph/plugins/agents/default_chat_agent.py +266 -74
- aethergraph/plugins/agents/default_chat_agent_v2.py +487 -0
- aethergraph/plugins/channel/adapters/webui.py +69 -21
- aethergraph/plugins/channel/routes/webui_routes.py +8 -48
- aethergraph/runtime/__init__.py +12 -0
- aethergraph/server/app_factory.py +3 -0
- aethergraph/server/ui_static/assets/index-CFktGdbW.js +4913 -0
- aethergraph/server/ui_static/assets/index-DcfkFlTA.css +1 -0
- aethergraph/server/ui_static/index.html +2 -2
- aethergraph/services/artifacts/facade.py +157 -21
- aethergraph/services/artifacts/types.py +35 -0
- aethergraph/services/artifacts/utils.py +42 -0
- aethergraph/services/channel/channel_bus.py +3 -1
- aethergraph/services/channel/event_hub copy.py +55 -0
- aethergraph/services/channel/event_hub.py +81 -0
- aethergraph/services/channel/factory.py +3 -2
- aethergraph/services/channel/session.py +709 -74
- aethergraph/services/container/default_container.py +69 -7
- aethergraph/services/execution/__init__.py +0 -0
- aethergraph/services/execution/local_python.py +118 -0
- aethergraph/services/indices/__init__.py +0 -0
- aethergraph/services/indices/global_indices.py +21 -0
- aethergraph/services/indices/scoped_indices.py +292 -0
- aethergraph/services/llm/generic_client.py +342 -46
- aethergraph/services/llm/generic_embed_client.py +359 -0
- aethergraph/services/llm/types.py +3 -1
- aethergraph/services/memory/distillers/llm_long_term.py +60 -109
- aethergraph/services/memory/distillers/llm_long_term_v1.py +180 -0
- aethergraph/services/memory/distillers/llm_meta_summary.py +57 -266
- aethergraph/services/memory/distillers/llm_meta_summary_v1.py +342 -0
- aethergraph/services/memory/distillers/long_term.py +48 -131
- aethergraph/services/memory/distillers/long_term_v1.py +170 -0
- aethergraph/services/memory/facade/chat.py +18 -8
- aethergraph/services/memory/facade/core.py +159 -19
- aethergraph/services/memory/facade/distillation.py +86 -31
- aethergraph/services/memory/facade/retrieval.py +100 -1
- aethergraph/services/memory/factory.py +4 -1
- aethergraph/services/planning/__init__.py +0 -0
- aethergraph/services/planning/action_catalog.py +271 -0
- aethergraph/services/planning/bindings.py +56 -0
- aethergraph/services/planning/dependency_index.py +65 -0
- aethergraph/services/planning/flow_validator.py +263 -0
- aethergraph/services/planning/graph_io_adapter.py +150 -0
- aethergraph/services/planning/input_parser.py +312 -0
- aethergraph/services/planning/missing_inputs.py +28 -0
- aethergraph/services/planning/node_planner.py +613 -0
- aethergraph/services/planning/orchestrator.py +112 -0
- aethergraph/services/planning/plan_executor.py +506 -0
- aethergraph/services/planning/plan_types.py +321 -0
- aethergraph/services/planning/planner.py +617 -0
- aethergraph/services/planning/planner_service.py +369 -0
- aethergraph/services/planning/planning_context_builder.py +43 -0
- aethergraph/services/planning/quick_actions.py +29 -0
- aethergraph/services/planning/routers/__init__.py +0 -0
- aethergraph/services/planning/routers/simple_router.py +26 -0
- aethergraph/services/rag/facade.py +0 -3
- aethergraph/services/scope/scope.py +30 -30
- aethergraph/services/scope/scope_factory.py +15 -7
- aethergraph/services/skills/__init__.py +0 -0
- aethergraph/services/skills/skill_registry.py +465 -0
- aethergraph/services/skills/skills.py +220 -0
- aethergraph/services/skills/utils.py +194 -0
- aethergraph/storage/artifacts/artifact_index_jsonl.py +16 -10
- aethergraph/storage/artifacts/artifact_index_sqlite.py +12 -2
- aethergraph/storage/docstore/sqlite_doc_sync.py +1 -1
- aethergraph/storage/memory/event_persist.py +42 -2
- aethergraph/storage/memory/fs_persist.py +32 -2
- aethergraph/storage/search_backend/__init__.py +0 -0
- aethergraph/storage/search_backend/generic_vector_backend.py +230 -0
- aethergraph/storage/search_backend/null_backend.py +34 -0
- aethergraph/storage/search_backend/sqlite_lexical_backend.py +387 -0
- aethergraph/storage/search_backend/utils.py +31 -0
- aethergraph/storage/search_factory.py +75 -0
- aethergraph/storage/vector_index/faiss_index.py +72 -4
- aethergraph/storage/vector_index/sqlite_index.py +521 -52
- aethergraph/storage/vector_index/sqlite_index_vanila.py +311 -0
- aethergraph/storage/vector_index/utils.py +22 -0
- {aethergraph-0.1.0a3.dist-info → aethergraph-0.1.0a4.dist-info}/METADATA +1 -1
- {aethergraph-0.1.0a3.dist-info → aethergraph-0.1.0a4.dist-info}/RECORD +107 -63
- {aethergraph-0.1.0a3.dist-info → aethergraph-0.1.0a4.dist-info}/WHEEL +1 -1
- aethergraph/plugins/agents/default_chat_agent copy.py +0 -90
- aethergraph/server/ui_static/assets/index-BR5GtXcZ.css +0 -1
- aethergraph/server/ui_static/assets/index-CQ0HZZ83.js +0 -400
- aethergraph/services/eventhub/event_hub.py +0 -76
- aethergraph/services/llm/generic_client copy.py +0 -691
- aethergraph/services/prompts/file_store.py +0 -41
- {aethergraph-0.1.0a3.dist-info → aethergraph-0.1.0a4.dist-info}/entry_points.txt +0 -0
- {aethergraph-0.1.0a3.dist-info → aethergraph-0.1.0a4.dist-info}/licenses/LICENSE +0 -0
- {aethergraph-0.1.0a3.dist-info → aethergraph-0.1.0a4.dist-info}/licenses/NOTICE +0 -0
- {aethergraph-0.1.0a3.dist-info → aethergraph-0.1.0a4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,613 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from aethergraph.api.v1.deps import RequestIdentity
|
|
8
|
+
from aethergraph.core.runtime.run_types import RunImportance, RunOrigin, RunVisibility
|
|
9
|
+
|
|
10
|
+
from .plan_executor import BackgroundExecutionHandle, ExecutionEvent, ExecutionResult
|
|
11
|
+
from .plan_types import CandidatePlan, PlanningContext, PlanningEvent
|
|
12
|
+
from .planner_service import PlannerService, PlanResult
|
|
13
|
+
|
|
14
|
+
PlanEventsCallback = Callable[[PlanningEvent], None]
|
|
15
|
+
ExecEventsCallback = Callable[[ExecutionEvent], None]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class NodePlanner:
|
|
20
|
+
"""
|
|
21
|
+
Node-bound facade over PlannerService.
|
|
22
|
+
|
|
23
|
+
- Knows about NodeContext identity/session/app/agent.
|
|
24
|
+
- Delegates to PlannerService but fills execution context automatically.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
service: PlannerService
|
|
28
|
+
node_ctx: Any # forward reference to NodeContext
|
|
29
|
+
|
|
30
|
+
# ---------- Planning ----------
|
|
31
|
+
async def plan(
|
|
32
|
+
self,
|
|
33
|
+
*,
|
|
34
|
+
goal: str,
|
|
35
|
+
user_inputs: dict[str, Any] | None = None,
|
|
36
|
+
external_slots: dict[str, Any] | None = None,
|
|
37
|
+
flow_ids: list[str] | None = None,
|
|
38
|
+
instruction: str | None = None,
|
|
39
|
+
allow_partial: bool = True,
|
|
40
|
+
preferred_external_keys: list[str] | None = None,
|
|
41
|
+
memory_snippets: list[str] | None = None,
|
|
42
|
+
artifact_snippets: list[str] | None = None,
|
|
43
|
+
on_event: PlanEventsCallback | None = None,
|
|
44
|
+
) -> PlanResult:
|
|
45
|
+
"""
|
|
46
|
+
Generate a plan based on the provided goal and context.
|
|
47
|
+
|
|
48
|
+
This method delegates the planning process to the underlying PlannerService,
|
|
49
|
+
using the provided inputs and optional callbacks for event handling.
|
|
50
|
+
|
|
51
|
+
Examples:
|
|
52
|
+
Basic usage to generate a plan:
|
|
53
|
+
```python
|
|
54
|
+
result = await node_planner.plan(goal="Optimize workflow")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Providing additional inputs and handling events:
|
|
58
|
+
```python
|
|
59
|
+
result = await node_planner.plan(
|
|
60
|
+
goal="Generate report",
|
|
61
|
+
user_inputs={"date": "2023-10-01"},
|
|
62
|
+
on_event=lambda event: print(f"Event: {event}")
|
|
63
|
+
)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
goal: The primary objective or goal for the planning process.
|
|
68
|
+
user_inputs: Optional dictionary of user-provided inputs for the plan.
|
|
69
|
+
external_slots: Optional dictionary of external slot values to consider.
|
|
70
|
+
flow_ids: Optional list of flow identifiers to constrain the planning scope.
|
|
71
|
+
instruction: Optional instruction or guidance for the planner.
|
|
72
|
+
allow_partial: Whether to allow partial plans if the goal cannot be fully satisfied (default: True).
|
|
73
|
+
preferred_external_keys: Optional list of preferred external keys to prioritize.
|
|
74
|
+
memory_snippets: Optional list of memory snippets to include in the planning context.
|
|
75
|
+
artifact_snippets: Optional list of artifact snippets to include in the planning context.
|
|
76
|
+
on_event: Optional callback function to handle planning events.
|
|
77
|
+
The callback should be of type `PlanningEventCallback = Callable[[PlanningEvent], None] | Callable[[PlanningEvent], Awaitable[None]]`.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
PlanResult: The result of the planning process, including the generated plan and metadata.
|
|
81
|
+
|
|
82
|
+
Notes:
|
|
83
|
+
You can use `on_event` to monitor the planning process and react to intermediate events.
|
|
84
|
+
"""
|
|
85
|
+
return await self.service.plan(
|
|
86
|
+
goal=goal,
|
|
87
|
+
user_inputs=user_inputs,
|
|
88
|
+
external_slots=external_slots,
|
|
89
|
+
flow_ids=flow_ids,
|
|
90
|
+
instruction=instruction,
|
|
91
|
+
allow_partial=allow_partial,
|
|
92
|
+
preferred_external_keys=preferred_external_keys,
|
|
93
|
+
memory_snippets=memory_snippets,
|
|
94
|
+
artifact_snippets=artifact_snippets,
|
|
95
|
+
on_event=on_event,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
async def plan_with_context(
|
|
99
|
+
self,
|
|
100
|
+
ctx: PlanningContext,
|
|
101
|
+
*,
|
|
102
|
+
on_event: PlanEventsCallback | None = None,
|
|
103
|
+
) -> PlanResult:
|
|
104
|
+
"""
|
|
105
|
+
Plan a task using the provided planning context.
|
|
106
|
+
|
|
107
|
+
This method delegates the planning process to the underlying service, allowing
|
|
108
|
+
for the generation of a plan based on the given context and optional event callback.
|
|
109
|
+
|
|
110
|
+
Examples:
|
|
111
|
+
Basic usage to generate a plan:
|
|
112
|
+
```python
|
|
113
|
+
result = await planner.plan_with_context(context)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Using an event callback to monitor planning progress:
|
|
117
|
+
```python
|
|
118
|
+
async def on_event(event):
|
|
119
|
+
print(f"Received event: {event}")
|
|
120
|
+
|
|
121
|
+
result = await planner.plan_with_context(context, on_event=on_event)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
ctx: The `PlanningContext` object containing the necessary information for planning.
|
|
126
|
+
on_event: Optional callback function to handle planning events. Defaults to None.
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
A `PlanResult` object containing the outcome of the planning process.
|
|
130
|
+
|
|
131
|
+
Notes:
|
|
132
|
+
- The `on_event` callback can be used to receive updates or intermediate results
|
|
133
|
+
during the planning process.
|
|
134
|
+
"""
|
|
135
|
+
return await self.service.plan_with_context(ctx, on_event=on_event)
|
|
136
|
+
|
|
137
|
+
async def parse_inputs(
|
|
138
|
+
self,
|
|
139
|
+
*,
|
|
140
|
+
message: str,
|
|
141
|
+
missing_keys: list[str],
|
|
142
|
+
instruction: str | None = None,
|
|
143
|
+
):
|
|
144
|
+
"""
|
|
145
|
+
Parse input data and handle missing keys.
|
|
146
|
+
|
|
147
|
+
This method processes the provided input message, identifies any missing keys,
|
|
148
|
+
and optionally uses an instruction to guide the parsing process. It delegates
|
|
149
|
+
the actual parsing logic to the `service.parse_inputs` method.
|
|
150
|
+
|
|
151
|
+
Examples:
|
|
152
|
+
Basic usage to parse inputs:
|
|
153
|
+
```python
|
|
154
|
+
result = await node_planner.parse_inputs(
|
|
155
|
+
message="Input data with key1 = 0.1 and key2 = dummy string inputs",
|
|
156
|
+
missing_keys=["key1", "key2"]
|
|
157
|
+
)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Parsing with an additional instruction:
|
|
161
|
+
```python
|
|
162
|
+
result = await node_planner.parse_inputs(
|
|
163
|
+
message="Input data with key1 equals 0.1 and key2 is some dummy string inputs",
|
|
164
|
+
missing_keys=["key1", "key2"],
|
|
165
|
+
instruction="key1 is a float and key2 is a string. Make sure all values are included in a dictionary."
|
|
166
|
+
)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
message: The input message to be parsed.
|
|
171
|
+
missing_keys: Field names whose values we want to extract.
|
|
172
|
+
instruction: Optional instruction to guide the parsing process.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
The result of the parsing operation as returned by the `service.parse_inputs` method.
|
|
176
|
+
|
|
177
|
+
Notes:
|
|
178
|
+
This method is asynchronous and relies on the `service.parse_inputs` implementation
|
|
179
|
+
for the actual parsing logic.
|
|
180
|
+
"""
|
|
181
|
+
return await self.service.parse_inputs(
|
|
182
|
+
message=message,
|
|
183
|
+
missing_keys=missing_keys,
|
|
184
|
+
instruction=instruction,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# ---------- Execution (auto-fill context) ----------
|
|
188
|
+
|
|
189
|
+
async def execute(
|
|
190
|
+
self,
|
|
191
|
+
plan: CandidatePlan,
|
|
192
|
+
*,
|
|
193
|
+
user_inputs: dict[str, Any] | None = None,
|
|
194
|
+
on_event: ExecEventsCallback | None = None,
|
|
195
|
+
identity: RequestIdentity | None = None,
|
|
196
|
+
visibility: RunVisibility = RunVisibility.normal,
|
|
197
|
+
importance: RunImportance = RunImportance.normal,
|
|
198
|
+
session_id: str | None = None,
|
|
199
|
+
agent_id: str | None = None,
|
|
200
|
+
app_id: str | None = None,
|
|
201
|
+
tags: list[str] | None = None,
|
|
202
|
+
origin: RunOrigin | None = None,
|
|
203
|
+
) -> ExecutionResult:
|
|
204
|
+
"""
|
|
205
|
+
Execute a plan with the provided context and parameters.
|
|
206
|
+
|
|
207
|
+
This method uses the NodeContext to auto-fill execution metadata such as
|
|
208
|
+
identity, session, agent, and application IDs. Callers can override these
|
|
209
|
+
defaults by providing explicit keyword arguments.
|
|
210
|
+
|
|
211
|
+
Examples:
|
|
212
|
+
Basic usage to execute a plan:
|
|
213
|
+
```python
|
|
214
|
+
result = await node_planner.execute(plan)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Executing with additional user inputs and event handling:
|
|
218
|
+
```python
|
|
219
|
+
result = await node_planner.execute(
|
|
220
|
+
plan,
|
|
221
|
+
user_inputs={"key1": "value1"},
|
|
222
|
+
on_event=lambda event: print(f"Execution event: {event}")
|
|
223
|
+
)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
plan: The `CandidatePlan` object to execute.
|
|
228
|
+
user_inputs: Optional dictionary of user-provided inputs for the execution. Values referenced as "${user.<key>}"
|
|
229
|
+
on_event: Optional callback function to handle execution events.
|
|
230
|
+
identity: Optional `RequestIdentity` to override the default identity.
|
|
231
|
+
visibility: Visibility level for the execution (default: `RunVisibility.normal`).
|
|
232
|
+
importance: Importance level for the execution (default: `RunImportance.normal`).
|
|
233
|
+
session_id: Optional session ID to override the default session.
|
|
234
|
+
agent_id: Optional agent ID to override the default agent.
|
|
235
|
+
app_id: Optional application ID to override the default application.
|
|
236
|
+
tags: Optional list of tags to associate with the execution.
|
|
237
|
+
origin: Optional `RunOrigin` to specify the origin of the execution.
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
ExecutionResult: The result of the execution process, including status and metadata.
|
|
241
|
+
|
|
242
|
+
Notes:
|
|
243
|
+
Use the `on_event` callback to monitor execution progress and handle intermediate events.
|
|
244
|
+
"""
|
|
245
|
+
ctx = self.node_ctx
|
|
246
|
+
|
|
247
|
+
eff_identity = identity or ctx.identity
|
|
248
|
+
eff_session_id = session_id or ctx.session_id
|
|
249
|
+
eff_agent_id = agent_id or ctx.agent_id
|
|
250
|
+
eff_app_id = app_id or ctx.app_id
|
|
251
|
+
|
|
252
|
+
eff_tags = list(tags or [])
|
|
253
|
+
# auto-add some helpful tags
|
|
254
|
+
eff_tags.append(f"graph:{ctx.graph_id}")
|
|
255
|
+
eff_tags.append(f"node:{ctx.node_id}")
|
|
256
|
+
if ctx.run_id:
|
|
257
|
+
eff_tags.append(f"run:{ctx.run_id}")
|
|
258
|
+
|
|
259
|
+
eff_origin = origin
|
|
260
|
+
if eff_origin is None:
|
|
261
|
+
# tiny heuristic; tune later
|
|
262
|
+
eff_origin = RunOrigin.agent if ctx.agent_id else RunOrigin.user
|
|
263
|
+
|
|
264
|
+
return await self.service.execute_plan(
|
|
265
|
+
plan,
|
|
266
|
+
user_inputs=user_inputs,
|
|
267
|
+
on_event=on_event,
|
|
268
|
+
identity=eff_identity,
|
|
269
|
+
visibility=visibility,
|
|
270
|
+
importance=importance,
|
|
271
|
+
session_id=eff_session_id,
|
|
272
|
+
agent_id=eff_agent_id,
|
|
273
|
+
app_id=eff_app_id,
|
|
274
|
+
tags=eff_tags,
|
|
275
|
+
origin=eff_origin,
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
async def plan_and_execute(
|
|
279
|
+
self,
|
|
280
|
+
*,
|
|
281
|
+
goal: str,
|
|
282
|
+
user_inputs: dict[str, Any] | None = None,
|
|
283
|
+
external_slots: dict[str, Any] | None = None,
|
|
284
|
+
flow_ids: list[str] | None = None,
|
|
285
|
+
instruction: str | None = None,
|
|
286
|
+
allow_partial: bool = False,
|
|
287
|
+
preferred_external_keys: list[str] | None = None,
|
|
288
|
+
memory_snippets: list[str] | None = None,
|
|
289
|
+
artifact_snippets: list[str] | None = None,
|
|
290
|
+
planning_events_cb: PlanEventsCallback | None = None,
|
|
291
|
+
execution_events_cb: ExecEventsCallback | None = None,
|
|
292
|
+
identity: RequestIdentity | None = None,
|
|
293
|
+
visibility: RunVisibility = RunVisibility.normal,
|
|
294
|
+
importance: RunImportance = RunImportance.normal,
|
|
295
|
+
session_id: str | None = None,
|
|
296
|
+
agent_id: str | None = None,
|
|
297
|
+
app_id: str | None = None,
|
|
298
|
+
tags: list[str] | None = None,
|
|
299
|
+
origin: RunOrigin | None = None,
|
|
300
|
+
) -> tuple[PlanResult, ExecutionResult | None]:
|
|
301
|
+
"""
|
|
302
|
+
Plan a task and execute the resulting plan with node-bound context.
|
|
303
|
+
|
|
304
|
+
This method combines the planning and execution phases into a single operation.
|
|
305
|
+
It generates a plan based on the provided goal and context, then executes the
|
|
306
|
+
accepted plan using the NodeContext to auto-fill execution metadata.
|
|
307
|
+
|
|
308
|
+
Examples:
|
|
309
|
+
Basic usage to plan and execute:
|
|
310
|
+
```python
|
|
311
|
+
plan_result, exec_result = await node_planner.plan_and_execute(goal="Optimize workflow")
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Providing additional inputs and handling events:
|
|
315
|
+
```python
|
|
316
|
+
plan_result, exec_result = await node_planner.plan_and_execute(
|
|
317
|
+
goal="Generate report",
|
|
318
|
+
user_inputs={"date": "2023-10-01"},
|
|
319
|
+
planning_events_cb=lambda event: print(f"Planning event: {event}"),
|
|
320
|
+
execution_events_cb=lambda event: print(f"Execution event: {event}")
|
|
321
|
+
)
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Args:
|
|
325
|
+
goal: The primary objective or goal for the planning process.
|
|
326
|
+
user_inputs: Optional dictionary of user-provided inputs for the plan and execution.
|
|
327
|
+
external_slots: Optional dictionary of external slot values to consider during planning.
|
|
328
|
+
flow_ids: Optional list of flow identifiers to constrain the planning scope.
|
|
329
|
+
instruction: Optional instruction or guidance for the planner.
|
|
330
|
+
allow_partial: Whether to allow partial plans if the goal cannot be fully satisfied (default: False).
|
|
331
|
+
preferred_external_keys: Optional list of preferred external keys to prioritize during planning.
|
|
332
|
+
memory_snippets: Optional list of memory snippets to include in the planning context.
|
|
333
|
+
artifact_snippets: Optional list of artifact snippets to include in the planning context.
|
|
334
|
+
planning_events_cb: Optional callback function to handle planning events.
|
|
335
|
+
execution_events_cb: Optional callback function to handle execution events.
|
|
336
|
+
identity: Optional `RequestIdentity` to override the default identity.
|
|
337
|
+
visibility: Visibility level for the execution (default: `RunVisibility.normal`).
|
|
338
|
+
importance: Importance level for the execution (default: `RunImportance.normal`).
|
|
339
|
+
session_id: Optional session ID to override the default session.
|
|
340
|
+
agent_id: Optional agent ID to override the default agent.
|
|
341
|
+
app_id: Optional application ID to override the default application.
|
|
342
|
+
tags: Optional list of tags to associate with the execution.
|
|
343
|
+
origin: Optional `RunOrigin` to specify the origin of the execution.
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
tuple[PlanResult, ExecutionResult | None]: A tuple containing the result of the planning process
|
|
347
|
+
and the result of the execution process (if applicable).
|
|
348
|
+
|
|
349
|
+
Notes:
|
|
350
|
+
- Use the `planning_events_cb` and `execution_events_cb` callbacks to monitor progress and handle
|
|
351
|
+
intermediate events during the planning and execution phases.
|
|
352
|
+
"""
|
|
353
|
+
ctx = self.node_ctx
|
|
354
|
+
|
|
355
|
+
eff_identity = identity or ctx.identity
|
|
356
|
+
eff_session_id = session_id or ctx.session_id
|
|
357
|
+
eff_agent_id = agent_id or ctx.agent_id
|
|
358
|
+
eff_app_id = app_id or ctx.app_id
|
|
359
|
+
|
|
360
|
+
eff_tags = list(tags or [])
|
|
361
|
+
eff_tags.append(f"graph:{ctx.graph_id}")
|
|
362
|
+
eff_tags.append(f"node:{ctx.node_id}")
|
|
363
|
+
if ctx.run_id:
|
|
364
|
+
eff_tags.append(f"run:{ctx.run_id}")
|
|
365
|
+
|
|
366
|
+
eff_origin = origin
|
|
367
|
+
# if eff_origin is None:
|
|
368
|
+
# eff_origin = RunOrigin.agent if ctx.agent_id else RunOrigin.user
|
|
369
|
+
|
|
370
|
+
return await self.service.plan_and_execute(
|
|
371
|
+
goal=goal,
|
|
372
|
+
user_inputs=user_inputs,
|
|
373
|
+
external_slots=external_slots,
|
|
374
|
+
flow_ids=flow_ids,
|
|
375
|
+
instruction=instruction,
|
|
376
|
+
allow_partial=allow_partial,
|
|
377
|
+
preferred_external_keys=preferred_external_keys,
|
|
378
|
+
memory_snippets=memory_snippets,
|
|
379
|
+
artifact_snippets=artifact_snippets,
|
|
380
|
+
planning_events_cb=planning_events_cb,
|
|
381
|
+
execution_events_cb=execution_events_cb,
|
|
382
|
+
identity=eff_identity,
|
|
383
|
+
visibility=visibility,
|
|
384
|
+
importance=importance,
|
|
385
|
+
session_id=eff_session_id,
|
|
386
|
+
agent_id=eff_agent_id,
|
|
387
|
+
app_id=eff_app_id,
|
|
388
|
+
tags=eff_tags,
|
|
389
|
+
origin=eff_origin,
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
# ---------- Background execution (auto-fill context) ----------
|
|
393
|
+
|
|
394
|
+
async def execute_background(
|
|
395
|
+
self,
|
|
396
|
+
plan: CandidatePlan,
|
|
397
|
+
*,
|
|
398
|
+
user_inputs: dict[str, Any] | None = None,
|
|
399
|
+
on_event: ExecEventsCallback | None = None,
|
|
400
|
+
identity: RequestIdentity | None = None,
|
|
401
|
+
visibility: RunVisibility = RunVisibility.normal,
|
|
402
|
+
importance: RunImportance = RunImportance.normal,
|
|
403
|
+
session_id: str | None = None,
|
|
404
|
+
agent_id: str | None = None,
|
|
405
|
+
app_id: str | None = None,
|
|
406
|
+
tags: list[str] | None = None,
|
|
407
|
+
origin: RunOrigin | None = None,
|
|
408
|
+
on_complete: Callable[[ExecutionResult], Any] | None = None,
|
|
409
|
+
exec_id: str | None = None,
|
|
410
|
+
) -> BackgroundExecutionHandle:
|
|
411
|
+
"""
|
|
412
|
+
Execute a candidate plan in the background, bound to this node.
|
|
413
|
+
This method initiates a fire-and-forget execution of the provided plan,
|
|
414
|
+
leveraging the node's context and metadata. Progress updates can be
|
|
415
|
+
reported via the `on_event` callback, and completion is signaled through
|
|
416
|
+
the `on_complete` callback.
|
|
417
|
+
|
|
418
|
+
Examples:
|
|
419
|
+
Basic usage to execute a plan in the background:
|
|
420
|
+
```python
|
|
421
|
+
handle = await node_planner.execute_background(plan)
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
Executing with additional metadata and callbacks:
|
|
425
|
+
```python
|
|
426
|
+
handle = await node_planner.execute_background(
|
|
427
|
+
user_inputs={"param1": "value1"},
|
|
428
|
+
on_event=event_callback,
|
|
429
|
+
on_complete=completion_callback,
|
|
430
|
+
tags=["custom:tag"],
|
|
431
|
+
)
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
Args:
|
|
435
|
+
plan: The candidate plan to execute.
|
|
436
|
+
user_inputs: Optional dictionary of user-provided inputs for the execution.
|
|
437
|
+
on_event: Optional callback to handle execution progress events.
|
|
438
|
+
identity: Optional identity to associate with the execution; defaults to the node's context identity.
|
|
439
|
+
visibility: The visibility level of the execution (default: RunVisibility.normal).
|
|
440
|
+
importance: The importance level of the execution (default: RunImportance.normal).
|
|
441
|
+
session_id: Optional session ID to associate with the execution; defaults to the node's context session ID.
|
|
442
|
+
agent_id: Optional agent ID to associate with the execution; defaults to the node's context agent ID.
|
|
443
|
+
app_id: Optional application ID to associate with the execution; defaults to the node's context app ID.
|
|
444
|
+
tags: Optional list of tags to associate with the execution; additional tags are derived from the node's context.
|
|
445
|
+
origin: Optional origin of the execution; defaults to `RunOrigin.agent` if an agent ID is present, otherwise `RunOrigin.user`.
|
|
446
|
+
on_complete: Optional callback to handle execution completion.
|
|
447
|
+
exec_id: Optional explicit execution ID to associate with the execution.
|
|
448
|
+
|
|
449
|
+
Returns:
|
|
450
|
+
BackgroundExecutionHandle: A handle to monitor or interact with the background execution.
|
|
451
|
+
|
|
452
|
+
Notes:
|
|
453
|
+
- Tags automatically include identifiers for the graph, node, and run (if available) from the node's context.
|
|
454
|
+
- The `on_event` callback is invoked with progress updates, while the `on_complete` callback is invoked upon completion.
|
|
455
|
+
"""
|
|
456
|
+
ctx = self.node_ctx
|
|
457
|
+
|
|
458
|
+
eff_identity = identity or ctx.identity
|
|
459
|
+
eff_session_id = session_id or ctx.session_id
|
|
460
|
+
eff_agent_id = agent_id or ctx.agent_id
|
|
461
|
+
eff_app_id = app_id or ctx.app_id
|
|
462
|
+
|
|
463
|
+
eff_tags = list(tags or [])
|
|
464
|
+
eff_tags.append(f"graph:{ctx.graph_id}")
|
|
465
|
+
eff_tags.append(f"node:{ctx.node_id}")
|
|
466
|
+
if ctx.run_id:
|
|
467
|
+
eff_tags.append(f"run:{ctx.run_id}")
|
|
468
|
+
|
|
469
|
+
eff_origin = origin
|
|
470
|
+
if eff_origin is None:
|
|
471
|
+
eff_origin = RunOrigin.agent if ctx.agent_id else RunOrigin.user
|
|
472
|
+
|
|
473
|
+
handle = await self.service.execute_background(
|
|
474
|
+
plan,
|
|
475
|
+
user_inputs=user_inputs,
|
|
476
|
+
on_event=on_event,
|
|
477
|
+
identity=eff_identity,
|
|
478
|
+
visibility=visibility,
|
|
479
|
+
importance=importance,
|
|
480
|
+
session_id=eff_session_id,
|
|
481
|
+
agent_id=eff_agent_id,
|
|
482
|
+
app_id=eff_app_id,
|
|
483
|
+
tags=eff_tags,
|
|
484
|
+
origin=eff_origin,
|
|
485
|
+
on_complete=on_complete,
|
|
486
|
+
exec_id=exec_id,
|
|
487
|
+
)
|
|
488
|
+
return handle
|
|
489
|
+
|
|
490
|
+
async def plan_and_execute_background(
|
|
491
|
+
self,
|
|
492
|
+
*,
|
|
493
|
+
goal: str,
|
|
494
|
+
user_inputs: dict[str, Any] | None = None,
|
|
495
|
+
external_slots: dict[str, Any] | None = None,
|
|
496
|
+
flow_ids: list[str] | None = None,
|
|
497
|
+
instruction: str | None = None,
|
|
498
|
+
allow_partial: bool = False,
|
|
499
|
+
preferred_external_keys: list[str] | None = None,
|
|
500
|
+
memory_snippets: list[str] | None = None,
|
|
501
|
+
artifact_snippets: list[str] | None = None,
|
|
502
|
+
planning_events_cb: PlanEventsCallback | None = None,
|
|
503
|
+
execution_events_cb: ExecEventsCallback | None = None,
|
|
504
|
+
identity: RequestIdentity | None = None,
|
|
505
|
+
visibility: RunVisibility = RunVisibility.normal,
|
|
506
|
+
importance: RunImportance = RunImportance.normal,
|
|
507
|
+
session_id: str | None = None,
|
|
508
|
+
agent_id: str | None = None,
|
|
509
|
+
app_id: str | None = None,
|
|
510
|
+
tags: list[str] | None = None,
|
|
511
|
+
origin: RunOrigin | None = None,
|
|
512
|
+
on_complete: Callable[[ExecutionResult], Any] | None = None,
|
|
513
|
+
exec_id: str | None = None,
|
|
514
|
+
) -> tuple[PlanResult, BackgroundExecutionHandle | None]:
|
|
515
|
+
"""
|
|
516
|
+
Plan and execute a goal asynchronously in the background.
|
|
517
|
+
This method delegates the planning and execution of a goal to the service layer,
|
|
518
|
+
while auto-filling the node context and other metadata. It supports callbacks
|
|
519
|
+
for planning and execution events, and allows for customization of execution
|
|
520
|
+
parameters such as visibility, importance, and tags.
|
|
521
|
+
|
|
522
|
+
Examples:
|
|
523
|
+
Basic usage to plan and execute a goal:
|
|
524
|
+
```python
|
|
525
|
+
plan_result, handle = await node_planner.plan_and_execute_background(
|
|
526
|
+
goal="Achieve X",
|
|
527
|
+
user_inputs={"key": "value"}
|
|
528
|
+
)
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
Using callbacks and additional metadata:
|
|
532
|
+
```python
|
|
533
|
+
plan_result, handle = await node_planner.plan_and_execute_background(
|
|
534
|
+
goal="Achieve Y",
|
|
535
|
+
planning_events_cb=on_planning_event,
|
|
536
|
+
execution_events_cb=on_execution_event,
|
|
537
|
+
tags=["custom-tag"],
|
|
538
|
+
visibility=RunVisibility.inline,
|
|
539
|
+
)
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
Args:
|
|
543
|
+
goal: The goal to achieve during the planning and execution process.
|
|
544
|
+
user_inputs: Optional dictionary of user-provided inputs for planning.
|
|
545
|
+
external_slots: Optional dictionary of external slots to use during planning.
|
|
546
|
+
flow_ids: Optional list of flow IDs to consider during execution.
|
|
547
|
+
instruction: Optional instruction to guide the planning process.
|
|
548
|
+
allow_partial: Whether to allow partial execution if the full goal cannot be achieved.
|
|
549
|
+
preferred_external_keys: Optional list of preferred external keys for planning.
|
|
550
|
+
memory_snippets: Optional list of memory snippets to include in planning.
|
|
551
|
+
artifact_snippets: Optional list of artifact snippets to include in planning.
|
|
552
|
+
planning_events_cb: Optional callback for planning events.
|
|
553
|
+
execution_events_cb: Optional callback for execution events.
|
|
554
|
+
identity: Optional identity to use for the execution context.
|
|
555
|
+
visibility: Visibility level for the execution (default: normal).
|
|
556
|
+
importance: Importance level for the execution (default: normal).
|
|
557
|
+
session_id: Optional session ID to associate with the execution.
|
|
558
|
+
agent_id: Optional agent ID to associate with the execution.
|
|
559
|
+
app_id: Optional application ID to associate with the execution.
|
|
560
|
+
tags: Optional list of tags to associate with the execution.
|
|
561
|
+
origin: Optional origin metadata for the execution.
|
|
562
|
+
on_complete: Optional callback to invoke upon completion of execution.
|
|
563
|
+
exec_id: Optional execution ID to associate with the process.
|
|
564
|
+
|
|
565
|
+
Returns:
|
|
566
|
+
A tuple containing the planning result and an optional background execution handle.
|
|
567
|
+
|
|
568
|
+
Notes:
|
|
569
|
+
- The method automatically appends node-specific tags such as `graph:<graph_id>`
|
|
570
|
+
and `node:<node_id>` to the provided tags.
|
|
571
|
+
- If a `run_id` is available in the node context, it is also appended as a tag.
|
|
572
|
+
"""
|
|
573
|
+
ctx = self.node_ctx
|
|
574
|
+
|
|
575
|
+
eff_identity = identity or ctx.identity
|
|
576
|
+
eff_session_id = session_id or ctx.session_id
|
|
577
|
+
eff_agent_id = agent_id or ctx.agent_id
|
|
578
|
+
eff_app_id = app_id or ctx.app_id
|
|
579
|
+
|
|
580
|
+
eff_tags = list(tags or [])
|
|
581
|
+
eff_tags.append(f"graph:{ctx.graph_id}")
|
|
582
|
+
eff_tags.append(f"node:{ctx.node_id}")
|
|
583
|
+
if ctx.run_id:
|
|
584
|
+
eff_tags.append(f"run:{ctx.run_id}")
|
|
585
|
+
|
|
586
|
+
eff_origin = origin
|
|
587
|
+
# keep same behavior as plan_and_execute (no default if None)
|
|
588
|
+
|
|
589
|
+
plan_result, handle = await self.service.plan_and_execute_background(
|
|
590
|
+
goal=goal,
|
|
591
|
+
user_inputs=user_inputs,
|
|
592
|
+
external_slots=external_slots,
|
|
593
|
+
flow_ids=flow_ids,
|
|
594
|
+
instruction=instruction,
|
|
595
|
+
allow_partial=allow_partial,
|
|
596
|
+
preferred_external_keys=preferred_external_keys,
|
|
597
|
+
memory_snippets=memory_snippets,
|
|
598
|
+
artifact_snippets=artifact_snippets,
|
|
599
|
+
planning_events_cb=planning_events_cb,
|
|
600
|
+
execution_events_cb=execution_events_cb,
|
|
601
|
+
identity=eff_identity,
|
|
602
|
+
visibility=visibility,
|
|
603
|
+
importance=importance,
|
|
604
|
+
session_id=eff_session_id,
|
|
605
|
+
agent_id=eff_agent_id,
|
|
606
|
+
app_id=eff_app_id,
|
|
607
|
+
tags=eff_tags,
|
|
608
|
+
origin=eff_origin,
|
|
609
|
+
on_complete=on_complete,
|
|
610
|
+
exec_id=exec_id,
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
return plan_result, handle
|