feat(adk): unify foreground and background task runtime - #1204
feat(adk): unify foreground and background task runtime#1204shentongmartin wants to merge 27 commits into
Conversation
2770e93 to
1b27dca
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## alpha/10 #1204 +/- ##
===========================================
Coverage ? 83.06%
===========================================
Files ? 228
Lines ? 41746
Branches ? 0
===========================================
Hits ? 34677
Misses ? 4691
Partials ? 2378 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
3318982 to
a553770
Compare
|
|
||
| Implemented on `feat/durabletask`. | ||
| Implemented on `feat/task-ownership-runtime`. | ||
|
|
There was a problem hiding this comment.
🚨 Breaking API Changes Detected
Package: github.com/cloudwego/eino/adk/backgroundtask/tool
Incompatible changes:
- AdoptRequest: removed
- AdoptResult: removed
- BackgroundTool: removed
- ErrResumeInputRejected: removed
- ExecutorKey: removed
- ForegroundHandoffTool: removed
- InputPreparer: removed
- InputRequest: removed
- ManagedToolConfig: removed
- ManagedToolResponseEvent: removed
- ManagedToolResponseEventForegroundResult: removed
- ManagedToolResponseEventLaunchResult: removed
- ManagedToolResponseEventType: removed
- ManagedToolResponseEventUpdate: removed
- MaterializeOutputRequest: removed
- NewManagedTool: removed
- NewProgressReader: removed
- NewRegistry: removed
- Outcome: removed
- OutputMaterializer: removed
- ProgressReader: removed
- ReadInputRequest: removed
- RecoverRequest: removed
- RecoverableBackgroundTool: removed
- RecoverableExecutorKey: removed
- RegisterExecutors: removed
- Registration: removed
- Registry: removed
- ReserveOutputRequest: removed
- ResumableBackgroundTool: removed
- ResumeRequest: removed
- Run: removed
- StartRequest: removed
- StartResult: removed
- Submit: removed
- SubmitRequest: removed
- Update: removed
- UpdateSource: removed
Review Guidelines
Please ensure that:
- The changes are absolutely necessary
- They are properly documented
- Migration guides are provided if needed
There was a problem hiding this comment.
当前通用能力已迁移到 adk/task/tool,ManagedToolConfig、NewManagedTool、Registry、Submit、Run 等仍在新包;ForegroundHandoffTool/Adopt* 等 tool-specific owner-transfer API 按 task-first 设计删除,auto 与 explicit background 统一由 Manager-owned execution 执行。迁移文档明确不为旧 alpha 包面提供兼容 shim。这是alpha breaking API决策,请维护者确认。
| "github.com/cloudwego/eino/adk/internal/agenttool" | ||
| "github.com/cloudwego/eino/adk/internal/foreground" | ||
| "github.com/cloudwego/eino/adk/internal/taskfirst" | ||
| "github.com/cloudwego/eino/adk/task" |
There was a problem hiding this comment.
🚨 Breaking API Changes Detected
Package: github.com/cloudwego/eino/adk/middlewares/subagent
Incompatible changes:
- BackgroundConfig: removed
- DurableBackgroundConfig: removed
- DurableTaskProgressReader: removed
- LocalBackgroundConfig: removed
- NameFromTask: changed from func(*github.com/cloudwego/eino/adk/backgroundtask.Task) string to func(*github.com/cloudwego/eino/adk/task/background.TaskSnapshot) string
- NewDurableTaskProgressReader: removed
- TypedBackgroundConfig: removed
- TypedConfig.Background: removed
- TypedDurableBackgroundConfig: removed
- TypedLocalBackgroundConfig: removed
Review Guidelines
Please ensure that:
- The changes are absolutely necessary
- They are properly documented
- Migration guides are provided if needed
There was a problem hiding this comment.
当前 adk/middlewares/subagent 将 Config.Background 收敛为 Config.Tasks,使用 TypedTaskConfig{Local, Durable};durable 配置以 subagent.Controller 作为统一 Start/Continue/Handle/恢复/handoff 入口,NameFromTask 相应接收持久化的 TaskSnapshot。这是alpha breaking API决策,请维护者确认。
| backgroundlocal "github.com/cloudwego/eino/adk/backgroundtask/local" | ||
| "github.com/cloudwego/eino/adk/filesystem" | ||
| "github.com/cloudwego/eino/adk/task/background" | ||
| backgroundlocal "github.com/cloudwego/eino/adk/task/local" |
There was a problem hiding this comment.
🚨 Breaking API Changes Detected
Package: github.com/cloudwego/eino/adk/middlewares/filesystem
Incompatible changes:
- CommandFromTask: changed from func(*github.com/cloudwego/eino/adk/backgroundtask.Task) string to func(*github.com/cloudwego/eino/adk/task/background.TaskSnapshot) string
- LocalBackgroundConfig.Runner: changed from *github.com/cloudwego/eino/adk/backgroundtask/local.Runner to *github.com/cloudwego/eino/adk/task/local.Runner
- ManagedExecuteToolDesc: value changed from "Executes a bash command and returns its output.\n\n- Working directo... to "Executes a bash command and returns its output.\n\n- Working directo...
- ManagedExecuteToolDescChinese: value changed from "执行一条 bash 命令并返回其输出。\n\n- 工作目录在多次调用间保持,但优先使用绝对路径 —— 复合命令中的
cd可能触发权... to "执行一条 bash 命令并返回其输出。\n\n- 工作目录在多次调用间保持,但优先使用绝对路径 —— 复合命令中的cd可能触发权... - RecoverableBackgroundConfig.Executors: removed
- RecoverableBackgroundConfig.Manager: changed from *github.com/cloudwego/eino/adk/backgroundtask.Manager to *github.com/cloudwego/eino/adk/task/background.Manager
- RecoverableBackgroundConfig.OutputMaterializer: changed from github.com/cloudwego/eino/adk/backgroundtask/tool.OutputMaterializer to github.com/cloudwego/eino/adk/task/tool.OutputMaterializer
- RecoverableBackgroundConfig.Shell: changed from github.com/cloudwego/eino/adk/backgroundtask/shell.RecoverableShell to github.com/cloudwego/eino/adk/task/shell.RecoverableShell
- RecoverableBackgroundConfig.ShouldAutoBackground: changed from func(context.Context, *github.com/cloudwego/eino/adk/internal/foreground.CandidateInfo) bool to github.com/cloudwego/eino/adk/task/foreground.ShouldAutoBackground
- RecoverableBackgroundConfig.ToolRegistry: changed from *github.com/cloudwego/eino/adk/backgroundtask/tool.Registry to *github.com/cloudwego/eino/adk/task/tool.Registry
Review Guidelines
Please ensure that:
- The changes are absolutely necessary
- They are properly documented
- Migration guides are provided if needed
There was a problem hiding this comment.
当前 filesystem 配置显式区分 BackgroundConfig.Local 与 Recoverable;相关类型迁移到 adk/task/{background,local,shell,tool,foreground},Executors 删除后由 Manager.LoadOrRegisterExecutor 内聚注册,策略回调改用可公开引用的 foreground 类型。工具描述变更对应新的 task-first 行为。这是alpha breaking API决策,请维护者确认。
| filesystem2 "github.com/cloudwego/eino/adk/middlewares/filesystem" | ||
| "github.com/cloudwego/eino/adk/middlewares/subagent" | ||
| taskmw "github.com/cloudwego/eino/adk/middlewares/task" | ||
| "github.com/cloudwego/eino/adk/task/background" |
There was a problem hiding this comment.
🚨 Breaking API Changes Detected
Package: github.com/cloudwego/eino/adk/prebuilt/deep
Incompatible changes:
- BackgroundConfig: removed
- RecoverableShellConfig.OutputMaterializer: changed from github.com/cloudwego/eino/adk/backgroundtask/tool.OutputMaterializer to github.com/cloudwego/eino/adk/task/tool.OutputMaterializer
- RecoverableShellConfig.Shell: changed from github.com/cloudwego/eino/adk/backgroundtask/shell.RecoverableShell to github.com/cloudwego/eino/adk/task/shell.RecoverableShell
- TypedBackgroundConfig: removed
- TypedConfig.Background: removed
- TypedDurableSubAgentConfig.Executor: removed
- TypedDurableSubAgentConfig.RunOptionsFactories: changed from map[string]github.com/cloudwego/eino/adk/backgroundtask/subagent.RunOptionsFactory to map[string]github.com/cloudwego/eino/adk/task/subagent.RunOptionsFactory
Review Guidelines
Please ensure that:
- The changes are absolutely necessary
- They are properly documented
- Migration guides are provided if needed
There was a problem hiding this comment.
当前 adk/prebuilt/deep 将 Config.Background 收敛为 Config.Tasks/TypedTaskConfig,在同一 TaskID 空间统一 sub-agent、local/recoverable shell 与 task control;durable sub-agent 由 Runtime *subagent.Controller 取代外置 Executor,相关依赖迁移到 adk/task/...。这是alpha breaking API决策,请维护者确认。
85d42c8 to
3aa547c
Compare
|
|
||
| Implemented on `feat/durabletask`. | ||
| Implemented on `feat/task-ownership-runtime`. | ||
|
|
There was a problem hiding this comment.
🚨 Breaking API Changes Detected
Package: github.com/cloudwego/eino/adk/prebuilt/deep
Incompatible changes:
- BackgroundConfig: removed
- RecoverableShellConfig.OutputMaterializer: changed from github.com/cloudwego/eino/adk/backgroundtask/tool.OutputMaterializer to github.com/cloudwego/eino/adk/task/tool.OutputMaterializer
- RecoverableShellConfig.Shell: changed from github.com/cloudwego/eino/adk/backgroundtask/shell.RecoverableShell to github.com/cloudwego/eino/adk/task/shell.RecoverableShell
- TypedBackgroundConfig: removed
- TypedConfig.Background: removed
- TypedDurableSubAgentConfig.Executor: removed
- TypedDurableSubAgentConfig.RunOptionsFactories: changed from map[string]github.com/cloudwego/eino/adk/backgroundtask/subagent.RunOptionsFactory to map[string]github.com/cloudwego/eino/adk/task/subagent.RunOptionsFactory
Review Guidelines
Please ensure that:
- The changes are absolutely necessary
- They are properly documented
- Migration guides are provided if needed
There was a problem hiding this comment.
与前一条 deep 报告相同:当前 adk/prebuilt/deep 使用 Config.Tasks/TypedTaskConfig 统一 TaskID 空间,durable sub-agent 改由 Runtime *subagent.Controller 管理,shell/tool 类型迁移到 adk/task/...,不保留旧 Background/Executor 配置面。这是alpha breaking API决策,请维护者确认。
There was a problem hiding this comment.
与前一条 deep 报告相同:当前 adk/prebuilt/deep 使用 Config.Tasks/TypedTaskConfig 统一 TaskID 空间,durable sub-agent 改由 Runtime *subagent.Controller 管理,shell/tool 类型迁移到 adk/task/...,不保留旧 Background/Executor 配置面。这是alpha breaking API决策,请维护者确认。
742ab53 to
43e65fc
Compare
5738375 to
d94e4dc
Compare
179f0fb to
385b813
Compare
Model task execution independently from its current lifecycle owner so foreground sub-agents can receive durable input and transfer to background execution without changing task identity. Unify mailbox, executor, outcome, and store APIs around the shared task runtime. Change-Id: I408ca382d8e623faa62fed225fe0a01ec3b5a3be
Separate task input intent from persisted records, make sub-agent handles explicitly recoverable through their controller, and remove duplicate ownership and manager configuration sources. Change-Id: I5102d50a4276f226ede1aced0c9e4096c368f043
Derive nested task scope from parent authority, share one outcome status model across task handles and managed tools, and make sub-agent policy names explicit. Change-Id: Ic9c7baedc4759dcb3b0b44fdf0c48aa376ff35b2
Change-Id: I34f664c01f740240dc1eb1260622bc1083f09f8b
Document the final comprehensive review and cover owner-neutral handle outcomes for failure, cancellation, and context termination. Change-Id: I5014d312a38e976e44155dd587ff2ad27cbb7c49
Carry the latest alpha/10 notification semantics through the task runtime migration and keep new concurrency tests compatible with the repository Go version. Change-Id: I0e4909aef0a54ff1ea89ae4aad0cd73eb18f5f2b
Change-Id: I9f8151ef2753f1e0494ad4b4631dcc66d038e421
Run auto-backgroundable local and managed-tool work under Manager ownership from attempt one. Add deferred publication so foreground completion stays hidden while timeout or caller abort can publish the same running task without handoff. Change-Id: I27820f38b67a0dc47cb504dec53017fbbaf2a0ef
Change-Id: I731b53448ba3f1a0291dd08d8c262c2bf1193e93
Move task event serialization behind executor-specific persisters so callers can receive typed events and persistence-owned streams. Persist replayable event parts through an attempt-fenced writer without holding Store locks for the stream lifetime. Change-Id: If53c20d634ee7478b29ed839b74b3318d73379dd
Change-Id: Ie554dc35b8558f9f91b066a54b427440ef787f4c
Change-Id: I1f1249e620edb1669a68725cbef66322eca4b40d
Change-Id: I12f81e2687d0706d0d648f58f35daaa6a7576111
Change-Id: I56233a949a1789aa84d7c27d2395ce4458ddb6a4
Change-Id: Ic41a43284b1566522dcf970ce7eb924282afe4b2
Change-Id: I10f32c10da694530e38ba0dfa89d392365180fff
Change-Id: I4ec029db1070c1ec0a5fddbe40676cee53cfef0c
Change-Id: I27907101d46859ac0ae3f1f9f645d1879d558ac1
Change-Id: I5b120e0811ac510818d34a162d077f0d5e206fbe
Change-Id: I20ec0bad860ad4e52ca874ecd075b398cd1586f1
Change-Id: I7d28356c3f4e960149f0f851c392b41bf6270d27
Change-Id: I69204ea2236a45bb04f34b13f8f082827dec3a79
Change-Id: I71dc9a9e03bdf7245406ee9335135604f7e9beed
Change-Id: Iff4c398afa0f4dcaf7ee5386001b7912ed93bbb5
Preserve the structured timeout contract while abandoning direct foreground mailboxes, and update stale tests to the current timeout and direct-result APIs. Change-Id: Id7549ed4906ec0765964bd9565c4d9ecd7edc102
Change-Id: I020b24970e2229dfea19aade11869609ca7ebd9b
Change-Id: Iebbb6277cacd712f34fcdc519a0cd93e2ed139d1
95fa766 to
86858f7
Compare
Unified Task Ownership Runtime
Problem
Foreground work may outlive the call that started it. The old runtime handled this in two incompatible ways:
background.Manager, but follow-up input and nested completion still needed one durable identity and mailbox.Public auto-background config also referenced
adk/internal/foreground.CandidateInfo, which external modules cannot name.Solution
This PR introduces one Task model with stable identity, durable communication, and explicit ownership:
TaskIDidentifies one finite execution;ChildSessionIDidentifies durable conversation history.Deferredremains hidden during foreground observation,OnCreatepublishes explicit background work, andOnBackgroundpublishes when the projection detaches.Manager.Publish(taskID)performs the only legal publication transition and does not advance lifecycleVersion, so it cannot invalidate the active attempt.adk/task/foregroundcontains only policy leaf types; timer, publish, cancellation, and terminal races remain in the internal task-first coordinator.Decisions
Canceledsnapshot before returning.Version; Store locking and expected-version fencing still make publish/terminal and publish/cancel races atomic.adk/backgroundtaskpackage or the managed-tool handoff/adopt API introduced within this branch.Key Insight
A Task has three independent concerns:
Keeping these dimensions separate lets one Manager attempt continue unchanged while the caller stops observing it, and lets true parent-owned Sub-agent handoff retain its existing ownership-transfer semantics.
Validation
go vet, andgolangci-lintpass locally.统一 Task Ownership Runtime
问题
Foreground 工作可能在当前调用结束后继续。旧 runtime 对这类场景有两套不一致的处理:
background.Manager,但后续输入和 nested completion 仍需要稳定的 Task 身份与 durable mailbox。此外,公开配置引用了
adk/internal/foreground.CandidateInfo,外部 module 无法命名该类型。方案
本 PR 建立统一 Task 模型,把身份、通信、执行 owner 和可见性明确拆开:
TaskID表示一次有限执行,ChildSessionID表示可持续的对话历史。Deferred在前台观察期间隐藏,OnCreate用于显式后台,OnBackground在 projection detach 时发布。Manager.Publish(taskID)固定执行唯一合法的 publication transition,且不推进 lifecycleVersion,因此不会让 active attempt 丢失 authority。adk/task/foreground只保留 policy leaf types;timer、publish、cancel 和 terminal 竞态都留在 internal task-first coordinator。关键决策
Canceledsnapshot,再同步返回。Version;Store lock 与 expected-version fencing 仍保证 publish/terminal、publish/cancel 竞态只有一个原子结果。adk/backgroundtask包,也不保留本分支曾引入的 managed-tool handoff/adopt API。核心认识
Task 有三个互相独立的维度:
拆开这三个维度后,caller 停止观察不会改变或重启 Manager attempt;真正的 parent-owned Sub-agent handoff 也可以继续保持明确的 owner transfer 语义。
验证
go vet和golangci-lint通过。Streaming Task Event Persistence
A background event may contain a one-shot stream. Serializing it before entering the runtime loses the original event shape; passing the live reader directly to a Store makes persistence compete with live delivery and can hold authorization for the lifetime of the stream.
The runtime now separates those responsibilities:
TaskEventPersister[E, Chunk]receives the typed event and a persistence-owned stream;TaskEventWriterowns TaskID, Attempt, and EventID and revalidates authority for every appended part;EventIDidentifies the logical event, while stablePartIDvalues make partial stream replay idempotent;Finalcloses the logical event, so recovery can replay an accepted prefix but cannot append after completion.The Store remains responsible only for durable bytes, ordering, and fencing. Local, Managed Tool, and Local Sub-agent integrations provide defaults while allowing callers to replace serialization. AgentTool already gives each receiver an independent stream copy, so persistence cannot consume the caller's live stream.
Streaming Task Event 持久化
后台 event 可能携带一次性 stream。过早序列化会丢失原始 event 结构;把 live reader 直接交给 Store,又会让持久化与实时消费竞争,并让授权跨越整个 stream 生命周期。
新的边界把职责拆开:
TaskEventPersister[E, Chunk]接收 typed event 和 persistence-owned stream;TaskEventWriter持有 TaskID、Attempt 和 EventID,并在每个 part 写入时重新校验 authority;EventID标识 logical event,稳定的PartID保证 partial stream 可幂等重放;Final封闭 logical event,恢复可以重放已接受前缀,但不能在完成后继续追加。Store 只负责 durable bytes、顺序和 fencing。Local、Managed Tool 和 Local Sub-agent 提供默认 persister,同时允许调用方替换序列化。AgentTool 已为每个 receiver 提供独立 stream copy,因此持久化不会消费 caller 的 live stream。