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
|
-
Both policies contribute their complete current meaning to the cache-safe runtime-context snapshot. The sourced `user/message` is the durable model-visible input; changing approval state appends a new full snapshot after retained history without
|
|
52
|
+
Both policies contribute their complete current meaning to the cache-safe runtime-context snapshot. The sourced `user/message` is the durable model-visible input; changing approval state appends a new full snapshot after retained history without touching the `system/message` nodes that hold the rendered system prompt.
|
|
53
53
|
|
|
54
54
|
## Approval request
|
|
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.md"
|
|
3
|
+
outline: [2,3]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Client Resources
|
|
7
|
+
|
|
8
|
+
The client resource model turns an address into live data for any Web Client component. [`dsh-client-resources`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/resources/README.md) provides the `ctx.resources` service and the `useResource` global standard hook; a package that owns a kind of content registers one **provider** for its **protocol**, and a component reads the content's current state by **address** without importing the owner's runtime. The right Sidebar's tabs are the model's first consumer ([Right Sidebar](./sidebar-right.md)); the decision record is the [client resource model Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-09-05-client-resource-model.md).
|
|
9
|
+
|
|
10
|
+
This page is the developer reference: how to write an address, how to register a provider, how to read a resource, what the states and failures mean, and how the model holds and releases a resource.
|
|
11
|
+
|
|
12
|
+
## Addresses
|
|
13
|
+
|
|
14
|
+
A resource address is a `dsh-resource://<type>/…` URL. The host names the protocol and must be a key of `ResourceProtocolMap`; the path is the protocol's own, and its owner percent-encodes each segment. A protocol that needs a scope puts it in the path: the `file` protocol's addresses read `dsh-resource://file/session/<sessionId>/<path>`, where path is workspace-relative or absolute with its leading slashes preserved, built with `fileAddressFor(sessionId, cwd, path)` and read back with `parseFileAddress(address)` from [`dsh-util-workspace-path`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/util/workspace-path/README.md). The model itself reads only the scheme and the host: `protocolOf(address)` returns the lower-cased host of a `dsh-resource://` URL and `undefined` for anything else. Addresses under any other scheme — the Sidebar's `sidebar://guide` — name no resource and read as `none`.
|
|
15
|
+
|
|
16
|
+
| Address | Protocol key | Reads as |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| `dsh-resource://file/session/s1/notes/a.md` | `file` | the metadata of `notes/a.md` under session `s1`'s workspace root, when the `file` provider is registered |
|
|
19
|
+
| `dsh-resource://file/absolute/home/me/notes.md` | `file` | parseable but fails with `workspace-file/unknown-workspace`: no authorizing Session, and neither current nor Tab Session is borrowed |
|
|
20
|
+
| `DSH-RESOURCE://File/session/s1/a` | `file` | a distinct record: addresses compare as strings, and `openResource` accepts only the canonical lower-case spelling that `fileAddressFor` emits |
|
|
21
|
+
| `sidebar://guide` | — | `none`: a navigation address |
|
|
22
|
+
| `/home/me/notes.md` | — | `none`: not a URL |
|
|
23
|
+
|
|
24
|
+
## Registering a provider
|
|
25
|
+
|
|
26
|
+
The owner of a protocol declares its value type on `ResourceProtocolMap` and registers one provider inside its own `ctx.effect`, so the protocol lives exactly as long as the plugin ([provide a protocol](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/resources/README.md#provide-a-protocol)). `open(address, { signal })` returns a stream of `RemoteResult` frames — the current state first, then one frame per change — and must stop when `signal` aborts. A failure is an `ok: false` frame carrying a `RemoteFailure`; a throw inside the stream is a programming error and is not caught.
|
|
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
|
+
A protocol has exactly one provider; a second registration throws. Registering while addresses of the protocol are already held opens their streams at once; disposing the provider ends those streams and the addresses read `none` until a provider returns.
|
|
54
|
+
|
|
55
|
+
## Reading a resource
|
|
56
|
+
|
|
57
|
+
Every slot component receives `useResource` in its props, whatever its scope ([Slots](./slots.md)). `useResource<P>(address)` names the protocol as the type argument and returns the address's current snapshot; subscribing is what holds the resource open, and a component that mounts while another holder keeps the resource alive reads the latest value at once without reopening the stream ([read a resource](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/resources/README.md#read-a-resource)).
|
|
58
|
+
|
|
59
|
+
| `status` | Meaning | `value` | `failure` |
|
|
60
|
+
|---|---|---|---|
|
|
61
|
+
| `none` | No provider is registered for the address's protocol, or the address is not a resource address | `undefined` | `undefined` |
|
|
62
|
+
| `loading` | The provider's stream is open and has not yielded yet | `undefined` | `undefined` |
|
|
63
|
+
| `live` | The latest frame succeeded | the latest `ok` value | `undefined` |
|
|
64
|
+
| `failed` | The latest frame reported a failure | the last `ok` value, kept | the frame's `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
|
+
A consumer presents `failed` itself: the model keeps the last value beside the failure so a body can show stale content with a notice rather than a blank, and the next `ok` frame clears the failure. Nothing in the model produces user-visible text.
|
|
85
|
+
|
|
86
|
+
## Holding and releasing
|
|
87
|
+
|
|
88
|
+
A resource is alive while it has a holder: a subscribed `useResource`, or a pin. `ctx.resources.pin(address, signal)` keeps a resource open without subscribing until `signal` aborts, and an already-aborted signal pins nothing; the right Sidebar pins every open tab record's address for the record's life, so switching tabs unmounts a body without closing its stream. The first holder opens the provider's stream; the last release aborts it, discards the value, and returns the snapshot to `loading` (provider present) or `none` (absent). A frame the provider yields after that release is dropped, and the iterator is returned. `ctx.resources.source(address)` is the bare observable behind the hook, reference-stable per address, for callers outside React; reading its snapshot does not hold the resource ([lifecycle](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/resources/README.md#lifecycle)).
|
|
89
|
+
|
|
90
|
+
Streams carry metadata, not content. The `file` provider's value is `WorkspaceFileStat { absolutePath, version, bytes? }`: the first frame comes from Host `stat`, and later observations update the version. A consumer reads content through the Workspace Files Remote namespace; Preview owns refresh independently per tab ([`dsh-api-workspace-files`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/api/workspace-files/README.md)).
|
|
91
|
+
|
|
92
|
+
## Limits
|
|
93
|
+
|
|
94
|
+
Records live for the page lifetime: an address's record stays after its last holder leaves, holding no stream and no value, so memory grows with the number of distinct addresses ever read. A provider that ignores `signal` keeps running until its next frame. The failure type is the Remote face's `RemoteFailure`, so a provider whose source is not a Remote call mints one. A misspelled protocol or a malformed address reads as `none` with no other diagnostic.
|
|
@@ -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
|
## Captured output and the failure taxonomy
|
|
136
140
|
|
|
137
|
-
Logs are plain strings
|
|
141
|
+
Logs are plain strings. Each source channel preserves emission order, while interleaving across independent channels is backend-dependent because channel metadata is not part of the seam. The runtime captures the program's console and stream output, and consumers render only the text. Implementations cap the serialized outer log-array plus completion-value or failure-message payload; fixed result-envelope syntax and consumer presentation whitespace are not part of that variable-payload ledger. Overflow is an explicit failure rather than in-band value substitution.
|
|
138
142
|
|
|
139
143
|
Failure kinds are **orthogonal outcomes reported independently** (per [defensive-patterns](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/defensive-patterns.md)): a budget expiry is not an exception, an abort is not a timeout, and a substrate death (e.g. OOM) is neither:
|
|
140
144
|
|
|
@@ -161,7 +165,7 @@ interface CodeRunFailure {
|
|
|
161
165
|
|
|
162
166
|
## The service
|
|
163
167
|
|
|
164
|
-
`CodeRuntime` (`ctx.codeRuntime`, abstract — defined in [`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)) is `run(request)` plus two readonly descriptors: `language` (what the program must be written in — `'typescript'` and `'python'` are the well-known values, those `dsh-tools` presents, and
|
|
168
|
+
`CodeRuntime` (`ctx.codeRuntime`, abstract — defined in [`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)) is `run(request)` plus two readonly descriptors: `language` (what the program must be written in — `'typescript'` and `'python'` are the well-known values, those `dsh-tools` presents, the TypeScript backend released and the Python backend experimental and private (not published); a consumer generating language-specific presentation switches on it and fails loud on one it cannot present) and `isolation` (the execution substrate — `'worker-thread'`, `'process'`, `'container'`; a diagnostic label, **not a security claim**). Implementations must keep runs isolated from each other (no cross-run state) and dispose to quiescence: in-flight runs are terminated and awaited before teardown completes.
|
|
165
169
|
|
|
166
170
|
<!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
|
|
167
171
|
|
|
@@ -11,7 +11,7 @@ Source: [`packages/interaction/commands/src/index.ts`](https://github.com/deepse
|
|
|
11
11
|
|
|
12
12
|
## Input metadata
|
|
13
13
|
|
|
14
|
-
The service exposes one optional unstructured-input descriptor: a hint plus an
|
|
14
|
+
The service exposes one optional unstructured-input descriptor: a hint plus an attachment-acceptance flag. Command availability follows plugin composition: every adapter consuming the registry sees every effective definition.
|
|
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 @@ Source: [`packages/compaction/compaction/src/types.ts`](https://github.com/deeps
|
|
|
11
11
|
|
|
12
12
|
## The `compaction/*` session events
|
|
13
13
|
|
|
14
|
-
Compaction extends [`SessionEventMap`](./session.md) with three event types via declaration merging. All three are **log-only** — they record the lock, summary, selected range, shadowed event seqs, token count, and model call without joining the surface. `SurfaceEventType` is deliberately NOT extended (only message-producing events reach the model), so the summary itself rides on a separate `user/message` with `surfaceOp: { op: 'replace',
|
|
14
|
+
Compaction extends [`SessionEventMap`](./session.md) with three event types via declaration merging. All three are **log-only** — they record the lock, summary, selected range, shadowed event seqs, token count, and model call without joining the surface. `SurfaceEventType` is deliberately NOT extended (only message-producing events reach the model), so the summary itself rides on a separate `user/message` with `surfaceOp: { op: 'replace', startSeq, endSeq }` — the only surface mutation performed by summary compaction. The [Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md) owns the rationale for reusing `user/message`.
|
|
15
15
|
|
|
16
16
|
| Event | Payload | Role |
|
|
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 @@ The optional tool-result pruning service reports each durable content replacemen
|
|
|
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 @@ This page defines the data model and the extension path for a business-owned Con
|
|
|
11
11
|
|
|
12
12
|
## Data model and ownership
|
|
13
13
|
|
|
14
|
-
The Session Controller owns the contiguous loaded logical-event window. Each `SessionEventLikeEntry` is either `{ type: 'event', event: SessionEvent }` or `{ type: '
|
|
14
|
+
The Session Controller owns the contiguous loaded logical-event window. Each `SessionEventLikeEntry` is either `{ type: 'event', event: SessionEvent }` for one durable event or `{ type: 'transient', event: AssistantLiveChunkEvent }` for one Client-only `assistant/live-chunk` presentation. Both inner events expose `type`, `seq`, `time`, and `data`. `ui-conversation` passes these entries to the assembler without opening a second history stream. One `ConversationNodeAssembler` per Session applies every registered Definition and publishes an independent source for each registered view target.
|
|
15
15
|
|
|
16
16
|
| Concept | Owner and purpose |
|
|
17
17
|
|---|---|
|
|
18
|
-
| Event Definition | A business package matches one
|
|
19
|
-
| Context | The engine-owned ordered Matches and current State for one `(kind, id)`. A
|
|
18
|
+
| Event Definition | A business package matches one durable or Client-only transient event at a time, correlates it by stable `(kind, id)`, folds deterministic State, and optionally materializes one target node. |
|
|
19
|
+
| Context | The engine-owned ordered Matches and current State for one `(kind, id)`. A transient event occupies one update Match; update-only evidence may remain pending until pagination supplies its unique durable start. |
|
|
20
20
|
| Location | The engine-owned Session, Turn, or Step coordinates derived from durable boundary events. Definitions may publish typed data onto one Turn or Step. |
|
|
21
21
|
| View Definition | A target package creates one incremental builder per Session and owns the final snapshot type for that target. |
|
|
22
22
|
| View | A Slot entry such as Chat or Trajectory reads only its target snapshot and renders target-owned nodes. |
|
|
23
23
|
|
|
24
24
|
Chat and Trajectory may recognize the same durable event family, but each keeps its own Definition State and final node payload. Shared target-neutral machinery is limited to identity routing, ordered replay, Location data, predecessor dependencies, and publication cadence.
|
|
25
25
|
|
|
26
|
+
## Target activation
|
|
27
|
+
|
|
28
|
+
Each Session keeps a monotonic set of active targets. Creating or reading a target source does not activate it. The shell explicitly activates its persisted or newly selected View, while another consumer activates a target through its first source subscription. First activation creates that target's builder and calls `replace()` once from the current target-indexed Contexts. Later flushes call `apply()` for every active target, and unsubscription does not remove one.
|
|
29
|
+
|
|
30
|
+
The shell owns View selection and resolves the registered preferred View or Chat fallback before rendering when a binding is created or selected as current, and after View-roster changes. The assembler receives only the resolved target id and does not select Chat or another default target. A third-party View participates through the same selection and activation operations.
|
|
31
|
+
|
|
26
32
|
## Replayable event families
|
|
27
33
|
|
|
28
34
|
Choose one stable business id before writing the Definition. Every event that contributes to the same Node must carry that id or derive it independently from its own payload; the client must never assign an update to “the latest unfinished” Context.
|
|
@@ -39,7 +45,7 @@ Use the producer-owned branded id type across the process boundary. Put the `Ses
|
|
|
39
45
|
|
|
40
46
|
Incremental events are supported. Prefer whole-value checkpoints when the producer can emit them cheaply, because they remain useful when the start is outside the loaded window. Each delta must carry the stable id and produce deterministic State when replayed in ascending log `seq`; it must not depend on live-only memory. If the current history window contains only updates, the assembler keeps a pending Context and builds no State until an older page supplies the start. If the product must render before the start is loaded, a terminal or checkpoint event must carry enough whole fallback state for the Definition to build that result directly; do not recover it by scanning unrelated events.
|
|
41
47
|
|
|
42
|
-
|
|
48
|
+
Live Assistant deltas arrive as Client-only `assistant/live-chunk` updates. Reconnect baselines expand the active process-local compact stream into the same transient events, while durable `assistant/message` and `assistant/attempt` events embed complete compact streams for history replay. Transient events can only be updates; `start()` receives a standard `SessionEvent`. A Definition that consumes Assistant output handles live chunks and durable settlements in the same `match()` and `update()` methods, while unrelated Definitions return `null` without expanding a stream.
|
|
43
49
|
|
|
44
50
|
## Definition and typed Chat payload
|
|
45
51
|
|
|
@@ -250,5 +256,6 @@ Add focused tests that establish these outcomes:
|
|
|
250
256
|
5. Repeated visible deltas preserve `context.key` and publish at most once per animation frame when requested.
|
|
251
257
|
6. The keyed renderer consumes `node.data` and constrained Location hooks only; it does not scan the Session event window, Contexts, or Chat Nodes.
|
|
252
258
|
7. Scalar and packed Assistant history produce the same final State, timing boundaries, and target snapshot, while one packed run remains one Match through replace, prepend, Location replay, and registry rebuild.
|
|
259
|
+
8. Creating a target source performs no builder work; explicit selection or the first subscription performs one complete replacement, later updates reach every active target, and repeated activation performs no replacement.
|
|
253
260
|
|
|
254
261
|
Use [`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) for streaming and interruption, [`inbox.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-chat/src/client/conversation-nodes/inbox.ts) plus [`message.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/ui-chat/src/client/conversation-nodes/message.ts) for predecessor queries, and [`packages/client/ui-deliverables`](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/client/ui-deliverables) for a Definition that publishes Turn data without creating its own Node.
|