Merge Team-wide communication into named subagents
This commit is contained in:
commit
eefd0e1ef4
661 files changed
+2977
-1557
No files matched your search
+2
-2
@@ -3,8 +3,8 @@
|
||||
# After editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-27-adjacent-agent-steer-messaging.md
|
||||
/agent-note-adjacent-agents-share-one-steer-send-message-operation:
|
||||
en: 758d31ae04ce0d4f
|
||||
zh: 112475efbd52b9f6
|
||||
en: dbbce49e8075750f
|
||||
zh: d7776487e70d5c69
|
||||
/agent-note-adjacent-agents-share-one-steer-send-message-operation/problem:
|
||||
en: c988b8a3be4e6f19
|
||||
zh: b58011fd8d2e878e
|
||||
|
||||
@@ -4,6 +4,8 @@ Status: implemented
|
||||
|
||||
English | [中文](2026-08-27-adjacent-agent-steer-messaging.zh.md)
|
||||
|
||||
The adjacency and discovery restrictions below are superseded by [tree-wide communication](2026-10-16-tree-wide-agent-communication.md); the remaining decisions stay active.
|
||||
|
||||
## Problem
|
||||
|
||||
Continuable Agents originally used direction-specific model controls. A parent called `send_message({ subagent_id, message })`, which delegated to a FIFO `followup` service operation. A child instead received a child-scoped `report({ output })` tool, a `tool:report` system-prompt section, and deployment-selected quiet or waking delivery. The tools described one adjacent-Agent operation through different schemas, service paths, source attribution, and scheduling.
|
||||
|
||||
@@ -4,6 +4,8 @@ Status: implemented
|
||||
|
||||
[English](2026-08-27-adjacent-agent-steer-messaging.md) | 中文
|
||||
|
||||
邻接消息和发现范围已由[整树通信](2026-10-16-tree-wide-agent-communication.zh.md)替代;其余决策仍然有效。
|
||||
|
||||
## 问题
|
||||
|
||||
可继续 Agent 最初使用方向专属的模型控制。parent 调用 `send_message({ subagent_id, message })`,委托给 FIFO `followup` 服务操作。child 则获得 child 作用域的 `report({ output })` 工具、`tool:report` 系统提示词 section,以及由部署选择的静默或唤醒投递。两个工具用不同 schema、服务路径、来源与调度描述同一个相邻 Agent 操作。
|
||||
|
||||
+4
-4
@@ -3,14 +3,14 @@
|
||||
# After editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-10-15-agent-teams-as-subagents.md
|
||||
/agent-note-agent-teams-teammates-are-subagents:
|
||||
en: 3a3c59709e08af73
|
||||
zh: 3ea1dd59c0f9866b
|
||||
en: 8d5d6b1e90ab4780
|
||||
zh: fbc3f1b7656304a3
|
||||
/agent-note-agent-teams-teammates-are-subagents/problem:
|
||||
en: ca2848e3bbc3a009
|
||||
zh: 0551e32ff6d187d0
|
||||
/agent-note-agent-teams-teammates-are-subagents/decision:
|
||||
en: 5742777c069a9bb6
|
||||
zh: ffddb9c47183da7e
|
||||
en: f8569461c69fe4d3
|
||||
zh: 05fa504abaf77a7b
|
||||
/agent-note-agent-teams-teammates-are-subagents/alternatives-considered:
|
||||
en: ef0cf648ff54784f
|
||||
zh: 2a0b3745a54e7072
|
||||
|
||||
@@ -6,6 +6,8 @@ English | [中文](2026-10-15-agent-teams-as-subagents.zh.md)
|
||||
|
||||
The name-free model interface below is superseded by [tree-wide agent names](2026-10-16-tree-wide-agent-names.md). Session identity, lineage authority, and Team reuse remain current.
|
||||
|
||||
The adjacency and discovery restrictions below are superseded by [tree-wide communication](2026-10-16-tree-wide-agent-communication.md); the remaining decisions stay active.
|
||||
|
||||
## Problem
|
||||
|
||||
Teammates already use the subagent runtime for creation, Session identity, catalog membership, capacity, cold resume, settlement, and interruption. A separate Team roster duplicates identity, provisioning recovery, and teardown. Team-scoped messaging and control tools shadow the standard subagent tools, forcing profiles to disable ordinary delegation and making fork tool schemas diverge from their parent.
|
||||
@@ -20,7 +22,7 @@ Every root Agent leads the Team identified by its Session id; every live subagen
|
||||
|
||||
Task ownership uses `ownerId`, and reassignment accepts a Session id. Team persists only task changes. Messages use the target Agent inbox; historical `team/message/*` records remain readable but are never delivered or acknowledged.
|
||||
|
||||
This supersedes the roster, provisioning, recovery, and messaging decisions in [Agent Teams](../feature/2026-08-05-agent-teams.md) and the [Team direct inbox decision](../../archived/simplification/2026-09-26-team-direct-inbox.md). The task-board and shared-checkout decisions remain active. [Adjacent Agent messaging](2026-08-27-adjacent-agent-steer-messaging.md) includes sibling routing, while [required runtime-context identity](2026-10-13-team-identity-runtime-context.md) owns the role statement. The [upgrade guide](../../../../docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.md) lists removed tools, methods, and configuration.
|
||||
This supersedes the roster, provisioning, recovery, and messaging decisions in [Agent Teams](../feature/2026-08-05-agent-teams.md) and the [Team direct inbox decision](../../archived/simplification/2026-09-26-team-direct-inbox.md). The task-board and shared-checkout decisions remain active. [Adjacent Agent messaging](2026-08-27-adjacent-agent-steer-messaging.md) includes sibling routing, while [required runtime-context identity](2026-10-13-team-identity-runtime-context.md) owns the role statement. The [upgrade guide](../../../../docs/upgrade-guide/v0.2.1-rc.1/agent-team-subagents/guide.md) lists removed tools, methods, and configuration.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ Status: implemented
|
||||
|
||||
下述不使用名字的模型接口已被[树内唯一 agent 名字](2026-10-16-tree-wide-agent-names.zh.md)取代。Session 身份、谱系权限和 Team 复用决策仍然有效。
|
||||
|
||||
邻接消息和发现范围已由[整树通信](2026-10-16-tree-wide-agent-communication.zh.md)替代;其余决策仍然有效。
|
||||
|
||||
## Problem
|
||||
|
||||
队友已经使用子代理运行时完成创建、Session 身份、目录成员关系、容量、冷恢复、结算和中断。独立 Team 成员列表重复了身份、创建恢复和释放职责。Team 作用域内的消息及控制工具覆盖标准子代理工具,迫使 profile 禁用普通委派,并使分叉工具模式偏离父级。
|
||||
@@ -20,7 +22,7 @@ Status: implemented
|
||||
|
||||
任务所有权使用 `ownerId`,重新分配接受 Session id。Team 只持久化任务变更。消息使用目标 Agent 收件箱;历史 `team/message/*` 记录仍可读取,但不会被投递或确认。
|
||||
|
||||
本决策取代 [Agent Teams](../feature/2026-08-05-agent-teams.zh.md) 的成员列表、创建、恢复和消息决策,以及 [Team 直接收件箱决策](../../archived/simplification/2026-09-26-team-direct-inbox.md)。任务板和共享工作树决策仍有效。[相邻 Agent 消息](2026-08-27-adjacent-agent-steer-messaging.zh.md)纳入同级路由,[必需运行时身份](2026-10-13-team-identity-runtime-context.zh.md)负责角色声明。[升级指南](../../../../docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.zh.md)列出移除的工具、方法和配置。
|
||||
本决策取代 [Agent Teams](../feature/2026-08-05-agent-teams.zh.md) 的成员列表、创建、恢复和消息决策,以及 [Team 直接收件箱决策](../../archived/simplification/2026-09-26-team-direct-inbox.md)。任务板和共享工作树决策仍有效。[相邻 Agent 消息](2026-08-27-adjacent-agent-steer-messaging.zh.md)纳入同级路由,[必需运行时身份](2026-10-13-team-identity-runtime-context.zh.md)负责角色声明。[升级指南](../../../../docs/upgrade-guide/v0.2.1-rc.1/agent-team-subagents/guide.zh.md)列出移除的工具、方法和配置。
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
# Bilingual-pair consistency record for 2026-10-16-tree-wide-agent-communication.md (docs/i18n/README.md): per heading
|
||||
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
||||
# After editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-10-16-tree-wide-agent-communication.md
|
||||
/agent-note-communication-follows-the-subagent-tree:
|
||||
en: 849d806b901e9f04
|
||||
zh: 649b2984f844d510
|
||||
/agent-note-communication-follows-the-subagent-tree/problem:
|
||||
en: c583c3cdb894e417
|
||||
zh: 6edc0354b79f4f26
|
||||
/agent-note-communication-follows-the-subagent-tree/decision:
|
||||
en: 4e200408de98593f
|
||||
zh: fe0e221d97ec61af
|
||||
/agent-note-communication-follows-the-subagent-tree/alternatives-considered:
|
||||
en: 470f9cf8c3e32af9
|
||||
zh: 73bbe29767c5d02a
|
||||
/agent-note-communication-follows-the-subagent-tree/consequences:
|
||||
en: ac643f43288e548a
|
||||
zh: d35465401626b4aa
|
||||
@@ -0,0 +1,29 @@
|
||||
# Agent Note: Communication follows the subagent tree
|
||||
|
||||
Status: implemented
|
||||
|
||||
English | [中文](2026-10-16-tree-wide-agent-communication.zh.md)
|
||||
|
||||
## Problem
|
||||
|
||||
A Team shares one task board across the root's entire subagent tree. Restricting discovery and messages to adjacent relatives forces deeper members to relay work through parents despite sharing tasks.
|
||||
|
||||
## Decision
|
||||
|
||||
`list_agents` starts at the caller's live root and lists that root and all reachable continuable descendants, including the caller. Parent names and depth remain relative to the root. The existing parent catalogs remain authoritative; no Team directory is stored separately.
|
||||
|
||||
`send_message` accepts another root or continuable member of the same tree. The sender must be the exact live root or a resident continuable subagent. Cross-branch routing preserves the actual sender, verifies durable child descriptors and parent catalogs, and restores cold ancestors under their recorded parents. Ancestor restoration does not deliver the target's message to those ancestors. Final inbox admission rechecks the sender and target parent. Cancellation or rejection before acceptance releases new restoration work; accepted input follows normal Agent persistence.
|
||||
|
||||
Parent ownership still governs capacity, restoration, and disposal. `interrupt_agent` retains ancestor-only authority. Ordinary Session forks lead independent trees; external and one-shot executions cannot receive follow-ups.
|
||||
|
||||
This supersedes only the adjacency and discovery restrictions in [adjacent messaging](2026-08-27-adjacent-agent-steer-messaging.md) and [subagent teammates](2026-10-15-agent-teams-as-subagents.md). Their shared inbox, scheduling, attribution, lifecycle, and Team reuse decisions remain active. Model tools use [tree-wide names](2026-10-16-tree-wide-agent-names.md); host APIs retain Session ids.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
**Relay through parents.** This preserves the narrower routing implementation but makes the creation hierarchy determine who can collaborate. Shared work requires direct communication across branches.
|
||||
|
||||
**Separate Team directory and delivery.** A second member list and message path would duplicate the existing catalogs, inbox, and restoration lifecycle. Tree membership supplies the required communication scope without another registry.
|
||||
|
||||
## Consequences
|
||||
|
||||
Discovery output grows with the whole tree. Cold delivery can consume several activation slots while restoring ancestors and rejects when capacity or history is unavailable. The sender's live ancestry must remain intact. Listing is a snapshot; it does not promise that a later send will succeed. Concurrent operations retain ordinary inbox acceptance and disposal ordering.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Agent Note: 通信范围由子代理树决定
|
||||
|
||||
Status: implemented
|
||||
|
||||
[English](2026-10-16-tree-wide-agent-communication.md) | 中文
|
||||
|
||||
## Problem
|
||||
|
||||
一个 Team 在根的整棵子代理树中共享任务板。把发现和消息限定在相邻成员之间,会迫使深层成员在共享任务的同时,仍通过父级转发工作。
|
||||
|
||||
## Decision
|
||||
|
||||
`list_agents` 从调用方的在线根开始,列出该根与所有可达的可继续后代,包括调用方。父级名字和深度始终相对根计算。现有父级目录仍是权威来源;不单独存储 Team 目录。
|
||||
|
||||
`send_message` 接受同一棵树中的其他根或可继续成员。发送者必须是确切在线根或驻留的可继续子代理。跨分支路由保留实际发送者,验证持久子级描述符和父级目录,并按记录的父级恢复冷祖先。祖先恢复不会向这些祖先投递发给目标的消息。最终收件箱准入重新检查发送者与目标父级。接受前的取消或拒绝会释放新建的恢复工作;已接受输入遵循普通 Agent 持久化。
|
||||
|
||||
父级所有权仍管理容量、恢复和释放。`interrupt_agent` 保留仅祖先可执行的权限。普通 Session 分叉领导独立树;外部执行和一次性执行不能接收后续消息。
|
||||
|
||||
本决策仅替代[相邻消息](2026-08-27-adjacent-agent-steer-messaging.zh.md)与[子代理队友](2026-10-15-agent-teams-as-subagents.zh.md)中的邻接和发现范围限制。它们的共享收件箱、调度、发送者归属、生命周期和 Team 复用决策仍有效。模型工具使用[树内名字](2026-10-16-tree-wide-agent-names.zh.md);宿主 API 保留 Session id。
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
**通过父级转发。** 这保留了更窄的路由实现,却让创建层级决定谁能协作。共享工作需要跨分支直接通信。
|
||||
|
||||
**单独的 Team 目录与投递。** 第二份成员列表和消息路径会重复现有目录、收件箱与恢复生命周期。树成员身份已经提供所需通信范围,无需另一个注册表。
|
||||
|
||||
## Consequences
|
||||
|
||||
发现输出随整棵树增长。冷投递在恢复祖先时可能占用多个激活槽位,容量或历史不可用时会被拒绝。发送者的在线祖先链必须保持完整。列表是快照,不保证之后发送成功。并发操作保留普通收件箱接受与释放顺序。
|
||||
@@ -15,8 +15,8 @@
|
||||
en: edd75556ef338a6a
|
||||
zh: 559136d889bacdb1
|
||||
/agent-note-tree-wide-agent-names/consequences:
|
||||
en: 7810ae426c76bfcd
|
||||
zh: 4b954c0f0672c534
|
||||
en: 49c32dc1569ecb31
|
||||
zh: 78d1bac09b0fa580
|
||||
/agent-note-tree-wide-agent-names/testing:
|
||||
en: daffbc8dcd19b36d
|
||||
zh: 0940af582fc7feb9
|
||||
@@ -24,7 +24,7 @@ This supersedes the name-free interface in [Agent Teams as subagents](2026-10-15
|
||||
|
||||
## Consequences
|
||||
|
||||
Creation requires a name and rejects duplicates before dispatch. Independent roots can reuse names. Tool results, initial child guidance, message prefixes, and settlement notices use names. Internal Session and task-owner ids stay stable. The [upgrade guide](../../../../docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.md) lists changed tool arguments and results.
|
||||
Creation requires a name and rejects duplicates before dispatch. Independent roots can reuse names. Tool results, initial child guidance, message prefixes, and settlement notices use names. Internal Session and task-owner ids stay stable. The [upgrade guide](../../../../docs/upgrade-guide/v0.2.1-rc.1/agent-team-subagents/guide.md) lists changed tool arguments and results.
|
||||
|
||||
## Testing
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ Session id 提供持久执行身份,但模型协作时难以阅读。描述可
|
||||
|
||||
## 影响
|
||||
|
||||
创建必须提供名字,分发前拒绝重名。独立根可以复用名字。工具结果、子级初始指引、消息前缀与结束通知使用名字。内部 Session 和任务负责人 id 保持稳定。[升级指南](../../../../docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.zh.md)列出变化的工具参数与结果。
|
||||
创建必须提供名字,分发前拒绝重名。独立根可以复用名字。工具结果、子级初始指引、消息前缀与结束通知使用名字。内部 Session 和任务负责人 id 保持稳定。[升级指南](../../../../docs/upgrade-guide/v0.2.1-rc.1/agent-team-subagents/guide.zh.md)列出变化的工具参数与结果。
|
||||
|
||||
## 测试
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh",
|
||||
"description": "dsh CLI: profile launch, plugin management, and configuration inspection",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@
|
||||
{"type":"session/title","data":{"title":"Start a background job.","messageSeqs":[3],"source":{"kind":"fallback"}}}
|
||||
{"type":"assistant/message","data":{"turn":2,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"list-once","name":"list_agents","arguments":"{}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"list-once","name":"list_agents","args":["{}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"list-once","name":"list_agents","arguments":"{}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
|
||||
{"type":"tool/call","data":{"turn":2,"step":1,"callId":"list-once","name":"list_agents","arguments":"{}"}}
|
||||
{"type":"tool/result","data":{"turn":2,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"list-once"},"toolCallId":"list-once","content":[{"type":"text","text":"legacy:{{sessionId}} [inactive] parent=lead depth=1 — descriptorless child"}],"isError":false,"id":"{{sessionId}}"}},"sourceEventSeqs":[22],"surfaceOp":"append"}
|
||||
{"type":"tool/result","data":{"turn":2,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"list-once"},"toolCallId":"list-once","content":[{"type":"text","text":"lead [running] — team lead\nlegacy:{{sessionId}} [inactive] parent=lead depth=1 — descriptorless child"}],"isError":false,"id":"{{sessionId}}"}},"sourceEventSeqs":[22],"surfaceOp":"append"}
|
||||
{"type":"step/end","data":{"turn":2,"step":1}}
|
||||
{"type":"step/start","data":{"turn":2,"step":2}}
|
||||
{"type":"assistant/message","data":{"turn":2,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"The catalogued subagent is ready. PARENT_DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"{{sessionId}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":0,"index":0,"dt":[],"texts":["The catalogued subagent is ready. PARENT_DONE"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"The catalogued subagent is ready. PARENT_DONE"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"}
|
||||
|
||||
@@ -66,7 +66,7 @@ function researcher(messages) {
|
||||
if (!names.includes('list_agents')) return toolChunks([{ name: 'list_agents', args: {} }])
|
||||
const sibling = messages.filter(message => message.role === 'tool')
|
||||
.flatMap(message => message.content.filter(block => block.type === 'text').flatMap(block => block.text.split('\n')))
|
||||
.find(line => line.endsWith('— sibling: Own deterministic implementation.'))?.split(' ')[0]
|
||||
.find(line => line.endsWith('— Own deterministic implementation.'))?.split(' ')[0]
|
||||
if (sibling === undefined) throw new Error('list_agents did not expose the implementation sibling')
|
||||
if (!names.includes('team_task_create')) {
|
||||
return toolChunks([{ name: 'team_task_create', args: {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import type { TokenUsage } from '@deepseek-ai/dsh-llm'
|
||||
import { lastAssistantStreamChunk, type RetryPolicyConfig, type TokenUsage } from '@deepseek-ai/dsh-llm'
|
||||
import { DeepSeekHarness } from '@deepseek-ai/dsh-sdk-client'
|
||||
import type { SessionEvent } from '@deepseek-ai/dsh-session'
|
||||
import { describe, expect, it, onTestFinished } from 'vitest'
|
||||
@@ -22,6 +22,8 @@ interface ObservedRequest {
|
||||
step: number
|
||||
body: {
|
||||
system?: string
|
||||
max_tokens: number
|
||||
thinking: { type: string }
|
||||
messages: { role: string; content: { type: string; text?: string; tool?: { name: string } }[] }[]
|
||||
tools?: { name: string; defer_loading?: true }[]
|
||||
}
|
||||
@@ -70,7 +72,7 @@ function registryChanges(previous: ObservedRequest, request: ObservedRequest): {
|
||||
}
|
||||
|
||||
describe.skipIf(!process.env.DEEPSEEK_API_KEY)('SDK native tool updates with real DeepSeek', () => {
|
||||
it.each([false, true])('keeps the preceding conversation cached after a tool addition (prompt update: %s)', { retry: 0 }, async (updatePrompt) => {
|
||||
it.each([false, true])('keeps the preceding conversation cached after a tool addition (prompt update: %s)', async (updatePrompt) => {
|
||||
const root = await mkdtemp(join(tmpdir(), 'dsh-sdk-tool-cache-'))
|
||||
onTestFinished(async () => { await rm(root, { recursive: true, force: true }) })
|
||||
const sampleLabel = `CACHE_SAMPLE_${randomUUID()}`
|
||||
@@ -80,7 +82,7 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('SDK native tool updates with rea
|
||||
await writeFile(patch, JSON.stringify([
|
||||
{ id: 'llm-deepseek', config: {
|
||||
apiKeyEnv: 'DEEPSEEK_API_KEY', thinking: 'disabled', maxTokens: 1024,
|
||||
retryPolicy: { maxRetries: 0 },
|
||||
retryPolicy: { mode: 'normal', maxRetries: 0 } satisfies RetryPolicyConfig,
|
||||
models: [{ id: 'deepseek-flash', systemPromptUpdate: 'in-history', toolUpdate: 'addition-only' }],
|
||||
} },
|
||||
{ id: 'tools', config: { mode: 'native' } },
|
||||
@@ -101,13 +103,19 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('SDK native tool updates with rea
|
||||
const run = async (prompt: string) => {
|
||||
const result = await session.run(prompt)
|
||||
events.push(...result.events)
|
||||
const failures = result.events.filter(event => event.type === 'assistant/attempt').map(event => ({
|
||||
turn: event.data.turn,
|
||||
step: event.data.step,
|
||||
reason: lastAssistantStreamChunk(event.data.stream, 'finish')?.reason,
|
||||
}))
|
||||
expect(failures, `Provider request failures: ${JSON.stringify(failures)}`).toEqual([])
|
||||
return result.finalResponse
|
||||
}
|
||||
await run('Do not call tools. Reply READY.')
|
||||
expect(await run('Do not call tools. Reply READY.')).toContain('READY')
|
||||
// Unique user history makes hits on shared profile instructions insufficient.
|
||||
const records = Array.from({ length: 96 }, (_, index) => `record-${index}: ${randomUUID()}`).join('\n')
|
||||
await run(`Keep these reference records. Do not call tools. Reply READY.\n${records}`)
|
||||
await run('Keep the reference records. Do not call tools. Reply READY.')
|
||||
expect(await run(`Keep these reference records. Do not call tools. Reply READY.\n${records}`)).toContain('READY')
|
||||
expect(await run('Keep the reference records. Do not call tools. Reply READY.')).toContain('READY')
|
||||
expect(await run(`Use cache_tool_control with action add. After it returns, call ${sampleTool} exactly once and report the generated sample label. This is synthetic example data for this run. Call these separately in order.`)).toContain(sampleLabel)
|
||||
expectCalledBefore(await recordedCalls(callsPath), 'add', 'sample')
|
||||
expect(await run('Use cache_tool_control with action remove. Whether it removes the sample tool or reports that it is not registered, reply REMOVED and do not call the sample tool.')).toContain('REMOVED')
|
||||
@@ -115,7 +123,6 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('SDK native tool updates with rea
|
||||
expectCalledBefore(calls, 'sample', 'remove')
|
||||
|
||||
const requests = (await readFile(evidencePath, 'utf8')).trim().split('\n').map(line => JSON.parse(line) as ObservedRequest)
|
||||
expect(events.filter(event => event.type === 'assistant/attempt')).toHaveLength(0)
|
||||
expect(requests).toHaveLength(events.filter(event => event.type === 'assistant/message').length)
|
||||
const [initial, history, warm] = requests
|
||||
const addedIndex = requests.findIndex(request => request.stage === 'added')
|
||||
@@ -123,6 +130,7 @@ describe.skipIf(!process.env.DEEPSEEK_API_KEY)('SDK native tool updates with rea
|
||||
const added = requests[addedIndex]
|
||||
const removed = requests.find(request => request.stage === 'removed')
|
||||
if (!initial || !history || !warm || !before || !added || !removed) throw new Error('Missing cache transition requests')
|
||||
expect(initial.body).toMatchObject({ max_tokens: 1024, thinking: { type: 'disabled' } })
|
||||
const historyInput = totalInput(usageFor(history, events))
|
||||
const precedingInput = totalInput(usageFor(before, events))
|
||||
const cached = usageFor(added, events).cacheReadTokens ?? 0
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-desktop-host",
|
||||
"description": "Private Node-mode host process for the Electron desktop application",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-desktop",
|
||||
"description": "Electron desktop shell for a bundled dsh runtime and external plugins",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-plugin-market-generator",
|
||||
"description": "Reference generator of plugin market index files from a list of npm packages and Git repositories",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-web-frontend",
|
||||
"description": "Web application entry: vite build over the @deepseek-ai/dsh-client-web shell library; dist/ served by apps/cli's dsh web",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -22,7 +22,7 @@ const MODE = webSnapshotMode()
|
||||
|
||||
const TOKEN = 'dsh_bonus_notice_test'
|
||||
const ACCOUNT_ID = 'bonus-user'
|
||||
const ORDER_FIRST = '22222222-2222-4222-8222-222222222222'
|
||||
const ORDER_FIRST = 'bonus-notice-first'
|
||||
const ORDER_LATER = '33333333-3333-4333-8333-333333333333'
|
||||
const ORDER_EN = '44444444-4444-4444-8444-444444444444'
|
||||
const ORDER_RETRY = '55555555-5555-4555-8555-555555555555'
|
||||
@@ -80,17 +80,17 @@ async function mockPlatform() {
|
||||
let failSummary = false
|
||||
/** Reply held back while the test controls when a read can answer. */
|
||||
let heldReply: (() => void) | undefined
|
||||
const grant = (orderId: string, amount: string): void => {
|
||||
const grant = (orderId: string, amount: string, extraCopy = ''): void => {
|
||||
unnotified.unshift({
|
||||
orderId, amount,
|
||||
zh_CN: `已赠送您 ${amount} 元 DSH 体验赠金。`,
|
||||
en_US: `You received a CNY ${amount} DSH trial credit.`,
|
||||
zh_CN: `已赠送您 ${amount} 元 DSH 体验赠金。${extraCopy}`,
|
||||
en_US: `You received a CNY ${amount} DSH trial credit.${extraCopy}`,
|
||||
})
|
||||
}
|
||||
/** @param value - granted bonus. @param locale - request language. @returns its wire fields. */
|
||||
const wire = (value: Granted, locale: string | undefined): unknown => ({
|
||||
order_id: value.orderId, campaign: 'dsh_login_bonus', amount: value.amount, currency: 'CNY',
|
||||
granted_at: new Date().toISOString(), expires_at: expiresAt(),
|
||||
order_id: value.orderId, expires_at: value.orderId === ORDER_FIRST ? null : expiresAt(),
|
||||
...(value.orderId === ORDER_FIRST ? { title: '平台通知' } : {}),
|
||||
msg: locale === 'en_US' ? value.en_US : value.zh_CN,
|
||||
})
|
||||
const server: Server = createServer((req, res) => {
|
||||
@@ -182,7 +182,7 @@ async function mockPlatform() {
|
||||
|
||||
/** @param page - page under test. @returns every rendered bonus notice card. */
|
||||
function noticeCards(page: Page): Locator {
|
||||
return page.locator('aside').filter({ hasText: '赠金已到账' })
|
||||
return page.locator('aside[data-front]')
|
||||
}
|
||||
|
||||
/** @param card - a rendered notice card. @returns its non-empty visible lines joined for the golden. */
|
||||
@@ -579,6 +579,75 @@ describe.skipIf(MODE === 'record')('web e2e: bonus notice', () => {
|
||||
await expect.poll(() => platform.acks.filter(item => item.orderId === ORDER_WEB).length).toBe(1)
|
||||
observations.push(`web.notice=${webNotice} acks=1`)
|
||||
await webPage.close()
|
||||
platform.clearUnnotified()
|
||||
platform.grant('stack-third', '23.00')
|
||||
platform.grant('stack-second', '22.00', '\nMore details'.repeat(8))
|
||||
platform.grant('stack-first', '21.00')
|
||||
const ackStart = platform.acks.length
|
||||
const stackPage = await openDesktopPage('zh-CN')
|
||||
await stackPage.emulateMedia({ colorScheme: 'light' })
|
||||
await stackPage.goto(scaffold.authenticatedUrl, { waitUntil: 'load' })
|
||||
const cards = noticeCards(stackPage)
|
||||
await expect.poll(() => cards.count()).toBe(3)
|
||||
await expect.poll(() => platform.acks.length).toBe(ackStart + 1)
|
||||
expect(platform.acks.slice(ackStart).map(ack => ack.orderId)).toEqual(['stack-first'])
|
||||
expect(await stackPage.getByRole('status').count()).toBe(1)
|
||||
const second = cards.filter({ hasText: '22.00' })
|
||||
const secondNode = await second.elementHandle()
|
||||
const frontBox = await cards.first().boundingBox()
|
||||
const backBox = await second.boundingBox()
|
||||
expect(frontBox!.width).toBeCloseTo(280, 0)
|
||||
expect(backBox!.width).toBeCloseTo(272, 0)
|
||||
expect(backBox!.y).toBeCloseTo(frontBox!.y - 4, 0)
|
||||
const transition = await second.evaluate((element) => {
|
||||
const style = getComputedStyle(element)
|
||||
return `${style.transitionDuration} ${style.transitionTimingFunction}`
|
||||
})
|
||||
expect(transition).toBe('0.25s ease-out')
|
||||
observations.push(`stack.initial cards=3 acks=stack-first widths=280,272 offset=-4 transition=${transition}`)
|
||||
const artifactDir = fileURLToPath(new URL('../../../.artifacts', import.meta.url))
|
||||
await mkdir(artifactDir, { recursive: true })
|
||||
await stackPage.screenshot({ path: join(artifactDir, 'bonus-notice-stack-light.png') })
|
||||
await stackPage.emulateMedia({ colorScheme: 'dark' })
|
||||
await expect.poll(() => stackPage.locator('body').getAttribute('data-ds-dark-theme')).not.toBeNull()
|
||||
await stackPage.screenshot({ path: join(artifactDir, 'bonus-notice-stack-dark.png') })
|
||||
const promotion = await stackPage.evaluate(() => {
|
||||
const front = document.querySelector<HTMLElement>('aside[data-front="true"]')!
|
||||
const next = front.nextElementSibling as HTMLElement
|
||||
const before = next.getBoundingClientRect()
|
||||
front.querySelector('button')!.click()
|
||||
const animation = next.getAnimations()[0]!
|
||||
animation.pause()
|
||||
animation.currentTime = 0
|
||||
const start = next.getBoundingClientRect()
|
||||
animation.currentTime = 125
|
||||
const middle = next.getBoundingClientRect()
|
||||
animation.finish()
|
||||
const end = next.getBoundingClientRect()
|
||||
return { before: { y: before.y, height: before.height }, start: { y: start.y, height: start.height },
|
||||
middle: { y: middle.y, height: middle.height }, end: { y: end.y, height: end.height } }
|
||||
})
|
||||
expect(promotion.start.y).toBeCloseTo(promotion.before.y, 0)
|
||||
expect(promotion.start.height).toBeCloseTo(promotion.before.height, 0)
|
||||
expect(promotion.end.height).toBeGreaterThan(promotion.start.height + 100)
|
||||
expect(promotion.middle.height).toBeGreaterThan(promotion.start.height)
|
||||
expect(promotion.middle.height).toBeLessThan(promotion.end.height)
|
||||
expect(promotion.middle.y).toBeLessThan(promotion.start.y)
|
||||
expect(promotion.middle.y).toBeGreaterThan(promotion.end.y)
|
||||
await expect.poll(() => cards.count()).toBe(2)
|
||||
await expect.poll(async () => Math.round((await second.boundingBox())!.width)).toBe(280)
|
||||
expect(await second.evaluate((element, previous) => element === previous, secondNode)).toBe(true)
|
||||
expect(await second.getAttribute('data-front')).toBe('true')
|
||||
await expect.poll(() => platform.acks.length).toBe(ackStart + 2)
|
||||
expect(platform.acks.slice(ackStart).map(ack => ack.orderId)).toEqual(['stack-first', 'stack-second'])
|
||||
observations.push('stack.promoted cards=2 acks=stack-first,stack-second width=280 same-node=true')
|
||||
await second.getByRole('button', { name: '关闭', exact: true }).click()
|
||||
await expect.poll(() => platform.acks.length).toBe(ackStart + 3)
|
||||
expect(platform.acks.slice(ackStart).map(ack => ack.orderId)).toEqual(['stack-first', 'stack-second', 'stack-third'])
|
||||
await cards.filter({ hasText: '23.00' }).getByRole('button', { name: '关闭', exact: true }).click()
|
||||
await expect.poll(() => cards.count()).toBe(0)
|
||||
observations.push('stack.dismissed cards=0 acks=stack-first,stack-second,stack-third')
|
||||
await stackPage.close()
|
||||
|
||||
await compareOrRefreshGolden(join(SNAPSHOT_DIR, 'notice-flow.expected.md'), observations.join('\n'), MODE)
|
||||
for (const tripwire of tripwires) {
|
||||
|
||||
@@ -92,6 +92,70 @@ describe('web e2e: the composer model switch is the default for later sessions',
|
||||
await scaffold?.close()
|
||||
})
|
||||
|
||||
it('exposes inline model labels with exact routes throughout the composer picker', async () => {
|
||||
const trigger = page.getByRole('button', { name: /^选择模型/ })
|
||||
const label = '[data-provider-id][data-model-id]'
|
||||
const readLabels = (surface: Locator) => surface.locator(label).evaluateAll(nodes => nodes.map(node => ({
|
||||
provider: node.getAttribute('data-provider-id'), model: node.getAttribute('data-model-id'),
|
||||
name: node.textContent, slot: node.querySelector('[data-slot]')?.getAttribute('data-slot'),
|
||||
inline: node.tagName === 'SPAN' && node.querySelector('div') === null,
|
||||
})))
|
||||
const current = {
|
||||
provider: START_ROUTE, model: START_MODEL, name: 'Origin Large',
|
||||
slot: 'conversation.input.model.label', inline: true,
|
||||
}
|
||||
await expect.poll(() => readLabels(trigger)).toEqual([current])
|
||||
try {
|
||||
await trigger.click()
|
||||
const cell = page.getByRole('menuitem', { name: /^模型/ })
|
||||
expect(await readLabels(cell)).toEqual([current])
|
||||
await cell.click()
|
||||
const menu = page.getByRole('menu', { name: '模型', exact: true })
|
||||
await compareOrRefreshGolden(
|
||||
fileURLToPath(new URL('./expected/default-model/model-labels.expected.md', import.meta.url)),
|
||||
JSON.stringify(await readLabels(menu), null, 2),
|
||||
webSnapshotMode(),
|
||||
)
|
||||
} finally {
|
||||
await page.keyboard.press('Escape')
|
||||
await page.keyboard.press('Escape')
|
||||
}
|
||||
})
|
||||
|
||||
it.each(['root', 'model'])('reanchors the %s menu when a label grows and shrinks without a window resize', async (pane) => {
|
||||
const viewport = page.viewportSize()!
|
||||
const trigger = page.getByRole('button', { name: /^选择模型/ })
|
||||
try {
|
||||
await page.setViewportSize({ width: 390, height: 844 })
|
||||
await trigger.click()
|
||||
if (pane === 'model') await page.getByRole('menuitem', { name: /^模型/ }).click()
|
||||
const surface = page.getByRole(pane === 'model' ? 'group' : 'menu', { name: '模型与推理等级', exact: true })
|
||||
const label = surface.locator('[data-provider-id="origin-gateway"][data-model-id="origin-large"]')
|
||||
await label.waitFor()
|
||||
const original = await surface.boundingBox()
|
||||
expect(original).not.toBeNull()
|
||||
// A Slot descendant can resize independently of ModelSelect's props and state.
|
||||
await label.evaluate((node) => {
|
||||
const badge = node.ownerDocument.createElement('span')
|
||||
badge.dataset.modelLabelResizeProbe = ''
|
||||
badge.textContent = ' — Provider identification badge with a long channel name'
|
||||
node.appendChild(badge)
|
||||
})
|
||||
await expect.poll(async () => (await surface.boundingBox())!.width).toBeGreaterThan(original!.width + 50)
|
||||
await expect.poll(async () => {
|
||||
const box = (await surface.boundingBox())!
|
||||
return box.x >= 12 && box.x + box.width <= 378
|
||||
}).toBe(true)
|
||||
await label.locator('[data-model-label-resize-probe]').evaluate((node) => { node.remove() })
|
||||
await expect.poll(async () => (await surface.boundingBox())!.width).toBeCloseTo(original!.width)
|
||||
await expect.poll(async () => (await surface.boundingBox())!.x).toBeCloseTo(original!.x)
|
||||
} finally {
|
||||
await page.keyboard.press('Escape')
|
||||
await page.keyboard.press('Escape')
|
||||
await page.setViewportSize(viewport)
|
||||
}
|
||||
})
|
||||
|
||||
it('keeps command popup search borders transparent in both palettes', async () => {
|
||||
const composer = page.locator('[data-composer-input]').first()
|
||||
await page.getByRole('button', { name: '添加文件或调用指令', exact: true }).click()
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
startup.held cards=0 acks=0
|
||||
startup.notice=赠金已到账 / 已赠送您 5.00 元 DSH 体验赠金。
|
||||
startup.ack orders=22222222-2222-4222-8222-222222222222
|
||||
startup.notice=平台通知 / 已赠送您 5.00 元 DSH 体验赠金。
|
||||
startup.ack orders=bonus-notice-first
|
||||
startup.get locale=zh_CN query=
|
||||
startup.ack method=POST path=/api/v0/users/ack_bonus_notified locale=zh_CN order_id=22222222-2222-4222-8222-222222222222 body="{\"order_id\":\"22222222-2222-4222-8222-222222222222\"}"
|
||||
startup.ack method=POST path=/api/v0/users/ack_bonus_notified locale=zh_CN order_id=bonus-notice-first body="{\"order_id\":\"bonus-notice-first\"}"
|
||||
open.held cards=0 acks=1 gets=1
|
||||
open.shown notice=赠金已到账 / 已赠送您 8.00 元 DSH 体验赠金。
|
||||
open.shown ack orders=22222222-2222-4222-8222-222222222222,33333333-3333-4333-8333-333333333333
|
||||
open.shown ack orders=bonus-notice-first,33333333-3333-4333-8333-333333333333
|
||||
open.shown painted-under-settings=true cards=1 acks=2
|
||||
open.get locale=zh_CN query= served=true gets=1
|
||||
open.balance bonus-row=true amount=true dated=false
|
||||
@@ -31,3 +31,6 @@ failed.reached usages=2 gets=1 summaries=1
|
||||
en.notice=Bonus credited / You received a CNY 9.00 DSH trial credit.
|
||||
en.get locale=en_US query=
|
||||
web.notice=赠金已到账 / 已赠送您 4.00 元 DSH 体验赠金。 acks=1
|
||||
stack.initial cards=3 acks=stack-first widths=280,272 offset=-4 transition=0.25s ease-out
|
||||
stack.promoted cards=2 acks=stack-first,stack-second width=280 same-node=true
|
||||
stack.dismissed cards=0 acks=stack-first,stack-second,stack-third
|
||||
@@ -30,7 +30,7 @@
|
||||
- text: deepseek-flash
|
||||
- textbox "显示名称 1":
|
||||
- /placeholder: 显示名称
|
||||
- text: DeepSeek-V4.1-Flash
|
||||
- text: DeepSeek-V4.1-Flash-1017
|
||||
- button "模型选项 1"
|
||||
- button "删除模型 1"
|
||||
- textbox "模型 ID 2":
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
[
|
||||
{
|
||||
"provider": "deepseek-official",
|
||||
"model": "deepseek-v4-flash",
|
||||
"name": "DeepSeek-V4-Flash",
|
||||
"slot": "conversation.input.model.label",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"provider": "deepseek-official",
|
||||
"model": "deepseek-v4-flash-vision-exp",
|
||||
"name": "DeepSeek-V4-Flash-Vision-Exp",
|
||||
"slot": "conversation.input.model.label",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"provider": "origin-gateway",
|
||||
"model": "origin-large",
|
||||
"name": "Origin Large",
|
||||
"slot": "conversation.input.model.label",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"provider": "acme-gateway",
|
||||
"model": "acme-large",
|
||||
"name": "Acme Large",
|
||||
"slot": "conversation.input.model.label",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"provider": "acme-gateway",
|
||||
"model": "acme-small",
|
||||
"name": "Acme Small",
|
||||
"slot": "conversation.input.model.label",
|
||||
"inline": true
|
||||
}
|
||||
]
|
||||
@@ -30,7 +30,7 @@
|
||||
- text: deepseek-flash
|
||||
- textbox "显示名称 1":
|
||||
- /placeholder: 显示名称
|
||||
- text: DeepSeek-V4.1-Flash
|
||||
- text: DeepSeek-V4.1-Flash-1017
|
||||
- button "模型选项 1" [expanded]
|
||||
- button "删除模型 1"
|
||||
- text: 上下文窗口
|
||||
|
||||
@@ -213,7 +213,7 @@ describe.skipIf(MODE === 'record')('web e2e: first-run DeepSeek credential setup
|
||||
await deepSeek.locator('xpath=ancestor::li').getByRole('button', { name: '编辑' }).click()
|
||||
await settings.getByText('自定义设置').click()
|
||||
expect(await settings.getByLabel('模型 ID 1').inputValue()).toBe('deepseek-flash')
|
||||
expect(await settings.getByLabel('显示名称 1').inputValue()).toBe('DeepSeek-V4.1-Flash')
|
||||
expect(await settings.getByLabel('显示名称 1').inputValue()).toBe('DeepSeek-V4.1-Flash-1017')
|
||||
expect(await settings.getByLabel('模型 ID 2').inputValue()).toBe('deepseek-v4-pro')
|
||||
expect(await settings.getByRole('button', { name: /删除模型/ }).count()).toBe(2)
|
||||
await settings.getByRole('button', { name: '模型选项 1' }).click()
|
||||
|
||||
@@ -375,6 +375,24 @@ describe('web e2e: shipped right Sidebar', () => {
|
||||
expect(answered).toBe(true)
|
||||
})
|
||||
|
||||
it('keeps the frame unscrolled when PageUp moves the composer caret beside the collapsed panel', async () => {
|
||||
onTestFailed(() => saveFailureShot(page, 'web-e2e-sidebar-right-pageup'))
|
||||
const frame = page.locator('[class*="frame"]').first()
|
||||
const composer = page.locator('textarea, [contenteditable="true"]').first()
|
||||
// The expand button exists only while the panel is collapsed, when its
|
||||
// docked hosts sit translated past the frame's right edge.
|
||||
await expandOf(page).waitFor({ timeout: 15_000 })
|
||||
await composer.click()
|
||||
await composer.pressSequentially('caret')
|
||||
// Outside macOS, PageUp moves the caret and reveals it against the start
|
||||
// edge of every scrollable ancestor, `overflow: hidden` ones included.
|
||||
await page.keyboard.press('PageUp')
|
||||
expect(await frame.evaluate(node => node.scrollLeft)).toBe(0)
|
||||
await page.keyboard.press('ControlOrMeta+a')
|
||||
await page.keyboard.press('Backspace')
|
||||
await expect.poll(async () => (await composer.innerText()).trim()).toBe('')
|
||||
})
|
||||
|
||||
it('starts collapsed behind a header button and squeezes the conversation when opened', async () => {
|
||||
onTestFailed(() => saveFailureShot(page, 'web-e2e-sidebar-right'))
|
||||
const frame = page.locator('[class*="frame"]').first()
|
||||
|
||||
@@ -41,8 +41,8 @@ This matrix shows which packages dispatch each harness-owned event and which pac
|
||||
| `cordis/request-run-resolved` | `emit` | [`packages/extensions/cordis-host-runner/src/types.ts:377`](../packages/extensions/cordis-host-runner/src/types.ts) | [`cordis-host-runner`](../packages/extensions/cordis-host-runner) (`emit`) | `remotes` |
|
||||
| `credentials/record-updated` | `emit` | [`packages/credentials/credentials/src/types.ts:99`](../packages/credentials/credentials/src/types.ts) | [`credentials`](../packages/credentials/credentials) (`events.dispatch`) | [`authorization`](../packages/credentials/authorization), [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform), `remotes` |
|
||||
| `credentials/reference-updated` | `emit` | [`packages/credentials/credentials/src/types.ts:87`](../packages/credentials/credentials/src/types.ts) | [`credentials`](../packages/credentials/credentials) (`events.dispatch`) | `remotes` |
|
||||
| `deepseek-account/model-sign-in-required` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:95`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account`](../packages/credentials/deepseek-account) (`emit`) | `remotes` |
|
||||
| `deepseek-account/session-expired` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:91`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform) (`emit`) | `account-controller`, `remotes` |
|
||||
| `deepseek-account/model-sign-in-required` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:97`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account`](../packages/credentials/deepseek-account) (`emit`) | `remotes` |
|
||||
| `deepseek-account/session-expired` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:93`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform) (`emit`) | `account-controller`, `remotes` |
|
||||
| `deepseek-account/signed-out` | `emit` | [`packages/credentials/deepseek-account/src/index.ts:12`](../packages/credentials/deepseek-account/src/index.ts) | [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform) (`emit`) | [`deepseek-account`](../packages/credentials/deepseek-account) |
|
||||
| `domain/changed` | `emit` | [`packages/storage/storage-domain/src/events.ts:46`](../packages/storage/storage-domain/src/events.ts) | [`storage-domain`](../packages/storage/storage-domain) (`emit`) | `workspace-controller` |
|
||||
| `feedback/committed` | `parallel` | [`packages/feedback/message-feedback/src/index.ts:58`](../packages/feedback/message-feedback/src/index.ts) | [`message-feedback`](../packages/feedback/message-feedback) (`parallel`) | [`session-telemetry-otel`](../packages/session/session-telemetry-otel) |
|
||||
|
||||
@@ -43,8 +43,8 @@
|
||||
| `cordis/request-run-resolved` | `emit` | [`packages/extensions/cordis-host-runner/src/types.ts:377`](../packages/extensions/cordis-host-runner/src/types.ts) | [`cordis-host-runner`](../packages/extensions/cordis-host-runner) (`emit`) | `remotes` |
|
||||
| `credentials/record-updated` | `emit` | [`packages/credentials/credentials/src/types.ts:99`](../packages/credentials/credentials/src/types.ts) | [`credentials`](../packages/credentials/credentials) (`events.dispatch`) | [`authorization`](../packages/credentials/authorization), [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform), `remotes` |
|
||||
| `credentials/reference-updated` | `emit` | [`packages/credentials/credentials/src/types.ts:87`](../packages/credentials/credentials/src/types.ts) | [`credentials`](../packages/credentials/credentials) (`events.dispatch`) | `remotes` |
|
||||
| `deepseek-account/model-sign-in-required` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:95`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account`](../packages/credentials/deepseek-account) (`emit`) | `remotes` |
|
||||
| `deepseek-account/session-expired` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:91`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform) (`emit`) | `account-controller`, `remotes` |
|
||||
| `deepseek-account/model-sign-in-required` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:97`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account`](../packages/credentials/deepseek-account) (`emit`) | `remotes` |
|
||||
| `deepseek-account/session-expired` | `emit` | [`packages/credentials/deepseek-account/src/types.ts:93`](../packages/credentials/deepseek-account/src/types.ts) | [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform) (`emit`) | `account-controller`, `remotes` |
|
||||
| `deepseek-account/signed-out` | `emit` | [`packages/credentials/deepseek-account/src/index.ts:12`](../packages/credentials/deepseek-account/src/index.ts) | [`deepseek-account-platform`](../packages/credentials/deepseek-account-platform) (`emit`) | [`deepseek-account`](../packages/credentials/deepseek-account) |
|
||||
| `domain/changed` | `emit` | [`packages/storage/storage-domain/src/events.ts:46`](../packages/storage/storage-domain/src/events.ts) | [`storage-domain`](../packages/storage/storage-domain) (`emit`) | `workspace-controller` |
|
||||
| `feedback/committed` | `parallel` | [`packages/feedback/message-feedback/src/index.ts:58`](../packages/feedback/message-feedback/src/index.ts) | [`message-feedback`](../packages/feedback/message-feedback) (`parallel`) | [`session-telemetry-otel`](../packages/session/session-telemetry-otel) |
|
||||
|
||||
@@ -657,6 +657,7 @@ flowchart TD
|
||||
pkg_deepseek_account --> pkg_agent
|
||||
pkg_deepseek_account --> pkg_brand
|
||||
pkg_deepseek_account --> pkg_llm
|
||||
pkg_deepseek_account --> pkg_util_values
|
||||
pkg_commands --> pkg_agent
|
||||
pkg_commands --> pkg_attachment
|
||||
pkg_commands --> pkg_brand
|
||||
@@ -1633,7 +1634,7 @@ flowchart TD
|
||||
| [`harness-dev-context`](../packages/context/harness-dev-context) | `context` | [`agent`](../packages/core/agent), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| [`time-context`](../packages/context/time-context) | `context` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection) |
|
||||
| [`tmux-context`](../packages/context/tmux-context) | `context` | [`agent`](../packages/core/agent), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`shell`](../packages/shell/shell) |
|
||||
| [`deepseek-account`](../packages/credentials/deepseek-account) | `credentials` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`llm`](../packages/llm/llm) |
|
||||
| [`deepseek-account`](../packages/credentials/deepseek-account) | `credentials` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`llm`](../packages/llm/llm), [`util-values`](../packages/util/values) |
|
||||
| [`commands`](../packages/interaction/commands) | `interaction` | [`agent`](../packages/core/agent), [`attachment`](../packages/attachment/attachment), [`brand`](../packages/util/brand), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`typert-protocol`](../packages/typert/protocol) |
|
||||
| [`user-approval`](../packages/interaction/user-approval) | `interaction` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| [`user-questions`](../packages/interaction/user-questions) | `interaction` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`typert-protocol`](../packages/typert/protocol) |
|
||||
|
||||
@@ -659,6 +659,7 @@ flowchart TD
|
||||
pkg_deepseek_account --> pkg_agent
|
||||
pkg_deepseek_account --> pkg_brand
|
||||
pkg_deepseek_account --> pkg_llm
|
||||
pkg_deepseek_account --> pkg_util_values
|
||||
pkg_commands --> pkg_agent
|
||||
pkg_commands --> pkg_attachment
|
||||
pkg_commands --> pkg_brand
|
||||
@@ -1635,7 +1636,7 @@ flowchart TD
|
||||
| [`harness-dev-context`](../packages/context/harness-dev-context) | `context` | [`agent`](../packages/core/agent), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| [`time-context`](../packages/context/time-context) | `context` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection) |
|
||||
| [`tmux-context`](../packages/context/tmux-context) | `context` | [`agent`](../packages/core/agent), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`shell`](../packages/shell/shell) |
|
||||
| [`deepseek-account`](../packages/credentials/deepseek-account) | `credentials` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`llm`](../packages/llm/llm) |
|
||||
| [`deepseek-account`](../packages/credentials/deepseek-account) | `credentials` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`llm`](../packages/llm/llm), [`util-values`](../packages/util/values) |
|
||||
| [`commands`](../packages/interaction/commands) | `interaction` | [`agent`](../packages/core/agent), [`attachment`](../packages/attachment/attachment), [`brand`](../packages/util/brand), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`typert-protocol`](../packages/typert/protocol) |
|
||||
| [`user-approval`](../packages/interaction/user-approval) | `interaction` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt) |
|
||||
| [`user-questions`](../packages/interaction/user-questions) | `interaction` | [`agent`](../packages/core/agent), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`session-projection`](../packages/session/session-projection), [`typert-protocol`](../packages/typert/protocol) |
|
||||
|
||||
@@ -161,6 +161,7 @@ Factory: conversation.content [ConversationContent]
|
||||
│ ├─ conversation.input.permission
|
||||
│ ├─ conversation.input.plan
|
||||
│ ├─ conversation.input.model
|
||||
│ │ └─ conversation.input.model.label
|
||||
│ ├─ conversation.input.overlay
|
||||
│ ├─ conversation.composer.dock
|
||||
│ ├─ conversation.input.left
|
||||
|
||||
@@ -163,6 +163,7 @@ Factory: conversation.content [ConversationContent]
|
||||
│ ├─ conversation.input.permission
|
||||
│ ├─ conversation.input.plan
|
||||
│ ├─ conversation.input.model
|
||||
│ │ └─ conversation.input.model.label
|
||||
│ ├─ conversation.input.overlay
|
||||
│ ├─ conversation.composer.dock
|
||||
│ ├─ conversation.input.left
|
||||
|
||||
@@ -469,6 +469,14 @@ nameOf(agent: Agent): string
|
||||
*/
|
||||
resolveName(caller: Agent, name: string, signal?: AbortSignal): Promise<SessionId>
|
||||
|
||||
/**
|
||||
* Resolve the root shared by an Agent and its teammates.
|
||||
* @param caller - exact live Agent whose subagent ancestry selects the tree.
|
||||
* @returns the live root; ordinary Session forks lead independent trees.
|
||||
* @throws when the caller or its live ancestry is unavailable.
|
||||
*/
|
||||
rootOf(caller: Agent): Agent
|
||||
|
||||
/**
|
||||
* Join progressing descendants without cancelling them. Idle descendants whose
|
||||
* inboxes require a later wake stay resident and do not delay host completion.
|
||||
@@ -478,18 +486,17 @@ resolveName(caller: Agent, name: string, signal?: AbortSignal): Promise<SessionI
|
||||
async waitForChildren(parent: Agent): Promise<boolean>
|
||||
|
||||
/**
|
||||
* Steer one model-authored message to the sender's direct parent, direct
|
||||
* continuable child, or continuable sibling under their shared live parent. A running target admits it at the nearest step boundary;
|
||||
* an idle target starts a turn, and an absent direct child cold-resumes from
|
||||
* persistence. The service derives durable sender attribution from the exact
|
||||
* live sender. Caller cancellation stops only pre-acceptance work.
|
||||
* @param sender - exact live Agent authorizing and originating the message.
|
||||
* @param targetId - durable direct-parent, direct-child, or sibling session id.
|
||||
* Steer one model-authored message to another member of the same subagent tree.
|
||||
* A running target receives it at its next step; an idle target starts a turn.
|
||||
* Cold targets and their continuable ancestors resume under their recorded
|
||||
* parents. Sender identity is rechecked before inbox acceptance; cancellation
|
||||
* stops only pre-acceptance work and never retracts an accepted message.
|
||||
* @param sender - exact live root or resident continuable Agent originating the message.
|
||||
* @param targetId - another root or continuable member's durable Session id.
|
||||
* @param content - model-authored content to deliver.
|
||||
* @param options - caller cancellation before inbox acceptance.
|
||||
* @returns the accepted message's inbox id.
|
||||
* @throws when continuation services are unavailable, adjacency is rejected,
|
||||
* or the message was not admitted.
|
||||
* @throws when the target is outside the tree, cannot resume, or rejects input.
|
||||
*/
|
||||
async sendMessage( sender: Agent, targetId: SessionId, content: ContentBlock[], options: SubagentSendMessageOptions, ): Promise<MessageId>
|
||||
|
||||
|
||||
@@ -471,6 +471,14 @@ nameOf(agent: Agent): string
|
||||
*/
|
||||
resolveName(caller: Agent, name: string, signal?: AbortSignal): Promise<SessionId>
|
||||
|
||||
/**
|
||||
* Resolve the root shared by an Agent and its teammates.
|
||||
* @param caller - exact live Agent whose subagent ancestry selects the tree.
|
||||
* @returns the live root; ordinary Session forks lead independent trees.
|
||||
* @throws when the caller or its live ancestry is unavailable.
|
||||
*/
|
||||
rootOf(caller: Agent): Agent
|
||||
|
||||
/**
|
||||
* Join progressing descendants without cancelling them. Idle descendants whose
|
||||
* inboxes require a later wake stay resident and do not delay host completion.
|
||||
@@ -480,18 +488,17 @@ resolveName(caller: Agent, name: string, signal?: AbortSignal): Promise<SessionI
|
||||
async waitForChildren(parent: Agent): Promise<boolean>
|
||||
|
||||
/**
|
||||
* Steer one model-authored message to the sender's direct parent, direct
|
||||
* continuable child, or continuable sibling under their shared live parent. A running target admits it at the nearest step boundary;
|
||||
* an idle target starts a turn, and an absent direct child cold-resumes from
|
||||
* persistence. The service derives durable sender attribution from the exact
|
||||
* live sender. Caller cancellation stops only pre-acceptance work.
|
||||
* @param sender - exact live Agent authorizing and originating the message.
|
||||
* @param targetId - durable direct-parent, direct-child, or sibling session id.
|
||||
* Steer one model-authored message to another member of the same subagent tree.
|
||||
* A running target receives it at its next step; an idle target starts a turn.
|
||||
* Cold targets and their continuable ancestors resume under their recorded
|
||||
* parents. Sender identity is rechecked before inbox acceptance; cancellation
|
||||
* stops only pre-acceptance work and never retracts an accepted message.
|
||||
* @param sender - exact live root or resident continuable Agent originating the message.
|
||||
* @param targetId - another root or continuable member's durable Session id.
|
||||
* @param content - model-authored content to deliver.
|
||||
* @param options - caller cancellation before inbox acceptance.
|
||||
* @returns the accepted message's inbox id.
|
||||
* @throws when continuation services are unavailable, adjacency is rejected,
|
||||
* or the message was not admitted.
|
||||
* @throws when the target is outside the tree, cannot resume, or rejects input.
|
||||
*/
|
||||
async sendMessage( sender: Agent, targetId: SessionId, content: ContentBlock[], options: SubagentSendMessageOptions, ): Promise<MessageId>
|
||||
|
||||
|
||||
@@ -66,8 +66,8 @@
|
||||
en: 76fbbf0fe38aef10
|
||||
zh: 76fbbf0fe38aef10
|
||||
/tool-schema-catalog/deepseek-ai-dsh-tools/run-code:
|
||||
en: d03bca78d96757a7
|
||||
zh: 0e7cd389c38e2d9f
|
||||
en: a2368a9d8136276e
|
||||
zh: d1a4918fc45a7c87
|
||||
/tool-schema-catalog/deepseek-ai-dsh-plan-mode:
|
||||
en: b500b530845e26a9
|
||||
zh: b500b530845e26a9
|
||||
@@ -243,8 +243,8 @@
|
||||
en: 9190a32df5e10ddd
|
||||
zh: 6ece9cbd62eb4d8e
|
||||
/tool-schema-catalog/deepseek-ai-dsh-tool-subagent-control/list-agents:
|
||||
en: 6caa1abcb5ac1aaf
|
||||
zh: f99f93111177da5f
|
||||
en: 40043afff6ae00c7
|
||||
zh: 004562c1ea21acdc
|
||||
/tool-schema-catalog/deepseek-ai-dsh-tool-subagent-control/send-message:
|
||||
en: 69c1c0a80c24e3a4
|
||||
zh: 8d3e8b8b1137e5c5
|
||||
|
||||
@@ -576,20 +576,20 @@ ask_user_question keeps the original blocking behavior by default; set `mode: ti
|
||||
|
||||
### `run_code`
|
||||
|
||||
Execute a TypeScript program against the available tools. Takes two required arguments: `description`, a short summary of what the program does, and `code`, the program to execute. Call tools as `await tools.name(args)` per the declarations in the system prompt. Curate the program output. Image-bearing subtool results are attached after the run.
|
||||
Execute a TypeScript program against the available tools. Takes two required arguments: `code`, the program to execute, and `description`, a short summary of what the program does. Call tools as `await tools.name(args)` per the declarations in the system prompt. Curate the program output. Image-bearing subtool results are attached after the run.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Clear, concise description of what this program does in active voice, 5-10 words (shown in the UI). Provide `description` before `code` in the arguments. Examples: \"Count TODO markers across packages\"; \"Read failing test and its fixture\"; \"Rename config key in every cordis.yml\"."
|
||||
},
|
||||
"code": {
|
||||
"type": "string",
|
||||
"description": "The TypeScript program to execute, following this tool's execution instructions."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Clear, concise description of what this program does in active voice, 5-10 words (shown in the UI). Examples: \"Count TODO markers across packages\"; \"Read failing test and its fixture\"; \"Rename config key in every cordis.yml\"."
|
||||
},
|
||||
"timeoutMs": {
|
||||
"type": "number",
|
||||
"description": "Positive elapsed-time budget in milliseconds, capped by the deployment maximum."
|
||||
@@ -608,8 +608,8 @@ Execute a TypeScript program against the available tools. Takes two required arg
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"description",
|
||||
"code"
|
||||
"code",
|
||||
"description"
|
||||
]
|
||||
}
|
||||
```
|
||||
@@ -2152,7 +2152,7 @@ Source: [`packages/subagent/tool-subagent-control/src/index.ts`](../packages/sub
|
||||
|
||||
### `list_agents`
|
||||
|
||||
List all your reachable continuable descendants and, when you are a continuable subagent, your parent and continuable siblings. Rows carry names, descriptions, and status; descendant rows also carry parent names and depth. You can message your parent, continuable siblings, and direct children. Deeper descendants accept only interrupt_agent. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.
|
||||
List your entire Team: the root agent and all reachable continuable descendants, including yourself. Rows carry names, descriptions, and status; descendant rows carry parent names and depth from the root. You can message any other Team member whose branch supports continuation. You can interrupt only your own descendants. running means it is working; inactive means it is not currently working. You will be notified when a direct child finishes; there is no need to keep checking its status. Use send_message to continue the conversation.
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -2173,7 +2173,7 @@ Send a message to an agent. A working agent receives it at its next step; an idl
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child."
|
||||
"description": "The name of another member of your Team, as shown by list_agents."
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
|
||||
@@ -580,20 +580,20 @@ ask_user_question 默认保持原有阻塞行为;设置 `mode: timed` 后才
|
||||
|
||||
### `run_code`
|
||||
|
||||
针对可用工具执行 TypeScript 程序。接受两个必填参数:`description`,简要说明该程序做什么;以及 `code`,要执行的程序。请根据系统提示词中的声明,以 `await tools.name(args)` 形式调用工具。请筛选程序输出。含图片的子工具结果会在运行结束后附加。
|
||||
针对可用工具执行 TypeScript 程序。接受两个必填参数:`code`,要执行的程序;以及 `description`,简要说明该程序做什么。请根据系统提示词中的声明,以 `await tools.name(args)` 形式调用工具。请筛选程序输出。含图片的子工具结果会在运行结束后附加。
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Clear, concise description of what this program does in active voice, 5-10 words (shown in the UI). Provide `description` before `code` in the arguments. Examples: \"Count TODO markers across packages\"; \"Read failing test and its fixture\"; \"Rename config key in every cordis.yml\"."
|
||||
},
|
||||
"code": {
|
||||
"type": "string",
|
||||
"description": "The TypeScript program to execute, following this tool's execution instructions."
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
"description": "Clear, concise description of what this program does in active voice, 5-10 words (shown in the UI). Examples: \"Count TODO markers across packages\"; \"Read failing test and its fixture\"; \"Rename config key in every cordis.yml\"."
|
||||
},
|
||||
"timeoutMs": {
|
||||
"type": "number",
|
||||
"description": "Positive elapsed-time budget in milliseconds, capped by the deployment maximum."
|
||||
@@ -612,8 +612,8 @@ ask_user_question 默认保持原有阻塞行为;设置 `mode: timed` 后才
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"description",
|
||||
"code"
|
||||
"code",
|
||||
"description"
|
||||
]
|
||||
}
|
||||
```
|
||||
@@ -2158,7 +2158,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,
|
||||
|
||||
### `list_agents`
|
||||
|
||||
列出全部可达的可继续后代;如果调用方是可继续子代理,还列出父代理和可继续同级。行包含名字、描述和状态;后代行还包含父级名字和深度。可以向父代理、可继续同级和直接子级发送消息,更深后代只接受 interrupt_agent。running 表示正在工作;inactive 表示当前没有工作。直属子代理结束时会收到通知,无需反复查询其状态。使用 send_message 继续对话。
|
||||
列出整个 Team:根代理及所有可达的可继续后代,包括调用方。行包含名字、描述和状态;后代行包含父级名字和相对根的深度。可以向分支支持继续执行的其他 Team 成员发送消息,只能中断自己的后代。running 表示正在工作;inactive 表示当前没有工作。直属子代理结束时会收到通知,无需反复查询其状态。使用 send_message 继续对话。
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -2179,7 +2179,7 @@ lsp 工具将提供方选择和语言服务器子进程置于 ctx.lsp 之后,
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The name of your direct continuable child, or your direct parent or continuable sibling when you are a resident continuable child."
|
||||
"description": "The name of another member of your Team, as shown by list_agents."
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# Bilingual-pair consistency record for guide.md (docs/i18n/README.md): per heading
|
||||
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
||||
# After editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/upgrade-guide/v0.2.1-alpha.4/account-notification-fields/guide.md
|
||||
/:
|
||||
en: 9b6666d42852a11b
|
||||
zh: b14c7d8590c54ba5
|
||||
/update-account-notification-consumers:
|
||||
en: 586faed9ab20343f
|
||||
zh: fb3cc099b39b0386
|
||||
/update-account-notification-consumers/change:
|
||||
en: 20cc8ba42b771270
|
||||
zh: da0ca5f650c74117
|
||||
/update-account-notification-consumers/migration:
|
||||
en: e9fe0c1ebba8acfc
|
||||
zh: 05b94685fb4c5ead
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
kind: upgrade-guide
|
||||
description: "AccountBonusNotification exposes unvalidated optional metadata and permits notices without an expiry."
|
||||
---
|
||||
|
||||
# Update account notification consumers
|
||||
|
||||
English | [中文](guide.zh.md)
|
||||
|
||||
## Change
|
||||
|
||||
The public `AccountBonusNotification` returned by `DeepSeekAccount.getUnnotifiedBonuses()` and `account/getUnnotifiedBonuses` preserves `campaign`, `amount`, `currency`, and `grantedAt` as optional, unvalidated metadata typed as `JsonValue`. Notifications retain `orderId`, `message`, and `expiresAt`, and add an optional `title`. An empty `expiresAt` means the notification never expires. `orderId` accepts arbitrary strings rather than requiring UUIDs.
|
||||
|
||||
## Migration
|
||||
|
||||
1. Narrow the optional metadata values before using them; their presence and format are no longer guaranteed. Display `message` and use the client's default title when `title` is absent.
|
||||
2. Treat an empty `expiresAt` as no expiry before parsing timestamps. Keep `orderId` unchanged when acknowledging a notification.
|
||||
3. Update provider fixtures to use the current fields. Confirm that a notification with a non-UUID ID and empty expiry displays and can be acknowledged.
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
kind: upgrade-guide
|
||||
description: "AccountBonusNotification 提供未经校验的可选元数据,并允许通知永不过期。"
|
||||
---
|
||||
|
||||
# 更新账号通知使用方
|
||||
|
||||
[English](guide.md) | 中文
|
||||
|
||||
## 变更
|
||||
|
||||
`DeepSeekAccount.getUnnotifiedBonuses()` 和 `account/getUnnotifiedBonuses` 返回的公开类型 `AccountBonusNotification` 保留 `campaign`、`amount`、`currency` 和 `grantedAt`,作为类型为 `JsonValue` 的可选元数据,不做校验。通知保留 `orderId`、`message` 和 `expiresAt`,并新增可选的 `title`。空字符串 `expiresAt` 表示通知永不过期。`orderId` 接受任意字符串,不再要求 UUID 格式。
|
||||
|
||||
## 迁移
|
||||
|
||||
1. 使用可选元数据前先收窄类型;这些值不再保证存在或符合原有格式。展示 `message`,在 `title` 缺省时使用客户端默认标题。
|
||||
2. 解析时间戳前,将空字符串 `expiresAt` 视为永不过期。确认通知时原样传递 `orderId`。
|
||||
3. 更新提供者测试夹具以使用当前字段。确认非 UUID 标识、空过期时间的通知可以展示并确认。
|
||||
+7
-7
@@ -1,16 +1,16 @@
|
||||
# Bilingual-pair consistency record for guide.md (docs/i18n/README.md): per heading
|
||||
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
|
||||
# After editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write docs/upgrade-guide/v0.2.1-alpha.4/agent-team-subagents/guide.md
|
||||
# pnpm run verify-translation-pairing --write docs/upgrade-guide/v0.2.1-rc.1/agent-team-subagents/guide.md
|
||||
/:
|
||||
en: 9a266a4f19673f89
|
||||
zh: 0b716c060f3e568d
|
||||
/agent-teams-uses-subagents-and-unique-agent-names:
|
||||
en: e2fd55138832d6e1
|
||||
zh: 5fc33b77673c6ea0
|
||||
en: 563e943c3c4447d5
|
||||
zh: 254c0e49d2f2a302
|
||||
/agent-teams-uses-subagents-and-unique-agent-names/change:
|
||||
en: 12a436db46a7ecf2
|
||||
zh: 8cdb01c672e5a89a
|
||||
en: 5bb67f34d859d1fc
|
||||
zh: d31987a7d12e4103
|
||||
/agent-teams-uses-subagents-and-unique-agent-names/migration:
|
||||
en: 4999c1a628cfb22e
|
||||
zh: 388d8df7d9fc45c3
|
||||
en: 84fd9ee43c23be82
|
||||
zh: c31fa1844e79cfab
|
||||
+3
-3
@@ -11,8 +11,8 @@ English | [中文](guide.zh.md)
|
||||
|
||||
The experimental Agent Teams plugins share agent creation, discovery, messaging, and interruption with subagents. Start a teammate with `subagent` or `subagent_fork`, give it a tree-wide unique `name`, describe its responsibility with `description`, and use its returned name for messages and task assignment. Descriptions may repeat and never identify a recipient.
|
||||
|
||||
- `spawn_teammate` and the Team-scoped `send_message`, `list_agents`, and `interrupt_agent` are removed. The standard control tools use `name`, not `agent_id` or `target`. Continuable children of one live parent can message each other by name.
|
||||
- `list_agents` takes no arguments and always lists all reachable continuable descendants, plus a continuable caller’s live parent and siblings. Remove the `scope` argument from scripted calls. Listing deeper descendants does not grant messaging or task-assignment authority.
|
||||
- `spawn_teammate` and the Team-scoped `send_message`, `list_agents`, and `interrupt_agent` are removed. The standard control tools use `name`, not `agent_id` or `target`. Members of one root tree can message each other across branches by name; interruption remains ancestor-only.
|
||||
- `list_agents` takes no arguments and lists the entire Team, including the root and caller. Remove scripted `scope` arguments. The root row uses `kind: root`; descendant rows use `kind: child`, with parent names and root-relative depth. Update consumers that expect `parent` or `sibling` rows. Discovery does not grant task-assignment authority.
|
||||
- The Team profile no longer disables the subagent tools. Team adds only task tools, `wait_agent`, and collaboration guidance.
|
||||
- `agent-team` rejects `maxMembers`, `maxMessageBytes`, and `disposalTimeoutMs`; `tool-agent-team` rejects `interrupt`, `freshProvider`, and `forkProvider`.
|
||||
- `ctx.agentTeams` removes `spawnTeammate()`, `sendMessage()`, `interrupt()`, and `listMembers()`. Host task views retain `ownerId` Session identities; model-facing task results expose `ownerName`, and task `owner` arguments use names. The root agent is always `lead`.
|
||||
@@ -22,6 +22,6 @@ The experimental Agent Teams plugins share agent creation, discovery, messaging,
|
||||
|
||||
1. Remove the obsolete configuration keys and any patch rows that disable subagent tools solely for Team support.
|
||||
2. Replace `spawn_teammate({ name, description, prompt, context })` with `subagent({ name, description, prompt })`, or `subagent_fork` for inherited conversation history. Choose a unique lower-case name with letters, digits, underscores, or hyphens; start with a letter. `lead` and `unowned` are reserved. Duplicate names fail before creation.
|
||||
3. Use `send_message({ name, message })` and `interrupt_agent({ name })`. Discover parent and sibling names with `list_agents`.
|
||||
3. Use `send_message({ name, message })` and `interrupt_agent({ name })`. Discover all Team member names with `list_agents`.
|
||||
4. Pass member names to task `owner` fields and read `ownerName` in tool results. Use `lead` for the root agent.
|
||||
5. Replace removed service calls with `ctx.subagents.startActivation()`, `sendMessage()`, `interrupt()`, and `listChildren()`. Supply `name` to `startActivation()`; host control APIs still use Session ids. Creation and ordinary name lookup require a readable root catalog. A failed root registration leaves no usable named child; retry creation with the same name and a fresh child id. Start a Team-enabled profile and verify that a child's description appears in the Team panel and that a name-addressed message reaches it.
|
||||
+3
-3
@@ -11,8 +11,8 @@ description: "Agent Teams 使用标准 subagent 工具与唯一 agent 名字;T
|
||||
|
||||
实验性 Agent Teams 插件与 subagent 共享创建、发现、消息与中断。使用 `subagent` 或 `subagent_fork` 启动队友,为其指定树内唯一的 `name`,用 `description` 描述职责,并以返回的名字发送消息和分配任务。描述可以重复,不标识接收方。
|
||||
|
||||
- `spawn_teammate` 及 Team 作用域的 `send_message`、`list_agents`、`interrupt_agent` 被移除。标准控制工具使用 `name`,而非 `agent_id` 或 `target`。同一在线父级的可继续子级可以按名字互发消息。
|
||||
- `list_agents` 不接受参数,始终列出所有可达的可继续后代,以及可继续调用方的在线父级和同级。脚本调用需移除 `scope` 参数。列出更深后代不授予消息或任务分配权限。
|
||||
- `spawn_teammate` 及 Team 作用域的 `send_message`、`list_agents`、`interrupt_agent` 被移除。标准控制工具使用 `name`,而非 `agent_id` 或 `target`。同一根树的成员可以按名字跨分支互发消息;中断仍仅允许祖先执行。
|
||||
- `list_agents` 不接受参数,列出整个 Team,包括根和调用方。脚本调用需移除 `scope` 参数。根行使用 `kind: root`;后代行使用 `kind: child`,带父级名字和相对根的深度。更新依赖 `parent` 或 `sibling` 行的消费者。发现成员不授予任务分配权限。
|
||||
- Team profile 不再禁用 subagent 工具。Team 只增加任务工具、`wait_agent` 和协作指引。
|
||||
- `agent-team` 拒绝 `maxMembers`、`maxMessageBytes` 与 `disposalTimeoutMs`;`tool-agent-team` 拒绝 `interrupt`、`freshProvider` 与 `forkProvider`。
|
||||
- `ctx.agentTeams` 移除 `spawnTeammate()`、`sendMessage()`、`interrupt()` 与 `listMembers()`。宿主任务视图保留 `ownerId` Session 身份;面向模型的任务结果公开 `ownerName`,任务 `owner` 参数使用名字。根 agent 始终名为 `lead`。
|
||||
@@ -22,6 +22,6 @@ description: "Agent Teams 使用标准 subagent 工具与唯一 agent 名字;T
|
||||
|
||||
1. 移除废弃配置键,以及仅为 Team 支持而禁用 subagent 工具的 patch 行。
|
||||
2. 将 `spawn_teammate({ name, description, prompt, context })` 改为 `subagent({ name, description, prompt })`,需要继承会话历史时使用 `subagent_fork`。选择唯一的小写名字,只含字母、数字、下划线或连字符,并以字母开头。`lead` 和 `unowned` 为保留名。重名在创建前失败。
|
||||
3. 使用 `send_message({ name, message })` 与 `interrupt_agent({ name })`。通过 `list_agents` 发现父级和同级名字。
|
||||
3. 使用 `send_message({ name, message })` 与 `interrupt_agent({ name })`。通过 `list_agents` 发现所有 Team 成员名字。
|
||||
4. 向任务 `owner` 字段传成员名字,读取工具结果中的 `ownerName`。根 agent 使用 `lead`。
|
||||
5. 将移除的服务调用改为 `ctx.subagents.startActivation()`、`sendMessage()`、`interrupt()` 与 `listChildren()`。向 `startActivation()` 提供 `name`;宿主控制 API 仍使用 Session id。创建与普通名字查找要求根 catalog 可读。根登记失败不会留下可用的命名子级;可使用相同名字和新 child id 重试创建。启动启用 Team 的 profile,确认子级描述出现在 Team 面板,并且按名字发送的消息能够到达。
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-root",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-acp",
|
||||
"description": "Automation-only Agent Client Protocol server for driving DeepSeek Harness agents over JSON-RPC stdio",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-api-account-controller",
|
||||
"description": "Expose safe account operations over authenticated Remote",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -51,8 +51,7 @@ it('delegates bonus reads and acknowledgements without altering their values', a
|
||||
const { provider, controller } = fixture()
|
||||
const accountId = 'account' as AccountUserId
|
||||
const orderId = 'order' as AccountBonusOrderId
|
||||
const batch: AccountBonusBatch = { accountId, bonuses: [{ orderId, campaign: 'dsh_login_bonus', amount: '5.00',
|
||||
currency: 'CNY', grantedAt: '2026-09-21T12:00:00Z', expiresAt: '2026-10-21T12:00:00Z', message: '已赠送您 5.00 元 DSH 体验赠金。' }] }
|
||||
const batch: AccountBonusBatch = { accountId, bonuses: [{ orderId, expiresAt: '2026-10-21T12:00:00Z', message: '已赠送您 5.00 元 DSH 体验赠金。' }] }
|
||||
provider.getUnnotifiedBonuses.mockResolvedValueOnce(batch)
|
||||
expect(await controller.getUnnotifiedBonuses(client)).toBe(batch)
|
||||
expect(provider.getUnnotifiedBonuses).toHaveBeenCalledExactlyOnceWith(client)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-api-gateway",
|
||||
"description": "Typert Remote Host dispatcher and Client API endpoint",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-api-job-controller",
|
||||
"description": "Job Remote observation stream and the reference-counted client job-output service",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-api-remote-access",
|
||||
"description": "Method-level Remote access control for non-owner Peers and the per-Peer access snapshot",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-api-remotes",
|
||||
"description": "Remote BFF assembly for application-selected Host capabilities",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-api-session-controller",
|
||||
"description": "Session Remote commands, cold reads, and live control transport",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-api-settings-controller",
|
||||
"description": "Remote owner for the configuration surfaces over the settings-domain seams",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-api-terminal-controller",
|
||||
"description": "Session-owned interactive terminals with shell discovery, screen recovery and typed Remote control",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-api-workspace-controller",
|
||||
"description": "Workspace Remote commands and reconnect-safe state transport",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-api-workspace-files",
|
||||
"description": "Workspace file service and Client resource provider: bounded reads, directory listing, and live metadata over the workspaceFiles Remote namespace",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-attachment-local",
|
||||
"description": "Private content-addressed DSH_HOME attachment storage",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-attachment",
|
||||
"description": "Durable immutable attachment storage seam for the DeepSeek Harness",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-app-boot",
|
||||
"description": "Shared boot glue for the app bins: .env loading, fail-loud Loader guards, snapshot-aware config resolution, and the Loader boot sequence",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-cmdline",
|
||||
"description": "Immutable command-line handoff from a dsh launcher to any app plugin that injects cmdlineArgs",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-config-editor",
|
||||
"description": "Persist plugin configuration through profile patches and Loader reconciliation",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-hmr",
|
||||
"description": "Coordinated module and profile configuration hot reload",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-plugin-manager",
|
||||
"description": "Current-profile plugin and bundle management shared by dsh CLI, Web and agent tools",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-plugin-market",
|
||||
"description": "Configured plugin market indexes for the Web Discover page and the plugin_market agent tool",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-browser-use",
|
||||
"description": "Exclusive named browser-use provider registration",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-acp-app",
|
||||
"description": "The dsh ACP profile bundle: automation-only JSON-RPC stdio and process lifecycle over dsh-base",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-base",
|
||||
"description": "The shared dsh core as a profile bundle: the first patch layer of base-backed profiles, inserting core rows over the empty profile root",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-headless",
|
||||
"description": "The dsh one-shot bundle: a direct core Agent/Session runner over dsh-base with no Host, HTTP, or browser layer",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
en: 4f88e647c6df4f42
|
||||
zh: 2bd3e4b0bdfe9412
|
||||
/deepseek-ai-dsh-sdk-app/model-experience/sdk-model-context/what-the-model-sees:
|
||||
en: 40f68e7d3f181ed6
|
||||
zh: 64b0d7c8bf63dfa1
|
||||
en: fc42eb5995eb2078
|
||||
zh: 4e47602e46ba5123
|
||||
/deepseek-ai-dsh-sdk-app/model-experience/sdk-model-context/token-effect:
|
||||
en: 92d8ecb761e3ca7b
|
||||
zh: e14c71ee2c31e818
|
||||
en: 4a0cdca06d358f53
|
||||
zh: d27080dcb68c661c
|
||||
/deepseek-ai-dsh-sdk-app/model-experience/sdk-model-context/kv-cache-effect:
|
||||
en: 5b0e33295fb90e19
|
||||
zh: 4d48ca75bb677202
|
||||
|
||||
@@ -44,11 +44,11 @@ The Python runtime exposes explicitly downloaded authoring resources and Office
|
||||
|
||||
#### What the model sees
|
||||
|
||||
The profile inherits the base system prompt, including the `You are an AI agent powered by DeepSeek Harness.` identity, without adding a task-specific persona. Each Session receives its current directory in required user-role context from [`dsh-working-directory`](../../session/working-directory/README.md). Default file tool schemas include `read`, `write`, and `edit`; they omit `str_replace_editor`.
|
||||
The profile inherits the base system prompt, including the `You are an AI agent powered by DeepSeek Harness.` identity, and adds the same model-interpolated coding persona as the Web and headless profiles. Each Session receives its current directory in required user-role context from [`dsh-working-directory`](../../session/working-directory/README.md). Default file tool schemas include `read`, `write`, and `edit`; they omit `str_replace_editor`.
|
||||
|
||||
#### Token effect
|
||||
|
||||
The base prompt sections and selected tool schemas determine token usage; this profile adds no persona text.
|
||||
The base prompt sections and selected tool schemas determine token usage; this profile adds one coding-persona sentence.
|
||||
|
||||
#### KV Cache effect
|
||||
|
||||
|
||||
@@ -44,11 +44,11 @@ Python 运行时向本 profile 提供显式下载的创作资源和 Office sidec
|
||||
|
||||
#### 模型看到什么
|
||||
|
||||
profile 继承 base 系统提示词,包括 `You are an AI agent powered by DeepSeek Harness.` 身份说明,不额外添加特定任务的 persona。每个 Session 通过 [`dsh-working-directory`](../../session/working-directory/README.zh.md) 提供的必需 user-role 上下文接收当前目录。默认文件工具 schema 包含 `read`、`write` 和 `edit`,不包含 `str_replace_editor`。
|
||||
profile 继承 base 系统提示词,包括 `You are an AI agent powered by DeepSeek Harness.` 身份说明,并添加与 Web 和 headless profile 相同、按当前模型插值的 coding persona。每个 Session 通过 [`dsh-working-directory`](../../session/working-directory/README.zh.md) 提供的必需 user-role 上下文接收当前目录。默认文件工具 schema 包含 `read`、`write` 和 `edit`,不包含 `str_replace_editor`。
|
||||
|
||||
#### Token 影响
|
||||
|
||||
base 提示词段落与所选工具 schema 决定 token 用量;此 profile 不额外添加 persona 文本。
|
||||
base 提示词段落与所选工具 schema 决定 token 用量;此 profile 额外添加一句 coding persona。
|
||||
|
||||
#### KV Cache 影响
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# The SDK application over dsh-base. Stdout belongs exclusively to JSON-RPC.
|
||||
|
||||
- id: system-prompt
|
||||
config:
|
||||
personaPrefix: >-
|
||||
You are a coding agent powered by the {{model}} model.
|
||||
|
||||
- id: session-title-llm
|
||||
disabled: true
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-sdk-app",
|
||||
"description": "The dsh SDK profile bundle: stdio JSON-RPC serving and process lifecycle over dsh-base",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -22,6 +22,9 @@ describe('dsh-sdk-app bundle', () => {
|
||||
) as Array<{ id?: string; disabled?: boolean; insert?: Array<{ id?: string; inject?: string[]; name?: string }> }>
|
||||
expect(patches.find(patch => patch.id === 'hmr')).toMatchObject({ disabled: true })
|
||||
expect(patches.find(patch => patch.id === 'session-title-llm')).toMatchObject({ disabled: true })
|
||||
expect(patches.find(patch => patch.id === 'system-prompt')).toMatchObject({
|
||||
config: { personaPrefix: 'You are a coding agent powered by the {{model}} model.' },
|
||||
})
|
||||
const rows = patches.flatMap(patch => patch.insert ?? [])
|
||||
expect(rows.find(row => row.id === 'sdk-app-startup')?.name).toBe('@deepseek-ai/dsh-sdk-app')
|
||||
expect(rows.find(row => row.id === 'sdk-jsonrpc-server')?.inject).toEqual(['sdkAppStartup', 'loader'])
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-sdk-minimal",
|
||||
"description": "The standalone minimal SDK profile bundle: JSON-RPC, one DeepSeek adapter, persistent shell, and JSONL sessions",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
en: 3bd37b85139d2fa7
|
||||
zh: ba86c807eb83866e
|
||||
/deepseek-ai-dsh-web-app/use-this-package/starting-the-web-gui:
|
||||
en: e3cac911f080d8ef
|
||||
zh: 60749e9f5c39c1bc
|
||||
en: a1cf03cc8ad908c5
|
||||
zh: c06b89454172a47d
|
||||
/deepseek-ai-dsh-web-app/use-this-package/configuration:
|
||||
en: b1787804544f2587
|
||||
zh: ce09d2c248ffd999
|
||||
|
||||
@@ -40,7 +40,7 @@ dsh --profile web --no-open --port 8080
|
||||
|
||||
After startup you see a `dsh web:` line whose root URL carries a fresh process token. Unless `--no-open` or an SSH session suppresses it, the default browser opens that URL, receives a signed cookie, and redirects to the same directory without the token. You know it worked when the page loads and you can chat with the agent. Two failures to expect: if the frontend is not built, startup stops with a build hint (`pnpm run build` in a checkout); if the browser cannot be opened, a credential-free diagnostic prints to stderr while the server keeps running — open the printed startup URL yourself.
|
||||
|
||||
**Settings → Models** displays **DeepSeek**, using `DEEPSEEK_API_KEY`. The default is `deepseek-official` / `deepseek-flash` (DeepSeek-V4.1-Flash). The [DeepSeek plugin](../../llm/llm-deepseek/README.md#endpoint-and-wire-format) uses the Messages API.
|
||||
**Settings → Models** displays **DeepSeek**, using `DEEPSEEK_API_KEY`. The default is `deepseek-official` / `deepseek-flash` (DeepSeek-V4.1-Flash-1017). The [DeepSeek plugin](../../llm/llm-deepseek/README.md#endpoint-and-wire-format) uses the Messages API.
|
||||
|
||||
Saved model selections override the composition default. The settings card accepts a Messages-compatible API address and a credential reference.
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ dsh --profile web --no-open --port 8080
|
||||
|
||||
启动后你会看到 `dsh web:` 行,其根 URL 携带新的进程 token。除非 `--no-open` 或 SSH 会话抑制,否则默认浏览器会打开该 URL、取得签名 cookie,再重定向到不含认证参数的同一目录。页面加载且你可以与 agent 对话,就说明成功了。两种可预期的失败:前端未构建时,启动会以构建提示停止(checkout 中运行 `pnpm run build`);浏览器无法打开时,stderr 会打印不含凭据的诊断,但服务器会继续运行——请自行打开已打印的启动 URL。
|
||||
|
||||
**设置 → 模型**显示 **DeepSeek**,使用 `DEEPSEEK_API_KEY`。默认模型为 `deepseek-official` / `deepseek-flash`(DeepSeek-V4.1-Flash)。[DeepSeek 插件](../../llm/llm-deepseek/README.zh.md#endpoint-and-wire-format)使用 Messages API。
|
||||
**设置 → 模型**显示 **DeepSeek**,使用 `DEEPSEEK_API_KEY`。默认模型为 `deepseek-official` / `deepseek-flash`(DeepSeek-V4.1-Flash-1017)。[DeepSeek 插件](../../llm/llm-deepseek/README.zh.md#endpoint-and-wire-format)使用 Messages API。
|
||||
|
||||
已保存的模型选择覆盖组合默认值。设置卡接受兼容 Messages 的 API 地址与凭据引用。
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-web-app",
|
||||
"description": "The dsh browser-surface bundle: the web patch layer over dsh-base plus the runtime glue plugin (frontend dist serving, bash runtime variables, URL line)",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-connection",
|
||||
"description": "Authenticated RPC transport and generation lifecycle",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-file-upload",
|
||||
"description": "Agent-scoped browser file upload, streaming intake, and staged receipt service",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-hmr",
|
||||
"description": "Web client graph synchronization and rebuilt-bundle reload transport",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-locale",
|
||||
"description": "Locale plugin: Host-backed preference, extensible language catalog, browser fallback, and typed built-in dictionaries",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-modules",
|
||||
"description": "Client module system, dual-face: node half composes the __DSH_BOOT__ entry graph (incremental dsh.client scan, bundle route, index tap, webPlugins service); browser half is the lazy-CJS module table the vendored cordis Loader consumes as its internal seam",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-product-analytics",
|
||||
"description": "Desktop product event collection and authenticated Host reporting",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-resources",
|
||||
"description": "Unified client resource model: protocol-registered providers turn URL addresses into live values, consumed through the useResource global standard hook",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-shortcuts",
|
||||
"description": "Application keyboard command registry and physical-key routing",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-store",
|
||||
"description": "React-free observable and snapshot-store contracts with the shared Zustand/Immer engine",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-ui-agent-preset",
|
||||
"description": "Agent-preset surfaces: the default for later sessions, this session's seat, and the composition editor",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-ui-approval",
|
||||
"description": "Approval composer takeover over the scoped Remote Event waterfall",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-ui-attachment",
|
||||
"description": "Dynamic attachment presentation plugin for conversation input, message-image, and trajectory image slots",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-ui-brand-official",
|
||||
"description": "Official DeepSeek Harness brand occupants for the Web client's sidebar slots",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-ui-chat",
|
||||
"description": "Chat Conversation target, node definitions, renderers, and details surface",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-ui-commands",
|
||||
"description": "Client command surface: global directory cache, '/' source, three command UI kinds, popupSelect registry",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-ui-conversation",
|
||||
"description": "Target-neutral Conversation assembly, shell, composer, queue, and view navigation",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-ui-deliverables",
|
||||
"description": "Changed-files card with per-file comparison tabs, delivery cards, and clickable final-response file references for Web",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-ui-directory-picker-browse",
|
||||
"description": "In-app directory browsing surface: the workspace directory-flow owner rendering the host's listing and creation primitives",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@deepseek-ai/dsh-client-ui-directory-picker-native",
|
||||
"description": "Native directory-picker surface: the renderless workspace directory-flow occupant driving the local Desktop or Host OS chooser",
|
||||
"version": "0.2.1-alpha.4",
|
||||
"version": "0.2.1-rc.1",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
|
||||
Loaded 100 of 661 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user