@fishwithcat/dsh-agent 0.0.0-stage → 0.2.2-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +109 -0
- package/README.md +218 -2
- package/README.zh.md +219 -0
- package/lib/index.js +917 -0
- package/lib/types/archive-admission.d.ts +24 -0
- package/lib/types/archive-admission.js +35 -0
- package/lib/types/assistant-stream-state.d.ts +53 -0
- package/lib/types/assistant-stream-state.js +88 -0
- package/lib/types/consumed-work.d.ts +39 -0
- package/lib/types/consumed-work.js +93 -0
- package/lib/types/dispatch.d.ts +111 -0
- package/lib/types/dispatch.js +95 -0
- package/lib/types/index.d.ts +394 -0
- package/lib/types/index.js +485 -0
- package/lib/types/model-selection.d.ts +57 -0
- package/lib/types/model-selection.js +139 -0
- package/lib/types/projection.d.ts +17 -0
- package/lib/types/projection.js +53 -0
- package/lib/types/runtime-types.d.ts +445 -0
- package/lib/types/runtime-types.js +8 -0
- package/lib/types/types.d.ts +111 -0
- package/lib/types/types.js +7 -0
- package/locale/de.json +6 -0
- package/locale/en.json +5 -0
- package/locale/es.json +6 -0
- package/locale/fr.json +6 -0
- package/locale/ja.json +6 -0
- package/locale/pt.json +6 -0
- package/locale/ru.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +66 -4
package/README.i18n.yaml
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
|
|
2
|
+
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
|
3
|
+
# After editing either side, bring the other along and re-record with:
|
|
4
|
+
# pnpm run verify-translation-pairing --write packages/core/agent/README.md
|
|
5
|
+
/:
|
|
6
|
+
en: b6bcf3c8b941d336
|
|
7
|
+
zh: 28b5d2aa43fdd026
|
|
8
|
+
/deepseek-ai-dsh-agent:
|
|
9
|
+
en: e6513350f94898d8
|
|
10
|
+
zh: feb04fc389801a62
|
|
11
|
+
/deepseek-ai-dsh-agent/summary:
|
|
12
|
+
en: 717e7d19a6f72e56
|
|
13
|
+
zh: 152c18689fe4f377
|
|
14
|
+
/deepseek-ai-dsh-agent/table-of-contents:
|
|
15
|
+
en: d152484eb41ac6b4
|
|
16
|
+
zh: 09388d293f9be9cb
|
|
17
|
+
/deepseek-ai-dsh-agent/use-this-package:
|
|
18
|
+
en: 7d1ae2375bd4fbfc
|
|
19
|
+
zh: b6b4b2e943174cb2
|
|
20
|
+
/deepseek-ai-dsh-agent/use-this-package/create-or-resume-an-agent:
|
|
21
|
+
en: 26d49c76bce41e30
|
|
22
|
+
zh: 9710f54e24b190d1
|
|
23
|
+
/deepseek-ai-dsh-agent/use-this-package/select-a-model:
|
|
24
|
+
en: 85b0ff72a187110f
|
|
25
|
+
zh: 3f61c1568d27b8bc
|
|
26
|
+
/deepseek-ai-dsh-agent/use-this-package/drive-an-agent-s-conversation:
|
|
27
|
+
en: 71e258897e2e7d73
|
|
28
|
+
zh: abf0991012faa17e
|
|
29
|
+
/deepseek-ai-dsh-agent/use-this-package/scope-registrations-to-one-agent:
|
|
30
|
+
en: 2594a1e02adea801
|
|
31
|
+
zh: cae8860369728efb
|
|
32
|
+
/deepseek-ai-dsh-agent/use-this-package/intercept-or-observe-work-in-flight:
|
|
33
|
+
en: 371511fb13093dd2
|
|
34
|
+
zh: 4be81d246cf299b2
|
|
35
|
+
/deepseek-ai-dsh-agent/understand-the-implementation:
|
|
36
|
+
en: ce7e776e9d516bdb
|
|
37
|
+
zh: 59d2751743db7795
|
|
38
|
+
/deepseek-ai-dsh-agent/understand-the-implementation/design-concept:
|
|
39
|
+
en: 7c850051d2857bfa
|
|
40
|
+
zh: 4cab817553114e15
|
|
41
|
+
/deepseek-ai-dsh-agent/understand-the-implementation/step-admission:
|
|
42
|
+
en: c5ebf07dbc1a883f
|
|
43
|
+
zh: 847735016e1727a3
|
|
44
|
+
/deepseek-ai-dsh-agent/understand-the-implementation/durable-inbox:
|
|
45
|
+
en: 8f3fe9303468d735
|
|
46
|
+
zh: 52162010ae1ed29e
|
|
47
|
+
/deepseek-ai-dsh-agent/understand-the-implementation/durable-model-selection:
|
|
48
|
+
en: 692ec951bbb16b33
|
|
49
|
+
zh: 5a650805ae8943c3
|
|
50
|
+
/deepseek-ai-dsh-agent/understand-the-implementation/source-map:
|
|
51
|
+
en: bdeb146a53d8eee6
|
|
52
|
+
zh: 38024efe70a2776f
|
|
53
|
+
/deepseek-ai-dsh-agent/understand-the-implementation/registry-and-lifecycle:
|
|
54
|
+
en: df92e97cedd0d02e
|
|
55
|
+
zh: f6040c145bffd933
|
|
56
|
+
/deepseek-ai-dsh-agent/understand-the-implementation/initiator-scope:
|
|
57
|
+
en: 3ca29c07144b36db
|
|
58
|
+
zh: 93580213b3de2004
|
|
59
|
+
/deepseek-ai-dsh-agent/understand-the-implementation/ownership-invariants:
|
|
60
|
+
en: e48eae6c7de88cf8
|
|
61
|
+
zh: 1f5b37bdb0e53788
|
|
62
|
+
/deepseek-ai-dsh-agent/further-exploration:
|
|
63
|
+
en: 4ef57cfafa344581
|
|
64
|
+
zh: 73575876bfdc7a18
|
|
65
|
+
/deepseek-ai-dsh-agent/model-experience:
|
|
66
|
+
en: 215e7ba838619b7b
|
|
67
|
+
zh: a311da3843709f90
|
|
68
|
+
/deepseek-ai-dsh-agent/model-experience/user-steering-and-injected-messages:
|
|
69
|
+
en: 962c598672b0eed6
|
|
70
|
+
zh: d05b3bc936685ad3
|
|
71
|
+
/deepseek-ai-dsh-agent/model-experience/user-steering-and-injected-messages/what-the-model-sees:
|
|
72
|
+
en: 2383fe2ec2859ac5
|
|
73
|
+
zh: 4211b6083cf58ecb
|
|
74
|
+
/deepseek-ai-dsh-agent/model-experience/user-steering-and-injected-messages/token-effect:
|
|
75
|
+
en: 95ed6c912ead0fba
|
|
76
|
+
zh: d5ad3d7257f7836c
|
|
77
|
+
/deepseek-ai-dsh-agent/model-experience/user-steering-and-injected-messages/kv-cache-effect:
|
|
78
|
+
en: 75dc61fe240860f0
|
|
79
|
+
zh: 621720291d1b4bd3
|
|
80
|
+
/deepseek-ai-dsh-agent/model-experience/agent-scoped-request-composition:
|
|
81
|
+
en: 215fc35b0f30e38a
|
|
82
|
+
zh: 21788ec980c300ea
|
|
83
|
+
/deepseek-ai-dsh-agent/model-experience/agent-scoped-request-composition/what-the-model-sees:
|
|
84
|
+
en: 09a31923f42fcadf
|
|
85
|
+
zh: c52117c2afbca7c6
|
|
86
|
+
/deepseek-ai-dsh-agent/model-experience/agent-scoped-request-composition/token-effect:
|
|
87
|
+
en: b25f4a4bb14fdfce
|
|
88
|
+
zh: 9369ace52f58a579
|
|
89
|
+
/deepseek-ai-dsh-agent/model-experience/agent-scoped-request-composition/kv-cache-effect:
|
|
90
|
+
en: 0d6f538ede133159
|
|
91
|
+
zh: 4f32f218e06fa432
|
|
92
|
+
/deepseek-ai-dsh-agent/model-experience/optional-model-switch-notice:
|
|
93
|
+
en: 43e32660a38f9ea1
|
|
94
|
+
zh: 334d24a453b14322
|
|
95
|
+
/deepseek-ai-dsh-agent/model-experience/optional-model-switch-notice/what-the-model-sees:
|
|
96
|
+
en: d7de2f137ff3b9b6
|
|
97
|
+
zh: 53e9098d97832b70
|
|
98
|
+
/deepseek-ai-dsh-agent/model-experience/optional-model-switch-notice/token-effect:
|
|
99
|
+
en: e38815dd2b8cf92e
|
|
100
|
+
zh: ec449b3b5ce10bf1
|
|
101
|
+
/deepseek-ai-dsh-agent/model-experience/optional-model-switch-notice/kv-cache-effect:
|
|
102
|
+
en: 2aba63100fcafc58
|
|
103
|
+
zh: 7484f7981d8cc955
|
|
104
|
+
/deepseek-ai-dsh-agent/known-limitations-and-deferred-work:
|
|
105
|
+
en: 00a2d12980ffe756
|
|
106
|
+
zh: c8bf69d06d165b36
|
|
107
|
+
/deepseek-ai-dsh-agent/known-limitations-and-deferred-work/dev-note:
|
|
108
|
+
en: 217405c92be96543
|
|
109
|
+
zh: 7bc21e6842079a57
|
package/README.md
CHANGED
|
@@ -1,3 +1,219 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
description: "The Agent handle, live registry, process-local initiator scope, and agent/* event vocabulary for plugins, UI, and orchestrators building or extending agents."
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
# @deepseek-ai/dsh-agent
|
|
7
|
+
|
|
8
|
+
English | [中文](README.zh.md)
|
|
9
|
+
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
Use `dsh-agent` to create or resume live agents, send follow-up or steering input, inject model-facing context, cancel work, and wait for idle completion. Plugins, UI, hooks, and orchestrators can also observe or intercept agent activity and apply capabilities to one agent without affecting others. Choose it when code needs to control or extend live agents through the public `Agent` API. Pair it with an agent driver such as `dsh-agent-loop`; this package does not create model requests by itself. Initiator attribution is process-local and must be carried explicitly across workers, processes, durable queues, and restarts.
|
|
13
|
+
|
|
14
|
+
## Table of Contents
|
|
15
|
+
|
|
16
|
+
- [Use this package](#use-this-package)
|
|
17
|
+
- [Understand the implementation](#understand-the-implementation)
|
|
18
|
+
- [Further Exploration](#further-exploration)
|
|
19
|
+
- [Model Experience](#model-experience)
|
|
20
|
+
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
|
|
21
|
+
- [Dev Note](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## Use this package
|
|
27
|
+
|
|
28
|
+
Mount `dsh-agent` with `dsh-session-projection`: it provides `ctx.agents`, the `Agent` handle, and `turnBoundaryOf(session)` for recorded turn and step positions. Creating or resuming an Agent also requires a driver to register a factory; the shipped driver is `dsh-agent-loop`. [Session model selection](#model-selection) is available on each handle as `agent.model`.
|
|
29
|
+
|
|
30
|
+
### Create or resume an agent
|
|
31
|
+
|
|
32
|
+
`ctx.agents.create()` builds a fresh agent and session under one identity; `ctx.agents.resume()` loads a persisted session and rebuilds the agent on it. Both delegate to the registered factory and return an `AgentHandle` — the only object that can tear that agent down. See [`AgentFactory`](src/index.ts) for publication and failure-cleanup timing. Set `parentAgent` in either operation's options to make the result a runtime child; omit it for a runtime root. `get(id)`, `list()`, and `roots()` find live agents, and `isOwnedBy(id, parent)` tests that exact live relation.
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
const handle = await ctx.agents.create({
|
|
36
|
+
sessionId,
|
|
37
|
+
agentOptions: { provider: 'deepseek', model: 'deepseek-chat' },
|
|
38
|
+
})
|
|
39
|
+
// later:
|
|
40
|
+
await handle.dispose() // stops the loop, unregisters, removes the session, unwinds the scope
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`AgentOptions` supplies the initial provider/model route, optional adapter-owned `reasoningEffort`, and optional positive `maxTokens` output cap. The loop validates exact-model reasoning support, resolves adapter defaults, records the effective values in the request header, and applies them to each conversation request. An optional `setup(agentCtx, agent)` callback composes the agent's scoped world before it is published: `agentCtx` owns registrations, while the explicit unpublished Agent provides its Session; the Context has no reverse Agent property. Scoped tools, prompt sections, and listeners exist before `agent/created`. Setup is composition-only: drive the agent only after creation resolves. The Session has entered its store and completed `session/created` before setup, so initialization events follow the live event feed.
|
|
44
|
+
|
|
45
|
+
<a id="model-selection"></a>
|
|
46
|
+
### Select a model
|
|
47
|
+
|
|
48
|
+
`agent.model` implements `Model`, alongside `agent.inbox`. `current()` returns a detached selection: the pending choice, then the latest request's choice, then live `agent.options`; it returns `undefined` when no source supplies both provider and model. Reading does not pin a choice or change a prepared step.
|
|
49
|
+
|
|
50
|
+
`select({ provider, model, reasoningEffort? })` assigns the complete choice for the next step whose preparation has not begun. Omitted effort uses adapter defaults; selection neither inherits old effort nor queries defaults. An equal recorded choice is a no-op, but a choice equal only to initial options is recorded as `model/selection`. Callers validate availability and capabilities; append failures retain the Session's existing guarantees.
|
|
51
|
+
|
|
52
|
+
Ordinary resume keeps the recorded choice. An entry point explicitly overriding the model first builds a complete selection, retaining the previous explicit effort only when the configured route is unchanged and omits effort, then calls `select()`. Web and ACP user selections call `select()` directly, so omitted effort means Auto. Selecting a Session model does not change deployment defaults.
|
|
53
|
+
|
|
54
|
+
For scoped switch notices, call `installModelSelection(agentCtx)` from `dsh-agent` during Agent setup. The scope owns the listener and removes it on disposal.
|
|
55
|
+
|
|
56
|
+
### Drive an agent's conversation
|
|
57
|
+
|
|
58
|
+
The handle's methods route identified user-role messages into the agent's inbox. `followup()` queues an ordinary next-turn prompt and wakes the driver; `steer()` submits next-step input and wakes it; `inject()` adds model-facing context without waking the driver, so it lands in the next admitted step. `cancel(cause)` aborts the active activity and, unless `keepInbox` is set, clears pending work; `whenIdle()` resolves after the whole agent reaches quiescence.
|
|
59
|
+
|
|
60
|
+
```text
|
|
61
|
+
handle.agent.followup({
|
|
62
|
+
content: [{ type: 'text', text: 'Summarize this workspace.' }],
|
|
63
|
+
source: { kind: 'user' },
|
|
64
|
+
})
|
|
65
|
+
handle.agent.steer({
|
|
66
|
+
content: [{ type: 'text', text: 'Focus on the tests.' }],
|
|
67
|
+
source: { kind: 'my-plugin' },
|
|
68
|
+
})
|
|
69
|
+
await handle.agent.whenIdle()
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Scope registrations to one agent
|
|
73
|
+
|
|
74
|
+
`Agent.ctx` is the agent's scoped context: registrations made through it (tools, prompt sections, variables, event listeners, restrictions) apply to that agent alone and unwind on disposal. The same mechanism is what agent presets use to give one session a different capability set without affecting its neighbors.
|
|
75
|
+
|
|
76
|
+
### Intercept or observe work in flight
|
|
77
|
+
|
|
78
|
+
`agent/request` is deprecated and retained for existing listeners. Do not add new listeners. Provider, model, and optional explicit reasoning effort are fixed at step preparation; listeners must preserve all three, including an absent effort. `AgentOptions.maxTokens` sets the output cap. Other per-request control overrides have no replacement API. See the [migration guide](../../../docs/upgrade-guide/v0.2.1-alpha.4/session-model-selection/guide.md) for affected callers.
|
|
79
|
+
|
|
80
|
+
The `agent/*` events let plugins act on live work without depending on the loop package. `agent/pre-step` can reject a proposed step or replace the messages entering it; `agent/request-error` lets a listener retry a failed model request; `agent/turn-stopping` runs before an otherwise completed turn closes and can steer to keep it open. `agent/assistant-stream` carries one process-local Assistant attempt's ordered start, transient chunk, and end frames. Start names the attempt's turn and step, chunk indexes are dense from zero, and `end.index` is the next chunk position. The loop commits the complete compact stream as one `assistant/message` or `assistant/attempt` before a committed end frame, so the live event remains presentation data rather than the replay source. `agent/status`, `agent/created`, and `agent/disposed` drive UI and coordination state, and the per-message `agent/inbox/*` notifications keep inbox projections in sync. Exact signatures, dispatch modes, and payload contracts live in the generated region of the [core subsystem page](../../../docs/subsystems/core.md#cordis-surface).
|
|
81
|
+
|
|
82
|
+
-----
|
|
83
|
+
|
|
84
|
+
<a id="understand-the-implementation"></a>
|
|
85
|
+
## Understand the implementation
|
|
86
|
+
|
|
87
|
+
<details>
|
|
88
|
+
<summary>Implementation internals — click to expand</summary>
|
|
89
|
+
|
|
90
|
+
This section explains how the package realizes the behavior above; the observable contract is covered in [Use this package](#use-this-package).
|
|
91
|
+
|
|
92
|
+
### Design concept
|
|
93
|
+
|
|
94
|
+
The package is built on one separation: the public `Agent` surface and registry live here, while construction and driving live in the loop package behind a registered factory. Consumers therefore depend on `dsh-agent` and never on `dsh-agent-loop`, keeping the driver swappable. The second idea is the initiator scope: an `AsyncLocalStorage` chain that carries the exact live `Agent` through the asynchronous driver work it starts, so helpers below a driver can attribute their work without forwarding the agent through every call.
|
|
95
|
+
|
|
96
|
+
### Step admission
|
|
97
|
+
|
|
98
|
+
`PreStepDecision` is either `{ kind: 'reject' }` or `{ kind: 'enter', messages, startsRequestSeries? }`. The enter branch contains the complete identified, frozen message batch. Acceptance does not commit it: after assembly and `step/start`, the deprecated `agent/request` hook adjusts controls without changing the step's model selection, and `prepareCall()` binds the adapter before the loop commits the system prompt and user batch. Cancellation during either async phase commits neither. `startsRequestSeries: true` declares a distinct model-message series; a wrapping listener preserves that declaration and the batch unless it intentionally replaces either one. Claiming removes offered messages from the inbox, while messages inserted after the claim remain pending for a later boundary.
|
|
99
|
+
|
|
100
|
+
### Durable inbox
|
|
101
|
+
|
|
102
|
+
`Agent.inbox` exposes only the structural `Inbox` interface and the projection vocabulary stays in this package. dsh-agent-loop owns the package-internal `ReactLoopInbox` and the standard `inbox` projection; the loop service acquires one registration for the durable `agent/inbox/spliced` fold and gives each inbox a state-reading callback. The registry remains the sole owner of the live `{ 'next-turn', 'next-step' }` state. Reconstruction rejects unsafe or out-of-range splice coordinates and duplicate `MessageId` values across both pending lists and reports the offending event seq.
|
|
103
|
+
|
|
104
|
+
`Inbox` exposes pending `nextTurn` and `nextStep` messages and mutates them through `append`, `prepend`, `replace`, `remove`, `clear`, and `splice`. Ordinary removals and `clear()` are durable cancellations. At a step boundary, the loop's internal implementation claims pending input through pure deletion splices. Live notifications are deliberately per-message and minimal: `agent/inbox/inserted { message }`, `agent/inbox/claimed { message, turn }`, and `agent/inbox/discarded { message }`.
|
|
105
|
+
|
|
106
|
+
### Durable model selection
|
|
107
|
+
|
|
108
|
+
`Model` and the `modelSelection` projection types live here. The default driver creates each `AgentModel` and owns projection registration alongside its inbox. Each instance binds the Session, live options, and a projection reader; it holds no second copy of the choice. The loop captures a detached selection before step preparation and retains it across retries.
|
|
109
|
+
|
|
110
|
+
### Source map
|
|
111
|
+
|
|
112
|
+
| File | Role |
|
|
113
|
+
|---|---|
|
|
114
|
+
| [`src/index.ts`](src/index.ts) | Plugin entry: `AgentRegistry`, factory slot, initiator scope, `CreateAgentOptions`/`ResumeAgentOptions` |
|
|
115
|
+
| [`src/runtime-types.ts`](src/runtime-types.ts) | `Agent`, structural `Inbox`, `AgentStatus`, and the `agent/*` event declarations |
|
|
116
|
+
| [`src/types.ts`](src/types.ts) | `AgentOptions`, cancellation causes, and inbox projection vocabulary |
|
|
117
|
+
| [`src/dispatch.ts`](src/dispatch.ts) | `agentEvents` fused dispatcher and `assembleContextFor(agent)` |
|
|
118
|
+
| [`src/model-selection.ts`](src/model-selection.ts) | `AgentModel`, its durable projection, and `installModelSelection` switch notices |
|
|
119
|
+
| [`src/consumed-work.ts`](src/consumed-work.ts) | `foldConsumedWork(events)`: what the log's consumed work became |
|
|
120
|
+
| [`src/archive-admission.ts`](src/archive-admission.ts) | The `turn` family of the Workspace registry's archive admission: a running turn and its user-cause cancel |
|
|
121
|
+
|
|
122
|
+
### Registry and lifecycle
|
|
123
|
+
|
|
124
|
+
`AgentRegistry` keeps one entry per live agent with its carrier and creator relation. Await `register()` to finish serial creation listeners with source `startup` before using an already-constructed agent; the async factory uses the split `enter()`/`announce()` pair so setup and initialization stay rollback-covered. A detach requested during creation waits for every awaited listener to settle, and each detach is bound to the exact entry, so a stale disposer cannot remove a later same-id replacement. Teardown stops and drains the loop, unwinds the scope, detaches the agent, then detaches the session; the id becomes reusable after private cleanup.
|
|
125
|
+
|
|
126
|
+
The registry also answers the Workspace registry's archive admission ([seam](../../workspace/workspace/README.md)) for every Agent it publishes: `workspace/session-activity` reports the `turn` family while the Session's Agent is running, a turn waiting for an approval or an answer included, and `workspace/session-stop` cancels that turn the way the user's own stop does — `agent.cancel({ kind: 'user' })`, but without the stop button's `keepInbox`, so queued input is discarded with a logged inbox splice instead of waking the archived Session later. Nothing is awaited to settlement; a Session without a live Agent has no turn that could run. The `turn` key is merged into `SessionActivityKindMap` from [`src/types.ts`](src/types.ts), so a Client that renders the families imports `@deepseek-ai/dsh-agent/types` for it.
|
|
127
|
+
|
|
128
|
+
### Initiator scope
|
|
129
|
+
|
|
130
|
+
Each driver runs its complete lifetime inside `ctx.agents.withInitiator(agent, ...)`, so inherited async chains observe that agent; `withoutInitiator()` hides it for unrelated process-local work such as shared timers. The boundary is process-local attribution only — ambient presence is neither liveness proof nor authorization, and explicit identity stays authoritative at worker, process, persistence, and wire boundaries. Teardown rejects new boundaries, lets returned-Promise boundaries drain, then disables the underlying storage. The [initiator-scope decision](../../../.agents/notes/implemented/architecture/2026-07-15-agent-initiator-scope.md) owns the detailed contract.
|
|
131
|
+
|
|
132
|
+
### Ownership invariants
|
|
133
|
+
|
|
134
|
+
The `AgentHandle` disposer is a capability: among consumers, only its holder can tear the agent down. The registered factory provider is a structural co-owner, because scoped agents depend on that provider's service API; provider unload stops and drains every live handle it made. `ctx.agents.get(id)` still returns a bare `Agent` — the handle is exposed only to the consumer that created it.
|
|
135
|
+
|
|
136
|
+
</details>
|
|
137
|
+
|
|
138
|
+
-----
|
|
139
|
+
|
|
140
|
+
<a id="further-exploration"></a>
|
|
141
|
+
## Further Exploration
|
|
142
|
+
|
|
143
|
+
The package-level contract is enough for most consumers; read these when you need the surrounding domain and the design rationale.
|
|
144
|
+
|
|
145
|
+
- [Core subsystem](../../../docs/subsystems/core.md) — the loop map, `Agent` handle, interception decisions, and generated service API.
|
|
146
|
+
- [agent-loop package](../agent-loop/README.md) — the default driver that creates, drives, and disposes agents.
|
|
147
|
+
- [Session subsystem](../../../docs/subsystems/session.md) — the durable log and derived history behind the handle.
|
|
148
|
+
- [Initiator-scope Agent Note](../../../.agents/notes/implemented/architecture/2026-07-15-agent-initiator-scope.md) — the boundary and teardown contract.
|
|
149
|
+
- [Core group map](../README.md) — how the core packages compose.
|
|
150
|
+
|
|
151
|
+
-----
|
|
152
|
+
|
|
153
|
+
<a id="model-experience"></a>
|
|
154
|
+
## Model Experience
|
|
155
|
+
|
|
156
|
+
### User, steering, and injected messages
|
|
157
|
+
|
|
158
|
+
#### What the model sees
|
|
159
|
+
|
|
160
|
+
`followup`, `steer`, and `inject` feed the owning session as identified user-role messages; accepted content becomes part of the derived history the model reads on later steps. `agent/pre-step` and the other declared events let plugins reject a proposed step or add durable request material. The optional scoped model-switch listener adds the notice described below.
|
|
161
|
+
|
|
162
|
+
#### Token effect
|
|
163
|
+
|
|
164
|
+
Accepted content becomes retained history or a repeated session prefix; blocked content contributes no request tokens. Size is caller- and plugin-dependent.
|
|
165
|
+
|
|
166
|
+
#### KV Cache effect
|
|
167
|
+
|
|
168
|
+
Accepted history and steering are append-only; a blocked submission sends no request. A session prefix remains stable within its loop instance, while a new or resumed instance may establish a different prefix.
|
|
169
|
+
|
|
170
|
+
### Agent-scoped request composition
|
|
171
|
+
|
|
172
|
+
#### What the model sees
|
|
173
|
+
|
|
174
|
+
Registrations through `agent.ctx` can shadow prompt sections or tools and can install agent-only interceptors during unpublished setup, so one agent sees a different prompt and tool set than its neighbors. Model selection captures one provider/model/effort value before prompt assembly and applies it to the same step's request and retries; a later concurrent change waits for another step.
|
|
175
|
+
|
|
176
|
+
#### Token effect
|
|
177
|
+
|
|
178
|
+
Scoped contributions affect only that agent and disappear on disposal.
|
|
179
|
+
|
|
180
|
+
#### KV Cache effect
|
|
181
|
+
|
|
182
|
+
Setup or reload that changes prompt sections, tool definitions, or request listeners may invalidate reuse from the first affected request token.
|
|
183
|
+
|
|
184
|
+
### Optional model-switch notice
|
|
185
|
+
|
|
186
|
+
#### What the model sees
|
|
187
|
+
|
|
188
|
+
The scoped listener appends `[model changed: assistant turns above this point were generated by <previous>; the session continues with <next>]` when an accepted step's fixed route differs from the last request. Labels include providers only for cross-provider switches. Initial requests, effort-only changes, rejected steps, and empty no-request decisions add nothing. Failure before header persistence causes the next request step to repeat the notice.
|
|
189
|
+
|
|
190
|
+
#### Token effect
|
|
191
|
+
|
|
192
|
+
Each admitted notice adds retained user-message text; selection events themselves add no prompt text.
|
|
193
|
+
|
|
194
|
+
#### KV Cache effect
|
|
195
|
+
|
|
196
|
+
Notices append without replacing earlier history. Switching models may prevent reuse of the previous model's cache; cache availability is provider-owned.
|
|
197
|
+
|
|
198
|
+
## Known Limitations and Deferred Work
|
|
199
|
+
|
|
200
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
These limits define when this package needs special care. They are current package constraints, not a task backlog.
|
|
204
|
+
|
|
205
|
+
- **Initiator scope is process-local** — workers, child processes, HTTP, durable queues, and restarts must materialize any required identity explicitly.
|
|
206
|
+
- **Ambient identity may outlive liveness** — consumers still check `agent.status`, cancellation, and the owning capability contract before lifecycle-sensitive work.
|
|
207
|
+
- **Creation listeners share the initialization lifetime.** An `agent/created` listener must not await `agent.whenIdle()` or its own owner's disposal: those operations wait for creation to finish. Return only after required asynchronous tool and prompt installation completes.
|
|
208
|
+
- **`cancel()` clears the inbox by default** — it aborts the in-flight turn plus queued and steering work; `cancel(cause, { keepInbox: true })` aborts only the turn and preserves pending items, and there is no step-only abort that keeps the turn running.
|
|
209
|
+
- **Each additional `UserMessage` carries exactly one `MessageSource`** — contributions from several plugins merged onto one message collapse under one source, so the message cannot name several producers.
|
|
210
|
+
|
|
211
|
+
<a id="dev-note"></a>
|
|
212
|
+
### Dev Note
|
|
213
|
+
|
|
214
|
+
<details>
|
|
215
|
+
<summary>Working context for maintainers — click to expand</summary>
|
|
216
|
+
|
|
217
|
+
This Dev Note is working context for maintainers; it is explicitly non-authoritative. Open, undecided directions: inter-agent channels beyond delegation — shared state, streaming child output, and background or poll semantics remain outside the current delegation seam; and the `SessionStartSource` values `'clear'`/`'compact'` are reserved with no emitter yet, pending the driving subsystems.
|
|
218
|
+
|
|
219
|
+
</details>
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "面向插件、UI 与编排器的 Agent 句柄、实时注册表、进程本地发起方作用域,以及 agent/* 事件词汇。"
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @deepseek-ai/dsh-agent
|
|
7
|
+
|
|
8
|
+
[English](README.md) | 中文
|
|
9
|
+
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
使用 `dsh-agent` 创建或恢复实时 agent(智能体)、发送后续或 steering(中途引导)输入、注入面向模型的上下文、取消工作,并等待 agent 进入空闲状态。插件、UI、钩子与编排器还可以观察或拦截 agent 活动,并仅为一个 agent 应用能力而不影响其他 agent。当代码需要通过公开 `Agent` API 控制或扩展实时 agent 时,请选择本包。请将它与 `dsh-agent-loop` 等 agent 驱动器配合使用;本包本身不会创建模型请求。发起方归因仅存在于进程内,跨 worker、进程、持久队列与重启时必须显式传递。
|
|
13
|
+
|
|
14
|
+
## 目录
|
|
15
|
+
|
|
16
|
+
- [使用本包](#use-this-package)
|
|
17
|
+
- [理解实现](#understand-the-implementation)
|
|
18
|
+
- [进一步探索](#further-exploration)
|
|
19
|
+
- [模型体验](#model-experience)
|
|
20
|
+
- [已知限制与延期工作](#known-limitations-and-deferred-work)
|
|
21
|
+
- [开发备注](#dev-note)
|
|
22
|
+
|
|
23
|
+
-----
|
|
24
|
+
|
|
25
|
+
<a id="use-this-package"></a>
|
|
26
|
+
## 使用本包
|
|
27
|
+
|
|
28
|
+
将 `dsh-agent` 与 `dsh-session-projection` 一起挂载:它提供 `ctx.agents`、`Agent` 句柄,以及读取已记录轮次和步骤位置的 `turnBoundaryOf(session)`。创建或恢复 Agent 还需要驱动器注册工厂;随附驱动器是 `dsh-agent-loop`。 [Session 模型选择](#model-selection) 通过每个句柄的 `agent.model` 提供。
|
|
29
|
+
|
|
30
|
+
### 创建或恢复 agent
|
|
31
|
+
|
|
32
|
+
`ctx.agents.create()` 在一个身份下构建全新 agent 与会话;`ctx.agents.resume()` 加载持久化会话并在此基础上重建 agent。两者都委托给已注册工厂,并返回 `AgentHandle`——唯一能拆除该 agent 的对象。发布和失败清理的时序见 [`AgentFactory`](src/index.ts)。在任一操作的 options 中设置 `parentAgent`,可使结果成为运行时子级;省略它则得到运行时根级。`get(id)`、`list()` 与 `roots()` 用于查找实时 agent;`isOwnedBy(id, parent)` 用于检验这项确切的实时所有权关系。
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
const handle = await ctx.agents.create({
|
|
36
|
+
sessionId,
|
|
37
|
+
agentOptions: { provider: 'deepseek', model: 'deepseek-chat' },
|
|
38
|
+
})
|
|
39
|
+
// later:
|
|
40
|
+
await handle.dispose() // stops the loop, unregisters, removes the session, unwinds the scope
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`AgentOptions` 提供初始提供方/模型路由、可选的由适配器定义的 `reasoningEffort`,以及可选的正数 `maxTokens` 输出上限。循环会校验确切模型的推理(reasoning)支持、解析适配器默认值、把生效值记录在请求头中,并将它们应用到每个对话请求。可选的 `setup(agentCtx, agent)` 回调会在 agent 发布之前组合其作用域世界:`agentCtx` 拥有注册,显式的未发布 Agent 则提供其 Session;Context 不含反向 Agent 属性。作用域工具、提示词段与监听器在 `agent/created` 之前就已存在。Setup 只做组合:创建完成后才能驱动 agent。 setup 开始前 Session 已进入 Store 并完成 `session/created`,因此初始化事件通过实时事件流发出。
|
|
44
|
+
|
|
45
|
+
<a id="model-selection"></a>
|
|
46
|
+
### 选择模型
|
|
47
|
+
|
|
48
|
+
`agent.model` 实现 `Model` 接口,与 `agent.inbox` 并列。`current()` 返回选择的独立副本:依次读取待生效选择、最近请求的选择和实时 `agent.options`;没有来源同时提供 provider 与 model 时返回 `undefined`。读取不会固定选择,也不会改变已经准备的步骤。
|
|
49
|
+
|
|
50
|
+
`select({ provider, model, reasoningEffort? })` 完整赋值,从下一个尚未开始准备的步骤生效。省略强度表示使用适配器默认值;选择操作既不继承旧强度,也不查询默认值。与已记录选择相同则不重复记录,但仅与初始 options 相同仍会记录 `model/selection`。调用方负责校验可用性与能力;追加失败沿用 Session 现有的失败保证。
|
|
51
|
+
|
|
52
|
+
普通恢复保留持久化选择。明确覆盖模型的入口先形成完整选择:仅在配置未指定强度且路由不变时保留旧的显式强度,然后调用 `select()`。Web 与 ACP 用户选择直接调用 `select()`,因此省略强度表示 Auto。选择 Session 模型不会改变部署默认值。
|
|
53
|
+
|
|
54
|
+
要启用作用域内的切换提示,在 Agent setup 中调用 `dsh-agent` 的 `installModelSelection(agentCtx)`。作用域拥有监听器,并在释放时移除它。
|
|
55
|
+
|
|
56
|
+
### 驱动 agent 的对话
|
|
57
|
+
|
|
58
|
+
句柄的方法把带标识的 user 角色消息路由进 agent 的收件箱。`followup()` 排队一条普通的下一个轮次提示词并唤醒驱动器;`steer()` 提交下一步输入并唤醒它;`inject()` 添加面向模型的上下文但不唤醒驱动器,因此它落在下一个被接纳的步骤中。`cancel(cause)` 中止当前活动,并在未设置 `keepInbox` 时清除待处理工作;`whenIdle()` 会在整个 agent 达到完全停稳后完成。
|
|
59
|
+
|
|
60
|
+
```text
|
|
61
|
+
handle.agent.followup({
|
|
62
|
+
content: [{ type: 'text', text: 'Summarize this workspace.' }],
|
|
63
|
+
source: { kind: 'user' },
|
|
64
|
+
})
|
|
65
|
+
handle.agent.steer({
|
|
66
|
+
content: [{ type: 'text', text: 'Focus on the tests.' }],
|
|
67
|
+
source: { kind: 'my-plugin' },
|
|
68
|
+
})
|
|
69
|
+
await handle.agent.whenIdle()
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 将注册限定到单个 agent
|
|
73
|
+
|
|
74
|
+
`Agent.ctx` 是该 agent 的作用域上下文:通过它进行的注册(工具、提示词段、变量、事件监听器、限制)只对该 agent 生效,并在 dispose(资源释放)时全部撤销。同一机制也是 agent preset 用来让一个会话获得不同能力集、同时不影响其邻居的方式。
|
|
75
|
+
|
|
76
|
+
### 拦截或观察进行中的工作
|
|
77
|
+
|
|
78
|
+
`agent/request` 已弃用,仅为现有监听器保留。不要添加新监听器。提供方、模型和可选的显式推理强度在步骤准备时固定;监听器必须保留三者,包括未指定强度的状态。`AgentOptions.maxTokens` 设置输出上限。其他逐请求控制参数覆盖没有替代 API。受影响的调用方参见[迁移指南](../../../docs/upgrade-guide/v0.2.1-alpha.4/session-model-selection/guide.zh.md)。
|
|
79
|
+
|
|
80
|
+
`agent/*` 事件让插件无需依赖循环包即可作用于实时工作。`agent/pre-step` 可以拒绝拟进入的步骤或替换进入它的消息;`agent/request-error` 让监听器重试失败的模型请求;`agent/turn-stopping` 在本可完成的轮次关闭前运行,并可通过 steer 使其保持打开。`agent/assistant-stream` 携带一个进程本地 Assistant attempt 的有序 start、瞬态分片与 end frame。start 给出该 attempt 的轮次与步骤,分片索引从零开始密集递增,`end.index` 则是下一个分片位置。loop 会在 committed end frame 前把完整紧凑流提交为一个 `assistant/message` 或 `assistant/attempt`,因此实时事件仍是呈现数据而非回放来源。`agent/status`、`agent/created` 与 `agent/disposed` 驱动 UI 与协调状态,逐消息的 `agent/inbox/*` 通知则让收件箱投影保持同步。确切签名、分发 mode 与 payload 约定见 [core 子系统页](../../../docs/subsystems/core.zh.md#cordis-surface) 的生成区块。
|
|
81
|
+
|
|
82
|
+
-----
|
|
83
|
+
|
|
84
|
+
<a id="understand-the-implementation"></a>
|
|
85
|
+
## 理解实现
|
|
86
|
+
|
|
87
|
+
<details>
|
|
88
|
+
<summary>实现细节——点击展开</summary>
|
|
89
|
+
|
|
90
|
+
本节解释该包如何实现上述行为;可观察约定已在[使用本包](#use-this-package)中完整说明。
|
|
91
|
+
|
|
92
|
+
### 设计理念
|
|
93
|
+
|
|
94
|
+
该包建立在一项职责分离之上:公开的 `Agent` 接口与注册表位于本包,构造与驱动则位于循环包,并通过已注册工厂提供。消费方因此依赖 `dsh-agent` 而不依赖 `dsh-agent-loop`,从而保持驱动器可替换。第二个理念是发起方作用域:一条 `AsyncLocalStorage` 链把确切的实时 `Agent` 携带经过它启动的异步驱动器工作,使驱动器之下的辅助函数无需逐调用转发 agent 即可归因自己的工作。
|
|
95
|
+
|
|
96
|
+
### 步骤准入
|
|
97
|
+
|
|
98
|
+
`PreStepDecision` 要么是 `{ kind: 'reject' }`,要么是 `{ kind: 'enter', messages, startsRequestSeries? }`。enter 分支包含完整、带标识且冻结的消息批次。接纳不等于提交:组装与 `step/start` 之后,已弃用的 `agent/request` hook 在不改变步骤模型选择的前提下调整控制参数,`prepareCall()` 绑定适配器,循环随后才提交系统提示词与用户批次。在任一异步阶段取消都不会提交这两者。`startsRequestSeries: true` 声明一个独立的模型消息序列;包装下游 enter 的监听器会保留该声明与批次,除非有意替换其中一项。领取会从 inbox 移除候选消息,领取后插入的消息则等待后续边界。
|
|
99
|
+
|
|
100
|
+
### 持久 inbox
|
|
101
|
+
|
|
102
|
+
`Agent.inbox` 只暴露结构型 `Inbox` 接口,投影词汇仍位于本包。dsh-agent-loop 持有包内部的 `ReactLoopInbox` 与标准 `inbox` 投影;loop 服务为持久 `agent/inbox/spliced` fold 获取一份注册,并向每个 inbox 提供状态读取回调。注册表继续作为实时 `{ 'next-turn', 'next-step' }` 状态的唯一所有者。重建过程会拒绝不安全或越界的 splice 坐标,以及跨两份待处理列表重复的 `MessageId`,并报告出错事件的 seq。
|
|
103
|
+
|
|
104
|
+
`Inbox` 暴露待处理的 `nextTurn` 与 `nextStep` 消息,并通过 `append`、`prepend`、`replace`、`remove`、`clear` 与 `splice` 变更它们。普通删除和 `clear()` 都是持久取消。在步骤边界,循环的内部实现会通过纯删除 splice 领取待处理输入。实时通知刻意采用逐消息的最小载荷:`agent/inbox/inserted { message }`、`agent/inbox/claimed { message, turn }` 与 `agent/inbox/discarded { message }`。
|
|
105
|
+
|
|
106
|
+
### 持久模型选择
|
|
107
|
+
|
|
108
|
+
`Model` 和 `modelSelection` 投影类型在本包定义。默认驱动器与 inbox 一起创建每个 `AgentModel` 并拥有投影注册。每个实例绑定 Session、实时选项和投影读取器,不维护选择的第二份副本。循环在步骤准备前捕获独立选择,并在重试间保留它。
|
|
109
|
+
|
|
110
|
+
### 源码地图
|
|
111
|
+
|
|
112
|
+
| 文件 | 职责 |
|
|
113
|
+
|---|---|
|
|
114
|
+
| [`src/index.ts`](src/index.ts) | 插件入口:`AgentRegistry`、工厂槽位、发起方作用域、`CreateAgentOptions`/`ResumeAgentOptions` |
|
|
115
|
+
| [`src/runtime-types.ts`](src/runtime-types.ts) | `Agent`、结构化 `Inbox`、`AgentStatus` 与 `agent/*` 事件声明 |
|
|
116
|
+
| [`src/types.ts`](src/types.ts) | `AgentOptions`、取消原因与收件箱投影词汇 |
|
|
117
|
+
| [`src/dispatch.ts`](src/dispatch.ts) | `agentEvents` 融合分发器与 `assembleContextFor(agent)` |
|
|
118
|
+
| [`src/model-selection.ts`](src/model-selection.ts) | `AgentModel`、持久投影与 `installModelSelection` 切换提示 |
|
|
119
|
+
| [`src/consumed-work.ts`](src/consumed-work.ts) | `foldConsumedWork(events)`:日志消费掉的工作最终怎样了 |
|
|
120
|
+
| [`src/archive-admission.ts`](src/archive-admission.ts) | Workspace 注册表归档准入中的 `turn` 族:运行中的回合及其用户原因取消 |
|
|
121
|
+
|
|
122
|
+
### 注册表与生命周期
|
|
123
|
+
|
|
124
|
+
`AgentRegistry` 为每个实时 agent 保留一个条目,含其载体与创建者关系。使用已构造的 agent 前,等待 `register()` 以 `startup` 来源完成串行创建监听器;异步工厂使用拆分的 `enter()`/`announce()` 对,使 setup 与初始化始终受回滚保护。创建期间请求的 detach 会等待所有已调用的异步监听器结算,且每次 detach 都绑定到确切条目,因此陈旧 disposer 无法移除之后出现的同 id 替代项。Teardown 停止并排空循环、撤销作用域、detach agent,再 detach 会话;私有清理完成后该 id 即可复用。
|
|
125
|
+
|
|
126
|
+
注册表还为它发布的每个 Agent 回答 Workspace 注册表的归档准入([接缝](../../workspace/workspace/README.zh.md)):`workspace/session-activity` 在会话的 Agent 运行时报告 `turn` 族(等待审批或回答的回合也算),`workspace/session-stop` 以用户自己的停止方式取消该回合——`agent.cancel({ kind: 'user' })`,但不带停止按钮的 `keepInbox`,因此排队输入被丢弃并记录一次收件箱拼接,而不会在之后唤醒已归档会话。任何一步都不等待收敛;没有活 Agent 的会话没有可运行的回合。`turn` 键从 [`src/types.ts`](src/types.ts) 合并进 `SessionActivityKindMap`,渲染各族的 Client 为此导入 `@deepseek-ai/dsh-agent/types`。
|
|
127
|
+
|
|
128
|
+
### 发起方作用域
|
|
129
|
+
|
|
130
|
+
每个驱动器在 `ctx.agents.withInitiator(agent, ...)` 内运行其完整生命周期,因此继承的异步链会观察到该 agent;`withoutInitiator()` 为共享定时器等无关的进程本地工作隐藏它。该边界只是进程本地归因——环境中的身份既不是存活证明,也不是授权,显式身份在 worker、进程、持久化与 wire 边界保持权威。Teardown 拒绝新边界,让返回 Promise 的边界排空,然后禁用底层存储。[发起方作用域决策](../../../.agents/notes/implemented/architecture/2026-07-15-agent-initiator-scope.zh.md) 拥有详细约定。
|
|
131
|
+
|
|
132
|
+
### 所有权不变式
|
|
133
|
+
|
|
134
|
+
`AgentHandle` disposer 是一项能力:在消费方中,只有其持有者能拆除该 agent。已注册的工厂提供方是结构化共同拥有者,因为作用域 agent 依赖该提供方的服务 API;提供方卸载会停止并排空它创建的每个实时句柄。`ctx.agents.get(id)` 仍返回裸 `Agent`——句柄只暴露给创建它的消费方。
|
|
135
|
+
|
|
136
|
+
</details>
|
|
137
|
+
|
|
138
|
+
-----
|
|
139
|
+
|
|
140
|
+
<a id="further-exploration"></a>
|
|
141
|
+
## 进一步探索
|
|
142
|
+
|
|
143
|
+
包级约定对大多数消费方已经足够;需要周边领域与设计原理时再阅读以下页面。
|
|
144
|
+
|
|
145
|
+
- [Core 子系统](../../../docs/subsystems/core.zh.md)——循环图、`Agent` 句柄、拦截决策与生成的服务 API。
|
|
146
|
+
- [agent-loop 包](../agent-loop/README.zh.md)——创建、驱动并拆除 agent 的默认驱动器。
|
|
147
|
+
- [会话子系统](../../../docs/subsystems/session.zh.md)——句柄背后的持久日志与派生历史。
|
|
148
|
+
- [发起方作用域 Agent Note](../../../.agents/notes/implemented/architecture/2026-07-15-agent-initiator-scope.zh.md)——边界与 teardown 约定。
|
|
149
|
+
- [core 分组地图](../README.zh.md)——core 各包如何组合。
|
|
150
|
+
|
|
151
|
+
-----
|
|
152
|
+
|
|
153
|
+
<a id="model-experience"></a>
|
|
154
|
+
## 模型体验
|
|
155
|
+
|
|
156
|
+
### 用户、steering 与注入消息
|
|
157
|
+
|
|
158
|
+
#### 模型看到什么
|
|
159
|
+
|
|
160
|
+
`followup`、`steer` 与 `inject` 以带标识的 user 角色消息馈送所属会话;被接纳的内容成为模型在后续步骤中读取的派生历史的一部分。`agent/pre-step` 与其他已声明事件让插件能够拒绝拟进入的步骤或添加持久请求材料。可选的作用域模型切换监听器会添加下文所述的提示。
|
|
161
|
+
|
|
162
|
+
#### Token 影响
|
|
163
|
+
|
|
164
|
+
被接纳内容成为保留历史,或成为每次请求重复的会话前缀;被阻止内容不贡献请求 token。大小取决于调用方与插件。
|
|
165
|
+
|
|
166
|
+
#### KV Cache 影响
|
|
167
|
+
|
|
168
|
+
被接纳历史与 steering 只追加;被阻止的提交不发送请求。会话前缀在循环实例内保持稳定,而新建或恢复的实例可能建立不同前缀。
|
|
169
|
+
|
|
170
|
+
### Agent 作用域的请求组合
|
|
171
|
+
|
|
172
|
+
#### 模型看到什么
|
|
173
|
+
|
|
174
|
+
通过 `agent.ctx` 进行的注册可以遮蔽提示词段或工具,也可以在未发布 setup 期间安装仅适用于该 agent 的拦截器,因此一个 agent 看到的提示词与工具集会与其邻居不同。模型选择会在提示词组装前捕获一次提供方/模型/推理强度值,并将其应用到同一步骤的请求与重试;之后发生的并发变更等待下一个步骤。
|
|
175
|
+
|
|
176
|
+
#### Token 影响
|
|
177
|
+
|
|
178
|
+
每次提供方/模型切换会增加一条简短且保留在历史中的 user 角色提示。其他带作用域贡献只影响该 agent,并在 dispose 时消失。
|
|
179
|
+
|
|
180
|
+
#### KV Cache 影响
|
|
181
|
+
|
|
182
|
+
改变提示词段、工具定义或请求监听器的 setup 或 reload,可能从第一个受影响的请求 token 起使复用失效。
|
|
183
|
+
|
|
184
|
+
### 可选的模型切换提示
|
|
185
|
+
|
|
186
|
+
#### 模型看到什么
|
|
187
|
+
|
|
188
|
+
已接纳步骤的固定路由与最近请求不同时,作用域监听器追加 `[model changed: assistant turns above this point were generated by <previous>; the session continues with <next>]`。只有跨提供方切换才在标签中包含提供方。首次请求、仅强度变化、被拒绝步骤和不会发起请求的空决策不添加提示。请求头持久化前失败时,下一个请求步骤会再次收到提示。
|
|
189
|
+
|
|
190
|
+
#### Token 影响
|
|
191
|
+
|
|
192
|
+
每条接纳的提示都会增加保留的用户消息文本;选择事件本身不增加提示词文本。
|
|
193
|
+
|
|
194
|
+
#### KV Cache 影响
|
|
195
|
+
|
|
196
|
+
提示只追加,不替换此前历史。切换模型可能无法复用原模型缓存;缓存可用性由提供方决定。
|
|
197
|
+
|
|
198
|
+
## 已知限制与延期工作
|
|
199
|
+
|
|
200
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
这些限制说明本包何时需要特别留意。它们是当前包约束,不是任务积压。
|
|
204
|
+
|
|
205
|
+
- **发起方作用域只存在于进程内**:worker、子进程、HTTP、持久队列和重启必须显式传递所需身份。
|
|
206
|
+
- **环境身份可能比存活状态更久**:消费方在生命周期敏感工作前,仍要检查 `agent.status`、取消状态和所属能力约定。
|
|
207
|
+
- **创建监听器共享初始化生命周期。** `agent/created` 监听器不得等待 `agent.whenIdle()` 或自身所有者的 dispose:这些操作要等待创建完成。所需的异步工具与提示词安装完成后,监听器才可返回。
|
|
208
|
+
- **`cancel()` 默认清空收件箱**:它会中止正在处理的轮次以及排队和 steering 工作;`cancel(cause, { keepInbox: true })` 只中止轮次并保留待处理项,且不存在让轮次继续运行、只中止步骤的操作。
|
|
209
|
+
- **每条附加 `UserMessage` 恰好携带一个 `MessageSource`**:多个插件合并到一条消息上的贡献会归入同一来源,因此该消息无法列出多个生产者。
|
|
210
|
+
|
|
211
|
+
<a id="dev-note"></a>
|
|
212
|
+
### 开发备注
|
|
213
|
+
|
|
214
|
+
<details>
|
|
215
|
+
<summary>维护者的工作上下文——点击展开</summary>
|
|
216
|
+
|
|
217
|
+
本开发备注是维护者的工作上下文;它明确不具权威性。尚未决定的开放方向:委派之外的 agent 间通道——共享状态、流式子输出以及后台或轮询语义仍不在当前委派 seam 之内;以及 `SessionStartSource` 的 `'clear'`/`'compact'` 值已保留但尚无发出方,待驱动子系统落地。
|
|
218
|
+
|
|
219
|
+
</details>
|