Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
| Cursor | 本地插件;CLI 真实写动作通过 | Windows;技能、草稿创建/保存/预览 |
| Claude Code | 原生插件,v0.2.1 | v0.2.0 公开市场安装和真实 MCP 连接通过;模型写动作待验收 |
| VS Code / Copilot、Gemini CLI | 配置安装器 | 默认 Windows 用户配置;尚未完成各客户端写动作验收 |
| DeepSeek Harness | DSH bundle 插件,v0.2.3 | Windows;安装包与转接已实现;v0.2.3 修复注入消息缺 id/role 导致历史无法加载。真实 DSH 会话写动作待验收 |
| DeepSeek Harness | DSH bundle 插件,v0.2.4 | Windows;`write-action` 以技能目录卡片按需加载,不再在每次会话开头注入整份编写说明。真实 DSH 会话写动作待验收 |

需要使用设置 → Agent 中带「启用 MCP」入口、并包含默认技能包发现修复的 Quicker 新构建。Release 支持已实现,待包含这些变更的正式版发布;已发布旧版没有该入口时仍不可用。本次已验证 Debug 的草稿编写与预览,Release 配置内核测试和正式前端构建通过,正式安装包端到端仍待验收,详见[兼容性说明](docs/兼容性.md)。

Expand Down Expand Up @@ -77,7 +77,7 @@ if ($LASTEXITCODE -eq 0) {

安装器把自包含 bundle 复制到 `%USERPROFILE%/.quicker/agent-integrations/dsh`。PATH 中有 `dsh` 时会再执行 `dsh plugin --profile web add link:<该目录>`;否则把打印出的命令贴到目标 profile。开发检出可直接 `dsh plugin --profile web add link:<仓库>/plugins/quicker-dsh`。

启用 Quicker 设置 → Agent 中的 MCP 与允许写入,重启 `dsh web` 或 DSH 桌面端。首次连接确认 `dsh-quicker-plugin`。工具名为 `mcp__quicker__skill_load` 这类带命名空间的名称。可以这样开始:
启用 Quicker 设置 → Agent 中的 MCP 与允许写入,重启 `dsh web` 或 DSH 桌面端。首次连接确认 `dsh-quicker-plugin`。工具名为 `mcp__quicker__skill_load` 这类带命名空间的名称。普通对话只会看到技能目录里的 `write-action` 卡片;写动作时模型会按需加载完整说明,也可输入 `/write-action`。可以这样开始:

> 用 Quicker 写一个动作,显示“来自 DeepSeek Harness”,保存到暂存区并打开预览,不运行。

Expand Down
4 changes: 2 additions & 2 deletions docs/兼容性.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
| Cursor CLI | 2026-09-07:2026.08.11-e8db854;v0.2.0 本地安装包技能加载、实时知识发现、4 步动作创建/保存/预览通过。IDE 3.7.12 的插件设置界面重载尚未单独操作验收 |
| Claude Code | 2026-09-07:2.1.263;v0.2.0 插件与市场通过官方 validator,隔离安装及真实用户配置下的公开市场安装成功;识别 write-action 技能与 MCP,mcp list 连接真实 Quicker 成功。模型调用因未登录退出,未验证 Claude 模型写动作 |
| VS Code / Gemini CLI | v0.2.0 默认用户配置安装/更新/卸载和隔离传输通过;尚未完成实际客户端写动作验收 |
| DeepSeek Harness | v0.2.3 补齐 `agent.inject` 的 `id` / `role`,避免会话回放报 `lacks an identified message`;bundle 清单、安装器复制、`dsh` Client 转接与隔离传输通过。0.2.0 已写入的旧会话不会自动修好。尚未完成真实 DSH 会话写动作验收 |
| DeepSeek Harness | v0.2.4 将 `write-action` 注册为 DSH 技能目录卡片,完整说明按需加载,不再在 `agent/session-start` 注入整份正文;bundle 清单、安装器复制、`dsh` Client 转接与隔离传输通过。尚未完成真实 DSH 会话写动作验收 |

## 版本记录

每个平台使用自己的插件 manifest 版本。发布记录应包含平台版本、Quicker 版本或构建、操作系统、插件版本与实测结果。尚未实测的最低版本写为未知,不猜测兼容范围。

当前 Claude Code 安装包版本为 `0.2.1`,补齐安装、认证、诊断与共存指引,MCP 运行配置和共享转接与 `0.2.0` 相同。DeepSeek Harness 安装包为 `0.2.3`,与发布批次 `v0.2.3` 对齐,只修注入消息标识。Codex / Cursor / 通用 MCP 仍为 `0.2.0`。各平台分发方式见[客户端安装](客户端安装.md)。旧个人市场原型使用的 `+codex.<时间戳>` 后缀只用于刷新开发缓存,不代表跨平台发布版本。
当前 Claude Code 安装包版本为 `0.2.1`,补齐安装、认证、诊断与共存指引,MCP 运行配置和共享转接与 `0.2.0` 相同。DeepSeek Harness 安装包为 `0.2.4`,写动作技能改为目录卡片按需加载。Codex / Cursor / 通用 MCP 仍为 `0.2.0`。各平台分发方式见[客户端安装](客户端安装.md)。旧个人市场原型使用的 `+codex.<时间戳>` 后缀只用于刷新开发缓存,不代表跨平台发布版本。

`0.1.1` 修复 `0.1.0` 安装成功但 MCP 无法启动的问题:当前 Codex legacy MCP 加载器不会展开参数中的 `${PLUGIN_ROOT}`,现改用 `cwd: "."` 与包内相对脚本路径。旧版用户按 README 的市场升级与重新安装步骤更新。隔离 HTTP fixture 用于传输回归,真实 Quicker 验收证据见下。

Expand Down
2 changes: 1 addition & 1 deletion docs/客户端安装.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ VS Code / Gemini / DSH 同样替换 Client。卸载只删除归属匹配且未

安装器复制 bundle 后,若 PATH 中有 `dsh`,会执行 `dsh plugin --profile web add link:<安装目录>`。桌面端或其它 profile 把 `web` 换成实际名称。没有 CLI 时,把安装器打印的命令贴进已初始化的 profile。

启用 Quicker 设置 → Agent 中的 MCP 与允许写入,重启 `dsh web` 或桌面端。首次连接确认 `dsh-quicker-plugin`。工具名为 `mcp__quicker__<原名>`。
启用 Quicker 设置 → Agent 中的 MCP 与允许写入,重启 `dsh web` 或桌面端。首次连接确认 `dsh-quicker-plugin`。工具名为 `mcp__quicker__<原名>`。`write-action` 只作为技能目录卡片出现;完整编写说明在 `skill({ name: "write-action" })` 或 `/write-action` 后加载,不会在每次新对话开头注入大段正文。

```powershell
powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "$env:USERPROFILE\.quicker\agent-integrations\dsh\scripts\quicker-mcp.ps1" -Check
Expand Down
8 changes: 4 additions & 4 deletions plugins/quicker-dsh/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Quicker DeepSeek Harness 插件

版本:0.2.3。需要 Windows PowerShell 5.1、已安装的 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(`dsh` CLI 或桌面端),以及设置 → Agent 中带「启用 MCP」入口的本机 Quicker。此目录是完整 DSH bundle:写动作引导、stdio 转接,以及把 `@deepseek-ai/dsh-mcp-client` 接到本机 Quicker 的入口。运行时不依赖开发检出。
版本:0.2.4。需要 Windows PowerShell 5.1、已安装的 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(`dsh` CLI 或桌面端),以及设置 → Agent 中带「启用 MCP」入口的本机 Quicker。此目录是完整 DSH bundle:写动作技能、stdio 转接,以及把 `@deepseek-ai/dsh-mcp-client` 接到本机 Quicker 的入口。运行时不依赖开发检出。

0.2.3 与发布批次 `v0.2.3` 对齐(`quicker-dsh-0.2.3.zip` 内即为 0.2.3)。功能与误标成 0.2.1 的 v0.2.2 相同:补齐 `agent.inject` 的 `id` / `role`。0.2.0 写入的会话在 DSH 回放时会报 `lacks an identified message` 并整段无法加载;本版只阻止新会话再被写坏,不能修好已经落盘的旧日志。
0.2.4 把 `write-action` 注册为 DSH 技能目录卡片:会话开头只出现名称和描述,完整写动作说明在模型调用 `skill({ name: "write-action" })` 或用户输入 `/write-action` 后才加载。不再在每次 `agent/session-start` 注入整份技能正文。0.2.3 曾补齐 `agent.inject` 的 `id` / `role`,避免旧注入消息导致会话无法回放;0.2.0 已写入的会话不会自动修好。

## 安装

Expand Down Expand Up @@ -30,11 +30,11 @@ dsh plugin --profile web add link:<本仓库>/plugins/quicker-dsh

启用 Quicker 设置 → Agent 中的 MCP 与允许写入,然后重启 `dsh web` 或 DSH 桌面端。首次连接在 Quicker 中确认 `dsh-quicker-plugin` 客户端。安装本身不授予执行或覆盖权限。

可以这样开始:
未写动作的对话只会看到技能目录里的 `write-action` 卡片,不会被整份编写协议占用。需要写动作时可以说:

> 用 Quicker 写一个动作,显示“来自 DeepSeek Harness”,保存到暂存区并打开预览,不运行。

Quicker 工具在 DSH 中的名称带命名空间,例如 `mcp__quicker__skill_load`、`mcp__quicker__quicker_create`。默认保存到暂存区;正式保留、覆盖或运行由用户要求和 Quicker 审批决定。
也可以直接输入 `/write-action`。Quicker 工具在 DSH 中的名称带命名空间,例如 `mcp__quicker__skill_load`、`mcp__quicker__quicker_create`;调用结果走 DSH 自带的工具卡片。默认保存到暂存区;正式保留、覆盖或运行由用户要求和 Quicker 审批决定。

## 更新、卸载和诊断

Expand Down
109 changes: 57 additions & 52 deletions plugins/quicker-dsh/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { randomUUID } from 'node:crypto'
import { readFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'

const PACKAGE_ROOT = dirname(fileURLToPath(import.meta.url))
const RELAY_SCRIPT = 'quicker-mcp.ps1'
const SKILL_FILE = join(PACKAGE_ROOT, 'skills', 'write-action', 'SKILL.md')
const SKILL_DIR = join(PACKAGE_ROOT, 'skills', 'write-action')
const SKILL_FILE = join(SKILL_DIR, 'SKILL.md')
const DSH_TOOL_NOTE = [
'Quicker MCP tools appear as mcp__quicker__<toolName>',
'(for example mcp__quicker__skill_load and mcp__quicker__quicker_create).',
'They edit Quicker virtual slots, not this workspace.',
].join(' ')

export const name = 'quicker'
export const inject = ['tools', 'loader']
export const inject = ['tools', 'loader', 'skills']

export function resolvePackageRoot() {
return PACKAGE_ROOT
Expand Down Expand Up @@ -36,63 +41,56 @@ export function mcpClientConfig(root = PACKAGE_ROOT) {
}
}

function loadWriteActionSkill() {
try {
return readFileSync(SKILL_FILE, 'utf8').trim()
} catch {
return [
'Use Quicker MCP tools to create, edit, save and preview actions.',
'Tool names are prefixed as mcp__quicker__<name>.',
'Load action-source with skill_load before editing program.source.yaml.',
].join(' ')
function unquoteYamlScalar(value) {
if (
(value.startsWith('"') && value.endsWith('"'))
|| (value.startsWith("'") && value.endsWith("'"))
) {
return value.slice(1, -1)
}
return value
}

function authoringPreamble() {
return [
'Quicker MCP tools are registered as mcp__quicker__<toolName>',
'(for example mcp__quicker__skill_load and mcp__quicker__quicker_create).',
'They edit Quicker virtual slots, not the local workspace.',
'',
loadWriteActionSkill(),
].join('\n')
}

function assertIdentifiedUserMessage(message) {
if (typeof message !== 'object' || message === null
|| typeof message.id !== 'string' || message.id === '') {
throw new Error('dsh-plugin-quicker inject requires an identified message')
export function parseSkillMarkdown(markdown) {
const match = /^\uFEFF?---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(markdown)
if (!match) {
throw new Error('write-action skill is missing YAML frontmatter')
}
if (message.role !== 'user') {
throw new Error('dsh-plugin-quicker inject requires role user')

const fields = {}
for (const line of match[1].split(/\r?\n/)) {
const separator = line.indexOf(':')
if (separator <= 0) continue
const key = line.slice(0, separator).trim()
const value = unquoteYamlScalar(line.slice(separator + 1).trim())
if (key !== '') fields[key] = value
}
if (typeof message.source !== 'object' || message.source === null
|| typeof message.source.kind !== 'string' || message.source.kind === '') {
throw new Error('dsh-plugin-quicker inject requires a message source')

const name = fields.name?.trim()
const description = fields.description?.trim()
if (!name || !description) {
throw new Error('write-action skill frontmatter requires name and description')
}
if (!Array.isArray(message.content)) {
throw new Error('dsh-plugin-quicker inject requires content')

return {
name,
description,
content: match[2].trim(),
}
}

export function createAuthoringGuideMessage(text) {
const message = {
id: randomUUID(),
role: 'user',
content: [{ type: 'text', text: text ?? authoringPreamble() }],
source: { kind: 'plugin', plugin: 'dsh-plugin-quicker' },
}
assertIdentifiedUserMessage(message)
return message
export function loadWriteActionSkill() {
return parseSkillMarkdown(readFileSync(SKILL_FILE, 'utf8'))
}

function injectAuthoringGuide(agent) {
const message = createAuthoringGuideMessage()
try {
// DSH persist + replay require a complete UserMessage (id + role).
agent.inject(message)
} catch {
// A disposed agent must not fail plugin activation.
export function writeActionSkillRegistration(skill = loadWriteActionSkill()) {
return {
name: skill.name,
description: skill.description,
content: `${DSH_TOOL_NOTE}\n\n${skill.content}`,
source: 'bundled',
path: SKILL_FILE,
resourceBase: { kind: 'directory', path: SKILL_DIR },
}
}

Expand All @@ -104,6 +102,9 @@ export async function apply(ctx) {
if (loader == null || typeof loader.create !== 'function') {
throw new Error('dsh-plugin-quicker requires the DSH loader to register @deepseek-ai/dsh-mcp-client')
}
if (ctx.skills == null || typeof ctx.skills.register !== 'function') {
throw new Error('dsh-plugin-quicker requires ctx.skills to register the write-action skill')
}

await ctx.effect(async () => {
const id = await loader.create({
Expand All @@ -116,7 +117,11 @@ export async function apply(ctx) {
}
}, 'dsh-plugin-quicker: mcp-client')

ctx.on('agent/session-start', ({ agent }) => {
injectAuthoringGuide(agent)
})
// Register a catalog card only. DSH's skill tool loads the body on demand
// (`skill({ name: "write-action" })` or `/write-action`). Do not inject the
// full guide into every session — that crowds out unrelated conversations.
await ctx.effect(
() => ctx.skills.register(writeActionSkillRegistration()),
'dsh-plugin-quicker: write-action',
)
}
2 changes: 1 addition & 1 deletion plugins/quicker-dsh/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dsh-plugin-quicker",
"version": "0.2.3",
"version": "0.2.4",
"description": "通过本机 Quicker MCP 编写、保存和预览自动化动作。",
"type": "module",
"main": "index.js",
Expand Down
102 changes: 0 additions & 102 deletions tests/dsh_inject_reload.mjs

This file was deleted.

Loading
Loading