mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-09-09 04:02:35 +00:00
refactor(agent): remove inbox service
This commit is contained in:
+2
-2
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-31-claimed-pre-step-inbox-lifecycle.md
|
||||
2026-07-31-claimed-pre-step-inbox-lifecycle.md: c46c22cde3e96fb774233d9621acf1abf4ba0c33
|
||||
2026-07-31-claimed-pre-step-inbox-lifecycle.zh.md: 51ada096a105a5c97cffd70c2d40782a71beddf7
|
||||
2026-07-31-claimed-pre-step-inbox-lifecycle.md: 8149c9df09ff69c017ba66a779d6fd3dfc314193
|
||||
2026-07-31-claimed-pre-step-inbox-lifecycle.zh.md: e855b88b26a55dd9f5c33c87a4b59d67496d00ed
|
||||
|
||||
+2
-2
@@ -18,11 +18,11 @@ Before every proposed step, `Inbox.claim(target)` atomically removes the complet
|
||||
|
||||
The durable inbox remains two `UserMessage[]` lists addressed by `MessageId`. `append`, `prepend`, and `splice` take a target, while `replace(messageId, newMessage)` and `remove(messageId)` locate the pending message across both lists before committing a normalized splice. Replacement may change identity and emits the old message as discarded followed by the new message as inserted. Every insertion emits `agent/inbox/inserted { message }`; an ordinary removal records `outcome: 'canceled'` and emits `agent/inbox/discarded { message }`. Claiming records pure deletions without an outcome and emits claimed events from Inbox itself. These live events add no placement, outcome, or batch fields.
|
||||
|
||||
The two event surfaces have separate consumers. Observers following one message use `agent/inbox/inserted`, `claimed`, and `discarded`. `InboxService` registers the standard `inbox` projection over the durable `agent/inbox/spliced` stream for whole-state consumers and live restoration; UI edits and removals route through an Inbox mutation method so the same projection records every change.
|
||||
The two event surfaces have separate consumers. Observers following one message use `agent/inbox/inserted`, `claimed`, and `discarded`. `AgentRegistry` contributes the standard `inbox` projection over the durable `agent/inbox/spliced` stream whenever the projection registry is composed; UI edits and removals route through an Inbox mutation method so the same projection records every change.
|
||||
|
||||
Plugins that need current-step atomic rewriting return messages from `agent/pre-step`. Plugins that only need later context may mutate `agent.inbox` directly. Workspace context uses both paths: asynchronous filesystem projections stage one replaceable `next-step` item, while the next entering pre-step folds that item or a newly composed baseline into its final batch and removes the pending copy. Rejection keeps the item queued.
|
||||
|
||||
The archived [addressable queue occurrence decision](../../archived/feature/2026-07-29-addressable-queue-operations.md) describes the superseded occurrence-wrapper design. `MessageId` now owns addressability, while `InboxService` registers `inbox` as the standard session projection over durable splices. The generic projection carrier serves that fold for live updates, history-tail reconnect baselines, and cold process-restart recovery without a live Agent mirror.
|
||||
The archived [addressable queue occurrence decision](../../archived/feature/2026-07-29-addressable-queue-operations.md) describes the superseded occurrence-wrapper design. `MessageId` owns addressability, while `AgentRegistry` contributes `inbox` as the standard session projection over durable splices. The generic projection carrier serves that fold for live updates, history-tail reconnect baselines, and cold process-restart recovery without a live Agent mirror.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
|
||||
+2
-2
@@ -18,11 +18,11 @@ Status: implemented
|
||||
|
||||
持久 inbox 仍是两份通过 `MessageId` 寻址的 `UserMessage[]` 列表。`append`、`prepend` 与 `splice` 接受 target;`replace(messageId, newMessage)` 与 `remove(messageId)` 则在提交规范化 splice 前,通过 `MessageId` 跨两份列表定位待处理消息。替换可以改变标识,并先将旧消息作为 discarded 发布,再将新消息作为 inserted 发布。每次插入发出 `agent/inbox/inserted { message }`;普通删除记录 `outcome: 'canceled'` 并发出 `agent/inbox/discarded { message }`。领取记录不带 outcome 的纯删除,并由 Inbox 自行发出 claimed 事件。这些实时事件不增加 placement、outcome 或批次字段。
|
||||
|
||||
两类事件接口服务不同消费方。跟踪单条消息的观察方使用 `agent/inbox/inserted`、`claimed` 与 `discarded`。`InboxService` 在持久 `agent/inbox/spliced` 流上注册标准 `inbox` 投影,供整体状态消费方与 live 恢复使用;UI 编辑与移除通过 Inbox 变更方法处理,从而让同一投影记录所有变化。
|
||||
两类事件接口服务不同消费方。跟踪单条消息的观察方使用 `agent/inbox/inserted`、`claimed` 与 `discarded`。`AgentRegistry` 会在投影注册表已组合时,在持久 `agent/inbox/spliced` 流上贡献标准 `inbox` 投影;UI 编辑与移除通过 Inbox 变更方法处理,从而让同一投影记录所有变化。
|
||||
|
||||
必须对当前步骤进行原子改写的插件从 `agent/pre-step` 返回消息。只需要稍后上下文的插件可以直接修改 `agent.inbox`。Workspace context 同时使用两条路径:异步文件系统投影会暂存一条可替换的 `next-step` 消息,而下一次进入步骤的 pre-step 会把该消息或新组合的基线折入最终批次,并移除仍待处理的副本。reject 会让该条目继续排队。
|
||||
|
||||
已归档的[可寻址队列项决策](../../archived/feature/2026-07-29-addressable-queue-operations.md)描述了已被取代的单次出现包装层设计。现在由 `MessageId` 负责寻址,而 `InboxService` 把 `inbox` 注册为持久 splice 上的标准会话投影。通用投影传输层会将该折叠结果用于实时更新、历史尾页的重连基线和冷进程重启恢复,无需 live Agent 镜像。
|
||||
已归档的[可寻址队列项决策](../../archived/feature/2026-07-29-addressable-queue-operations.md)描述了已被取代的单次出现包装层设计。`MessageId` 负责寻址,而 `AgentRegistry` 把 `inbox` 作为持久 splice 上的标准会话投影贡献给投影注册表。通用投影传输层会将该折叠结果用于实时更新、历史尾页的重连基线和冷进程重启恢复,无需 live Agent 镜像。
|
||||
|
||||
## 曾考虑的替代方案
|
||||
|
||||
|
||||
@@ -30,8 +30,6 @@ flowchart LR
|
||||
cfg --> plugin_dsh_base_user_questions
|
||||
plugin_dsh_base_agent["agent<br/>@deepseek-ai/dsh-agent"]
|
||||
cfg --> plugin_dsh_base_agent
|
||||
plugin_dsh_base_agent_inbox["agent-inbox<br/>@deepseek-ai/dsh-agent/inbox"]
|
||||
cfg --> plugin_dsh_base_agent_inbox
|
||||
plugin_dsh_base_agent_default_model["agent-default-model<br/>@deepseek-ai/dsh-agent-default-model"]
|
||||
cfg --> plugin_dsh_base_agent_default_model
|
||||
plugin_dsh_base_jobs["jobs<br/>@deepseek-ai/dsh-jobs-local"]
|
||||
@@ -181,7 +179,6 @@ flowchart LR
|
||||
| `session-title-llm` | `@deepseek-ai/dsh-session-title-first-prompt-llm` |
|
||||
| `user-questions` | `@deepseek-ai/dsh-user-questions` |
|
||||
| `agent` | `@deepseek-ai/dsh-agent` |
|
||||
| `agent-inbox` | `@deepseek-ai/dsh-agent/inbox` |
|
||||
| `agent-default-model` | `@deepseek-ai/dsh-agent-default-model` |
|
||||
| `jobs` | `@deepseek-ai/dsh-jobs-local` |
|
||||
| `llm-retry` | `@deepseek-ai/dsh-llm-retry` |
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import { agentEvents, type Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { agentEvents, Inbox, type Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
import { boot, loadOverlayPatches } from '@deepseek-ai/dsh-app-boot'
|
||||
import { SessionId } from '@deepseek-ai/dsh-session'
|
||||
@@ -34,7 +34,7 @@ try {
|
||||
runMaintenance: job => job(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(agent, { inbox: ctx.inboxes.create(agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(ctx, agent.session, agentEvents(ctx, agent)) })
|
||||
const decision = await agentEvents(ctx, agent).waterfall(
|
||||
'agent/pre-step',
|
||||
{ messages: [], turn: 1, step: 1, signal: new AbortController().signal },
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/capability-seams.md
|
||||
capability-seams.md: 2f6bc45f9cb60809cedf31f86fcb68785ef80b9a
|
||||
capability-seams.zh.md: a9eeb06c063a86cdcd6ef3560677129d3adb2798
|
||||
capability-seams.md: a84a6d6e0836524e1f39f2fd067ae1f6570741a5
|
||||
capability-seams.zh.md: b6b0aba72729f9b9b752347ab00cd76a45c248d9
|
||||
|
||||
@@ -31,7 +31,6 @@ flowchart LR
|
||||
pkg_subagent_inprocess["subagent-inprocess"]
|
||||
pkg_invariants["invariants"]
|
||||
pkg_message_feedback["message-feedback"]
|
||||
svc_inboxes["ctx.inboxes<br/>Durable pending-input facade"]
|
||||
svc_invariants["ctx.invariants<br/>Package-owned invariant registry"]
|
||||
pkg_scope["scope"]
|
||||
pkg_typert_registry["typert-registry"]
|
||||
@@ -202,7 +201,6 @@ flowchart LR
|
||||
svc_cordisInspect["ctx.cordisInspect<br/>Dynamic Cordis inspect registry"]
|
||||
pkg_acp --> svc_approval
|
||||
pkg_agent --> svc_agents
|
||||
pkg_agent --> svc_inboxes
|
||||
pkg_agent_default_model --> svc_agentDefaultModel
|
||||
pkg_agent_loop --> svc_agentLoop
|
||||
pkg_agent_presets --> svc_agentPresets
|
||||
@@ -329,7 +327,6 @@ flowchart LR
|
||||
svc_e2b --> pkg_fs_e2b
|
||||
svc_e2b --> pkg_subprocess_e2b
|
||||
svc_fs --> pkg_tool_fs
|
||||
svc_inboxes --> pkg_agent_loop
|
||||
svc_invariants --> pkg_agent
|
||||
svc_invariants --> pkg_agent_loop
|
||||
svc_invariants --> pkg_scope
|
||||
@@ -429,7 +426,6 @@ flowchart LR
|
||||
| `ctx.tokenMeter` | `core` | [`token-meter`](../packages/llm/token-meter) | - | [`compaction-basic`](../packages/compaction/compaction-basic) | - | Owns isolated per-session replay folds; pressure consumers share immutable revisioned measurements. |
|
||||
| `ctx.toolResultPruner` | `core` | [`compaction-tool-result-pruner`](../packages/compaction/compaction-tool-result-pruner) | - | [`compaction-basic`](../packages/compaction/compaction-basic) | - | Rewrites oversized current tool results through replayable single-node surface replacements before summary compaction. |
|
||||
| `ctx.sessions` | `core` | [`session`](../packages/core/session) | - | [`agent-loop`](../packages/core/agent-loop), [`agent`](../packages/core/agent), [`session-persistence`](../packages/session/session-persistence), [`session-query`](../packages/session-query/session-query), [`session-query-sqlite`](../packages/session-query/session-query-sqlite), `subagent-inprocess`, [`invariants`](../packages/runtime-diagnostics/invariants), [`message-feedback`](../packages/feedback/message-feedback) | - | Owns append-only Session instances and emits the durable session event feed. |
|
||||
| `ctx.inboxes` | `core` | [`agent`](../packages/core/agent) | - | [`agent-loop`](../packages/core/agent-loop) | - | Registers the standard Inbox projection and creates command facades over its sole live state. |
|
||||
| `ctx.invariants` | `core` | [`invariants`](../packages/runtime-diagnostics/invariants) | - | [`session`](../packages/core/session), [`agent`](../packages/core/agent), [`scope`](../packages/core/scope), [`agent-loop`](../packages/core/agent-loop) | - | Companion subpaths register owner-local checks; the service owns selection, uniqueness, child fibers, and package-attributed failures. |
|
||||
| `ctx.typert` | `core` | [`typert-registry`](../packages/typert/registry) | - | [`typert-loader`](../packages/typert/loader), [`api-gateway`](../packages/api/gateway) | - | Plugins register live zod contributions directly or through dsh-typert-loader; the API gateway consumes invocation descriptors and providers, while other runtime consumers query schemas and reflection metadata at their own edges. |
|
||||
| `ctx.typertGateway` | `core` | [`api-gateway`](../packages/api/gateway) | - | - | - | Associates generated Remote descriptors with live Cordis services, resolves registered identities, and exposes unary calls through the shared Connection RPC carrier. |
|
||||
|
||||
@@ -33,7 +33,6 @@ flowchart LR
|
||||
pkg_subagent_inprocess["subagent-inprocess"]
|
||||
pkg_invariants["invariants"]
|
||||
pkg_message_feedback["message-feedback"]
|
||||
svc_inboxes["ctx.inboxes<br/>Durable pending-input facade"]
|
||||
svc_invariants["ctx.invariants<br/>Package-owned invariant registry"]
|
||||
pkg_scope["scope"]
|
||||
pkg_typert_registry["typert-registry"]
|
||||
@@ -204,7 +203,6 @@ flowchart LR
|
||||
svc_cordisInspect["ctx.cordisInspect<br/>Dynamic Cordis inspect registry"]
|
||||
pkg_acp --> svc_approval
|
||||
pkg_agent --> svc_agents
|
||||
pkg_agent --> svc_inboxes
|
||||
pkg_agent_default_model --> svc_agentDefaultModel
|
||||
pkg_agent_loop --> svc_agentLoop
|
||||
pkg_agent_presets --> svc_agentPresets
|
||||
@@ -331,7 +329,6 @@ flowchart LR
|
||||
svc_e2b --> pkg_fs_e2b
|
||||
svc_e2b --> pkg_subprocess_e2b
|
||||
svc_fs --> pkg_tool_fs
|
||||
svc_inboxes --> pkg_agent_loop
|
||||
svc_invariants --> pkg_agent
|
||||
svc_invariants --> pkg_agent_loop
|
||||
svc_invariants --> pkg_scope
|
||||
@@ -431,7 +428,6 @@ flowchart LR
|
||||
| `ctx.tokenMeter` | `core` | [`token-meter`](../packages/llm/token-meter) | - | [`compaction-basic`](../packages/compaction/compaction-basic) | - | 拥有按会话隔离的回放折叠区;压力消费方共享不可变且带修订版本的测量结果。 |
|
||||
| `ctx.toolResultPruner` | `core` | [`compaction-tool-result-pruner`](../packages/compaction/compaction-tool-result-pruner) | - | [`compaction-basic`](../packages/compaction/compaction-basic) | - | 在摘要压缩前,通过可回放的单节点表层替换来改写过大的当前工具结果。 |
|
||||
| `ctx.sessions` | `core` | [`session`](../packages/core/session) | - | [`agent-loop`](../packages/core/agent-loop), [`agent`](../packages/core/agent), [`session-persistence`](../packages/session/session-persistence), [`session-query`](../packages/session-query/session-query), [`session-query-sqlite`](../packages/session-query/session-query-sqlite), `subagent-inprocess`, [`invariants`](../packages/runtime-diagnostics/invariants), [`message-feedback`](../packages/feedback/message-feedback) | - | 拥有仅追加的 Session 实例,并发出持久的会话事件流。 |
|
||||
| `ctx.inboxes` | `core` | [`agent`](../packages/core/agent) | - | [`agent-loop`](../packages/core/agent-loop) | - | 注册标准 Inbox 投影,并在其唯一 live 状态上创建命令 facade。 |
|
||||
| `ctx.invariants` | `core` | [`invariants`](../packages/runtime-diagnostics/invariants) | - | [`session`](../packages/core/session), [`agent`](../packages/core/agent), [`scope`](../packages/core/scope), [`agent-loop`](../packages/core/agent-loop) | - | 配套子路径注册所属包本地的检查;该服务负责选择、唯一性、子 fiber,以及标明所属包的失败。 |
|
||||
| `ctx.typert` | `core` | [`typert-registry`](../packages/typert/registry) | - | [`typert-loader`](../packages/typert/loader), [`api-gateway`](../packages/api/gateway) | - | 插件直接或通过 dsh-typert-loader 注册实时 zod 贡献;API 网关消费调用描述符和提供方,其他运行时消费方则在各自边界查询 schema 与反射元数据。 |
|
||||
| `ctx.typertGateway` | `core` | [`api-gateway`](../packages/api/gateway) | - | - | - | 将生成的 Remote 描述符与实时 Cordis 服务关联,解析已注册的身份,并通过共享的 Connection RPC 载体提供一元调用。 |
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/config-catalog.md
|
||||
config-catalog.md: b35358c651454ed42a9c0cfd466f305c7d632e70
|
||||
config-catalog.zh.md: f6bb73d14e3da28e05628d7b1d7c29d053382f24
|
||||
config-catalog.md: 453065bec7ddc373627f9f632445db7e16b56f59
|
||||
config-catalog.zh.md: 2c2a9d84f051e79437493490af63cea70358c300
|
||||
|
||||
@@ -136,7 +136,7 @@ Source: [`packages/context/agent-instructions/src/config.ts:18`](../packages/con
|
||||
|
||||
## `@deepseek-ai/dsh-agent-loop`
|
||||
|
||||
Requires: `agents` · `inboxes` · `sessions` · `llm` · `tools` · `systemPrompt`
|
||||
Requires: `agents` · `sessionProjections` · `sessions` · `llm` · `tools` · `systemPrompt`
|
||||
|
||||
```ts config-catalog
|
||||
/** Agent-loop plugin configuration. */
|
||||
@@ -292,7 +292,7 @@ export interface GoalConfig {
|
||||
|
||||
Depends on: [`AgentLoopConfig`](#deepseek-aidsh-agent-loop) · [`GoalDomainConfig`](#deepseek-aidsh-goal) · [`InvariantConfig`](#deepseek-aidsh-invariants) · [`JobsConfig`](#deepseek-aidsh-jobs-local) · [`SessionTitleConfig`](#deepseek-aidsh-session-title) · [`SkillFileSystem`](../packages/skill/skill-filesystem/src/index.ts) · [`SkillRegistryConfig`](#deepseek-aidsh-skill) · [`SystemPromptConfig`](#deepseek-aidsh-system-prompt) · [`toolBash`](../packages/shell/tool-bash/src/index.ts) · [`toolGoal`](../packages/goal/tool-goal/src/index.ts) · [`toolJobs`](../packages/jobs/tool-jobs/src/index.ts) · [`ToolsConfig`](#deepseek-aidsh-tools) · [`toolSkill`](../packages/skill/tool-skill/src/index.ts) · [`workspaceContext`](../packages/context/agent-instructions/src/index.ts)
|
||||
|
||||
Source: [`packages/examples/agent-spine-demo/src/index.ts:94`](../packages/examples/agent-spine-demo/src/index.ts)
|
||||
Source: [`packages/examples/agent-spine-demo/src/index.ts:93`](../packages/examples/agent-spine-demo/src/index.ts)
|
||||
|
||||
<a id="deepseek-aidsh-agent-tool-presentation"></a>
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ export interface Config {
|
||||
|
||||
## `@deepseek-ai/dsh-agent-loop`
|
||||
|
||||
需要:`agents` · `inboxes` · `sessions` · `llm` · `tools` · `systemPrompt`
|
||||
需要:`agents` · `sessionProjections` · `sessions` · `llm` · `tools` · `systemPrompt`
|
||||
|
||||
```ts config-catalog
|
||||
/** Agent-loop plugin configuration. */
|
||||
@@ -294,7 +294,7 @@ export interface GoalConfig {
|
||||
|
||||
依赖:[`AgentLoopConfig`](#deepseek-aidsh-agent-loop) · [`GoalDomainConfig`](#deepseek-aidsh-goal) · [`InvariantConfig`](#deepseek-aidsh-invariants) · [`JobsConfig`](#deepseek-aidsh-jobs-local) · [`SessionTitleConfig`](#deepseek-aidsh-session-title) · [`SkillFileSystem`](../packages/skill/skill-filesystem/src/index.ts) · [`SkillRegistryConfig`](#deepseek-aidsh-skill) · [`SystemPromptConfig`](#deepseek-aidsh-system-prompt) · [`toolBash`](../packages/shell/tool-bash/src/index.ts) · [`toolGoal`](../packages/goal/tool-goal/src/index.ts) · [`toolJobs`](../packages/jobs/tool-jobs/src/index.ts) · [`ToolsConfig`](#deepseek-aidsh-tools) · [`toolSkill`](../packages/skill/tool-skill/src/index.ts) · [`workspaceContext`](../packages/context/agent-instructions/src/index.ts)
|
||||
|
||||
来源:[`packages/examples/agent-spine-demo/src/index.ts:94`](../packages/examples/agent-spine-demo/src/index.ts)
|
||||
来源:[`packages/examples/agent-spine-demo/src/index.ts:93`](../packages/examples/agent-spine-demo/src/index.ts)
|
||||
|
||||
<a id="deepseek-aidsh-agent-tool-presentation"></a>
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/module-graph.md
|
||||
module-graph.md: 4fa25899f83f2140a8e28af123ed5ff202a437e4
|
||||
module-graph.zh.md: ba604a3ee7462584cd2d2324ee90936502ee35f9
|
||||
module-graph.md: c9b0d3dd7305bf0444c777f21468c3baa27d12d9
|
||||
module-graph.zh.md: b3eaf5a47cb5267fcbaa45017ea932948eaec68d
|
||||
|
||||
@@ -759,6 +759,7 @@ flowchart TD
|
||||
pkg_agent_loop --> pkg_scope
|
||||
pkg_agent_loop --> pkg_session
|
||||
pkg_agent_loop --> pkg_session_persistence
|
||||
pkg_agent_loop --> pkg_session_projection
|
||||
pkg_agent_loop --> pkg_settings
|
||||
pkg_agent_loop --> pkg_system_prompt
|
||||
pkg_agent_loop --> pkg_tools
|
||||
@@ -1580,7 +1581,7 @@ flowchart TD
|
||||
| [`pwsh-sandbox`](../packages/shell/pwsh-sandbox) | `shell` | [`invariants`](../packages/runtime-diagnostics/invariants), [`pwsh-local`](../packages/shell/pwsh-local), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`shell`](../packages/shell/shell) |
|
||||
| [`terminal-bash`](../packages/terminal/terminal-bash) | `terminal` | [`agent`](../packages/core/agent), [`invariants`](../packages/runtime-diagnostics/invariants), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`subprocess`](../packages/subprocess/subprocess), [`terminal`](../packages/terminal/terminal) |
|
||||
| [`token-meter`](../packages/llm/token-meter) | `llm` | [`compaction`](../packages/compaction/compaction), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection) |
|
||||
| [`agent-loop`](../packages/core/agent-loop) | `core` | [`agent`](../packages/core/agent), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`settings`](../packages/settings/settings), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
|
||||
| [`agent-loop`](../packages/core/agent-loop) | `core` | [`agent`](../packages/core/agent), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`settings`](../packages/settings/settings), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
|
||||
| [`agent-tool-presentation`](../packages/core/agent-tool-presentation) | `core` | [`invariants`](../packages/runtime-diagnostics/invariants), [`tools`](../packages/core/tools) |
|
||||
| [`tool-goal`](../packages/goal/tool-goal) | `goal` | [`agent`](../packages/core/agent), [`goal`](../packages/goal/goal), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
|
||||
| [`tool-fs`](../packages/fs/tool-fs) | `fs` | [`attachment`](../packages/attachment/attachment), [`fs`](../packages/fs/fs), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
|
||||
@@ -760,6 +760,7 @@ flowchart TD
|
||||
pkg_agent_loop --> pkg_scope
|
||||
pkg_agent_loop --> pkg_session
|
||||
pkg_agent_loop --> pkg_session_persistence
|
||||
pkg_agent_loop --> pkg_session_projection
|
||||
pkg_agent_loop --> pkg_settings
|
||||
pkg_agent_loop --> pkg_system_prompt
|
||||
pkg_agent_loop --> pkg_tools
|
||||
@@ -1581,7 +1582,7 @@ flowchart TD
|
||||
| [`pwsh-sandbox`](../packages/shell/pwsh-sandbox) | `shell` | [`invariants`](../packages/runtime-diagnostics/invariants), [`pwsh-local`](../packages/shell/pwsh-local), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`shell`](../packages/shell/shell) |
|
||||
| [`terminal-bash`](../packages/terminal/terminal-bash) | `terminal` | [`agent`](../packages/core/agent), [`invariants`](../packages/runtime-diagnostics/invariants), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`subprocess`](../packages/subprocess/subprocess), [`terminal`](../packages/terminal/terminal) |
|
||||
| [`token-meter`](../packages/llm/token-meter) | `llm` | [`compaction`](../packages/compaction/compaction), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection) |
|
||||
| [`agent-loop`](../packages/core/agent-loop) | `core` | [`agent`](../packages/core/agent), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`settings`](../packages/settings/settings), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
|
||||
| [`agent-loop`](../packages/core/agent-loop) | `core` | [`agent`](../packages/core/agent), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-persistence`](../packages/session/session-persistence), [`session-projection`](../packages/session/session-projection), [`settings`](../packages/settings/settings), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
|
||||
| [`agent-tool-presentation`](../packages/core/agent-tool-presentation) | `core` | [`invariants`](../packages/runtime-diagnostics/invariants), [`tools`](../packages/core/tools) |
|
||||
| [`tool-goal`](../packages/goal/tool-goal) | `goal` | [`agent`](../packages/core/agent), [`goal`](../packages/goal/goal), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
|
||||
| [`tool-fs`](../packages/fs/tool-fs) | `fs` | [`attachment`](../packages/attachment/attachment), [`fs`](../packages/fs/fs), [`invariants`](../packages/runtime-diagnostics/invariants), [`llm`](../packages/llm/llm), [`sandbox`](../packages/sandbox/sandbox), [`sandbox-policy`](../packages/sandbox/sandbox-policy), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools), [`user-approval`](../packages/interaction/user-approval) |
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/subsystems/core.md
|
||||
core.md: 6e919d02ac1c23cf4f49e92e5ce50a8983ac449d
|
||||
core.zh.md: 853d9500cd7e51b02ec2f9595bd7f294f7b1d66f
|
||||
core.md: b978cfdc102c93e0939dfc48c24947c45c96ee6f
|
||||
core.zh.md: 0dfef5b75ef9273884afe6e038a83e7e5785d9bc
|
||||
|
||||
+2
-19
@@ -175,7 +175,7 @@ The inbox is the delivery vocabulary — two ordered pending-message lists the a
|
||||
type InboxTarget = 'next-turn' | 'next-step'
|
||||
```
|
||||
|
||||
Every pending occurrence is its `UserMessage`; `MessageId` is the sole identity. `Inbox.append`, `prepend`, `replace`, `remove`, `clear`, `splice`, and `claim` record normalized durable `agent/inbox/spliced` mutations and reject duplicate pending ids. `replace(messageId, newMessage)` and `remove(messageId)` locate the pending message across both lists; replacement may change identity and emits the old message as discarded followed by the new message as inserted. Ordinary removals and `clear()` are cancellations. `claim(target)` removes the proposed step batch — all `next-step` input plus, at a turn boundary, one `next-turn` message — through pure deletion splices without emitting discarded notifications, then Inbox emits per-message claimed notifications. `InboxService` registers the standard `inbox` projection; its registry cell is the sole live state and the same fold serves cold consumers. Consumers following one message use the exact `agent/inbox/inserted`, `claimed`, and `discarded` notifications.
|
||||
Every pending occurrence is its `UserMessage`; `MessageId` is the sole identity. `Inbox.append`, `prepend`, `replace`, `remove`, `clear`, `splice`, and `claim` record normalized durable `agent/inbox/spliced` mutations and reject duplicate pending ids. `replace(messageId, newMessage)` and `remove(messageId)` locate the pending message across both lists; replacement may change identity and emits the old message as discarded followed by the new message as inserted. Ordinary removals and `clear()` are cancellations. `claim(target)` removes the proposed step batch — all `next-step` input plus, at a turn boundary, one `next-turn` message — through pure deletion splices without emitting discarded notifications, then Inbox emits per-message claimed notifications. `AgentRegistry` contributes the standard `inbox` projection whenever the projection registry is composed; its cell is the sole live state and the same fold serves cold consumers. Consumers following one message use the exact `agent/inbox/inserted`, `claimed`, and `discarded` notifications.
|
||||
|
||||
Cancellation:
|
||||
|
||||
@@ -720,24 +720,7 @@ list(): Agent[]
|
||||
roots(): Agent[]
|
||||
```
|
||||
|
||||
Source: [`packages/core/agent/src/index.ts:256`](../../packages/core/agent/src/index.ts)
|
||||
|
||||
<a id="ctxinboxes--inboxservice"></a>
|
||||
|
||||
### `ctx.inboxes` — `InboxService`
|
||||
|
||||
Root Inbox service: creates live inboxes and owns their durable projection.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Restore one live Inbox for an agent and publish its committed mutations.
|
||||
* @param agent - agent that owns the durable session and live Inbox events.
|
||||
* @returns the restored Inbox.
|
||||
*/
|
||||
create(agent: Agent): Inbox
|
||||
```
|
||||
|
||||
Source: [`packages/core/agent/src/inbox.ts:25`](../../packages/core/agent/src/inbox.ts)
|
||||
Source: [`packages/core/agent/src/index.ts:259`](../../packages/core/agent/src/index.ts)
|
||||
|
||||
<a id="agent-events"></a>
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ inbox 即投递词汇——agent 以持久投影形式拥有的两条有序待
|
||||
type InboxTarget = 'next-turn' | 'next-step'
|
||||
```
|
||||
|
||||
每个待处理入队项就是其 `UserMessage`;`MessageId` 是唯一标识。`Inbox.append`、`prepend`、`replace`、`remove`、`clear`、`splice` 与 `claim` 会记录规范化的持久 `agent/inbox/spliced` 变更,并拒绝重复的待处理 id。`replace(messageId, newMessage)` 与 `remove(messageId)` 通过 `MessageId` 跨两份列表定位待处理消息;替换可以改变标识,并先将旧消息作为 discarded 发布,再将新消息作为 inserted 发布。普通删除和 `clear()` 都表示取消。`claim(target)` 通过纯删除 splice 移除拟进入步骤的批次——全部 `next-step` 输入,外加轮次边界上的一条 `next-turn` 消息——且不发出 discarded 通知,随后由 Inbox 逐条发出 claimed 通知。`InboxService` 注册标准 `inbox` 投影;其注册表 cell 是唯一 live 状态,同一份折叠也服务于冷消费方。跟踪单条消息的消费方使用精确的 `agent/inbox/inserted`、`claimed` 与 `discarded` 通知。
|
||||
每个待处理入队项就是其 `UserMessage`;`MessageId` 是唯一标识。`Inbox.append`、`prepend`、`replace`、`remove`、`clear`、`splice` 与 `claim` 会记录规范化的持久 `agent/inbox/spliced` 变更,并拒绝重复的待处理 id。`replace(messageId, newMessage)` 与 `remove(messageId)` 通过 `MessageId` 跨两份列表定位待处理消息;替换可以改变标识,并先将旧消息作为 discarded 发布,再将新消息作为 inserted 发布。普通删除和 `clear()` 都表示取消。`claim(target)` 通过纯删除 splice 移除拟进入步骤的批次——全部 `next-step` 输入,外加轮次边界上的一条 `next-turn` 消息——且不发出 discarded 通知,随后由 Inbox 逐条发出 claimed 通知。`AgentRegistry` 会在投影注册表已组合时贡献标准 `inbox` 投影;其 cell 是唯一 live 状态,同一份折叠也服务于冷消费方。跟踪单条消息的消费方使用精确的 `agent/inbox/inserted`、`claimed` 与 `discarded` 通知。
|
||||
|
||||
取消:
|
||||
|
||||
@@ -728,24 +728,7 @@ list(): Agent[]
|
||||
roots(): Agent[]
|
||||
```
|
||||
|
||||
Source: [`packages/core/agent/src/index.ts:256`](../../packages/core/agent/src/index.ts)
|
||||
|
||||
<a id="ctxinboxes--inboxservice"></a>
|
||||
|
||||
### `ctx.inboxes` — `InboxService`
|
||||
|
||||
Root Inbox service: creates live inboxes and owns their durable projection.
|
||||
|
||||
```ts cordis-catalog
|
||||
/**
|
||||
* Restore one live Inbox for an agent and publish its committed mutations.
|
||||
* @param agent - agent that owns the durable session and live Inbox events.
|
||||
* @returns the restored Inbox.
|
||||
*/
|
||||
create(agent: Agent): Inbox
|
||||
```
|
||||
|
||||
Source: [`packages/core/agent/src/inbox.ts:25`](../../packages/core/agent/src/inbox.ts)
|
||||
Source: [`packages/core/agent/src/index.ts:259`](../../packages/core/agent/src/index.ts)
|
||||
|
||||
<a id="agent-events"></a>
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import ToolRuntime, { RUN_CODE_NAME, defineTool } from '@deepseek-ai/dsh-tools'
|
||||
import type { ToolExecutionResult } from '@deepseek-ai/dsh-tools'
|
||||
import AgentRegistry, { type Agent } from '@deepseek-ai/dsh-agent'
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
|
||||
import AgentLoop from '@deepseek-ai/dsh-agent-loop'
|
||||
import { LocalBashExecutor } from '@deepseek-ai/dsh-bash-local'
|
||||
@@ -56,7 +55,6 @@ async function codeModeHarness(cwd: string): Promise<Context> {
|
||||
await harness.plugin(LlmRuntime)
|
||||
await harness.plugin(SessionStore)
|
||||
await harness.plugin(SessionProjectionRegistry)
|
||||
await harness.plugin(InboxService)
|
||||
await harness.plugin(SystemPrompt, { persona: PERSONA })
|
||||
await harness.plugin(ToolRuntime, { mode: 'code' })
|
||||
await harness.plugin(AgentRegistry)
|
||||
@@ -75,7 +73,6 @@ async function workspaceCodeModeHarness(): Promise<Context> {
|
||||
await harness.plugin(LlmRuntime)
|
||||
await harness.plugin(SessionStore)
|
||||
await harness.plugin(SessionProjectionRegistry)
|
||||
await harness.plugin(InboxService)
|
||||
await harness.plugin(SystemPrompt, { persona: PERSONA })
|
||||
await harness.plugin(ToolRuntime, { mode: 'code' })
|
||||
await harness.plugin(AgentRegistry)
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { readFile } from 'node:fs/promises'
|
||||
import { resolve } from 'node:path'
|
||||
import { boot } from '@deepseek-ai/dsh-app-boot'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { agentEvents, Inbox, type Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import type {} from '@deepseek-ai/dsh-fs-e2b'
|
||||
import type {} from '@deepseek-ai/dsh-bash-local'
|
||||
@@ -30,7 +30,7 @@ const owner: Agent = {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(owner, { inbox: ctx.inboxes.create(owner) })
|
||||
Object.assign(owner, { inbox: new Inbox(ctx, owner.session, agentEvents(ctx, owner)) })
|
||||
const unregisterOwner = ctx.agents.register(owner)
|
||||
let terminalId: Awaited<ReturnType<typeof ctx.terminals.spawn>>['sessionId'] | undefined
|
||||
try {
|
||||
|
||||
@@ -58,9 +58,6 @@
|
||||
- id: agent
|
||||
name: '@deepseek-ai/dsh-agent'
|
||||
|
||||
- id: agent-inbox
|
||||
name: '@deepseek-ai/dsh-agent/inbox'
|
||||
|
||||
# The transport-independent default for Agents created by entry points.
|
||||
# Settings may supply a saved selection; consumers read it at creation time.
|
||||
- id: agent-default-model
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import AgentRegistry from '@deepseek-ai/dsh-agent'
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent, AgentHandle, CreateAgentOptions } from '@deepseek-ai/dsh-agent'
|
||||
import AgentDefaultModelConfig from '@deepseek-ai/dsh-agent-default-model'
|
||||
import { createAssistantMessage } from '@deepseek-ai/dsh-llm'
|
||||
@@ -57,7 +56,6 @@ async function bench(script: Script): Promise<{
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
await ctx.plugin(AgentDefaultModelConfig, { provider: 'test-provider', model: 'test-model' })
|
||||
ctx.agents.setFactory({
|
||||
@@ -86,7 +84,7 @@ async function bench(script: Script): Promise<{
|
||||
inject: () => {},
|
||||
whenIdle: () => idle,
|
||||
} satisfies Partial<Agent>)
|
||||
Object.assign(agent, { inbox: ctx.inboxes.create(agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(ctx, agent.session, agentEvents(ctx, agent)) })
|
||||
await options.setup?.(agentCtx)
|
||||
script.before?.(session)
|
||||
ctx.agents.register(agent)
|
||||
|
||||
@@ -7,8 +7,7 @@ import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import * as workspaceContext from '@deepseek-ai/dsh-agent-instructions'
|
||||
import LlmRuntime, { createUserMessage, CallId, type Message, type StreamChunk } from '@deepseek-ai/dsh-llm'
|
||||
import SessionStore, { SessionId, type SessionEvent, type UserMessage } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, { agentEvents, type Agent } from '@deepseek-ai/dsh-agent'
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import AgentRegistry, { agentEvents, Inbox, type Agent } from '@deepseek-ai/dsh-agent'
|
||||
import AgentLoop from '@deepseek-ai/dsh-agent-loop'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { FileSystem, FsTargetKey, FsVersion } from '@deepseek-ai/dsh-fs'
|
||||
@@ -52,7 +51,7 @@ const testToolSignal = new AbortController().signal
|
||||
const isolatedInboxCtx = new Context()
|
||||
await isolatedInboxCtx.plugin(SessionStore)
|
||||
await isolatedInboxCtx.plugin(SessionProjectionRegistry)
|
||||
await isolatedInboxCtx.plugin(InboxService)
|
||||
await isolatedInboxCtx.plugin(AgentRegistry)
|
||||
let nextStubSession = 1
|
||||
|
||||
async function tempRepo(): Promise<string> {
|
||||
@@ -209,7 +208,7 @@ function stubAgent(cwd?: string, seed: SessionEvent[] = []): Agent {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(agent, { inbox: agentCtx.inboxes.create(agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agentCtx, agent.session, agentEvents(agentCtx, agent)) })
|
||||
return agent
|
||||
}
|
||||
|
||||
@@ -2523,7 +2522,6 @@ describe('dynamic nested workspace context injection', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -51,7 +51,7 @@ function sessionAgent(session: Session, id = 'agent'): Agent {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent.session, agentEvents(agent.ctx, agent)) })
|
||||
return agent
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ function sessionAgent(session: Session, id = 'agent'): Agent {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent.session, agentEvents(agent.ctx, agent)) })
|
||||
return agent
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
"@deepseek-ai/dsh-scope": "workspace:^",
|
||||
"@deepseek-ai/dsh-session": "workspace:^",
|
||||
"@deepseek-ai/dsh-session-persistence": "workspace:^",
|
||||
"@deepseek-ai/dsh-session-projection": "workspace:^",
|
||||
"@deepseek-ai/dsh-system-prompt": "workspace:^",
|
||||
"@deepseek-ai/dsh-tools": "workspace:^",
|
||||
"@deepseek-ai/cordis": "workspace:^",
|
||||
|
||||
@@ -11,12 +11,11 @@ import type {
|
||||
AgentOptions,
|
||||
AgentStatus,
|
||||
CancelOptions,
|
||||
Inbox,
|
||||
InboxTarget,
|
||||
PreStepDecision,
|
||||
RequestErrorAction,
|
||||
} from '@deepseek-ai/dsh-agent'
|
||||
import { agentEvents, assembleContextFor } from '@deepseek-ai/dsh-agent'
|
||||
import { Inbox, agentEvents, assembleContextFor } from '@deepseek-ai/dsh-agent'
|
||||
import type { GenerateOptions, LlmCallConfig, Message, PreparedLlmCall } from '@deepseek-ai/dsh-llm'
|
||||
import {
|
||||
BlockAssembler,
|
||||
@@ -85,7 +84,7 @@ export class ReactLoopAgent implements Agent {
|
||||
public readonly session: Session,
|
||||
) {
|
||||
this.dispatch = agentEvents(loopCtx, this)
|
||||
this.inbox = loopCtx.inboxes.create(this)
|
||||
this.inbox = new Inbox(loopCtx, session, this.dispatch)
|
||||
const lastTurn = session.events.findLast(event => event.type === 'turn/start')?.data.turn ?? 0
|
||||
this.phase = { kind: 'idle', lastTurn }
|
||||
this.scope = createScope(loopCtx, this)
|
||||
|
||||
@@ -294,7 +294,7 @@ function validateConfiguredAgents(agents: Config['agents']): void {
|
||||
|
||||
/** Concrete agent factory and driver service. */
|
||||
export class AgentLoop extends Service implements AgentFactory {
|
||||
static inject = ['agents', 'inboxes', 'sessions', 'llm', 'tools', 'systemPrompt']
|
||||
static inject = ['agents', 'sessionProjections', 'sessions', 'llm', 'tools', 'systemPrompt']
|
||||
|
||||
/** Runtime schema for declarative agents. */
|
||||
static Config = z.object({
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { Context, type Fiber } from '@deepseek-ai/cordis'
|
||||
@@ -24,7 +23,6 @@ async function harness(adapter: LlmAdapter): Promise<Harness> {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
const agentsFiber = await ctx.plugin(AgentRegistry)
|
||||
@@ -126,7 +124,6 @@ describe('AgentLoop initiator scope', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -387,7 +384,6 @@ describe('AgentLoop initiator scope', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
@@ -16,7 +15,6 @@ async function harness(adapter: MockAdapter): Promise<Context> {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { CallId, createUserMessage } from '@deepseek-ai/dsh-llm'
|
||||
/**
|
||||
@@ -28,7 +27,6 @@ async function harness(adapter: MockAdapter) {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -674,7 +672,6 @@ describe('Agent.cancel()', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
@@ -32,7 +31,6 @@ async function makeCoreContext(): Promise<Context> {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -332,7 +330,6 @@ describe('config-driven session id', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -359,7 +356,6 @@ describe('config-driven session id', () => {
|
||||
await ctx1.plugin(LlmRuntime)
|
||||
await ctx1.plugin(SessionStore)
|
||||
await ctx1.plugin(SessionProjectionRegistry)
|
||||
await ctx1.plugin(InboxService)
|
||||
await ctx1.plugin(SystemPrompt)
|
||||
await ctx1.plugin(ToolRuntime)
|
||||
await ctx1.plugin(AgentRegistry)
|
||||
@@ -380,7 +376,6 @@ describe('config-driven session id', () => {
|
||||
await ctx2.plugin(LlmRuntime)
|
||||
await ctx2.plugin(SessionStore)
|
||||
await ctx2.plugin(SessionProjectionRegistry)
|
||||
await ctx2.plugin(InboxService)
|
||||
await ctx2.plugin(SystemPrompt)
|
||||
await ctx2.plugin(ToolRuntime)
|
||||
await ctx2.plugin(AgentRegistry)
|
||||
@@ -406,7 +401,6 @@ describe('config-driven session id', () => {
|
||||
await ctx1.plugin(LlmRuntime)
|
||||
await ctx1.plugin(SessionStore)
|
||||
await ctx1.plugin(SessionProjectionRegistry)
|
||||
await ctx1.plugin(InboxService)
|
||||
await ctx1.plugin(SystemPrompt)
|
||||
await ctx1.plugin(ToolRuntime)
|
||||
await ctx1.plugin(AgentRegistry)
|
||||
@@ -424,7 +418,6 @@ describe('config-driven session id', () => {
|
||||
await ctx2.plugin(LlmRuntime)
|
||||
await ctx2.plugin(SessionStore)
|
||||
await ctx2.plugin(SessionProjectionRegistry)
|
||||
await ctx2.plugin(InboxService)
|
||||
await ctx2.plugin(SystemPrompt)
|
||||
await ctx2.plugin(ToolRuntime)
|
||||
await ctx2.plugin(AgentRegistry)
|
||||
@@ -451,7 +444,6 @@ describe('config-driven session id', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
@@ -33,7 +32,6 @@ async function harness(adapter: MockAdapter) {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -530,7 +528,6 @@ describe('turn numbering continues across seeded sessions', () => {
|
||||
await ctx2.plugin(LlmRuntime)
|
||||
await ctx2.plugin(SessionStore)
|
||||
await ctx2.plugin(SessionProjectionRegistry)
|
||||
await ctx2.plugin(InboxService)
|
||||
await ctx2.plugin(SystemPrompt)
|
||||
await ctx2.plugin(ToolRuntime)
|
||||
await ctx2.plugin(AgentRegistry)
|
||||
@@ -683,7 +680,6 @@ describe('turn and step boundary recovery', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -1117,7 +1113,6 @@ describe('disposal and cancellation during pre-step assembly', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -1169,7 +1164,6 @@ describe('disposal and cancellation during pre-step assembly', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -1221,7 +1215,6 @@ describe('disposal and cancellation during pre-step assembly', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -1269,7 +1262,6 @@ describe('disposal and cancellation during pre-step assembly', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -1319,7 +1311,6 @@ describe('disposal and cancellation during pre-step assembly', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
@@ -21,7 +20,6 @@ async function harness(adapter: MockAdapter) {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
@@ -34,7 +33,6 @@ async function harness(adapter: MockAdapter) {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
@@ -20,7 +19,6 @@ async function harness(adapter: MockAdapter, persona = '') {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt, { persona })
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -1454,7 +1452,6 @@ describe('agent loop', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -1480,7 +1477,6 @@ describe('agent loop', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
/**
|
||||
* Property-based tests for the agent loop's inbox/turn scheduling (the
|
||||
@@ -42,7 +41,6 @@ async function harness() {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -6,7 +6,6 @@ import SessionStore, { SessionId } from '@deepseek-ai/dsh-session'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import ToolRuntime, { defineContentToolFixture } from '@deepseek-ai/dsh-tools'
|
||||
import AgentRegistry, { type Agent } from '@deepseek-ai/dsh-agent'
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
|
||||
import AgentLoop from '@deepseek-ai/dsh-agent-loop'
|
||||
import * as LlmDeepSeek from '@deepseek-ai/dsh-llm-deepseek'
|
||||
@@ -44,7 +43,6 @@ async function loopHarness(): Promise<Context> {
|
||||
await created.plugin(LlmRuntime)
|
||||
await created.plugin(SessionStore)
|
||||
await created.plugin(SessionProjectionRegistry)
|
||||
await created.plugin(InboxService)
|
||||
await created.plugin(SystemPrompt, { persona: SYSTEM })
|
||||
await created.plugin(ToolRuntime)
|
||||
await created.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
@@ -16,7 +15,6 @@ async function harness(adapter: MockAdapter): Promise<Context> {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
/**
|
||||
* Loop-level reconstructability: every request the loop sends is a pure function of the
|
||||
@@ -31,7 +30,6 @@ async function harnessRoutes(
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt, { persona })
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -260,7 +258,6 @@ describe('request stability across the loop', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt, { persona: 'stable base' })
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -380,7 +377,6 @@ describe('request stability across the loop', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt, { persona: 'stable base' })
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
@@ -31,7 +30,6 @@ async function mountPersistentHarness(root: string, adapter: MockAdapter): Promi
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -249,7 +247,6 @@ describe('the session-persistence Agent Note: AgentLoop factory create/resume',
|
||||
await ctx2.plugin(LlmRuntime)
|
||||
await ctx2.plugin(SessionStore)
|
||||
await ctx2.plugin(SessionProjectionRegistry)
|
||||
await ctx2.plugin(InboxService)
|
||||
await ctx2.plugin(SystemPrompt)
|
||||
await ctx2.plugin(ToolRuntime)
|
||||
await ctx2.plugin(AgentRegistry)
|
||||
@@ -279,7 +276,6 @@ describe('the session-persistence Agent Note: AgentLoop factory create/resume',
|
||||
await ctx2.plugin(LlmRuntime)
|
||||
await ctx2.plugin(SessionStore)
|
||||
await ctx2.plugin(SessionProjectionRegistry)
|
||||
await ctx2.plugin(InboxService)
|
||||
await ctx2.plugin(SystemPrompt)
|
||||
await ctx2.plugin(ToolRuntime)
|
||||
await ctx2.plugin(AgentRegistry)
|
||||
@@ -531,7 +527,6 @@ describe('the session-persistence Agent Note: AgentLoop factory create/resume',
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -596,7 +591,6 @@ describe('the session-persistence Agent Note: AgentLoop factory create/resume',
|
||||
await ctx2.plugin(LlmRuntime)
|
||||
await ctx2.plugin(SessionStore)
|
||||
await ctx2.plugin(SessionProjectionRegistry)
|
||||
await ctx2.plugin(InboxService)
|
||||
await ctx2.plugin(SystemPrompt)
|
||||
await ctx2.plugin(ToolRuntime)
|
||||
await ctx2.plugin(AgentRegistry)
|
||||
@@ -630,7 +624,6 @@ describe('the session-persistence Agent Note: AgentLoop factory create/resume',
|
||||
await ctx2.plugin(LlmRuntime)
|
||||
await ctx2.plugin(SessionStore)
|
||||
await ctx2.plugin(SessionProjectionRegistry)
|
||||
await ctx2.plugin(InboxService)
|
||||
await ctx2.plugin(SystemPrompt)
|
||||
await ctx2.plugin(ToolRuntime)
|
||||
await ctx2.plugin(AgentRegistry)
|
||||
@@ -668,7 +661,6 @@ describe('the session-persistence Agent Note: AgentLoop factory create/resume',
|
||||
await ctx2.plugin(LlmRuntime)
|
||||
await ctx2.plugin(SessionStore)
|
||||
await ctx2.plugin(SessionProjectionRegistry)
|
||||
await ctx2.plugin(InboxService)
|
||||
await ctx2.plugin(SystemPrompt)
|
||||
await ctx2.plugin(ToolRuntime)
|
||||
await ctx2.plugin(AgentRegistry)
|
||||
@@ -703,7 +695,6 @@ describe('the session-persistence Agent Note: AgentLoop factory create/resume',
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -894,7 +885,6 @@ describe('configured-start failure edges', () => {
|
||||
await configured.plugin(LlmRuntime)
|
||||
await configured.plugin(SessionStore)
|
||||
await configured.plugin(SessionProjectionRegistry)
|
||||
await configured.plugin(InboxService)
|
||||
await configured.plugin(SystemPrompt)
|
||||
await configured.plugin(ToolRuntime)
|
||||
await configured.plugin(AgentRegistry)
|
||||
@@ -941,7 +931,6 @@ describe('configured-start failure edges', () => {
|
||||
await configured.plugin(LlmRuntime)
|
||||
await configured.plugin(SessionStore)
|
||||
await configured.plugin(SessionProjectionRegistry)
|
||||
await configured.plugin(InboxService)
|
||||
await configured.plugin(SystemPrompt)
|
||||
await configured.plugin(ToolRuntime)
|
||||
await configured.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
@@ -20,7 +19,6 @@ async function harnessWithLoop(adapter: MockAdapter = new MockAdapter([textRespo
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt, { persona: 'You are the deployment.' })
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
/** The `agent-loop` settings section layered over the composition entry. */
|
||||
|
||||
@@ -37,7 +36,6 @@ async function boot(): Promise<{ ctx: Context; settingsFiber: Fiber; loopFiber:
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
/**
|
||||
* Exercises scheduler ordering and cancellation with deterministic gated tools.
|
||||
@@ -23,7 +22,6 @@ async function harness(adapter: MockAdapter, maxParallelToolCalls?: number) {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt, { persona: '' })
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -283,7 +281,6 @@ describe('tool-call scheduler: rolling pool honors maxParallelToolCalls', () =>
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt, { persona: '' })
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -353,7 +350,6 @@ describe('tool-call scheduler: rolling pool honors maxParallelToolCalls', () =>
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt, { persona: '' })
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -713,7 +709,6 @@ describe('code-mode native-tool denial through the agent loop', () => {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt, { persona: '' })
|
||||
await ctx.plugin(ToolRuntime, { mode: 'code' })
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- FakeCodeRuntime is an internal test helper with an opaque type shape
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
||||
/**
|
||||
@@ -26,7 +25,6 @@ async function harness(adapter: MockAdapter, toolOrder?: SystemPromptConfig['too
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt, { persona: 'stable base', ...toolOrder !== undefined ? { toolOrder } : {} })
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/core/agent/README.md
|
||||
README.md: 6af7e57bdb0ae710a6d1e6e58ca2ac187a45eeb8
|
||||
README.zh.md: 1533f918e037c7dc7d131c7046d25fc259d33580
|
||||
README.md: aeddc6caf24289333a3e5b0f9b29124b1e591316
|
||||
README.zh.md: f815283ba638f0374ae30d8a8c3fe4ce6a66968b
|
||||
|
||||
@@ -54,7 +54,7 @@ Most interception points are cooperative waterfalls. `agent/pre-step` receives a
|
||||
|
||||
`PreStepDecision` is either `{ kind: 'reject' }` or `{ kind: 'enter', messages }`. The enter branch is the complete identified, frozen batch for the proposed step. A listener that wraps downstream entry preserves that batch unless it intentionally replaces it; additions follow the waterfall's natural return order. Claiming already removed the offered messages from the inbox, so rejection does not retain them. Messages inserted after the claim remain pending for a later boundary.
|
||||
|
||||
`InboxService` owns the standard `inbox` session projection. The projection registry folds durable `agent/inbox/spliced` events once and remains the sole owner of the live `{ 'next-turn', 'next-step' }` state; Inbox is a command facade that reads the registry snapshot rather than replaying or copying the fold. Inbox live notifications are deliberately per-message and minimal: `agent/inbox/inserted { message }`, `agent/inbox/claimed { message, turn }`, and `agent/inbox/discarded { message }`. Inbox emits them as it commits the corresponding mutation, without adding another lifecycle envelope.
|
||||
`AgentRegistry` contributes the standard `inbox` session projection whenever the projection registry is composed. The registry folds durable `agent/inbox/spliced` events once and remains the sole owner of the live `{ 'next-turn', 'next-step' }` state; Inbox is a command facade that reads that unit rather than replaying or copying the fold. Inbox live notifications are deliberately per-message and minimal: `agent/inbox/inserted { message }`, `agent/inbox/claimed { message, turn }`, and `agent/inbox/discarded { message }`. Inbox emits them as it commits the corresponding mutation, without adding another lifecycle envelope.
|
||||
|
||||
Turn and step boundaries and the model token stream are durable `session/event` facts rather than mirrored `agent/*` notifications. Consumers read `turn/*`, `step/*`, and `assistant/chunk` from the session feed; tool policy and outcome observation belong to the complete pipeline documented by [`dsh-tools`](../tools/README.md).
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ Agent *创建* 由实现 `AgentFactory` 的插件(`dsh-agent-loop`)提供,
|
||||
|
||||
`PreStepDecision` 要么是 `{ kind: 'reject' }`,要么是 `{ kind: 'enter', messages }`。enter 分支是拟进入步骤的完整、带标识且冻结的批次。包装下游 enter 的监听器会保留该批次,除非有意替换它;新增消息遵循 waterfall 的自然返回顺序。领取操作已经把候选消息从 inbox 删除,因此 reject 不会保留它们;领取后插入的消息仍等待后续边界。
|
||||
|
||||
`InboxService` 拥有标准 `inbox` 会话投影。投影注册表只折叠一次持久 `agent/inbox/spliced` 事件,并继续作为 live `{ 'next-turn', 'next-step' }` 状态的唯一所有者;Inbox 是读取注册表快照的命令 facade,不会重新回放或复制折叠结果。Inbox 的实时通知刻意采用逐消息的最小载荷:`agent/inbox/inserted { message }`、`agent/inbox/claimed { message, turn }` 与 `agent/inbox/discarded { message }`。Inbox 在提交对应变更时自行发出这些通知,不引入另一层生命周期封套。
|
||||
`AgentRegistry` 会在投影注册表已组合时贡献标准 `inbox` 会话投影。注册表只折叠一次持久 `agent/inbox/spliced` 事件,并继续作为 live `{ 'next-turn', 'next-step' }` 状态的唯一所有者;Inbox 是读取该单元的命令 facade,不会重新回放或复制折叠结果。Inbox 的实时通知刻意采用逐消息的最小载荷:`agent/inbox/inserted { message }`、`agent/inbox/claimed { message, turn }` 与 `agent/inbox/discarded { message }`。Inbox 在提交对应变更时自行发出这些通知,不引入另一层生命周期封套。
|
||||
|
||||
轮次和步骤边界以及模型 token 流是持久 `session/event` 事实,而不是镜像的 `agent/*` 通知。消费方从会话事件流读取 `turn/*`、`step/*` 和 `assistant/chunk`;工具策略与结果观测属于 [`dsh-tools`](../tools/README.md) 记录的完整流水线。
|
||||
|
||||
|
||||
@@ -18,14 +18,6 @@
|
||||
"types": "./lib/types/index.d.ts",
|
||||
"default": "./lib/index.js"
|
||||
},
|
||||
"./inbox": {
|
||||
"types": "./lib/types/inbox.d.ts",
|
||||
"default": "./lib/types/inbox.js"
|
||||
},
|
||||
"./inbox-projection": {
|
||||
"types": "./lib/types/inbox-projection.d.ts",
|
||||
"default": "./lib/types/inbox-projection.js"
|
||||
},
|
||||
"./invariant": {
|
||||
"types": "./lib/types/invariant.d.ts",
|
||||
"default": "./lib/invariant.js"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** Inbox projection schema and its inferred wire value. */
|
||||
|
||||
import type { UserMessage } from '@deepseek-ai/dsh-llm/types'
|
||||
import type { ProjectionDefinition } from '@deepseek-ai/dsh-session-projection'
|
||||
import { z } from 'zod'
|
||||
|
||||
/** Wire validation for pending agent input reconstructed from durable inbox splices. */
|
||||
@@ -12,6 +13,30 @@ export const inboxProjectionSchema = z.object({
|
||||
/** Complete pending Inbox value reconstructed from durable splices. */
|
||||
export type InboxState = z.infer<typeof inboxProjectionSchema>
|
||||
|
||||
/** Standard fold that reconstructs pending agent input from durable splices. */
|
||||
export const inboxProjectionDefinition = {
|
||||
key: 'inbox',
|
||||
stateSchema: inboxProjectionSchema,
|
||||
init: (): InboxState => ({ 'next-turn': [], 'next-step': [] }),
|
||||
apply(state: InboxState, event) {
|
||||
if (event.type !== 'agent/inbox/spliced') return state
|
||||
const splice = event.data
|
||||
const next = state[splice.target].toSpliced(
|
||||
splice.start,
|
||||
splice.removedCount ?? 0,
|
||||
...splice.inserted,
|
||||
)
|
||||
return splice.target === 'next-turn'
|
||||
? { 'next-turn': next, 'next-step': state['next-step'] }
|
||||
: { 'next-turn': state['next-turn'], 'next-step': next }
|
||||
},
|
||||
wire: {
|
||||
viewSchema: inboxProjectionSchema,
|
||||
view: (state: InboxState) => state,
|
||||
},
|
||||
stateVersion: 1,
|
||||
} satisfies ProjectionDefinition<'inbox', InboxState>
|
||||
|
||||
declare module '@deepseek-ai/dsh-session-projection/types' {
|
||||
interface SessionProjectionMap {
|
||||
/** Pending agent input reconstructed from durable inbox splices. */
|
||||
|
||||
@@ -1,70 +1,25 @@
|
||||
/**
|
||||
* Incremental projection of durable agent inbox events.
|
||||
* Command facade over the durable agent Inbox projection.
|
||||
*
|
||||
* @module @deepseek-ai/dsh-agent/inbox
|
||||
*/
|
||||
|
||||
import { Context, Service } from '@deepseek-ai/cordis'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type { MessageId } from '@deepseek-ai/dsh-llm'
|
||||
import type { SessionEventMap, UserMessage } from '@deepseek-ai/dsh-session'
|
||||
import type { ProjectionDefinition } from '@deepseek-ai/dsh-session-projection'
|
||||
import { agentEvents } from './dispatch.ts'
|
||||
// Type-only: resolves ctx.sessionProjections for the required Inbox projection.
|
||||
import type {} from '@deepseek-ai/dsh-session-projection'
|
||||
import type { Session, SessionEventMap, UserMessage } from '@deepseek-ai/dsh-session'
|
||||
import type { AgentEventDispatch } from './dispatch.ts'
|
||||
import { inboxProjectionSchema } from './inbox-projection.ts'
|
||||
import type { InboxState } from './inbox-projection.ts'
|
||||
import type { Agent } from './runtime-types.ts'
|
||||
import type { InboxTarget } from './types.ts'
|
||||
|
||||
declare module '@deepseek-ai/cordis' {
|
||||
interface Context {
|
||||
inboxes: InboxService
|
||||
}
|
||||
}
|
||||
|
||||
/** Root Inbox service: creates live inboxes and owns their durable projection. */
|
||||
export class InboxService extends Service {
|
||||
static inject = ['sessionProjections']
|
||||
|
||||
constructor(ctx: Context) {
|
||||
super(ctx, 'inboxes')
|
||||
ctx.sessionProjections.register({
|
||||
key: 'inbox',
|
||||
schema: inboxProjectionSchema,
|
||||
init: () => ({ 'next-turn': [], 'next-step': [] }),
|
||||
apply(state, event) {
|
||||
if (event.type !== 'agent/inbox/spliced') return state
|
||||
const splice = event.data
|
||||
const next = state[splice.target].toSpliced(
|
||||
splice.start,
|
||||
splice.removedCount ?? 0,
|
||||
...splice.inserted,
|
||||
)
|
||||
return splice.target === 'next-turn'
|
||||
? { 'next-turn': next, 'next-step': state['next-step'] }
|
||||
: { 'next-turn': state['next-turn'], 'next-step': next }
|
||||
},
|
||||
view: state => state,
|
||||
stateVersion: 1,
|
||||
} satisfies ProjectionDefinition<'inbox', InboxState>)
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore one live Inbox for an agent and publish its committed mutations.
|
||||
* @param agent - agent that owns the durable session and live Inbox events.
|
||||
* @returns the restored Inbox.
|
||||
*/
|
||||
create(agent: Agent): Inbox {
|
||||
return new Inbox(this.ctx, agent)
|
||||
}
|
||||
}
|
||||
|
||||
/** Agent-owned command facade over the standard durable Inbox projection. */
|
||||
export class Inbox {
|
||||
private readonly dispatch: AgentEventDispatch
|
||||
|
||||
constructor(private readonly ctx: Context, private readonly agent: Agent) {
|
||||
this.dispatch = agentEvents(ctx, agent)
|
||||
}
|
||||
constructor(
|
||||
private readonly ctx: Context,
|
||||
private readonly session: Session,
|
||||
private readonly dispatch: AgentEventDispatch,
|
||||
) {}
|
||||
|
||||
/** Prompts awaiting individual turns. */
|
||||
get nextTurn(): readonly UserMessage[] {
|
||||
@@ -171,11 +126,11 @@ export class Inbox {
|
||||
return undefined
|
||||
}
|
||||
|
||||
/** Read the current durable projection value. */
|
||||
/** Read the current durable projection state. */
|
||||
private current(): InboxState {
|
||||
// InboxService registers this required projection before creating an Inbox.
|
||||
// AgentLoop requires sessionProjections; AgentRegistry contributes this unit to it.
|
||||
// oxlint-disable-next-line typescript/no-non-null-assertion
|
||||
return this.ctx.sessionProjections.snapshot(this.agent.session).values.inbox!
|
||||
return this.ctx.sessionProjections.stateOf(this.session, 'inbox')!
|
||||
}
|
||||
|
||||
/** Commit one normalized mutation and publish its live events. */
|
||||
@@ -216,7 +171,7 @@ export class Inbox {
|
||||
...(outcome === undefined ? {} : { outcome }),
|
||||
}
|
||||
const removed = inbox.slice(actualStart, actualStart + actualDeleteCount)
|
||||
const event = this.agent.session.append('agent/inbox/spliced', splice)
|
||||
const event = this.session.append('agent/inbox/spliced', splice)
|
||||
if (discardRemoved) {
|
||||
for (const message of removed) this.dispatch.emit('agent/inbox/discarded', { message })
|
||||
}
|
||||
@@ -226,5 +181,3 @@ export class Inbox {
|
||||
return removed
|
||||
}
|
||||
}
|
||||
|
||||
export default InboxService
|
||||
|
||||
@@ -12,7 +12,10 @@ import { isPromise } from 'node:util/types'
|
||||
import { scopeTarget } from '@deepseek-ai/dsh-scope'
|
||||
import type { Scoped } from '@deepseek-ai/dsh-scope'
|
||||
import type { SessionEvent, SessionId } from '@deepseek-ai/dsh-session'
|
||||
// Type-only: resolves ctx.sessionProjections for the optional Inbox projection contribution.
|
||||
import type {} from '@deepseek-ai/dsh-session-projection'
|
||||
import type { TypertContext, TypertLookup } from '@deepseek-ai/dsh-typert-protocol'
|
||||
import { inboxProjectionDefinition } from './inbox-projection.ts'
|
||||
import type { Agent, AgentOptions } from './runtime-types.ts'
|
||||
|
||||
export * from './runtime-types.ts'
|
||||
@@ -265,6 +268,9 @@ export class AgentRegistry extends Service {
|
||||
|
||||
constructor(ctx: Context) {
|
||||
super(ctx, 'agents')
|
||||
ctx.inject(['sessionProjections'], (projectionCtx) => {
|
||||
projectionCtx.sessionProjections.register(inboxProjectionDefinition)
|
||||
})
|
||||
ctx.inject(['typert'], (typeCtx) => {
|
||||
typeCtx.typert.lookups.register('agent', {
|
||||
parameter: 'agent',
|
||||
|
||||
@@ -4,10 +4,9 @@ import { createUserMessage, freezeMessage } from '@deepseek-ai/dsh-llm'
|
||||
import SessionStore, { Session, SessionId, type UserMessage } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, {
|
||||
agentEvents,
|
||||
InboxService,
|
||||
Inbox,
|
||||
} from '@deepseek-ai/dsh-agent'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import type {} from '@deepseek-ai/dsh-agent/inbox-projection'
|
||||
import TypertRegistry from '@deepseek-ai/dsh-typert-registry'
|
||||
|
||||
import type {
|
||||
@@ -48,10 +47,10 @@ async function inboxAgent(rawId: string): Promise<{ ctx: Context; session: Sessi
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
const session = ctx.sessions.create(SessionId(rawId))
|
||||
const agent = stubAgent(rawId, { ctx, session })
|
||||
Object.assign(agent, { inbox: ctx.inboxes.create(agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(ctx, agent.session, agentEvents(ctx, agent)) })
|
||||
return { ctx, session, agent }
|
||||
}
|
||||
|
||||
@@ -65,7 +64,7 @@ describe('Inbox', () => {
|
||||
parentAgent.inbox.append('next-turn', inherited)
|
||||
const child = ctx.sessions.fork(parent, undefined, SessionId('inbox-fork-child'))
|
||||
const childAgent = stubAgent('inbox-fork-child', { ctx, session: child })
|
||||
Object.assign(childAgent, { inbox: ctx.inboxes.create(childAgent) })
|
||||
Object.assign(childAgent, { inbox: new Inbox(ctx, childAgent.session, agentEvents(ctx, childAgent)) })
|
||||
|
||||
expect(child.header.seedLength).toBe(parent.events.length)
|
||||
expect(childAgent.inbox.nextTurn).toEqual([inherited])
|
||||
@@ -169,15 +168,15 @@ describe('Inbox', () => {
|
||||
expect(session.events).toHaveLength(beforeClear + 2)
|
||||
})
|
||||
|
||||
it('registers the durable Inbox projection from the Inbox service', async () => {
|
||||
it('registers the durable Inbox projection from the Agent registry', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
const inboxFiber = ctx.plugin(InboxService)
|
||||
await inboxFiber
|
||||
const agentFiber = ctx.plugin(AgentRegistry)
|
||||
await agentFiber
|
||||
const session = ctx.sessions.create(SessionId('inbox-projection'))
|
||||
const agent = stubAgent('inbox-projection', { ctx, session })
|
||||
Object.assign(agent, { inbox: ctx.inboxes.create(agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(ctx, agent.session, agentEvents(ctx, agent)) })
|
||||
const pending = createUserMessage({
|
||||
content: [{ type: 'text', text: 'pending' }],
|
||||
source: { kind: 'user' },
|
||||
@@ -189,7 +188,7 @@ describe('Inbox', () => {
|
||||
'next-turn': [pending],
|
||||
'next-step': [],
|
||||
})
|
||||
await inboxFiber.dispose()
|
||||
await agentFiber.dispose()
|
||||
expect(ctx.sessionProjections.snapshot(session).values).toEqual({})
|
||||
})
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { join, posix } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { runLoaderSmoke } from '@deepseek-ai/dsh-loader-smoke'
|
||||
import {
|
||||
@@ -96,7 +96,7 @@ describe.skipIf(!process.env.E2B_API_KEY)('E2B live Loader composition', () => {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(owner, { inbox: new Inbox(owner.ctx, owner) })
|
||||
Object.assign(owner, { inbox: new Inbox(owner.ctx, owner.session, agentEvents(owner.ctx, owner)) })
|
||||
const backend = new BashTerminalBackend(ctx, {
|
||||
backendType: 'shell', shellDialect: 'bash', shellPath: '/bin/bash', shellArgs: ['--noprofile', '--norc', '-i'],
|
||||
rows: 24, cols: 80,
|
||||
|
||||
@@ -20,7 +20,6 @@ import ToolRuntime, { type Config as ToolsConfig } from '@deepseek-ai/dsh-tools'
|
||||
import SkillRegistry, { type Config as SkillRegistryConfig } from '@deepseek-ai/dsh-skill'
|
||||
import * as SkillFileSystem from '@deepseek-ai/dsh-skill-filesystem'
|
||||
import AgentRegistry from '@deepseek-ai/dsh-agent'
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import GoalService, { type Config as GoalDomainConfig } from '@deepseek-ai/dsh-goal'
|
||||
import * as goalSession from '@deepseek-ai/dsh-goal-round-driver'
|
||||
import * as toolGoal from '@deepseek-ai/dsh-tool-goal'
|
||||
@@ -238,7 +237,6 @@ export function apply(ctx: Context, config: Config): void {
|
||||
ctx.plugin(SkillFileSystem, Object.assign({}, config.skills?.filesystem, { dshHome }))
|
||||
}
|
||||
ctx.plugin(AgentRegistry)
|
||||
ctx.plugin(InboxService)
|
||||
ctx.plugin(llmRetry)
|
||||
if (config.goals !== undefined && config.goals !== false) {
|
||||
ctx.plugin(GoalService, config.goals.domain ?? {})
|
||||
|
||||
@@ -807,19 +807,6 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'inboxes',
|
||||
summary: 'Root Inbox service: creates live inboxes and owns their durable projection.',
|
||||
description: 'Root Inbox service: creates live inboxes and owns their durable projection.',
|
||||
methods: [
|
||||
{
|
||||
signature: 'create(agent: Agent): Inbox',
|
||||
description: 'Restore one live Inbox for an agent and publish its committed mutations.',
|
||||
parameters: [{ name: 'agent', description: 'agent that owns the durable session and live Inbox events.' }],
|
||||
returns: 'the restored Inbox.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'invariants',
|
||||
summary: 'Package-owned invariant registry with global and regex-based selection.',
|
||||
@@ -2762,6 +2749,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [
|
||||
name: 'AgentCancelCause',
|
||||
declaration: 'export type AgentCancelCause = {\n readonly kind: \'user\';\n} | {\n readonly kind: \'parent\';\n} | {\n readonly kind: \'hook\';\n readonly reason: string;\n} | {\n readonly kind: \'disposed\';\n};',
|
||||
},
|
||||
{
|
||||
name: 'AgentEventDispatch',
|
||||
declaration: 'export interface AgentEventDispatch {\n emit<K extends AgentSubjectEvent>(name: K, payload: PayloadRest<K>): void;\n serial<K extends AgentSubjectEvent>(name: K, payload: PayloadRest<K>): Promise<Awaited<Return<Events[K]>>>;\n waterfall<K extends AgentSubjectEvent>(name: K, payload: PayloadRest<K>, ...rest: Tail<K>): Return<Events[K]>;\n}',
|
||||
},
|
||||
{
|
||||
name: 'AgentFactory',
|
||||
declaration: 'export interface AgentFactory {\n createAgent(ownerCtx: Context, options: CreateAgentOptions): Promise<AgentHandle>;\n resume(ownerCtx: Context, options: ResumeAgentOptions): Promise<AgentHandle>;\n}',
|
||||
@@ -2790,6 +2781,10 @@ export const TYPE_API: readonly TypeApiEntry[] = [
|
||||
name: 'AgentStatus',
|
||||
declaration: 'export type AgentStatus = \'idle\' | \'running\';',
|
||||
},
|
||||
{
|
||||
name: 'AgentSubjectEvent',
|
||||
declaration: 'export type AgentSubjectEvent = {\n [K in keyof Events]: Events[K] extends (this: Scoped<Agent>, ...args: infer P) => unknown ? P extends [\n infer Payload,\n ...unknown[]\n ] ? Payload extends {\n agent: Agent;\n } ? K : never : never : never;\n}[keyof Events];',
|
||||
},
|
||||
{
|
||||
name: 'ApprovalOutcome',
|
||||
declaration: 'export type ApprovalOutcome = \'allowed-once\' | \'rejected\' | \'cancelled\' | \'unavailable\';',
|
||||
@@ -3300,7 +3295,7 @@ export const TYPE_API: readonly TypeApiEntry[] = [
|
||||
},
|
||||
{
|
||||
name: 'Inbox',
|
||||
declaration: 'export class Inbox {\n constructor(private readonly ctx: Context, private readonly agent: Agent);\n get nextTurn(): readonly UserMessage[];\n get nextStep(): readonly UserMessage[];\n get hasPending(): boolean;\n clear(): void;\n claim(target: InboxTarget, turn: number): UserMessage[];\n append(target: InboxTarget, message: UserMessage): void;\n prepend(target: InboxTarget, message: UserMessage): void;\n replace(messageId: MessageId, newMessage: UserMessage): boolean;\n remove(messageId: MessageId): boolean;\n splice(target: InboxTarget, start: number, deleteCount: number, inserted: UserMessage[]): UserMessage[];\n}',
|
||||
declaration: 'export class Inbox {\n constructor(private readonly ctx: Context, private readonly session: Session, private readonly dispatch: AgentEventDispatch);\n get nextTurn(): readonly UserMessage[];\n get nextStep(): readonly UserMessage[];\n get hasPending(): boolean;\n clear(): void;\n claim(target: InboxTarget, turn: number): UserMessage[];\n append(target: InboxTarget, message: UserMessage): void;\n prepend(target: InboxTarget, message: UserMessage): void;\n replace(messageId: MessageId, newMessage: UserMessage): boolean;\n remove(messageId: MessageId): boolean;\n splice(target: InboxTarget, start: number, deleteCount: number, inserted: UserMessage[]): UserMessage[];\n}',
|
||||
},
|
||||
{
|
||||
name: 'InboxTarget',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent, AgentStatus } from '@deepseek-ai/dsh-agent'
|
||||
import CommandRuntime from '@deepseek-ai/dsh-commands'
|
||||
import SessionStore, { foldSurface, Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
@@ -59,7 +59,7 @@ function stubAgent(ctx: Context, id: string): { agent: Agent; session: Session }
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle() { return Promise.resolve() },
|
||||
}
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent.session, agentEvents(agent.ctx, agent)) })
|
||||
return { agent, session }
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import Include from '@deepseek-ai/cordis-plugin-include'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent, AgentStatus } from '@deepseek-ai/dsh-agent'
|
||||
import CommandRuntime from '@deepseek-ai/dsh-commands'
|
||||
import SessionStore, { SessionId } from '@deepseek-ai/dsh-session'
|
||||
@@ -45,7 +45,7 @@ function agent(ctx: Context): Agent {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(value, { inbox: new Inbox(value.ctx, value) })
|
||||
Object.assign(value, { inbox: new Inbox(value.ctx, value.session, agentEvents(value.ctx, value)) })
|
||||
ctx.agents.register(value)
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Context } from '@deepseek-ai/cordis'
|
||||
import { FsVersion } from '@deepseek-ai/dsh-fs'
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import LocalFileSystem from '@deepseek-ai/dsh-fs-local'
|
||||
import * as FsPolicy from '@deepseek-ai/dsh-fs-observation-policy'
|
||||
@@ -44,7 +44,7 @@ function agent(ctx: Context, cwd: string): Agent {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(value, { inbox: new Inbox(value.ctx, value) })
|
||||
Object.assign(value, { inbox: new Inbox(value.ctx, value.session, agentEvents(value.ctx, value)) })
|
||||
ctx.agents.register(value)
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent, AgentStatus } from '@deepseek-ai/dsh-agent'
|
||||
import CommandRuntime from '@deepseek-ai/dsh-commands'
|
||||
import GoalService from '@deepseek-ai/dsh-goal'
|
||||
@@ -36,7 +36,7 @@ function stubAgent(ctx: Context, id: string): { agent: Agent; session: Session }
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle() { return Promise.resolve() },
|
||||
}
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent.session, agentEvents(agent.ctx, agent)) })
|
||||
return { agent, session }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import AgentRegistry, { agentEvents } from '@deepseek-ai/dsh-agent'
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { createUserMessage, HarnessError } from '@deepseek-ai/dsh-llm'
|
||||
import SessionStore, { Session, SessionId, type UserMessage } from '@deepseek-ai/dsh-session'
|
||||
@@ -22,7 +21,7 @@ interface StubAgent {
|
||||
const isolatedInboxCtx = new Context()
|
||||
await isolatedInboxCtx.plugin(SessionStore)
|
||||
await isolatedInboxCtx.plugin(SessionProjectionRegistry)
|
||||
await isolatedInboxCtx.plugin(InboxService)
|
||||
await isolatedInboxCtx.plugin(AgentRegistry)
|
||||
const sessionStubs = new WeakMap<Session, StubAgent>()
|
||||
|
||||
/** Number the next balanced test-fixture turn. */
|
||||
@@ -59,7 +58,7 @@ function stubAgentForSession(session: Session, suppliedCtx?: Context): StubAgent
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle() { return Promise.resolve() },
|
||||
}
|
||||
Object.assign(agent, { inbox: agentCtx.inboxes.create(agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agentCtx, agent.session, agentEvents(agentCtx, agent)) })
|
||||
const stub = {
|
||||
agent,
|
||||
session,
|
||||
@@ -84,7 +83,6 @@ async function harness(config: { defaultMaxGoalRounds?: number } = {}) {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
await ctx.plugin(GoalService, config)
|
||||
const stub = stubAgent(`goal-test-${Math.random()}`)
|
||||
@@ -195,7 +193,6 @@ describe('GoalService creation and replay', () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
await ctx.plugin(GoalService)
|
||||
const parent = stubAgentForSession(ctx.sessions.create(SessionId('goal-fork-parent')), ctx)
|
||||
@@ -451,7 +448,6 @@ describe('GoalService mutations', () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
await ctx.plugin(GoalService)
|
||||
const stub = stubAgentForSession(ctx.sessions.create(SessionId('goal-reentrant-observer')), ctx)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import AgentRegistry, { agentEvents } from '@deepseek-ai/dsh-agent'
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent, AgentStatus } from '@deepseek-ai/dsh-agent'
|
||||
import GoalService, { GoalId } from '@deepseek-ai/dsh-goal'
|
||||
import type { GoalRef } from '@deepseek-ai/dsh-goal'
|
||||
@@ -26,7 +25,7 @@ interface StubAgent {
|
||||
const isolatedInboxCtx = new Context()
|
||||
await isolatedInboxCtx.plugin(SessionStore)
|
||||
await isolatedInboxCtx.plugin(SessionProjectionRegistry)
|
||||
await isolatedInboxCtx.plugin(InboxService)
|
||||
await isolatedInboxCtx.plugin(AgentRegistry)
|
||||
|
||||
/** Build one registry-compatible live agent whose injections enter the durable inbox. */
|
||||
function stubAgent(rawId: string, supplied?: Session, suppliedCtx?: Context): StubAgent {
|
||||
@@ -55,7 +54,7 @@ function stubAgent(rawId: string, supplied?: Session, suppliedCtx?: Context): St
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle() { return Promise.resolve() },
|
||||
}
|
||||
Object.assign(agent, { inbox: agentCtx.inboxes.create(agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agentCtx, agent.session, agentEvents(agentCtx, agent)) })
|
||||
return { agent, session, setStatus(value) { status = value } }
|
||||
}
|
||||
|
||||
@@ -87,7 +86,6 @@ async function harness(config: toolGoal.Config = {}) {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
|
||||
@@ -10,9 +10,7 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import { z } from 'zod'
|
||||
import AgentRegistry from '@deepseek-ai/dsh-agent'
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import type {} from '@deepseek-ai/dsh-agent/inbox-projection'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import { AttachmentStore } from '@deepseek-ai/dsh-attachment'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
||||
@@ -71,7 +69,6 @@ async function harness(withRegistry: boolean): Promise<{ ctx: Context; session:
|
||||
await ctx.plugin(AgentRegistry)
|
||||
if (withRegistry) {
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
}
|
||||
const session = ctx.sessions.create()
|
||||
const agent = {
|
||||
@@ -89,7 +86,7 @@ async function harness(withRegistry: boolean): Promise<{ ctx: Context; session:
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
} satisfies Agent
|
||||
if (withRegistry) Object.assign(agent, { inbox: ctx.inboxes.create(agent) })
|
||||
if (withRegistry) Object.assign(agent, { inbox: new Inbox(ctx, agent.session, agentEvents(ctx, agent)) })
|
||||
ctx.agents.register(agent)
|
||||
return { ctx, session }
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { homedir, tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent, AgentFactory } from '@deepseek-ai/dsh-agent'
|
||||
import SessionStore, { SessionId } from '@deepseek-ai/dsh-session'
|
||||
import type { Session } from '@deepseek-ai/dsh-session'
|
||||
@@ -55,7 +55,7 @@ function stubAgent(session: Session): Agent {
|
||||
runMaintenance: job => job(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent.session, agentEvents(agent.ctx, agent)) })
|
||||
return agent
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, expectTypeOf, it, vi } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { bindScopeParent, createScope, scopeOf } from '@deepseek-ai/dsh-scope'
|
||||
import type { ScopeKey } from '@deepseek-ai/dsh-scope'
|
||||
@@ -45,7 +45,7 @@ function stubAgent(ctx: Context, rawId: string, presetScope?: ScopeKey): Agent {
|
||||
runMaintenance: <T>(job: (signal: AbortSignal) => Promise<T>) => job(new AbortController().signal),
|
||||
whenIdle() { return Promise.resolve() },
|
||||
}
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent.session, agentEvents(agent.ctx, agent)) })
|
||||
agentScopeDisposers.set(agent, async () => { await scopeFiber.dispose() })
|
||||
return agent
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import { Context } from '@deepseek-ai/cordis'
|
||||
import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import Include from '@deepseek-ai/cordis-plugin-include'
|
||||
import AgentRegistry from '@deepseek-ai/dsh-agent'
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import AgentLoop from '@deepseek-ai/dsh-agent-loop'
|
||||
import LlmRuntime, { createUserMessage, LlmAdapter, LlmError, resolveRetryPolicy } from '@deepseek-ai/dsh-llm'
|
||||
import type { GenerateOptions, ResolvedRetryPolicy, StreamChunk } from '@deepseek-ai/dsh-llm'
|
||||
@@ -66,7 +65,6 @@ async function loadYaml(lines: readonly string[]): Promise<Context> {
|
||||
['@deepseek-ai/dsh-system-prompt', SystemPrompt],
|
||||
['@deepseek-ai/dsh-tools', ToolRuntime],
|
||||
['@deepseek-ai/dsh-agent', AgentRegistry],
|
||||
['@deepseek-ai/dsh-agent/inbox', InboxService],
|
||||
['@deepseek-ai/dsh-llm-retry', retry],
|
||||
['@deepseek-ai/dsh-agent-loop', AgentLoop],
|
||||
])
|
||||
@@ -97,7 +95,6 @@ describe('real Loader composition', () => {
|
||||
"- name: '@deepseek-ai/dsh-system-prompt'",
|
||||
"- name: '@deepseek-ai/dsh-tools'",
|
||||
"- name: '@deepseek-ai/dsh-agent'",
|
||||
"- name: '@deepseek-ai/dsh-agent/inbox'",
|
||||
"- name: '@deepseek-ai/dsh-llm-retry'",
|
||||
"- name: '@deepseek-ai/dsh-agent-loop'",
|
||||
])
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import LlmRuntime, { createUserMessage, type StreamChunk } from '@deepseek-ai/dsh-llm'
|
||||
import SessionStore, { SessionId, type SessionEvent } from '@deepseek-ai/dsh-session'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
@@ -26,7 +25,6 @@ async function harness(adapter: MockAdapter): Promise<Context> {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt)
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { dirname, join } from 'node:path'
|
||||
import { fileURLToPath, pathToFileURL } from 'node:url'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import Include from '@deepseek-ai/cordis-plugin-include'
|
||||
import LlmRuntime from '@deepseek-ai/dsh-llm'
|
||||
@@ -30,7 +29,6 @@ async function harness(roster: Partial<Config> = {}): Promise<Context> {
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt, { persona: '' })
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -3,7 +3,6 @@ import { tmpdir } from 'node:os'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { fileURLToPath, pathToFileURL } from 'node:url'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import Include from '@deepseek-ai/cordis-plugin-include'
|
||||
import LlmRuntime from '@deepseek-ai/dsh-llm'
|
||||
@@ -48,7 +47,6 @@ async function harness(roster: Config = { default: 'standard', roots: ROOTS, inc
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt, { persona: '' })
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
@@ -419,7 +417,6 @@ describe('the preset file is an input, never a persistence target', () => {
|
||||
await scoped.plugin(LlmRuntime)
|
||||
await scoped.plugin(SessionStore)
|
||||
await scoped.plugin(SessionProjectionRegistry)
|
||||
await scoped.plugin(InboxService)
|
||||
await scoped.plugin(SystemPrompt, { persona: '' })
|
||||
await scoped.plugin(ToolRuntime)
|
||||
await scoped.plugin(AgentRegistry)
|
||||
@@ -586,7 +583,6 @@ describe('replacing a composition', () => {
|
||||
await scoped.plugin(LlmRuntime)
|
||||
await scoped.plugin(SessionStore)
|
||||
await scoped.plugin(SessionProjectionRegistry)
|
||||
await scoped.plugin(InboxService)
|
||||
await scoped.plugin(SystemPrompt, { persona: '' })
|
||||
await scoped.plugin(ToolRuntime)
|
||||
await scoped.plugin(AgentRegistry)
|
||||
|
||||
@@ -16,7 +16,6 @@ import SessionStore, { SessionId } from '@deepseek-ai/dsh-session'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import ToolRuntime from '@deepseek-ai/dsh-tools'
|
||||
import AgentRegistry from '@deepseek-ai/dsh-agent'
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import AgentLoop from '@deepseek-ai/dsh-agent-loop'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
import FileSettingsProvider from '@deepseek-ai/dsh-settings-file'
|
||||
@@ -46,7 +45,6 @@ async function harness(
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt, { persona: '' })
|
||||
await ctx.plugin(ToolRuntime)
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent, AgentCancelCause, InboxTarget } from '@deepseek-ai/dsh-agent'
|
||||
import type { UserMessage } from '@deepseek-ai/dsh-llm'
|
||||
import SessionStore, { SessionId } from '@deepseek-ai/dsh-session'
|
||||
@@ -96,7 +96,7 @@ async function harness(): Promise<RuntimeHarness> {
|
||||
steer(_message: UserMessage) {},
|
||||
inject(_message: UserMessage) {},
|
||||
}
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent.session, agentEvents(agent.ctx, agent)) })
|
||||
const disposeAgent = ctx.agents.register(agent)
|
||||
ctx.on('session/event', (_session, event) => {
|
||||
if (event.type === 'schedule/change' && event.data.operation === 'dispatch') order.push('dispatch')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent, AgentCancelCause, InboxTarget } from '@deepseek-ai/dsh-agent'
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
import type { UserMessage } from '@deepseek-ai/dsh-llm'
|
||||
@@ -39,7 +39,7 @@ function stubAgent(ctx: Context, id: string): Agent {
|
||||
steer(_message: UserMessage) {},
|
||||
inject(_message: UserMessage) {},
|
||||
}
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent.session, agentEvents(agent.ctx, agent)) })
|
||||
return agent
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import Include from '@deepseek-ai/cordis-plugin-include'
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import TerminalSessionService from '@deepseek-ai/dsh-terminal'
|
||||
import * as TerminalLocal from '@deepseek-ai/dsh-terminal-bash'
|
||||
@@ -55,7 +55,7 @@ function agent(ctx: Context, cwd: string): Agent {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(value, { inbox: new Inbox(value.ctx, value) })
|
||||
Object.assign(value, { inbox: new Inbox(value.ctx, value.session, agentEvents(value.ctx, value)) })
|
||||
ctx.agents.register(value)
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import TerminalSessionService from '@deepseek-ai/dsh-terminal'
|
||||
import type {
|
||||
@@ -50,7 +50,7 @@ function agent(ctx: Context, cwd: string | undefined): Agent {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(value, { inbox: new Inbox(value.ctx, value) })
|
||||
Object.assign(value, { inbox: new Inbox(value.ctx, value.session, agentEvents(value.ctx, value)) })
|
||||
ctx.agents.register(value)
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import Include from '@deepseek-ai/cordis-plugin-include'
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import TerminalSessionService from '@deepseek-ai/dsh-terminal'
|
||||
import * as TerminalBash from '@deepseek-ai/dsh-terminal-bash'
|
||||
@@ -51,7 +51,7 @@ function agent(ctx: Context, cwd: string): Agent {
|
||||
id,
|
||||
options: {},
|
||||
session,
|
||||
inbox: new Inbox(session, { inserted: () => {}, discarded: () => {}, claimed: () => {} }),
|
||||
inbox: undefined as never,
|
||||
status: 'idle',
|
||||
ctx: scope.ctx,
|
||||
send: () => {},
|
||||
@@ -62,6 +62,7 @@ function agent(ctx: Context, cwd: string): Agent {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(value, { inbox: new Inbox(value.ctx, value.session, agentEvents(value.ctx, value)) })
|
||||
ctx.agents.register(value)
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import TerminalSessionService from '@deepseek-ai/dsh-terminal'
|
||||
import type {
|
||||
@@ -39,7 +39,7 @@ function agent(ctx: Context, cwd: string | undefined): Agent {
|
||||
id,
|
||||
options: {},
|
||||
session,
|
||||
inbox: new Inbox(session, { inserted: () => {}, discarded: () => {}, claimed: () => {} }),
|
||||
inbox: undefined as never,
|
||||
status: 'idle',
|
||||
ctx: scope.ctx,
|
||||
send: () => {},
|
||||
@@ -50,6 +50,7 @@ function agent(ctx: Context, cwd: string | undefined): Agent {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(value, { inbox: new Inbox(value.ctx, value.session, agentEvents(value.ctx, value)) })
|
||||
ctx.agents.register(value)
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ function agentForCwd(cwd: string): Agent {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent.session, agentEvents(agent.ctx, agent)) })
|
||||
return agent
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ function sessionAgent(session: Session, id = 'tool-skill-agent'): Agent {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent.session, agentEvents(agent.ctx, agent)) })
|
||||
return agent
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { resolve } from 'node:path'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import SessionStore, { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, { Inbox, type Agent } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox, type Agent } from '@deepseek-ai/dsh-agent'
|
||||
import SandboxProvider from '@deepseek-ai/dsh-sandbox'
|
||||
import type { ConfinedArgv, SandboxPolicy } from '@deepseek-ai/dsh-sandbox'
|
||||
import SandboxPolicyService, { setSandboxMode } from '@deepseek-ai/dsh-sandbox-policy'
|
||||
@@ -59,7 +59,7 @@ function agent(ctx: Context, cwd?: string): Agent {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent.session, agentEvents(agent.ctx, agent)) })
|
||||
return agent
|
||||
}
|
||||
|
||||
@@ -530,7 +530,7 @@ describe('terminal-bash plugin shape', () => {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(owner, { inbox: new Inbox(owner.ctx, owner) })
|
||||
Object.assign(owner, { inbox: new Inbox(owner.ctx, owner.session, agentEvents(owner.ctx, owner)) })
|
||||
ctx.agents.register(owner)
|
||||
const providerFiber = await registerStubLocalBackend(ctx, () => stubLocalSession())
|
||||
const created = await ctx.terminals.spawn(owner, { type: 'stub' })
|
||||
@@ -580,7 +580,7 @@ describe('terminal-bash plugin shape', () => {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(owner, { inbox: new Inbox(owner.ctx, owner) })
|
||||
Object.assign(owner, { inbox: new Inbox(owner.ctx, owner.session, agentEvents(owner.ctx, owner)) })
|
||||
ctx.agents.register(owner)
|
||||
const gate = Promise.withResolvers<undefined>()
|
||||
await registerStubLocalBackend(ctx, () => stubLocalSession(() => gate.promise))
|
||||
|
||||
@@ -5,7 +5,7 @@ import { join } from 'node:path'
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import TerminalSessionService from '@deepseek-ai/dsh-terminal'
|
||||
import type { TerminalSendOperation } from '@deepseek-ai/dsh-terminal'
|
||||
@@ -46,7 +46,7 @@ function stubAgent(ctx: Context, rawId: string): Agent {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent.session, agentEvents(agent.ctx, agent)) })
|
||||
return agent
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, expectTypeOf, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import TerminalSessionService, { TerminalBackendCleanupError, TerminalError, TerminalSessionId } from '@deepseek-ai/dsh-terminal'
|
||||
import type {
|
||||
@@ -37,7 +37,7 @@ function stubAgent(ctx: Context, rawId: string): Agent {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent.session, agentEvents(agent.ctx, agent)) })
|
||||
agentScopeDisposers.set(agent, async () => { await scopeFiber.dispose() })
|
||||
return agent
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import Include from '@deepseek-ai/cordis-plugin-include'
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import ToolRuntime from '@deepseek-ai/dsh-tools'
|
||||
@@ -49,7 +49,7 @@ function agent(ctx: Context): Agent {
|
||||
runMaintenance: job => job(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(value, { inbox: new Inbox(value.ctx, value) })
|
||||
Object.assign(value, { inbox: new Inbox(value.ctx, value.session, agentEvents(value.ctx, value)) })
|
||||
ctx.agents.register(value)
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import ToolRuntime, { renderToolsSdk } from '@deepseek-ai/dsh-tools'
|
||||
@@ -26,7 +26,7 @@ function fakeAgent(ctx: Context, rawId: string): Agent {
|
||||
runMaintenance: job => job(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent) })
|
||||
Object.assign(agent, { inbox: new Inbox(agent.ctx, agent.session, agentEvents(agent.ctx, agent)) })
|
||||
ctx.agents.register(agent)
|
||||
return agent
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import AgentRegistry from '@deepseek-ai/dsh-agent'
|
||||
import InboxService from '@deepseek-ai/dsh-agent/inbox'
|
||||
import LlmRuntime from '@deepseek-ai/dsh-llm'
|
||||
import SessionStore from '@deepseek-ai/dsh-session'
|
||||
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
|
||||
@@ -43,7 +42,6 @@ export async function mountAgentLoopTestDependencies(
|
||||
await ctx.plugin(LlmRuntime)
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(SessionProjectionRegistry)
|
||||
await ctx.plugin(InboxService)
|
||||
await ctx.plugin(SystemPrompt, options.systemPrompt ?? {})
|
||||
await ctx.plugin(ToolRuntime, options.tools ?? {})
|
||||
await ctx.plugin(AgentRegistry)
|
||||
|
||||
@@ -11,7 +11,7 @@ import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import Include from '@deepseek-ai/cordis-plugin-include'
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import AgentRegistry, { Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import AgentRegistry, { agentEvents, Inbox } from '@deepseek-ai/dsh-agent'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import ToolRuntime from '@deepseek-ai/dsh-tools'
|
||||
@@ -38,7 +38,7 @@ function agent(ctx: Context): Agent {
|
||||
runMaintenance: task => task(new AbortController().signal),
|
||||
whenIdle: () => Promise.resolve(),
|
||||
}
|
||||
Object.assign(value, { inbox: new Inbox(value.ctx, value) })
|
||||
Object.assign(value, { inbox: new Inbox(value.ctx, value.session, agentEvents(value.ctx, value)) })
|
||||
ctx.agents.register(value)
|
||||
return value
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ export const SERVICE_PAGE: Record<string, string> = {
|
||||
agentDefaultModel: 'core.md',
|
||||
agentPresets: 'core.md',
|
||||
agents: 'core.md',
|
||||
inboxes: 'core.md',
|
||||
apiProxy: 'typert.md',
|
||||
approval: 'approval.md',
|
||||
attachments: 'attachment.md',
|
||||
|
||||
@@ -139,14 +139,6 @@ const SERVICE_ROLES: ServiceRole[] = [
|
||||
consumers: ['agent-loop', 'agent', 'session-persistence', 'session-query', 'session-query-sqlite', 'subagent-inprocess', 'invariants', 'message-feedback'],
|
||||
note: 'Owns append-only Session instances and emits the durable session event feed.',
|
||||
},
|
||||
{
|
||||
key: 'inboxes',
|
||||
pkg: 'agent',
|
||||
title: 'Durable pending-input facade',
|
||||
mode: 'core',
|
||||
consumers: ['agent-loop'],
|
||||
note: 'Registers the standard Inbox projection and creates command facades over its sole live state.',
|
||||
},
|
||||
{
|
||||
key: 'invariants',
|
||||
pkg: 'invariants',
|
||||
|
||||
@@ -98,8 +98,6 @@
|
||||
"@deepseek-ai/dsh-user-questions/types": ["./packages/interaction/user-questions/src/types.ts"],
|
||||
"@deepseek-ai/dsh-agent/types": ["./packages/core/agent/src/types.ts"],
|
||||
"@deepseek-ai/dsh-agent/brand": ["./packages/core/agent/src/brand.ts"],
|
||||
"@deepseek-ai/dsh-agent/inbox": ["./packages/core/agent/src/inbox.ts"],
|
||||
"@deepseek-ai/dsh-agent/inbox-projection": ["./packages/core/agent/src/inbox-projection.ts"],
|
||||
"@deepseek-ai/dsh-agent/invariant": ["./packages/core/agent/src/invariant.ts"],
|
||||
"@deepseek-ai/dsh-scope/invariant": ["./packages/core/scope/src/invariant.ts"],
|
||||
"@deepseek-ai/dsh-agent-loop/invariant": ["./packages/core/agent-loop/src/invariant.ts"],
|
||||
|
||||
Reference in New Issue
Block a user