@deepseek-ai/dsh-action-cards 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/LICENSE +21 -0
- package/README.i18n.yaml +67 -0
- package/README.md +136 -2
- package/README.zh.md +137 -0
- package/lib/index.js +625 -0
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +873 -0
- package/lib/typert.remote-client.d.ts +31 -0
- package/lib/typert.remote-client.js +137 -0
- package/lib/types/index.d.ts +178 -0
- package/lib/types/index.js +398 -0
- package/lib/types/projection.d.ts +66 -0
- package/lib/types/projection.js +122 -0
- package/lib/types/types.d.ts +81 -0
- package/lib/types/types.js +2 -0
- package/locale/de.json +6 -0
- package/locale/en.json +6 -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 +72 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DeepSeek
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.i18n.yaml
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
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/experimental/action-cards/README.md
|
|
5
|
+
/:
|
|
6
|
+
en: 1a68a7a733a2676d
|
|
7
|
+
zh: 01f72eb61a0626b7
|
|
8
|
+
/deepseek-ai-dsh-action-cards:
|
|
9
|
+
en: 63bf9077e164f6fe
|
|
10
|
+
zh: 8b696bb8c3d6fcd4
|
|
11
|
+
/deepseek-ai-dsh-action-cards/summary:
|
|
12
|
+
en: 7621088773d073f4
|
|
13
|
+
zh: 57674e6dcee15997
|
|
14
|
+
/deepseek-ai-dsh-action-cards/table-of-contents:
|
|
15
|
+
en: d152484eb41ac6b4
|
|
16
|
+
zh: b00dddf4c88f0a45
|
|
17
|
+
/deepseek-ai-dsh-action-cards/use-this-package:
|
|
18
|
+
en: e239e255a6692f95
|
|
19
|
+
zh: ae8e359e37e484b3
|
|
20
|
+
/deepseek-ai-dsh-action-cards/use-this-package/register-a-card-kind:
|
|
21
|
+
en: 8432c02ef18eda11
|
|
22
|
+
zh: 6d43a0a32edd7e30
|
|
23
|
+
/deepseek-ai-dsh-action-cards/use-this-package/card-rules:
|
|
24
|
+
en: 2f5b3ccb91f3b30e
|
|
25
|
+
zh: 9bd877d9d92615da
|
|
26
|
+
/deepseek-ai-dsh-action-cards/understand-the-implementation:
|
|
27
|
+
en: d92243d71d2106c1
|
|
28
|
+
zh: 47f0840fa723bb31
|
|
29
|
+
/deepseek-ai-dsh-action-cards/further-exploration:
|
|
30
|
+
en: 1966ab8d7063c450
|
|
31
|
+
zh: 033c2c0d258a257f
|
|
32
|
+
/deepseek-ai-dsh-action-cards/model-experience:
|
|
33
|
+
en: 215e7ba838619b7b
|
|
34
|
+
zh: a311da3843709f90
|
|
35
|
+
/deepseek-ai-dsh-action-cards/model-experience/card-tool:
|
|
36
|
+
en: 4925bc5f7153825a
|
|
37
|
+
zh: 3a7bfb2210d9c6aa
|
|
38
|
+
/deepseek-ai-dsh-action-cards/model-experience/card-tool/what-the-model-sees:
|
|
39
|
+
en: 58521d3992ce42ec
|
|
40
|
+
zh: 45681f7b43e67613
|
|
41
|
+
/deepseek-ai-dsh-action-cards/model-experience/card-tool/token-effect:
|
|
42
|
+
en: 7efaaad09be98a07
|
|
43
|
+
zh: 86c7fa13d60c3588
|
|
44
|
+
/deepseek-ai-dsh-action-cards/model-experience/card-tool/kv-cache-effect:
|
|
45
|
+
en: d4192e35d47b5fa3
|
|
46
|
+
zh: c786828e123de657
|
|
47
|
+
/deepseek-ai-dsh-action-cards/model-experience/card-status-notice:
|
|
48
|
+
en: 407ebca5eb94992e
|
|
49
|
+
zh: 779819ea83974103
|
|
50
|
+
/deepseek-ai-dsh-action-cards/model-experience/card-status-notice/what-the-model-sees:
|
|
51
|
+
en: a14013ca3ddb5ee3
|
|
52
|
+
zh: 18cd7ffc62fd6590
|
|
53
|
+
/deepseek-ai-dsh-action-cards/model-experience/card-status-notice/what-the-model-sees/notice-preamble:
|
|
54
|
+
en: 04dd9469bfaff052
|
|
55
|
+
zh: 35110b231b8e3928
|
|
56
|
+
/deepseek-ai-dsh-action-cards/model-experience/card-status-notice/token-effect:
|
|
57
|
+
en: 4e73a2cff60b5e88
|
|
58
|
+
zh: 4887212815e7425d
|
|
59
|
+
/deepseek-ai-dsh-action-cards/model-experience/card-status-notice/kv-cache-effect:
|
|
60
|
+
en: 58785543e2428dba
|
|
61
|
+
zh: 4b082f77b3b2f482
|
|
62
|
+
/deepseek-ai-dsh-action-cards/known-limitations-and-deferred-work:
|
|
63
|
+
en: 8e3eba4e9fda82cb
|
|
64
|
+
zh: afaf74aad9a01533
|
|
65
|
+
/deepseek-ai-dsh-action-cards/known-limitations-and-deferred-work/dev-note:
|
|
66
|
+
en: e67f633dc6fe7773
|
|
67
|
+
zh: bd8a8936229e035e
|
package/README.md
CHANGED
|
@@ -1,3 +1,137 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
description: "Shared Host service of optional action cards: the propose_action tool, card state, user actions and status notices that experiment packages register card kinds into."
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
# @deepseek-ai/dsh-action-cards
|
|
7
|
+
|
|
8
|
+
English | [中文](README.zh.md)
|
|
9
|
+
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
An experiment can offer one optional action below an answer, such as creating a page, without adding a tool of its own. The model loads the experiment's skill, then calls `propose_action`; the card appears after the turn ends, and nothing runs until the user acts on it. Each choice is recorded and reported to the model on its next request. The tool costs nothing until a card skill loads in the conversation.
|
|
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
|
+
The [Personalized recommendations](../personalized-recommendations/README.md) bundle inserts this service and its [browser half](../client-ui-action-cards/README.md). The service has one configuration field:
|
|
29
|
+
|
|
30
|
+
| Field | Default | Meaning |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| `queuedMessageLimit` | `2` | Queued next-turn user messages at or above which `propose_action` refuses the call, so no card is offered. |
|
|
33
|
+
|
|
34
|
+
The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-action-cards) is the exhaustive source for accepted fields.
|
|
35
|
+
|
|
36
|
+
### Register a card kind
|
|
37
|
+
|
|
38
|
+
A kind package injects `actionCards` and calls `ctx.actionCards.register(kind)` from its own plugin; unloading that plugin removes the kind, and actions on its cards are then refused as unavailable, except that Not now still dismisses an unstarted card. The kind names its action, the skill that proposes it, the closing invitation guidance that an accepted call's result gives the model, a zod schema for the card's `details`, the user actions it accepts and the shared checks each needs (`global` Remote access, `writes` refused in a read-only Session), the recorded phases that still offer dismissal, optional status guidance, the decision data fields the status notice reports, an optional `reconcile` that updates the card's recorded decision from state outside the Session before every action, and the handler for every action except `dismiss`. The handler records each new decision with `ctx.actionCards.record()`, which refuses an action no kind registered and the derived `replaced` phase, and returns `accepted`, `settled` with the decision in effect, `refused` or `unconfirmed`.
|
|
39
|
+
|
|
40
|
+
### Card rules
|
|
41
|
+
|
|
42
|
+
- The first accepted `propose_action` call of a turn becomes the card. The tool refuses a second call in the same turn, an unregistered action, a call whose kind skill was not loaded in the current turn, a blank title or brief, details that fail the kind schema, calls dispatched from code, calls from a subagent, and any call while `queuedMessageLimit` or more user messages wait for later turns.
|
|
43
|
+
- A newer card of any kind replaces every unstarted earlier card. Replacement is derived from the log and never recorded.
|
|
44
|
+
- Events a forked Session inherits create no cards.
|
|
45
|
+
- Before every action, including Not now, the kind's `reconcile` updates the card from state outside the Session. Not now is then recorded for an unstarted card and for the phases the kind lists; dismissed and replaced cards accept no further action. Without its registered kind, Not now still dismisses an unstarted card, and every other action is refused as unavailable.
|
|
46
|
+
- Concurrent actions on one card share one operation. Actions require the card's live root Agent.
|
|
47
|
+
|
|
48
|
+
-----
|
|
49
|
+
|
|
50
|
+
<a id="understand-the-implementation"></a>
|
|
51
|
+
## Understand the implementation
|
|
52
|
+
|
|
53
|
+
<details>
|
|
54
|
+
<summary>Implementation internals — click to expand</summary>
|
|
55
|
+
|
|
56
|
+
The package default-exports the `actionCards` Remote service. It registers `propose_action` once, globally, with a `when` condition: a live root Agent becomes eligible when its own direct `skill` call loads the skill of a registered kind, while loads by subagents or from code are ignored. The flag lives in memory until the Agent is disposed. The call's `execute` checks the live root, the queued messages the projection counts against `queuedMessageLimit` and the current turn's skill loads through the turn boundary, and keeps an in-memory mark of the turn's accepted call; the logged `tool/call` and its successful `tool/result` are the durable proposal.
|
|
57
|
+
|
|
58
|
+
The `actionCards` Session projection (state version 2) pairs each `propose_action` call with its successful result, records decisions from `plugin:action-cards/decision`, counts queued next-turn messages from inbox splices for the tool's limit, and keeps unreported decisions until a status notice whose `through` covers them enters the log. Its Client view `{ proposals, decisions }` is excluded from Session summaries.
|
|
59
|
+
|
|
60
|
+
The Remote `act(sessionId, callId, verb, payload?)` checks the owner, the live root and the card; Not now continues without a registered kind, while other verbs need the kind, the verb and Remote access. It then shares one operation per card. The kind's `reconcile` runs first and the live root is checked again; a dismissed or replaced card then settles unchanged, Not now is recorded, a writing verb is refused in a read-only Session, and every other verb goes to the kind handler under the Agent's initiator. `record()` also accepts an action whose kind has unregistered, because Cordis disposes a plugin's effects concurrently and an unloading kind still records the outcome of work it started. An `agent/pre-step` listener adds the status notice after later listeners prepared the step.
|
|
61
|
+
|
|
62
|
+
| Source | Contents |
|
|
63
|
+
|---|---|
|
|
64
|
+
| [`src/index.ts`](src/index.ts) | Service, tool, kind registry, Remote action and status notice |
|
|
65
|
+
| [`src/projection.ts`](src/projection.ts) | Session projection |
|
|
66
|
+
| [`src/types.ts`](src/types.ts) | Proposal, decision, view and result types |
|
|
67
|
+
| [`tests/`](tests/) | Activation, validation, projection, action and notice tests |
|
|
68
|
+
|
|
69
|
+
</details>
|
|
70
|
+
|
|
71
|
+
-----
|
|
72
|
+
|
|
73
|
+
<a id="further-exploration"></a>
|
|
74
|
+
## Further Exploration
|
|
75
|
+
|
|
76
|
+
- [Action card display](../client-ui-action-cards/README.md) — the browser frame, kind bodies and the process row.
|
|
77
|
+
- [Personalized pages](../creation-recommendations/README.md) and [Plugin recommendations](../plugin-recommendations/README.md) — the shipped card kinds.
|
|
78
|
+
- [Tools](../../core/tools/README.md) — conditional registration and step admission.
|
|
79
|
+
- [Session projection](../../session/session-projection/README.md) — the card state the browser reads.
|
|
80
|
+
|
|
81
|
+
<a id="model-experience"></a>
|
|
82
|
+
## Model Experience
|
|
83
|
+
|
|
84
|
+
### Card tool
|
|
85
|
+
|
|
86
|
+
#### What the model sees
|
|
87
|
+
|
|
88
|
+
The [`propose_action` declaration](../../../docs/tool-catalog.md#deepseek-aidsh-action-cards) appears only to a live root Agent whose own direct call loaded the skill of a registered kind in this Session, from the next step on, for that Agent's lifetime. Subagents never see it, and neither do PTC presets, whose skill loads are dispatched from code, so they show no cards. A kind's skill names the action and the fields of `details`. An accepted call returns `Card shown below your answer. Do not restate it. <invitation>`, where `<invitation>` is the kind's one- or two-sentence guidance on inviting the user to the card in the user's language, so the model writes an invitation only after a card exists. A refused call carries no invitation and returns its reason, for example `Load skill <skill> first, then call propose_action.`, `One card per turn; the earlier card stands.`, `The user has queued more messages; show no card and answer briefly.`, `Cards are offered in the main conversation only.`, `Unknown action "<action>". Registered actions: <actions>.`, where the list reads `none` once the last kind unregistered, or the failing `details` fields.
|
|
89
|
+
|
|
90
|
+
#### Token effect
|
|
91
|
+
|
|
92
|
+
Before a card skill loads, the tool adds no tokens. Afterwards each request of that Agent declares it: 574 characters of JSON, about 144 tokens at the token meter's four characters per token. A card costs one extra model round trip, the call before the final answer, and its tool result: a 49-character prefix plus the kind's invitation. The Personalized pages result is 305 characters, about 77 tokens at the same rate.
|
|
93
|
+
|
|
94
|
+
#### KV Cache effect
|
|
95
|
+
|
|
96
|
+
Activation is append-only on routes that declare tool updates, such as DeepSeek-V4.1-Flash: when the condition turns true the loop logs a header change and a `tool-addition` developer message, and those routes receive the definition as a deferred declaration referenced at that position, so the cached prefix is kept. A route without tool updates receives the tool in its declaration list from that step on, which changes the request prefix once. Disposing the Agent drops the activation; a reopened Session declares the tool again only after a card skill loads again, logging a removal and a later addition.
|
|
97
|
+
|
|
98
|
+
### Card status notice
|
|
99
|
+
|
|
100
|
+
#### What the model sees
|
|
101
|
+
|
|
102
|
+
After a decision is recorded, the next request carries one `action-cards` notice: the preamble below, the guidance sentences of each involved kind, `Continue with the user’s current request.`, and a JSON array of the changed cards with `action`, `callId`, `title`, `phase` and the data fields their kind reports.
|
|
103
|
+
|
|
104
|
+
##### Notice preamble
|
|
105
|
+
|
|
106
|
+
```markdown
|
|
107
|
+
Latest status of action cards from user actions and background work. These are status facts, not a request to start or retry work. Use these receipts instead of the earlier proposal when describing progress.
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
#### Token effect
|
|
111
|
+
|
|
112
|
+
One notice per request that follows new decisions, sized by the changed cards; unchanged cards add nothing, and several decisions of one card collapse to its latest.
|
|
113
|
+
|
|
114
|
+
#### KV Cache effect
|
|
115
|
+
|
|
116
|
+
The notice is appended after the request's other new context and never rewrites earlier messages. The notice neither starts a turn nor wakes an idle conversation.
|
|
117
|
+
|
|
118
|
+
## Known Limitations and Deferred Work
|
|
119
|
+
|
|
120
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
121
|
+
|
|
122
|
+
- Activation is per live Agent and kept in memory, so after a Session reopens the tool appears again only after a card skill loads again.
|
|
123
|
+
- PTC presets show no cards: skill loads and calls dispatched from code never activate or reach the tool, because the log records them as program dispatches rather than tool calls.
|
|
124
|
+
- Cards are offered in the main conversation only. A subagent's skill load, including a Creator child's, activates nothing and its calls are refused, because only a live root can act on a card.
|
|
125
|
+
- Only one card is offered per turn across all kinds. A later card of any kind replaces every unstarted earlier card, so a second kind's card replaces an unstarted card of the first.
|
|
126
|
+
- Refusal reasons of user actions are plain strings by design: the service defines `closing`, `not-live-root`, `unknown`, `unavailable`, `access-denied` and `read-only`, each kind adds its own, and a browser body names the reasons it knows and treats others as unavailable.
|
|
127
|
+
- Each kind validates `details` on both sides, with its Host schema when the model proposes and before each action, and with its browser body's own schema, so the two schemas change together.
|
|
128
|
+
|
|
129
|
+
<a id="dev-note"></a>
|
|
130
|
+
### Dev Note
|
|
131
|
+
|
|
132
|
+
<details>
|
|
133
|
+
<summary>Working context for maintainers — click to expand</summary>
|
|
134
|
+
|
|
135
|
+
None.
|
|
136
|
+
|
|
137
|
+
</details>
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "可选操作卡片的共享 Host 服务:propose_action 工具、卡片状态、用户操作和状态通知,各实验包把自己的卡片种类注册进来。"
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @deepseek-ai/dsh-action-cards
|
|
7
|
+
|
|
8
|
+
[English](README.md) | 中文
|
|
9
|
+
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
实验可以在回答下方提供一个可选操作,例如创建页面,而不必新增自己的工具。模型先加载该实验的 Skill,再调用 `propose_action`;本轮结束后卡片出现在回答下方,用户操作之前不会执行任何事。用户的每次选择都会被记录,并在模型的下一次请求中告知模型。对话中加载卡片 Skill 之前,这个工具不占用任何 token。
|
|
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
|
+
[个性化推荐](../personalized-recommendations/README.zh.md) Bundle 会插入本服务及其[浏览器端](../client-ui-action-cards/README.zh.md)。本服务只有一个配置字段:
|
|
29
|
+
|
|
30
|
+
| 字段 | 默认值 | 含义 |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| `queuedMessageLimit` | `2` | 排队到后续轮次的用户消息达到该数量时,`propose_action` 拒绝调用,因此不会展示卡片。 |
|
|
33
|
+
|
|
34
|
+
生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-action-cards)是可接受字段的完整来源。
|
|
35
|
+
|
|
36
|
+
### 注册卡片种类
|
|
37
|
+
|
|
38
|
+
种类所在的包注入 `actionCards`,并在自己的插件中调用 `ctx.actionCards.register(kind)`;该插件卸载时种类随之移除,此后对其卡片的操作会以 unavailable 拒绝,只有“暂不需要”仍可忽略尚未开始的卡片。种类需要给出:动作名、提议该动作的 Skill、被接受的调用结果交给模型的结尾邀请指引、卡片 `details` 的 zod 校验、接受的用户操作及各自需要的共享检查(`global` 表示需要全局 Remote 权限,`writes` 表示只读会话中拒绝)、仍可忽略卡片的已记录阶段、可选的状态说明、状态通知要报告的决定数据字段、可选的 `reconcile`(每次操作前根据会话之外的状态更新卡片的已记录决定),以及处理 `dismiss` 以外所有操作的处理器。处理器用 `ctx.actionCards.record()` 记录每个新决定(该方法拒绝没有种类注册过的动作和推导得出的 `replaced` 阶段),并返回 `accepted`、带当前决定的 `settled`、`refused` 或 `unconfirmed`。
|
|
39
|
+
|
|
40
|
+
### 卡片规则
|
|
41
|
+
|
|
42
|
+
- 一轮中第一个被接受的 `propose_action` 调用成为卡片。工具会拒绝同一轮的第二次调用、未注册的动作、本轮没有加载对应种类 Skill 的调用、空白的标题或说明、未通过种类校验的 details、从代码中发起的调用、来自 subagent 的调用,以及排队到后续轮次的用户消息达到 `queuedMessageLimit` 条时的任何调用。
|
|
43
|
+
- 任何种类的新卡片都会替换此前所有尚未开始的卡片。替换从日志推导,从不单独记录。
|
|
44
|
+
- fork 出的会话从父会话继承的事件不会产生卡片。
|
|
45
|
+
- 每次操作(包括“暂不需要”)之前,种类的 `reconcile` 先根据会话之外的状态更新卡片。之后,对尚未开始的卡片,以及处于种类列出阶段的卡片,“暂不需要”会被记录;已忽略、已替换的卡片不再接受任何操作。卡片的种类未注册时,“暂不需要”仍可忽略尚未开始的卡片,其他操作一律以 unavailable 拒绝。
|
|
46
|
+
- 同一张卡片上的并发操作共用一次处理。操作要求卡片所在会话的根 Agent 仍然在线。
|
|
47
|
+
|
|
48
|
+
-----
|
|
49
|
+
|
|
50
|
+
<a id="understand-the-implementation"></a>
|
|
51
|
+
## 实现原理
|
|
52
|
+
|
|
53
|
+
<details>
|
|
54
|
+
<summary>实现细节——点击展开</summary>
|
|
55
|
+
|
|
56
|
+
本包默认导出 `actionCards` Remote 服务。它在全局注册一次 `propose_action`,并附带 `when` 条件:在线的根 Agent 自己直接调用 `skill` 加载了已注册种类的 Skill 后,该 Agent 才满足条件,subagent 或代码中发起的加载一律忽略;这个标记保存在内存中,直到 Agent 被释放。调用的 `execute` 检查在线根 Agent、投影累计的排队消息是否达到 `queuedMessageLimit`,并通过轮次边界检查本轮加载过的 Skill,同时在内存中标记本轮已接受的调用;日志中的 `tool/call` 及其成功的 `tool/result` 就是持久的提议。
|
|
57
|
+
|
|
58
|
+
`actionCards` 会话投影(状态版本 2)把每个 `propose_action` 调用与其成功结果配对,从 `plugin:action-cards/decision` 读取决定,从收件箱拼接事件累计排队到下一轮的消息供工具上限使用,并保留尚未报告的决定,直到 `through` 覆盖它们的状态通知写入日志。投影的客户端视图 `{ proposals, decisions }` 不进入会话摘要。
|
|
59
|
+
|
|
60
|
+
Remote `act(sessionId, callId, verb, payload?)` 先检查服务所有者、在线根 Agent 和卡片;“暂不需要”在种类未注册时也继续处理,其他操作还需要种类、操作和 Remote 权限。然后同一张卡片共用一次处理。种类的 `reconcile` 先运行,之后再次检查在线根 Agent;已忽略或已替换的卡片原样返回,“暂不需要”被记录,写入类操作在只读会话中被拒绝,其余操作在该 Agent 的发起方作用域内交给种类处理器。`record()` 也接受种类已注销的动作,因为 Cordis 并发释放插件的各个 effect,卸载中的种类仍要记录已开始工作的结果。一个 `agent/pre-step` 监听器在后续监听器准备好本步之后追加状态通知。
|
|
61
|
+
|
|
62
|
+
| 源码 | 内容 |
|
|
63
|
+
|---|---|
|
|
64
|
+
| [`src/index.ts`](src/index.ts) | 服务、工具、种类注册表、Remote 操作与状态通知 |
|
|
65
|
+
| [`src/projection.ts`](src/projection.ts) | 会话投影 |
|
|
66
|
+
| [`src/types.ts`](src/types.ts) | 提议、决定、视图与结果类型 |
|
|
67
|
+
| [`tests/`](tests/) | 激活、校验、投影、操作与通知测试 |
|
|
68
|
+
|
|
69
|
+
</details>
|
|
70
|
+
|
|
71
|
+
-----
|
|
72
|
+
|
|
73
|
+
<a id="further-exploration"></a>
|
|
74
|
+
## 延伸阅读
|
|
75
|
+
|
|
76
|
+
- [操作卡片显示](../client-ui-action-cards/README.zh.md) — 浏览器端卡片框架、种类正文与过程行。
|
|
77
|
+
- [个性化页面](../creation-recommendations/README.zh.md)和[插件推荐](../plugin-recommendations/README.zh.md) — 随产品提供的卡片种类。
|
|
78
|
+
- [工具](../../core/tools/README.zh.md) — 条件注册与每步准入。
|
|
79
|
+
- [会话投影](../../session/session-projection/README.zh.md) — 浏览器读取的卡片状态。
|
|
80
|
+
|
|
81
|
+
<a id="model-experience"></a>
|
|
82
|
+
## 模型体验
|
|
83
|
+
|
|
84
|
+
### 卡片工具
|
|
85
|
+
|
|
86
|
+
#### 模型看到什么
|
|
87
|
+
|
|
88
|
+
[`propose_action` 声明](../../../docs/tool-catalog.zh.md#deepseek-aidsh-action-cards)只对在本会话中自己直接调用加载过已注册种类 Skill 的在线根 Agent 出现,从下一步开始,持续到该 Agent 被释放。subagent 看不到它;PTC 预设的 Skill 加载由代码发起,也看不到它,因此不会展示卡片。种类的 Skill 给出动作名和 `details` 的字段。被接受的调用返回 `Card shown below your answer. Do not restate it. <invitation>`,其中 `<invitation>` 是种类给出的一两句指引,说明如何用用户的语言邀请用户使用卡片,因此模型只会在卡片已经存在之后写邀请。被拒绝的调用不带邀请,只返回原因,例如 `Load skill <skill> first, then call propose_action.`、`One card per turn; the earlier card stands.`、`The user has queued more messages; show no card and answer briefly.`、`Cards are offered in the main conversation only.`、`Unknown action "<action>". Registered actions: <actions>.`(最后一个种类注销后列表为 `none`),或未通过校验的 `details` 字段。
|
|
89
|
+
|
|
90
|
+
#### Token 影响
|
|
91
|
+
|
|
92
|
+
加载卡片 Skill 之前,工具不增加任何 token。加载之后,该 Agent 的每次请求都会声明它:574 个字符的 JSON,按 token 计量器每 4 个字符计 1 个 token 约 144 个 token。出一张卡片多一次模型往返(最终回答前的这次调用)以及一条工具结果:49 个字符的前缀加上种类的邀请。个性化页面的结果为 305 个字符,按同样的比例约 77 个 token。
|
|
93
|
+
|
|
94
|
+
#### KV Cache 影响
|
|
95
|
+
|
|
96
|
+
在声明支持工具更新的路由上(例如 DeepSeek-V4.1-Flash),激活只追加内容:条件变为真时,循环记录一次请求头变化和一条 `tool-addition` 开发者消息,这些路由以延迟加载声明的形式在该位置引用新定义,因此已缓存的前缀保持不变。不支持工具更新的路由从这一步起在声明列表中收到该工具,请求前缀因此改变一次。Agent 被释放后激活随之失效;重新打开的会话要再次加载卡片 Skill 才会再次声明该工具,并依次记录一次移除和一次添加。
|
|
97
|
+
|
|
98
|
+
### 卡片状态通知
|
|
99
|
+
|
|
100
|
+
#### 模型看到什么
|
|
101
|
+
|
|
102
|
+
记录决定之后,下一次请求会带一条 `action-cards` 通知:下方的开头段落、所涉及各种类的说明句、`Continue with the user’s current request.`,以及一个 JSON 数组,列出发生变化的卡片的 `action`、`callId`、`title`、`phase` 和种类要报告的数据字段。
|
|
103
|
+
|
|
104
|
+
##### 通知开头
|
|
105
|
+
|
|
106
|
+
```markdown
|
|
107
|
+
Latest status of action cards from user actions and background work. These are status facts, not a request to start or retry work. Use these receipts instead of the earlier proposal when describing progress.
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
#### Token 影响
|
|
111
|
+
|
|
112
|
+
有新决定之后的每次请求带一条通知,大小取决于发生变化的卡片;没有变化的卡片不增加内容,同一张卡片的多次决定只报告最新一次。
|
|
113
|
+
|
|
114
|
+
#### KV Cache 影响
|
|
115
|
+
|
|
116
|
+
通知追加在本次请求其他新上下文之后,从不改写之前的消息。通知既不会开始新轮次,也不会唤醒空闲的对话。
|
|
117
|
+
|
|
118
|
+
## 已知限制与后续工作
|
|
119
|
+
|
|
120
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
121
|
+
|
|
122
|
+
- 激活按在线 Agent 记在内存中,因此会话重新打开后,要再次加载卡片 Skill 工具才会再次出现。
|
|
123
|
+
- PTC 预设不会展示卡片:从代码中发起的 Skill 加载和调用既不会激活工具,也到达不了工具,因为日志把它们记为程序派发而不是工具调用。
|
|
124
|
+
- 卡片只在主对话中提供。subagent(包括 Creator 子 Agent)加载 Skill 不会激活任何东西,其调用也会被拒绝,因为只有在线的根 Agent 才能对卡片进行操作。
|
|
125
|
+
- 所有种类合计每轮只展示一张卡片。任何种类的新卡片都会替换此前所有尚未开始的卡片,因此第二个种类的卡片会替换第一个种类尚未开始的卡片。
|
|
126
|
+
- 用户操作的拒绝原因有意设计为普通字符串:服务定义 `closing`、`not-live-root`、`unknown`、`unavailable`、`access-denied` 和 `read-only`,各种类可以添加自己的原因,浏览器端正文为已知原因显示文案,其余按 unavailable 处理。
|
|
127
|
+
- 每个种类在两端各自校验 `details`:Host 端的 schema 在模型提议时和每次操作前校验,浏览器端正文用自己的 schema 校验,因此两个 schema 要一起修改。
|
|
128
|
+
|
|
129
|
+
<a id="dev-note"></a>
|
|
130
|
+
### 开发备注
|
|
131
|
+
|
|
132
|
+
<details>
|
|
133
|
+
<summary>维护者工作背景——点击展开</summary>
|
|
134
|
+
|
|
135
|
+
无。
|
|
136
|
+
|
|
137
|
+
</details>
|