fix: keep creation proposals scoped to one explicit need

This commit is contained in:
ZiyaZhang committed 2026-10-20 01:15:34 -07:00
1 parent 29317a82c8
commit 257c14743a
10 files changed
+94 -16

No files matched your search

+4 -4
View File
@@ -15,11 +15,11 @@
en: b0727c5ef1bdec4b
zh: b0727c5ef1bdec4b
/tool-schema-catalog/deepseek-ai-dsh-experimental-creation-recommendations/list-creation-plugins:
en: dcac6a70f8e3399b
zh: a31bf92ff567d6b1
en: 895f2c5e7c10f02a
zh: 6f8bb646c1b1474d
/tool-schema-catalog/deepseek-ai-dsh-experimental-creation-recommendations/suggest-view:
en: 86b58ee4be83d3da
zh: 2a157c7883c429b7
en: 7c26bf33c30ca6fc
zh: d3fc7ab4c6305a09
/tool-schema-catalog/deepseek-ai-dsh-plugin-manager:
en: e0143916bb634762
zh: e0143916bb634762
+3 -3
View File
@@ -57,7 +57,7 @@ This table connects model-visible tool names to the plugin package and service s
### `list_creation_plugins`
Read shipped DSH plugins and their current enabled state before proposing a new interface. This read-only catalog works in ordinary conversations. Prefer a suitable existing plugin; an absent entry does not prove that DSH lacks a built-in feature. Keep discovery at product level: do not search source files, private profiles or implementation docs just to propose or discuss a feature. Clarify vague wishes before discovery.
Read shipped DSH plugins and their enabled state to check existing capabilities before proposing a new interface. Select one need first: follow explicit priority; otherwise prefer a suitable existing plugin. If list_official_plugins already found a plugin for that need, use it without querying this catalog to plan another, unselected need. Do not query after offering a card or for vague, quoted or discussion-only requests that decline recommendations. Clarify missing requirements before discovery. An absent entry does not prove that DSH lacks a built-in feature. Keep discovery at product level; do not inspect source, private profiles or implementation docs just to propose a feature.
```json
{
@@ -70,7 +70,7 @@ Source: [`packages/experimental/creation-recommendations/src/index.ts`](../packa
### `suggest_view`
Offer a new persistent interface or feature plugin for an explicit user need, including wishes such as "I want a..." or "I wish I could...". Keep proposal planning at product level; defer source/API inspection and implementation choices to the Creator after the user clicks Create. Read list_creation_plugins before proposing; use a suitable existing capability instead, or suggest_plugin when available for an eligible disabled plugin. If suggest_plugin is unavailable, explain how to open the existing plugin in Plugins; do not create a duplicate. Do not offer a card for one-off questions, ordinary tasks, vague wishes that need clarification, or when the user asks only to discuss feasibility or explicitly declines recommendations. Plan the requested behavior, data sources, relevant conversation context and completion criteria in a concise self-contained brief, and recommend a location. Offer at most one recommendation per turn, across suggest_view and suggest_plugin. Call this tool before your final response, then give one concise answer with the plan; do not repeat the answer around the tool call. The card appears below the completed answer. Refer to its actions in the user’s language. Do not start creating or installing anything; the user must click Create. A Creator agent then executes this plan as a new removable plugin. Existing plugins are never edited.
Propose a new persistent interface for one explicit need, including everyday wishes. Select ONE recommendation per turn across suggest_view and suggest_plugin before calling either, even if multiple cards are requested; never batch recommendations. Honor explicit priority; otherwise prefer a suitable existing plugin. Discuss other independent needs in the answer, without merging them or promising an automatic later card. Clarify an unknown purpose, data source or interaction before proposing; do not guess these from an unrelated need. Read list_creation_plugins for the selected creation need first. Use an existing capability when suitable, or suggest_plugin if available for an eligible disabled plugin; otherwise explain its Plugins entry, without creating a duplicate. No cards for vague wishes, ordinary tasks, quoted requests or discussion-only requests that decline recommendations. Keep the brief concise and at product level: requested behavior, known data sources, relevant context, completion criteria and location. Defer source/API inspection to the Creator. Call before the final answer, then answer concisely in the user’s language using only successful results; a rejected call created no card. The card appears below the completed answer. Do not create or install anything: the user must click Create, which starts a Creator to build a new removable plugin. Existing plugins are never edited.
```json
{
@@ -82,7 +82,7 @@ Offer a new persistent interface or feature plugin for an explicit user need, in
},
"brief": {
"type": "string",
"description": "Concise implementation plan in the user’s language: explicit need, behavior, data sources, relevant context and completion criteria. This is shown on the card and passed to the Creator."
"description": "Concise plan for only the selected need: behavior, known data sources, relevant context and completion criteria, in the user’s language. Do not infer its purpose from another independent wish. Clarify missing requirements before calling. Shown on the card and passed to the Creator."
},
"slot": {
"type": "string",
+3 -3
View File
@@ -61,7 +61,7 @@
### `list_creation_plugins`
提出新界面建议前,读取随应用提供的 DSH 插件及当前启用状态。此只读清单可用于普通会话。优先使用合适的现有插件;清单中没有某项不代表 DSH 缺少对应内置功能。发现阶段只处理产品能力,不要为了建议或讨论功能而搜索源码、私有配置档案或实现文档。愿望模糊时先澄清,再查询。
为新界面提出建议前,读取随应用提供的 DSH 插件及启用状态,检查已有能力。先选定一个需求:遵循明确优先级,否则优先使用现成插件。如果 list_official_plugins 已找到满足该需求的插件,直接使用,不再为另一个未选中的需求查询本目录。出卡后,以及模糊、引用或明确拒绝推荐的纯讨论请求,不应查询。缺少信息时先澄清。目录中没有某项不代表 DSH 缺少对应内置功能。发现阶段只处理产品能力,不要为了提议功能而查源码、私有配置档案或实现文档。
```json
{
@@ -74,7 +74,7 @@
### `suggest_view`
针对明确需求(包括“我想要一个……”等愿望)推荐新的持久界面或功能插件。建议阶段只规划产品行为,将源码、API 调研和技术选型留给用户点击创建后的 Creator。建议前读取 list_creation_plugins;已有合适能力时直接使用,或在 suggest_plugin 可用时推荐符合条件的未启用插件。suggest_plugin 不可用时,说明如何在“插件”页打开已有插件,不要重复创建。普通任务、一次性问题、需要澄清的模糊愿望,以及明确要求只讨论可行性或拒绝推荐的请求不应显示卡片。在简明、完整的方案中写清行为、数据来源、相关上下文和验收点,并推荐位置。每轮 suggest_view 与 suggest_plugin 合计最多一条推荐。在最终回答之前调用工具,再给出一次包含方案的简洁回答,避免工具调用前后重复;卡片显示在完整回答末尾。用用户的语言称呼操作。不要开始创建或安装;用户点击创建后,Creator 才会按方案生成新的可卸载插件,不修改已有插件。
为一个明确需求(包括日常愿望)提出新的持久界面方案。调用前先从 suggest_view 与 suggest_plugin 中选定本轮唯一推荐,即使用户要求多张卡也不得同批提交多个建议。遵循明确优先级,否则优先使用现成插件。其他独立需求在正文说明,不合并需求,也不承诺以后自动出卡。用途、数据来源或交互不清楚时先澄清,不从无关需求中推断。针对选定的创造需求,先读取 list_creation_plugins。已有合适能力时直接使用,或在 suggest_plugin 可用时推荐符合条件的未启用插件;否则说明插件页入口,不重复创建。模糊愿望、普通任务、引用内容或明确拒绝推荐的纯讨论请求不出卡。方案保持简洁并聚焦产品:所需行为、已知数据来源、相关上下文、验收点和位置。源码与 API 调研留给 Creator。最终回答前调用,再用用户的语言根据成功结果简洁作答;被拒绝的调用不会生成卡片。卡片显示在完整回答下方。不要创建或安装;用户点击创建后,Creator 才会生成新的可卸载插件,不修改已有插件。
```json
{
@@ -86,7 +86,7 @@
},
"brief": {
"type": "string",
"description": "Concise implementation plan in the user’s language: explicit need, behavior, data sources, relevant context and completion criteria. This is shown on the card and passed to the Creator."
"description": "Concise plan for only the selected need: behavior, known data sources, relevant context and completion criteria, in the user’s language. Do not infer its purpose from another independent wish. Clarify missing requirements before calling. Shown on the card and passed to the Creator."
},
"slot": {
"type": "string",
@@ -15,8 +15,8 @@
en: d152484eb41ac6b4
zh: b00dddf4c88f0a45
/deepseek-ai-dsh-experimental-creation-recommendations/use-this-package:
en: cb2c3fd5bf037568
zh: 4aeb67ba2c3cd75f
en: 7883a45b272e9bb6
zh: 263d1abab6261c9a
/deepseek-ai-dsh-experimental-creation-recommendations/use-this-package/outcomes-and-recovery:
en: c4e5a6c2dd90e4cc
zh: 2373e7aeb1cafabc
@@ -37,6 +37,8 @@ The left entry and its global page form one placement, including global streamin
Personalized pages works with the plugin recommendation experiment disabled or absent. When discovery finds an existing plugin, tool guidance directs the Agent to its Plugins entry instead of creating a duplicate. If the recommendation experiment is also enabled, it can offer that plugin through `suggest_plugin`; both experiments share the one-card-per-turn limit.
For multiple independent needs, guidance selects one proposal across creation and plugin recommendations before calling either tool. Explicit user priority wins; otherwise an existing plugin takes precedence. Other needs stay in the answer, with clarification when their purpose, data source or interaction is unknown. The plan must not infer these from another wish. A rejected proposal creates no card and does not schedule a future one. Discovery for an unselected creation is unnecessary once an existing plugin is selected. These semantic instructions supplement the Host’s one-successful-card limit; they do not make one experiment depend on the other.
### Outcomes and recovery
Creation requires a live root conversation and permission to modify the profile. Cancel is available during generation; retry waits for the child’s cleanup. Once installation starts, the card shows Completing installation and lets the accepted operation finish. Closing or leaving the conversation does not uninstall a completed plugin. Receipts survive reconnects; interrupted or uncertain runs are reconciled with the installed bundle before retry. Failed removal preserves the existing receipt and its application outcome for retry. Unloading this recommendation bundle stops its Creator work and local follow-up. Plugin Manager owns accepted profile changes and may finish after reload; reopening checks the installed profile before retrying. Installed plugins remain. Recovery confirms installation only; it does not infer runtime activation from the profile’s enabled flag.
@@ -37,6 +37,8 @@ kind: "package-bundle"
即使未安装或未启用插件推荐实验,个性化页面也可独立使用。发现已有插件能满足需求时,工具指引 Agent 说明它在插件页的入口,避免重复创建;同时启用插件推荐实验后,也可以通过 `suggest_plugin` 推荐该插件。两个实验共用每轮最多一张卡片的限制。
面对多个独立需求,指引要求在调用工具前从个性化页面和插件推荐中选定一项。优先遵循用户明确指定的顺序,否则先推荐现成插件。其余需求在正文说明;用途、数据来源或交互不清楚时先澄清,不从另一个愿望推断这些信息。被拒绝的建议不会生成卡片,也不会安排未来自动出卡。选定现成插件后,无需为未选中的创造需求查询目录。这些语义指引补充 Host 每轮最多一张成功卡片的限制,不引入两个实验之间的依赖。
### 操作结果与恢复
创建要求当前会话是活动的根会话,并且连接有权修改配置档案。生成阶段可取消,子任务清理完毕后才能重试。安装开始后显示“正在完成安装”,等待已接纳的操作结束。关闭或离开会话不会卸载已完成的插件。重新连接后会恢复操作记录;重试之前会对照已安装插件检查中断或结果不明的创建。移除失败时保留已有记录和实际生效结果,以便重试。卸载推荐插件会停止它负责的 Creator 任务和本地后续处理。已接纳的配置变更由插件管理器负责,可能在重载后完成;重新打开会话时先检查安装状态再允许重试。已安装插件仍然保留。恢复只确认安装,不根据配置中的开启标记推断运行时已生效。
@@ -75,7 +75,7 @@ export default class CreationRecommendations extends TypertRemoteService {
const state = this.projection.stateOf(exec.agent.session)
const reserved = this.reservations.get(exec.agent.id)
const first = state.firstCall ?? (reserved?.turn === state.turn ? reserved.callId : undefined)
if (first !== undefined && first !== exec.callId) return 'This turn already has a recommendation. Finish the answer.'
if (first !== undefined && first !== exec.callId) return 'This turn already has a recommendation. This call created no card. Finish using successful results only; do not promise an automatic later card.'
this.reservations.set(exec.agent.id, { turn: state.turn, callId: exec.callId })
return undefined
})
@@ -86,7 +86,7 @@ export default class CreationRecommendations extends TypertRemoteService {
})
this.ctx.tools.register(defineTool({
name: 'list_creation_plugins',
description: 'Read shipped DSH plugins and their current enabled state before proposing a new interface. This read-only catalog works in ordinary conversations. Prefer a suitable existing plugin; an absent entry does not prove that DSH lacks a built-in feature. Keep discovery at product level: do not search source files, private profiles or implementation docs just to propose or discuss a feature. Clarify vague wishes before discovery.',
description: 'Read shipped DSH plugins and their enabled state to check existing capabilities before proposing a new interface. Select one need first: follow explicit priority; otherwise prefer a suitable existing plugin. If list_official_plugins already found a plugin for that need, use it without querying this catalog to plan another, unselected need. Do not query after offering a card or for vague, quoted or discussion-only requests that decline recommendations. Clarify missing requirements before discovery. An absent entry does not prove that DSH lacks a built-in feature. Keep discovery at product level; do not inspect source, private profiles or implementation docs just to propose a feature.',
// jscpd:ignore-start -- Each independent experiment owns its catalog tool declaration.
parameters: {},
output: { schema: { type: 'string' }, render: (_args, value) => [{ type: 'text', text: value }] },
@@ -102,10 +102,10 @@ export default class CreationRecommendations extends TypertRemoteService {
}))
this.ctx.tools.register(defineTool({
name: 'suggest_view',
description: 'Offer a new persistent interface or feature plugin for an explicit user need, including wishes such as "I want a..." or "I wish I could...". Keep proposal planning at product level; defer source/API inspection and implementation choices to the Creator after the user clicks Create. Read list_creation_plugins before proposing; use a suitable existing capability instead, or suggest_plugin when available for an eligible disabled plugin. If suggest_plugin is unavailable, explain how to open the existing plugin in Plugins; do not create a duplicate. Do not offer a card for one-off questions, ordinary tasks, vague wishes that need clarification, or when the user asks only to discuss feasibility or explicitly declines recommendations. Plan the requested behavior, data sources, relevant conversation context and completion criteria in a concise self-contained brief, and recommend a location. Offer at most one recommendation per turn, across suggest_view and suggest_plugin. Call this tool before your final response, then give one concise answer with the plan; do not repeat the answer around the tool call. The card appears below the completed answer. Refer to its actions in the user’s language. Do not start creating or installing anything; the user must click Create. A Creator agent then executes this plan as a new removable plugin. Existing plugins are never edited.',
description: 'Propose a new persistent interface for one explicit need, including everyday wishes. Select ONE recommendation per turn across suggest_view and suggest_plugin before calling either, even if multiple cards are requested; never batch recommendations. Honor explicit priority; otherwise prefer a suitable existing plugin. Discuss other independent needs in the answer, without merging them or promising an automatic later card. Clarify an unknown purpose, data source or interaction before proposing; do not guess these from an unrelated need. Read list_creation_plugins for the selected creation need first. Use an existing capability when suitable, or suggest_plugin if available for an eligible disabled plugin; otherwise explain its Plugins entry, without creating a duplicate. No cards for vague wishes, ordinary tasks, quoted requests or discussion-only requests that decline recommendations. Keep the brief concise and at product level: requested behavior, known data sources, relevant context, completion criteria and location. Defer source/API inspection to the Creator. Call before the final answer, then answer concisely in the user’s language using only successful results; a rejected call created no card. The card appears below the completed answer. Do not create or install anything: the user must click Create, which starts a Creator to build a new removable plugin. Existing plugins are never edited.',
parameters: {
title: { type: 'string', required: true, description: 'Short name in the user’s language.' },
brief: { type: 'string', required: true, description: 'Concise implementation plan in the user’s language: explicit need, behavior, data sources, relevant context and completion criteria. This is shown on the card and passed to the Creator.' },
brief: { type: 'string', required: true, description: 'Concise plan for only the selected need: behavior, known data sources, relevant context and completion criteria, in the user’s language. Do not infer its purpose from another independent wish. Clarify missing requirements before calling. Shown on the card and passed to the Creator.' },
slot: { type: 'string', enum: ['sidebar-right', 'page', 'sidebar-left'], required: true, description: 'Apply this order: (1) Honor a location explicitly requested by the user. (2) A global feature uses sidebar-left: one left entry opens a standalone main-area page without Chat/Trajectory tabs, including global streaming tools. (3) A Session-bound streaming dialogue or interactive assistant uses page: a tab beside Chat and Trajectory; Session scope is not a reason to put streaming dialogue in the right sidebar. (4) Other Session-bound viewers, editors and Context inspection use sidebar-right. Do not invent a right-sidebar preference to replace the streaming-tab rule. If scope or interaction is unclear, clarify first.' },
},
output: {
@@ -0,0 +1,44 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`interface creation > discovers shipped plugins without the recommendation or management tools and withdraws discovery on unload > one selected need without invented requirements 1`] = `
{
"discovery": "Read shipped DSH plugins and their enabled state to check existing capabilities before proposing a new interface. Select one need first: follow explicit priority; otherwise prefer a suitable existing plugin. If list_official_plugins already found a plugin for that need, use it without querying this catalog to plan another, unselected need. Do not query after offering a card or for vague, quoted or discussion-only requests that decline recommendations. Clarify missing requirements before discovery. An absent entry does not prove that DSH lacks a built-in feature. Keep discovery at product level; do not inspect source, private profiles or implementation docs just to propose a feature.",
"parameters": {
"properties": {
"brief": {
"description": "Concise plan for only the selected need: behavior, known data sources, relevant context and completion criteria, in the user’s language. Do not infer its purpose from another independent wish. Clarify missing requirements before calling. Shown on the card and passed to the Creator.",
"type": "string",
},
"slot": {
"description": "Apply this order: (1) Honor a location explicitly requested by the user. (2) A global feature uses sidebar-left: one left entry opens a standalone main-area page without Chat/Trajectory tabs, including global streaming tools. (3) A Session-bound streaming dialogue or interactive assistant uses page: a tab beside Chat and Trajectory; Session scope is not a reason to put streaming dialogue in the right sidebar. (4) Other Session-bound viewers, editors and Context inspection use sidebar-right. Do not invent a right-sidebar preference to replace the streaming-tab rule. If scope or interaction is unclear, clarify first.",
"enum": [
"sidebar-right",
"page",
"sidebar-left",
],
"type": "string",
},
"title": {
"description": "Short name in the user’s language.",
"type": "string",
},
},
"required": [
"title",
"brief",
"slot",
],
"type": "object",
},
"proposal": "Propose a new persistent interface for one explicit need, including everyday wishes. Select ONE recommendation per turn across suggest_view and suggest_plugin before calling either, even if multiple cards are requested; never batch recommendations. Honor explicit priority; otherwise prefer a suitable existing plugin. Discuss other independent needs in the answer, without merging them or promising an automatic later card. Clarify an unknown purpose, data source or interaction before proposing; do not guess these from an unrelated need. Read list_creation_plugins for the selected creation need first. Use an existing capability when suitable, or suggest_plugin if available for an eligible disabled plugin; otherwise explain its Plugins entry, without creating a duplicate. No cards for vague wishes, ordinary tasks, quoted requests or discussion-only requests that decline recommendations. Keep the brief concise and at product level: requested behavior, known data sources, relevant context, completion criteria and location. Defer source/API inspection to the Creator. Call before the final answer, then answer concisely in the user’s language using only successful results; a rejected call created no card. The card appears below the completed answer. Do not create or install anything: the user must click Create, which starts a Creator to build a new removable plugin. Existing plugins are never edited.",
}
`;
exports[`interface creation > reserves one recommendation before parallel tools settle, including the official recommendation tool > rejected extra proposal does not promise a card 1`] = `
[
{
"text": "Error: This turn already has a recommendation. This call created no card. Finish using successful results only; do not promise an automatic later card.",
"type": "text",
},
]
`;
@@ -22,6 +22,11 @@ describe('interface creation', () => {
)
expect(f.ctx.tools.get('list_official_plugins')).toBeUndefined()
expect(f.ctx.tools.get('plugin_manager')).toBeUndefined()
expect({
discovery: f.ctx.tools.get('list_creation_plugins', f.agent)?.description,
proposal: f.ctx.tools.get('suggest_view', f.agent)?.description,
parameters: f.ctx.tools.get('suggest_view', f.agent)?.parameters,
}).toMatchSnapshot('one selected need without invented requirements')
const result = await f.ctx.tools.execute({ name: 'list_creation_plugins', arguments: {}, agent: f.agent,
callId: ToolCallId('discovery'), signal: new AbortController().signal })
expect(result.value).toBe(JSON.stringify([
@@ -179,6 +184,7 @@ describe('interface creation', () => {
const calls = await Promise.all([f.execute(), f.ctx.tools.execute({ name: 'suggest_plugin', arguments: {},
callId: ToolCallId('official'), agent: f.agent, signal: new AbortController().signal })])
expect(calls.filter(result => !result.isError)).toHaveLength(1)
expect(calls.find(result => result.isError)?.content).toMatchSnapshot('rejected extra proposal does not promise a card')
expect((await f.execute(proposal, ToolCallId('third'))).isError).toBe(true)
const result = await f.ctx.tools.execute({ name: 'suggest_view', arguments: proposal,
callId, signal: new AbortController().signal })
@@ -28,5 +28,29 @@
"id": "defer_creation",
"prompt": "我想要右侧计数器,但这次只讨论可行性,不要推荐插件或创建入口。",
"expected": "Discussion only; no card or generation."
},
{
"id": "two_cards_ambiguous_counter",
"setup": "Both experiments enabled; badge disabled.",
"prompt": "我需要每个 PR 的 DSH 标识,以及一个右侧栏计数器。请给两个入口:已有插件一张卡,创造一张卡,但先别执行。",
"expected": "Exactly one badge proposal, no rejected extra call. Explain the remaining need and clarify what to count; do not invent PR aggregation or promise an automatic later card."
},
{
"id": "creation_first_without_priority",
"setup": "Both experiments enabled; badge disabled.",
"prompt": "我想在当前会话右侧放一个手动小成就计数器,能加一、归零并按会话保存。另外我希望每个 PR 都有 DSH 标识。这两个都给我入口,先不要执行。",
"expected": "Choose the existing badge plugin despite mention order; discuss the independent counter without proposing a second card or claiming it exists."
},
{
"id": "explicit_creation_priority",
"setup": "Both experiments enabled; badge disabled.",
"prompt": "我希望每个 PR 都有 DSH 标识,也想在当前会话右侧放一个手动小成就计数器,能加一、归零并按会话保存。这轮优先给计数器的创建方案入口,徽章暂时只说明,不要执行。",
"expected": "Exactly one suggest_view sidebar-right for the manual counter; no badge proposal and no generation before clicking Create."
},
{
"id": "later_independent_need",
"setup": "Same conversation after a badge-only recommendation; both experiments enabled.",
"prompt": "现在给计数器方案:当前会话右侧的手动小成就计数器,可以加一、归零并按会话保存,先不要创建。",
"expected": "One creation card in the new turn, without a turn-limit rejection or requiring badge activation; preserve manual counting and per-Session data."
}
]