dsh-plugin-dev-kb 1.0.9 → 1.3.0
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/CHANGELOG.md +26 -0
- package/README.en.md +14 -8
- package/README.md +14 -8
- package/docs/banner.svg +25 -0
- package/kb/INDEX.md +8 -2
- package/kb/README.md +4 -4
- package/kb/extra/AGENTS.md +3 -3
- package/kb/extra/cookbook/adding-a-remote-api.md +197 -0
- package/kb/extra/cookbook/adding-a-remote-api.zh.md +197 -0
- package/kb/extra/cookbook/adding-a-session-format-version.md +109 -0
- package/kb/extra/cookbook/adding-a-session-format-version.zh.md +109 -0
- package/kb/extra/cookbook/adding-a-vendored-package.md +1 -1
- package/kb/extra/cookbook/adding-a-vendored-package.zh.md +1 -1
- package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.md +1 -1
- package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.zh.md +1 -1
- package/kb/extra/deepseek-llm-api-wire-extensions.md +19 -15
- package/kb/extra/deepseek-llm-api-wire-extensions.zh.md +19 -15
- package/kb/extra/development.md +13 -3
- package/kb/extra/development.zh.md +13 -3
- package/kb/extra/event-producer-consumer.md +49 -46
- package/kb/extra/event-producer-consumer.zh.md +52 -49
- package/kb/extra/i18n/README.md +2 -1
- package/kb/extra/i18n/README.zh.md +3 -2
- package/kb/extra/i18n/style-samples.md +2 -2
- package/kb/extra/i18n/translation-prompt.md +1 -1
- package/kb/extra/module-graph.md +493 -1002
- package/kb/extra/module-graph.zh.md +495 -1004
- package/kb/extra/rescope.md +1 -1
- package/kb/extra/rescope.zh.md +1 -1
- package/kb/extra/session-format-status.md +47 -0
- package/kb/extra/session-format-status.zh.md +47 -0
- package/kb/extra/subsystems/agent-team.md +3 -2
- package/kb/extra/subsystems/agent-team.zh.md +3 -2
- package/kb/extra/subsystems/attachment.md +157 -4
- package/kb/extra/subsystems/attachment.zh.md +157 -4
- package/kb/extra/subsystems/feedback.md +164 -30
- package/kb/extra/subsystems/feedback.zh.md +164 -30
- package/kb/extra/testing.md +9 -4
- package/kb/extra/testing.zh.md +9 -4
- package/kb/extra/web-styling.md +5 -0
- package/kb/extra/web-styling.zh.md +5 -0
- package/kb/meta/search-index.json +223 -151
- package/kb/meta/site-pages.txt +187 -181
- package/kb/meta/source.json +5 -5
- package/kb/meta/topics.md +5 -5
- package/kb/site/develop/basic/publish.md +1 -1
- package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +3 -2
- package/kb/site/develop/practice/llm-adapter.md +4 -3
- package/kb/site/en/develop/basic/publish.md +1 -1
- package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +3 -2
- package/kb/site/en/develop/practice/llm-adapter.md +4 -3
- package/kb/site/en/guide/network-proxy.md +87 -0
- package/kb/site/en/guide/providers.md +70 -17
- package/kb/site/en/guide/python-sdk.md +19 -3
- package/kb/site/en/guide/schedule.md +2 -0
- package/kb/site/en/reference/agent-lifecycle.md +17 -8
- package/kb/site/en/reference/api-gateway.md +2 -2
- package/kb/site/en/reference/capability-seams.md +24 -10
- package/kb/site/en/reference/config-catalog.md +322 -264
- package/kb/site/en/reference/cookbook/adding-a-package.md +1 -2
- package/kb/site/en/reference/cookbook/adding-a-settings-card.md +10 -8
- package/kb/site/en/reference/cookbook/adding-a-tool.md +1 -1
- package/kb/site/en/reference/cookbook/extension-cookbook.md +16 -13
- package/kb/site/en/reference/index.md +26 -9
- package/kb/site/en/reference/persistence-catalog.md +189 -95
- package/kb/site/en/reference/subsystems/approval.md +1 -1
- package/kb/site/en/reference/subsystems/client-modules.md +9 -0
- package/kb/site/en/reference/subsystems/client-resources.md +94 -0
- package/kb/site/en/reference/subsystems/code-runtime.md +7 -3
- package/kb/site/en/reference/subsystems/commands.md +25 -16
- package/kb/site/en/reference/subsystems/compaction.md +10 -10
- package/kb/site/en/reference/subsystems/conversation.md +11 -4
- package/kb/site/en/reference/subsystems/core.md +173 -29
- package/kb/site/en/reference/subsystems/credentials.md +5 -4
- package/kb/site/en/reference/subsystems/filesystem.md +15 -0
- package/kb/site/en/reference/subsystems/goal.md +38 -2
- package/kb/site/en/reference/subsystems/index.md +3 -1
- package/kb/site/en/reference/subsystems/invariants.md +1 -1
- package/kb/site/en/reference/subsystems/llm-streaming.md +43 -12
- package/kb/site/en/reference/subsystems/lsp.md +1 -1
- package/kb/site/en/reference/subsystems/permission-presets.md +5 -5
- package/kb/site/en/reference/subsystems/persistence.md +211 -199
- package/kb/site/en/reference/subsystems/plan.md +3 -3
- package/kb/site/en/reference/subsystems/sandbox.md +2 -0
- package/kb/site/en/reference/subsystems/schedule.md +9 -3
- package/kb/site/en/reference/subsystems/scope.md +1 -1
- package/kb/site/en/reference/subsystems/session-projection.md +50 -24
- package/kb/site/en/reference/subsystems/session-query.md +19 -13
- package/kb/site/en/reference/subsystems/session-reference.md +29 -1
- package/kb/site/en/reference/subsystems/session-telemetry.md +27 -10
- package/kb/site/en/reference/subsystems/session-title.md +6 -6
- package/kb/site/en/reference/subsystems/session.md +208 -103
- package/kb/site/en/reference/subsystems/settings.md +30 -12
- package/kb/site/en/reference/subsystems/shell.md +9 -6
- package/kb/site/en/reference/subsystems/sidebar-right.md +151 -0
- package/kb/site/en/reference/subsystems/skills.md +1 -1
- package/kb/site/en/reference/subsystems/slots.md +41 -32
- package/kb/site/en/reference/subsystems/spill.md +13 -6
- package/kb/site/en/reference/subsystems/storage.md +28 -5
- package/kb/site/en/reference/subsystems/subagent.md +58 -105
- package/kb/site/en/reference/subsystems/subprocess.md +25 -26
- package/kb/site/en/reference/subsystems/system-prompt.md +18 -3
- package/kb/site/en/reference/subsystems/token-meter.md +4 -3
- package/kb/site/en/reference/subsystems/tools.md +5 -5
- package/kb/site/en/reference/subsystems/typert.md +18 -18
- package/kb/site/en/reference/subsystems/web-client.md +1 -1
- package/kb/site/en/reference/subsystems/workspace.md +88 -9
- package/kb/site/en/reference/tool-catalog.md +56 -66
- package/kb/site/en/reference/tool-execution-pipeline.md +2 -2
- package/kb/site/guide/network-proxy.md +87 -0
- package/kb/site/guide/providers.md +70 -17
- package/kb/site/guide/python-sdk.md +19 -3
- package/kb/site/guide/schedule.md +2 -0
- package/kb/site/reference/agent-lifecycle.md +17 -8
- package/kb/site/reference/api-gateway.md +2 -2
- package/kb/site/reference/capability-seams.md +24 -10
- package/kb/site/reference/config-catalog.md +321 -263
- package/kb/site/reference/cookbook/adding-a-package.md +1 -2
- package/kb/site/reference/cookbook/adding-a-settings-card.md +10 -8
- package/kb/site/reference/cookbook/adding-a-tool.md +1 -1
- package/kb/site/reference/cookbook/extension-cookbook.md +16 -13
- package/kb/site/reference/index.md +26 -9
- package/kb/site/reference/persistence-catalog.md +190 -96
- package/kb/site/reference/subsystems/approval.md +1 -1
- package/kb/site/reference/subsystems/client-modules.md +9 -0
- package/kb/site/reference/subsystems/client-resources.md +94 -0
- package/kb/site/reference/subsystems/code-runtime.md +7 -3
- package/kb/site/reference/subsystems/commands.md +25 -16
- package/kb/site/reference/subsystems/compaction.md +10 -10
- package/kb/site/reference/subsystems/conversation.md +11 -4
- package/kb/site/reference/subsystems/core.md +173 -29
- package/kb/site/reference/subsystems/credentials.md +5 -4
- package/kb/site/reference/subsystems/filesystem.md +15 -0
- package/kb/site/reference/subsystems/goal.md +38 -2
- package/kb/site/reference/subsystems/index.md +14 -12
- package/kb/site/reference/subsystems/invariants.md +1 -1
- package/kb/site/reference/subsystems/llm-streaming.md +43 -12
- package/kb/site/reference/subsystems/lsp.md +1 -1
- package/kb/site/reference/subsystems/permission-presets.md +5 -5
- package/kb/site/reference/subsystems/persistence.md +210 -198
- package/kb/site/reference/subsystems/plan.md +3 -3
- package/kb/site/reference/subsystems/schedule.md +9 -3
- package/kb/site/reference/subsystems/scope.md +1 -1
- package/kb/site/reference/subsystems/session-projection.md +50 -24
- package/kb/site/reference/subsystems/session-query.md +19 -13
- package/kb/site/reference/subsystems/session-reference.md +29 -1
- package/kb/site/reference/subsystems/session-telemetry.md +27 -10
- package/kb/site/reference/subsystems/session-title.md +6 -6
- package/kb/site/reference/subsystems/session.md +208 -103
- package/kb/site/reference/subsystems/settings.md +30 -12
- package/kb/site/reference/subsystems/shell.md +9 -6
- package/kb/site/reference/subsystems/sidebar-right.md +151 -0
- package/kb/site/reference/subsystems/skills.md +1 -1
- package/kb/site/reference/subsystems/slots.md +41 -32
- package/kb/site/reference/subsystems/spill.md +13 -6
- package/kb/site/reference/subsystems/storage.md +28 -5
- package/kb/site/reference/subsystems/subagent.md +58 -105
- package/kb/site/reference/subsystems/subprocess.md +25 -26
- package/kb/site/reference/subsystems/system-prompt.md +18 -3
- package/kb/site/reference/subsystems/token-meter.md +4 -3
- package/kb/site/reference/subsystems/tools.md +5 -5
- package/kb/site/reference/subsystems/typert.md +18 -18
- package/kb/site/reference/subsystems/web-client.md +1 -1
- package/kb/site/reference/subsystems/workspace.md +88 -9
- package/kb/site/reference/tool-catalog.md +55 -65
- package/kb/site/reference/tool-execution-pipeline.md +2 -2
- package/lib/index.js +25 -44
- package/package.json +3 -2
- package/skills/dsh-plugin-dev-kb.md +4 -4
|
@@ -49,7 +49,7 @@ type ApprovalOutcome = 'allowed-once' | 'rejected' | 'cancelled' | 'unavailable'
|
|
|
49
49
|
type ApprovalPolicy = 'ask' | 'never'
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
两种策略都会将各自完整的当前含义贡献给缓存安全的运行时上下文快照。带来源的 `user/message`
|
|
52
|
+
两种策略都会将各自完整的当前含义贡献给缓存安全的运行时上下文快照。带来源的 `user/message` 是持久化且模型可见的输入;审批状态变化时,会在保留的历史后追加一份新的完整快照,而不触碰承载渲染后系统提示词的 `system/message` 节点。
|
|
53
53
|
|
|
54
54
|
## 审批请求
|
|
55
55
|
|
|
@@ -133,6 +133,15 @@ graph(): WebBootGraph
|
|
|
133
133
|
*/
|
|
134
134
|
clientPath(id: string): string | undefined
|
|
135
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Serve an advertised revisioned bundle or source map without a Web server.
|
|
138
|
+
* Unknown URLs return 404, unsupported methods return 405, and `HEAD`
|
|
139
|
+
* returns the same immutable headers without a body.
|
|
140
|
+
* @param request - shell-carrier request for a `/plugins` resource.
|
|
141
|
+
* @returns the exact response also exposed by the optional Web route.
|
|
142
|
+
*/
|
|
143
|
+
fetchBundle(request: Request): Response
|
|
144
|
+
|
|
136
145
|
/**
|
|
137
146
|
* Filesystem baseline captured before an entry's current bytes were read.
|
|
138
147
|
* HMR compares it with the live files when installing a watch, so a write
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
editSource: "docs/subsystems/client-resources.zh.md"
|
|
3
|
+
outline: [2,3]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 客户端资源
|
|
7
|
+
|
|
8
|
+
客户端资源模型把一个地址变成任何 Web Client 组件都能读的活数据。[`dsh-client-resources`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/resources/README.zh.md) 提供 `ctx.resources` 服务与 `useResource` 全局标准 hook;拥有某类内容的包为它的**协议**注册一个**提供方**,组件按**地址**读取该内容的当前状态,而无需引用拥有者的运行时。右侧 Sidebar 的 tab 是这个模型的第一个消费方([右侧 Sidebar](./sidebar-right.md));决策记录见 [客户端资源模型 Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-09-05-client-resource-model.zh.md)。
|
|
9
|
+
|
|
10
|
+
本页是面向开发者的参考:地址怎么写、提供方怎么注册、资源怎么读、状态与失败各是什么意思、模型怎样持有与释放一份资源。
|
|
11
|
+
|
|
12
|
+
## 地址
|
|
13
|
+
|
|
14
|
+
资源地址是 `dsh-resource://<type>/…` 形式的 URL。host 命名协议,必须是 `ResourceProtocolMap` 的键;路径归协议自己,由其拥有者逐段做百分号编码。需要作用域的协议把作用域放进路径:`file` 协议的地址形如 `dsh-resource://file/session/<sessionId>/<path>`,其中 path 可以相对工作区根,也可以是保留前导斜杠的绝对路径,用 [`dsh-util-workspace-path`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/util/workspace-path/README.zh.md) 的 `fileAddressFor(sessionId, cwd, path)` 构造、`parseFileAddress(address)` 读回。模型本身只读 scheme 与 host:`protocolOf(address)` 对 `dsh-resource://` URL 返回小写 host,对其它任何字串返回 `undefined`。其它 scheme 下的地址——Sidebar 的 `sidebar://guide`——不指向资源,读作 `none`。
|
|
15
|
+
|
|
16
|
+
| 地址 | 协议键 | 读作 |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| `dsh-resource://file/session/s1/notes/a.md` | `file` | 会话 `s1` 工作区根下 `notes/a.md` 的元数据(`file` 提供方已注册时) |
|
|
19
|
+
| `dsh-resource://file/absolute/home/me/notes.md` | `file` | 可解析,但没有授权 Session,以 `workspace-file/unknown-workspace` 失败;不借用当前或 Tab Session |
|
|
20
|
+
| `DSH-RESOURCE://File/session/s1/a` | `file` | 另一份记录:地址按字符串比较,`openResource` 只接受 `fileAddressFor` 生成的规范小写拼写 |
|
|
21
|
+
| `sidebar://guide` | — | `none`:导航地址 |
|
|
22
|
+
| `/home/me/notes.md` | — | `none`:不是 URL |
|
|
23
|
+
|
|
24
|
+
## 注册提供方
|
|
25
|
+
|
|
26
|
+
协议拥有者在 `ResourceProtocolMap` 上声明其值类型,并在自己的 `ctx.effect` 里注册一个提供方,使协议与插件同寿([提供协议](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/resources/README.zh.md#provide-a-protocol))。`open(address, { signal })` 返回一条 `RemoteResult` 帧流——首帧是当前状态,之后每次变化一帧——并且必须在 `signal` 中止时停下。失败是携带 `RemoteFailure` 的 `ok: false` 帧;流里抛出是编程错误,不会被捕获。
|
|
27
|
+
|
|
28
|
+
```ts ignore-check
|
|
29
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
30
|
+
import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol'
|
|
31
|
+
import type {} from '@deepseek-ai/dsh-client-resources/client'
|
|
32
|
+
|
|
33
|
+
interface NoteView { readonly title: string; readonly updatedAt: string }
|
|
34
|
+
|
|
35
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
36
|
+
interface ResourceProtocolMap { note: NoteView }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const inject = ['resources', 'remote']
|
|
40
|
+
|
|
41
|
+
export function apply(ctx: Context): void {
|
|
42
|
+
ctx.effect(() => ctx.resources.register<'note'>({
|
|
43
|
+
protocol: 'note',
|
|
44
|
+
async *open(address, { signal }): AsyncIterable<RemoteResult<NoteView>> {
|
|
45
|
+
const id = new URL(address).pathname.slice(1)
|
|
46
|
+
yield await ctx.remote.notes.read(id, signal)
|
|
47
|
+
for await (const change of ctx.remote.notes.follow(id, signal)) yield change
|
|
48
|
+
},
|
|
49
|
+
}), 'my-notes: note resource provider')
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
一个协议恰有一个提供方;第二次注册抛错。注册时若该协议的地址已被持有,则立刻打开它们的流;提供方 dispose 时结束这些流,地址读作 `none` 直到提供方回来。
|
|
54
|
+
|
|
55
|
+
## 读取资源
|
|
56
|
+
|
|
57
|
+
每个 slot 组件不论作用域都在 props 上收到 `useResource`([Slots](./slots.md))。`useResource<P>(address)` 以类型参数命名协议,返回该地址的当前快照;订阅就是持有资源的方式,另一个持有者让资源存活时,新挂载的组件立刻读到最新值而不重开流([读取资源](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/resources/README.zh.md#read-a-resource))。
|
|
58
|
+
|
|
59
|
+
| `status` | 含义 | `value` | `failure` |
|
|
60
|
+
|---|---|---|---|
|
|
61
|
+
| `none` | 地址的协议没有注册提供方,或地址不是资源地址 | `undefined` | `undefined` |
|
|
62
|
+
| `loading` | 提供方的流已打开、尚未产出 | `undefined` | `undefined` |
|
|
63
|
+
| `live` | 最新一帧成功 | 最新的 `ok` 值 | `undefined` |
|
|
64
|
+
| `failed` | 最新一帧报告了失败 | 保留的上一个 `ok` 值 | 该帧的 `RemoteFailure` |
|
|
65
|
+
|
|
66
|
+
```tsx ignore-check
|
|
67
|
+
import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'
|
|
68
|
+
import type {} from '@deepseek-ai/dsh-api-workspace-files/client'
|
|
69
|
+
|
|
70
|
+
type Props = PropsRuntime<'sidebar.right.pane.tab'>
|
|
71
|
+
|
|
72
|
+
export function FileHeader({ useTabInfo, useResource, t }: Props) {
|
|
73
|
+
const { tab } = useTabInfo()
|
|
74
|
+
const meta = useResource<'file'>(tab.contentId)
|
|
75
|
+
if (meta.status === 'failed') return <p role="alert">{t('failed', { code: meta.failure.code })}</p>
|
|
76
|
+
return (
|
|
77
|
+
<header>
|
|
78
|
+
{tab.title}
|
|
79
|
+
</header>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`failed` 由消费方自己呈现:模型把最后一个值留在失败旁,正文可以带提示显示旧内容而不是一片空白,下一个 `ok` 帧会清除失败。模型本身不产生任何用户可见文案。
|
|
85
|
+
|
|
86
|
+
## 持有与释放
|
|
87
|
+
|
|
88
|
+
资源有持有者就存活:一个订阅中的 `useResource`,或一次钉住。`ctx.resources.pin(address, signal)` 在不订阅的情况下让资源保持打开直到 `signal` 中止,已中止的信号什么也不钉;右侧 Sidebar 在每条打开的 tab 记录存续期内钉住其地址,因此切 tab 卸载正文不关流。第一个持有者打开提供方的流;最后一个释放时中止它、丢弃值,并把快照回到 `loading`(有提供方)或 `none`(没有)。提供方在这次释放之后产出的帧被丢弃,迭代器被归还。`ctx.resources.source(address)` 是 hook 背后的裸 observable,按地址引用稳定,供 React 之外的调用方使用;只读它的快照不算持有([生命周期](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/resources/README.zh.md#lifecycle))。
|
|
89
|
+
|
|
90
|
+
流只推元数据不推内容。`file` 提供方的值是 `WorkspaceFileStat { absolutePath, version, bytes? }`:首帧来自 Host 的 `stat`,后续观察更新版本。消费方自己经 Workspace Files Remote 命名空间读取内容;Preview 按 tab 独立刷新([`dsh-api-workspace-files`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/api/workspace-files/README.zh.md))。
|
|
91
|
+
|
|
92
|
+
## 限制
|
|
93
|
+
|
|
94
|
+
记录在页面存续期内保留:地址的记录在最后一个持有者离开后仍留着,不持有流也不持有值,因此内存随读过的不同地址数增长。忽略 `signal` 的提供方会一直跑到它的下一帧。失败类型是 Remote 面的 `RemoteFailure`,来源不是 Remote 调用的提供方得自己铸一个。拼错的协议或畸形的地址读作 `none`,没有别的诊断。
|
|
@@ -55,7 +55,11 @@ interface CodeRunResult {
|
|
|
55
55
|
* rendered string; a failed or value-less run leaves this absent.
|
|
56
56
|
*/
|
|
57
57
|
value?: CodeJsonValue
|
|
58
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Captured text. Each source channel preserves emission order; interleaving
|
|
60
|
+
* across independent channels is backend-dependent. Bounded only as part of
|
|
61
|
+
* the outer result.
|
|
62
|
+
*/
|
|
59
63
|
logs: string[]
|
|
60
64
|
/** Present iff the run failed; see {@link CodeRunFailure} for the taxonomy. */
|
|
61
65
|
error?: CodeRunFailure
|
|
@@ -134,7 +138,7 @@ type CodeBindingFunction = (args: unknown) => Promise<CodeJsonValue>
|
|
|
134
138
|
|
|
135
139
|
## 捕获的输出与失败分类体系
|
|
136
140
|
|
|
137
|
-
|
|
141
|
+
日志是纯字符串。每个来源通道保留自身的发出顺序;由于通道元数据不属于 seam,相互独立的通道如何交错由后端决定。运行时捕获程序的 console 与流输出,Consumer 只渲染文本。实现会对序列化后的外层日志数组,以及完成值或失败消息的组合载荷设置上限;固定的结果封装语法与 Consumer 展示空白不计入这份可变载荷计量。超限会显式失败,而不会在值中插入替代内容。
|
|
138
142
|
|
|
139
143
|
失败类型是**正交的结果,独立报告**(见 [defensive-patterns](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/defensive-patterns.zh.md)):预算耗尽不是异常,中止不是超时,基底崩溃(如 OOM)也不是二者中的任何一个:
|
|
140
144
|
|
|
@@ -161,7 +165,7 @@ interface CodeRunFailure {
|
|
|
161
165
|
|
|
162
166
|
## 服务
|
|
163
167
|
|
|
164
|
-
`CodeRuntime`(`ctx.codeRuntime`,抽象服务,定义于 [`packages/code-runtime/code-runtime/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/code-runtime/code-runtime/src/index.ts))由 `run(request)` 加两个只读描述符组成:`language`(程序必须使用的语言,已知值为 `'typescript'` 与 `'python'`,即 `dsh-tools`
|
|
168
|
+
`CodeRuntime`(`ctx.codeRuntime`,抽象服务,定义于 [`packages/code-runtime/code-runtime/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/code-runtime/code-runtime/src/index.ts))由 `run(request)` 加两个只读描述符组成:`language`(程序必须使用的语言,已知值为 `'typescript'` 与 `'python'`,即 `dsh-tools` 能呈现的那些,TypeScript 后端已发布、Python 后端为实验性且私有(未发布);生成语言相关展示的 Consumer 据此切换,遇到无法展示的语言时应显式报错)和 `isolation`(执行基底,`'worker-thread'`、`'process'`、`'container'`;仅为诊断标签,**不构成安全承诺**)。实现必须保证各次运行彼此隔离(无跨运行状态),并在 dispose(资源释放)时等待系统完全停稳:teardown 要等到所有进行中的运行均已终止并结算后才完成。
|
|
165
169
|
|
|
166
170
|
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
167
171
|
|
|
@@ -11,7 +11,7 @@ outline: [2,3]
|
|
|
11
11
|
|
|
12
12
|
## 输入元数据
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
该服务公开一个可选的非结构化输入描述符:提示文本加附件接受标志。命令的可用性由插件组合决定:每个消费注册表的适配器都会看到全部生效定义。
|
|
15
15
|
|
|
16
16
|
```ts type-equiv
|
|
17
17
|
/** Immutable metadata for a command's optional unstructured input. */
|
|
@@ -19,13 +19,13 @@ interface CommandInputDescriptor {
|
|
|
19
19
|
/** Placeholder shown before the user supplies free-form input. */
|
|
20
20
|
readonly hint: string
|
|
21
21
|
/**
|
|
22
|
-
* Whether composer
|
|
23
|
-
* false = the executor rejects an invocation carrying
|
|
22
|
+
* Whether composer attachments may accompany an invocation. Absent or
|
|
23
|
+
* false = the executor rejects an invocation carrying attachments and capable
|
|
24
24
|
* composers refuse the submission before dispatch. A declaring command's
|
|
25
25
|
* handler receives the admitted durable blocks and owns every further
|
|
26
26
|
* grammar decision, including rejecting sub-commands that cannot use them.
|
|
27
27
|
*/
|
|
28
|
-
readonly
|
|
28
|
+
readonly attachments?: boolean
|
|
29
29
|
}
|
|
30
30
|
```
|
|
31
31
|
|
|
@@ -67,13 +67,13 @@ interface CommandInvocation {
|
|
|
67
67
|
/** Exact text following the registered command name, including separator whitespace. */
|
|
68
68
|
readonly rawInput: string
|
|
69
69
|
/**
|
|
70
|
-
* Durably admitted image blocks accompanying this invocation, in submission
|
|
71
|
-
* order; empty unless the definition declares `input.
|
|
70
|
+
* Durably admitted image and file blocks accompanying this invocation, in submission
|
|
71
|
+
* order; empty unless the definition declares `input.attachments`. The handler
|
|
72
72
|
* owns their model-visible use — the registry never schedules them itself —
|
|
73
73
|
* and a handler whose grammar cannot use them in this invocation returns an
|
|
74
74
|
* error so the dispatching composer retains the originals.
|
|
75
75
|
*/
|
|
76
|
-
readonly attachments: readonly ImageBlock[]
|
|
76
|
+
readonly attachments: readonly (ImageBlock | FileBlock)[]
|
|
77
77
|
/** Cancellation signal owned by the dispatching UI request. */
|
|
78
78
|
readonly signal: AbortSignal
|
|
79
79
|
}
|
|
@@ -86,7 +86,7 @@ type CommandResult =
|
|
|
86
86
|
readonly kind: 'success'
|
|
87
87
|
readonly text?: string
|
|
88
88
|
/** Earlier authoritative domain event that owns a richer presentation. */
|
|
89
|
-
readonly sourceEventSeq?:
|
|
89
|
+
readonly sourceEventSeq?: SessionSeq
|
|
90
90
|
}
|
|
91
91
|
| { readonly kind: 'error'; readonly text: string }
|
|
92
92
|
```
|
|
@@ -141,6 +141,13 @@ Human-command registry. Plain-context definitions are global; definitions regist
|
|
|
141
141
|
*/
|
|
142
142
|
register(definition: CommandDefinition): () => void
|
|
143
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Register the sole authority that resolves staged file receipts for command submissions.
|
|
146
|
+
* @param resolver - Session-aware receipt resolver.
|
|
147
|
+
* @returns disposer that removes this exact resolver.
|
|
148
|
+
*/
|
|
149
|
+
registerFileReceiptResolver(resolver: CommandFileReceiptResolver): () => void
|
|
150
|
+
|
|
144
151
|
/**
|
|
145
152
|
* List the effective immutable command descriptors for one agent.
|
|
146
153
|
* @param agent - exact receiving agent and scoped-layer key.
|
|
@@ -169,23 +176,25 @@ find(agent: Agent, name: string): CommandDefinition | undefined
|
|
|
169
176
|
* handler-failure path is contained so the handler's own error stays the
|
|
170
177
|
* reported failure.
|
|
171
178
|
*
|
|
172
|
-
*
|
|
173
|
-
* command that does not declare `input.
|
|
174
|
-
* and an exceeded
|
|
175
|
-
* the handler runs
|
|
179
|
+
* Attachment admission is enforced here, not in the composer: attachments sent to a
|
|
180
|
+
* command that does not declare `input.attachments`, an absent attachment store,
|
|
181
|
+
* and an exceeded image limit each settle as an error result before
|
|
182
|
+
* the handler runs. Validation rejection starts no attachment writes;
|
|
183
|
+
* a storage failure can leave only unreachable content-addressed objects
|
|
184
|
+
* for deferred collection.
|
|
176
185
|
*
|
|
177
186
|
* @param agent - exact receiving agent.
|
|
178
187
|
* @param line - complete slash-command line.
|
|
179
|
-
* @param
|
|
180
|
-
* submission order; empty for a plain invocation.
|
|
188
|
+
* @param submittedAttachments - encoded images and staged file receipts accompanying the line,
|
|
189
|
+
* in submission order; empty for a plain invocation.
|
|
181
190
|
* @param signal - cancellation signal owned by the UI request.
|
|
182
191
|
* @returns the settled execution (result + lifecycle pairing id), or
|
|
183
192
|
* `undefined` when syntax or name does not resolve.
|
|
184
193
|
*/
|
|
185
|
-
@Remote async execute( agent: Agent, line: string,
|
|
194
|
+
@Remote async execute( agent: Agent, line: string, submittedAttachments: readonly CommandSubmitAttachment[], signal: AbortSignal, ): Promise<CommandExecution | undefined>
|
|
186
195
|
```
|
|
187
196
|
|
|
188
|
-
Types: [Agent](./core.md)
|
|
197
|
+
Types: [Agent](./core.md)
|
|
189
198
|
|
|
190
199
|
Source: [`packages/interaction/commands/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/interaction/commands/src/index.ts)
|
|
191
200
|
|
|
@@ -11,7 +11,7 @@ outline: [2,3]
|
|
|
11
11
|
|
|
12
12
|
## `compaction/*` 会话事件
|
|
13
13
|
|
|
14
|
-
压缩通过声明合并为 [`SessionEventMap`](./session.md) 扩展三种事件类型。三者都**仅写入日志**——它们记录锁、摘要、选中范围、被遮蔽事件 seq、token 数以及模型调用,绝不进入 surface。这里有意不扩展 `SurfaceEventType`(只有产生消息的事件才到达模型),因此摘要本身承载在另一条带有 `surfaceOp: { op: 'replace',
|
|
14
|
+
压缩通过声明合并为 [`SessionEventMap`](./session.md) 扩展三种事件类型。三者都**仅写入日志**——它们记录锁、摘要、选中范围、被遮蔽事件 seq、token 数以及模型调用,绝不进入 surface。这里有意不扩展 `SurfaceEventType`(只有产生消息的事件才到达模型),因此摘要本身承载在另一条带有 `surfaceOp: { op: 'replace', startSeq, endSeq }` 的 `user/message` 上——这是摘要压缩执行的唯一 surface 变更。[Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.zh.md) 负责复用 `user/message` 的决策依据。
|
|
15
15
|
|
|
16
16
|
| 事件 | 载荷 | 作用 |
|
|
17
17
|
|---|---|---|
|
|
@@ -37,11 +37,11 @@ interface CompactionResult {
|
|
|
37
37
|
/** Human command that initiated this compaction, when it was manual. */
|
|
38
38
|
sourceCommandId?: CommandId
|
|
39
39
|
/** The seq of the appended `compaction/start` event. */
|
|
40
|
-
startSeq:
|
|
40
|
+
startSeq: SessionSeq
|
|
41
41
|
/** The seq of the appended `compaction/summary` event. */
|
|
42
|
-
summarySeq:
|
|
42
|
+
summarySeq: SessionSeq
|
|
43
43
|
/** The seq of the appended `compaction/end` event. */
|
|
44
|
-
endSeq:
|
|
44
|
+
endSeq: SessionSeq
|
|
45
45
|
/** The summary content blocks produced by the backend. */
|
|
46
46
|
summary: ContentBlock[]
|
|
47
47
|
/**
|
|
@@ -52,9 +52,9 @@ interface CompactionResult {
|
|
|
52
52
|
* can be GREATER than `end`. {@link CompactionResult.shadowedSeqs} is the
|
|
53
53
|
* authoritative set of shadowed nodes, in surface order.
|
|
54
54
|
*/
|
|
55
|
-
shadowedRange: { start:
|
|
55
|
+
shadowedRange: { start: SessionSeq; end: SessionSeq }
|
|
56
56
|
/** The seqs of all shadowed surface nodes, in surface order. */
|
|
57
|
-
shadowedSeqs:
|
|
57
|
+
shadowedSeqs: SessionSeq[]
|
|
58
58
|
/** Estimated token count of the shadowed content. */
|
|
59
59
|
shadowedTokenCount: number
|
|
60
60
|
}
|
|
@@ -98,9 +98,9 @@ type ManualCompactionErrorCode =
|
|
|
98
98
|
/** Cited source event and size accounting for one landed surface replacement. */
|
|
99
99
|
interface PrunedEntry {
|
|
100
100
|
/** Full-fidelity tool-result event shadowed by the replacement. */
|
|
101
|
-
readonly originalSeq:
|
|
101
|
+
readonly originalSeq: SessionSeq
|
|
102
102
|
/** Newly appended pruned tool-result event. */
|
|
103
|
-
readonly replacementSeq:
|
|
103
|
+
readonly replacementSeq: SessionSeq
|
|
104
104
|
/** Tool call shared by the original and replacement. */
|
|
105
105
|
readonly callId: ToolCallId
|
|
106
106
|
/** Original text size in Unicode code points. */
|
|
@@ -190,10 +190,10 @@ abstract compactNow( agent: ManualCompactAgentContext, signal: AbortSignal, sour
|
|
|
190
190
|
* @throws when compaction is active or the range is missing, reversed, or unbalanced.
|
|
191
191
|
* @returns the appended event seqs, summary, replaced range, and token accounting.
|
|
192
192
|
*/
|
|
193
|
-
abstract compactRegion( start:
|
|
193
|
+
abstract compactRegion( start: SessionSeq, end: SessionSeq, agent: CompactionAgentContext, signal?: AbortSignal, ): Promise<CompactionResult>
|
|
194
194
|
```
|
|
195
195
|
|
|
196
|
-
Types: [CommandId](./commands.md)
|
|
196
|
+
Types: [CommandId](./commands.md) · [SessionSeq](./session.md)
|
|
197
197
|
|
|
198
198
|
Source: [`packages/compaction/compaction/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/compaction/compaction/src/index.ts)
|
|
199
199
|
|
|
@@ -11,18 +11,24 @@ Conversation 是 Client `SessionEventLikeEntry` window 与浏览器 view 之间
|
|
|
11
11
|
|
|
12
12
|
## 数据模型与所有权
|
|
13
13
|
|
|
14
|
-
Session Controller 拥有连续的已加载逻辑 event window。每个 `SessionEventLikeEntry`
|
|
14
|
+
Session Controller 拥有连续的已加载逻辑 event window。每个 `SessionEventLikeEntry` 要么是表示一个持久事件的 `{ type: 'event', event: SessionEvent }`,要么是表示一个 Client-only `assistant/live-chunk` 呈现的 `{ type: 'transient', event: AssistantLiveChunkEvent }`;两种内部 event 都公开 `type`、`seq`、`time` 与 `data`。`ui-conversation` 把这些 entry 直接交给 assembler,不另开 history stream。每个 Session 对应一个 `ConversationNodeAssembler`,它应用所有已注册 Definition,并为每个已注册 view target 发布独立 source。
|
|
15
15
|
|
|
16
16
|
| 概念 | Owner 与用途 |
|
|
17
17
|
|---|---|
|
|
18
|
-
| Event Definition |
|
|
19
|
-
| Context | Engine 为一个 `(kind, id)` 拥有的有序 Match 与当前 State
|
|
18
|
+
| Event Definition | 业务包一次匹配一个持久 event 或 Client-only 瞬态 event,以稳定 `(kind, id)` 关联输入、折叠确定性 State,并可选择 materialize 一个 target node。 |
|
|
19
|
+
| Context | Engine 为一个 `(kind, id)` 拥有的有序 Match 与当前 State。一个瞬态 event 只占一个 update Match;只有 update 的证据可以保持 pending,直到分页补齐其唯一持久 start。 |
|
|
20
20
|
| Location | Engine 根据持久 boundary event 推导的 Session、Turn 或 Step 坐标。Definition 可以向一个 Turn 或 Step 发布类型化数据。 |
|
|
21
21
|
| View Definition | Target 包为每个 Session 创建一个增量 builder,并拥有该 target 的最终 snapshot 类型。 |
|
|
22
22
|
| View | Chat 或 Trajectory 等 Slot entry 只读取自身 target snapshot,并渲染 target 自有 node。 |
|
|
23
23
|
|
|
24
24
|
Chat 与 Trajectory 可以识别同一个持久 event family,但各自保留自己的 Definition State 与最终 node payload。共享的 target-neutral 机制只包括 identity routing、有序 replay、Location data、predecessor dependency 与 publication cadence。
|
|
25
25
|
|
|
26
|
+
## Target 激活
|
|
27
|
+
|
|
28
|
+
每个 Session 都保留单调增长的 active target 集合。创建或读取 target source 不会激活它。shell 会显式激活持久化选择或新选择的 View,其他消费者则通过 target source 的首个订阅激活 target。首次激活会创建该 target 的 builder,并从当前按 target 索引的 Context 调用一次 `replace()`。后续 flush 对每个 active target 调用 `apply()`,取消订阅不会移除 target。
|
|
29
|
+
|
|
30
|
+
shell 拥有 View 选择,并在 binding 创建、被选为 current 或 View roster 变化时,于渲染前解析已注册的偏好 View 或 Chat fallback。assembler 只接收解析后的 target id,不自行选择 Chat 或其他默认 target。第三方 View 使用相同的选择与激活操作。
|
|
31
|
+
|
|
26
32
|
## 可回放 event family
|
|
27
33
|
|
|
28
34
|
编写 Definition 前先选定稳定的业务 id。构成同一个 Node 的每条事件都必须携带该 id,或只凭自身 payload 独立推导出该 id;Client 绝不能把 update 猜测为属于“最近一个未完成”的 Context。
|
|
@@ -39,7 +45,7 @@ Chat 与 Trajectory 可以识别同一个持久 event family,但各自保留
|
|
|
39
45
|
|
|
40
46
|
系统支持增量事件。如果生产方能以较低成本发出 whole-value checkpoint,应优先采用,因为 start 位于已加载窗口之外时它仍可直接使用。每条 delta 都必须携带稳定 id,并且按照日志 `seq` 升序回放时能够确定性地产生 State;它不能依赖只存在于实时内存中的状态。如果当前历史窗口只有 update,Assembler 会保留一个 pending Context,并在更早分页补齐 start 前不构造 State。如果产品必须在 start 尚未加载时渲染,terminal 或 checkpoint 事件就必须携带足够的完整 fallback 状态,让 Definition 能直接构造结果;不要通过扫描无关事件恢复它。
|
|
41
47
|
|
|
42
|
-
|
|
48
|
+
实时 Assistant delta 作为 Client-only `assistant/live-chunk` update 到达。重连 baseline 会把活跃的进程内紧凑 stream 展开为相同的瞬态 event,持久 `assistant/message` 与 `assistant/attempt` event 则嵌入完整紧凑 stream 供历史回放。瞬态 event 只能充当 update;`start()` 只接收标准 `SessionEvent`。消费 Assistant 输出的 Definition 在同一组 `match()` 与 `update()` 方法里处理 live chunk 与持久 settlement,其他 Definition 直接返回 `null`,无需展开 stream。
|
|
43
49
|
|
|
44
50
|
## Definition 与类型化 Chat payload
|
|
45
51
|
|
|
@@ -250,5 +256,6 @@ Assembler 会记录这项依赖。如果后续 older prepend 带来了更近的
|
|
|
250
256
|
5. 重复的可见 delta 保持 `context.key`,并在请求 `animation-frame` 时每帧最多发布一次。
|
|
251
257
|
6. keyed renderer 只消费 `node.data` 与受限 Location hook,不扫描 Session 事件窗口、Context 或 Chat Node。
|
|
252
258
|
7. scalar 与 packed Assistant 历史产生相同的最终 State、timing boundary 和 target snapshot;一个 packed run 在 replace、prepend、Location replay 与 registry rebuild 中始终只保留一个 Match。
|
|
259
|
+
8. 创建 target source 不执行 builder 工作;显式选择或首次订阅执行一次完整 replace,后续更新送达所有 active target,重复激活不会再次 replace。
|
|
253
260
|
|
|
254
261
|
流式与中断处理可参考 [`packages/client/ui-chat/src/client/conversation-nodes/assistant.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-chat/src/client/conversation-nodes/assistant.ts),前序查询可参考 [`inbox.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-chat/src/client/conversation-nodes/inbox.ts) 与 [`message.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-chat/src/client/conversation-nodes/message.ts),只发布 Turn data 而不创建自有 Node 的例子见 [`packages/client/ui-deliverables`](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/client/ui-deliverables)。
|