Merge pull request #1696 from deepseek-harness/codex/dsh-badge-plugin

feat: add optional dsh badge skill provider
This commit is contained in:
Turtle
2026-08-08 16:33:00 +08:00
committed by GitHub
46 changed files with 651 additions and 25 deletions

View File

@@ -218,6 +218,10 @@
- id: skill-local
name: '@deepseek-ai/dsh-skill-local'
- id: skill-badge
name: '@deepseek-ai/dsh-skill-badge'
disabled: true
- id: tool-skill
name: '@deepseek-ai/dsh-tool-skill'

View File

@@ -70,6 +70,7 @@
"@deepseek-ai/dsh-session-title-first-message-llm": "workspace:^",
"@deepseek-ai/dsh-settings-local": "workspace:^",
"@deepseek-ai/dsh-skill": "workspace:^",
"@deepseek-ai/dsh-skill-badge": "workspace:^",
"@deepseek-ai/dsh-skill-local": "workspace:^",
"@deepseek-ai/dsh-spill-local": "workspace:^",
"@deepseek-ai/dsh-spill-policy": "workspace:^",

View File

@@ -0,0 +1 @@
[]

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/skill/README.md
README.md: d10049ac3e741350fddb42f430b70f063da1d12d
README.zh.md: 67f2da6f75edecd180ff861122c6392684ed9bdb
README.md: 533904859ad998de4f371a073fde98b68660097b
README.zh.md: 1fad581cc61a05251f671577dcb7edab37281283

View File

@@ -7,6 +7,7 @@ This family discovers reusable agent instructions and exposes them to the model
| Package | Role | ctx key |
|---|---|---|
| [`skill/`](skill/README.md) | Defines skill provider registration and lookup | `ctx.skills` |
| [`skill-badge/`](skill-badge/README.md) | Contributes the optional bundled dsh badge skill | registers on `ctx.skills` |
| [`skill-local/`](skill-local/README.md) | Discovers skills from local filesystems | registers on `ctx.skills` |
| [`tool-skill/`](tool-skill/README.md) | Publishes the skill catalog and model-facing loader | registers on `ctx.tools` |

View File

@@ -7,6 +7,7 @@
| 包 | 职责 | ctx 键 |
|---|---|---|
| [`skill/`](skill/README.md) | 定义 skill 提供方注册和查找 | `ctx.skills` |
| [`skill-badge/`](skill-badge/README.md) | 贡献可选的内置 dsh 徽章 skill | 注册到 `ctx.skills` |
| [`skill-local/`](skill-local/README.md) | 从本地文件系统发现 skill | 注册到 `ctx.skills` |
| [`tool-skill/`](tool-skill/README.md) | 发布 skill 目录和面向模型的 loader | 注册到 `ctx.tools` |

View File

@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/skill/skill-badge/README.md
README.md: 49b38023a7c110bb52bb351668905c702e251216
README.zh.md: bf7eb0d7d4c0552c07f9cdf5665f8a20df829483

View File

@@ -0,0 +1,22 @@
# @deepseek-ai/dsh-skill-badge
English | [中文](README.zh.md)
Optional bundled skill provider that contributes `dsh-badge` to `ctx.skills`. The skill supplies the official “powered by dsh” Markdown snippets and the packaged PNG for systems that cannot import a remote image reliably.
Mount the plugin to enable the provider. It has no configuration. The shipped CLI composition includes the plugin as `disabled: true`; users must explicitly enable its `skill-badge` row before the skill enters a catalog.
The provider exposes its packaged `assets/` directory as the skill resource base. `dsh-badge.png` is the 726×120 source asset, and consumers render it at 121×20.
## Model Experience
Indirectly, through `@deepseek-ai/dsh-tool-skill`, which renders the catalog entry and selected skill body.
#### KV Cache effect
Disabled by default, the plugin changes no request. When enabled, its catalog entry and any loaded body change the provider KV prefix at their insertion points.
## Known Limitations and Deferred Work
- The provider contributes one fixed skill and has no runtime customization.
- Remote Markdown uses Shields.io; use the packaged PNG when the target cannot fetch remote images reliably.

View File

@@ -0,0 +1,22 @@
# @deepseek-ai/dsh-skill-badge
[English](README.md) | 中文
可选的内置 skill技能提供方`ctx.skills` 贡献 `dsh-badge`。该 skill 提供官方「powered by dsh」Markdown 片段和随包分发的 PNG供无法可靠导入远程图片的系统使用。
挂载该插件即可启用提供方。它没有配置。交付的 CLI命令行界面组合以 `disabled: true` 包含该插件;用户必须显式启用其 `skill-badge` 配置行,该 skill 才会进入目录。
该提供方将随包分发的 `assets/` 目录作为 skill 资源基底公开。`dsh-badge.png` 是尺寸为 726×120 的源图资源,消费方以 121×20 的尺寸渲染。
## 模型体验
通过 `@deepseek-ai/dsh-tool-skill` 间接影响模型;该包会渲染目录条目和所选 skill 的正文。
#### KV Cache 影响
该插件默认禁用,不会改变任何请求。启用后,其目录条目和任何已加载正文都会在各自插入点改变提供方的 KV 前缀。
## 已知限制与暂缓事项
- 该提供方只贡献一个固定 skill不提供运行时自定义。
- 远程 Markdown 使用 Shields.io当目标环境无法可靠获取远程图片时请使用随包分发的 PNG。

View File

@@ -0,0 +1,31 @@
# dsh Badge
Add the official “powered by dsh” badge without recreating or restyling it.
## Assets
- Local PNG: [`dsh-badge.png`](dsh-badge.png), 726×120 source image; render at 121×20
- Shields.io image URL: `https://img.shields.io/badge/powered_by-dsh-4D6BFE?style=flat-square&logo=deepseek&logoColor=white`
- Project URL: `https://github.com/deepseek-ai/deepseek-harness-sdk`
## Markdown
Use this linked badge in Markdown:
```markdown
[![](https://img.shields.io/badge/powered_by-dsh-4D6BFE?style=flat-square&logo=deepseek&logoColor=white)](https://github.com/deepseek-ai/deepseek-harness-sdk)
```
If attribution should not be linked, use:
```markdown
![](https://img.shields.io/badge/powered_by-dsh-4D6BFE?style=flat-square&logo=deepseek&logoColor=white)
```
## Usage rules
- For GitHub or GitLab Markdown, use the Shields.io URL and link it to the project URL unless the user asks for an unlinked image.
- For Feishu and other systems that import remote images unreliably, upload `dsh-badge.png` from this skill directory instead of generating another badge.
- Preserve the badge's 121×20 dimensions and aspect ratio.
- Place the badge at the end of the attributed document or section unless the user specifies another position.
- Do not substitute another color, logo, label, or project URL.

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,37 @@
{
"name": "@deepseek-ai/dsh-skill-badge",
"description": "Bundled dsh badge skill provider for DeepSeek Harness",
"version": "0.0.1",
"private": true,
"type": "module",
"main": "lib/index.js",
"types": "lib/types/index.d.ts",
"exports": {
".": {
"types": "./lib/types/index.d.ts",
"default": "./lib/index.js"
},
"./invariant": {
"types": "./lib/types/invariant.d.ts",
"default": "./lib/invariant.js"
},
"./package.json": "./package.json"
},
"files": [
"lib/index.js",
"lib/invariant.js",
"assets",
"lib/types/**/*.d.ts"
],
"license": "BSD-3-Clause",
"peerDependencies": {
"@deepseek-ai/dsh-invariants": "^0.0.1",
"@deepseek-ai/dsh-skill": "^0.0.1",
"cordis": "^4.0.0-rc.7"
},
"devDependencies": {
"@deepseek-ai/dsh-invariants": "workspace:^",
"@deepseek-ai/dsh-skill": "workspace:^",
"cordis": "^4.0.0-rc.7"
}
}

View File

@@ -0,0 +1,60 @@
/**
* Bundled `dsh-badge` skill provider.
*
* @module @deepseek-ai/dsh-skill-badge
*/
import { readFile } from 'node:fs/promises'
import { fileURLToPath } from 'node:url'
import type { Context } from 'cordis'
import {
BUNDLED_SKILL_RANK,
type SkillCandidate,
type SkillDefinition,
type SkillProvider,
} from '@deepseek-ai/dsh-skill'
const PROVIDER_NAME = 'dsh-badge'
const SKILL_BODY_URL = new URL('../assets/dsh-badge.md', import.meta.url)
const RESOURCE_BASE = {
kind: 'directory',
path: fileURLToPath(new URL('../assets/', import.meta.url)),
} as const
const INVOCATION = { modelInvocable: true, userInvocable: true } as const
const DESCRIPTION = 'Add the official “powered by dsh” badge to documents, pull requests, merge requests, and other content produced with DeepSeek Harness. Use whenever creating a pull request or merge request. Also use when the user asks for a dsh badge, powered-by-dsh attribution, or a reusable dsh badge asset or snippet.'
const CANDIDATE: SkillCandidate = {
name: 'dsh-badge',
description: DESCRIPTION,
invocation: INVOCATION,
provider: PROVIDER_NAME,
source: 'bundled',
resourceBase: RESOURCE_BASE,
rank: BUNDLED_SKILL_RANK,
locator: SKILL_BODY_URL,
}
const provider: SkillProvider = {
name: PROVIDER_NAME,
list: () => Promise.resolve([CANDIDATE]),
async get(_candidate): Promise<SkillDefinition> {
return {
name: CANDIDATE.name,
description: CANDIDATE.description,
invocation: CANDIDATE.invocation,
provider: CANDIDATE.provider,
source: CANDIDATE.source,
resourceBase: RESOURCE_BASE,
content: await readFile(SKILL_BODY_URL, 'utf8'),
}
},
}
/** Cordis plugin name. */
export const name = 'skill-badge'
/** Service required by the bundled provider. */
export const inject = ['skills']
/** Register the bundled `dsh-badge` provider on `ctx.skills`. */
export function apply(ctx: Context): void {
ctx.skills.registerProvider(() => provider)
}

View File

@@ -0,0 +1,30 @@
/**
* Package-owned invariant companion for `@deepseek-ai/dsh-skill-badge`.
* @module @deepseek-ai/dsh-skill-badge/invariant
*/
/* jscpd:ignore-start */
import type { Context } from 'cordis'
import type { InvariantInstaller } from '@deepseek-ai/dsh-invariants'
const PACKAGE_NAME = '@deepseek-ai/dsh-skill-badge'
/** Cordis companion plugin name. */
export const name = 'skill-badge-invariant'
/** Service required before the companion can reserve package ownership. */
export const inject = ['invariants']
/**
* No runtime invariant: the package owns one immutable provider registration,
* while the skill registry owns registration uniqueness and lifecycle checks.
*/
const install: InvariantInstaller = () => {}
/**
* Register this package's invariant companion.
* @param ctx - Cordis context carrying the invariant service.
* @returns the installed registration's disposer after setup succeeds.
*/
export const apply = (ctx: Context): Promise<() => void> =>
Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install))
/* jscpd:ignore-end */

View File

@@ -0,0 +1,40 @@
import { createHash } from 'node:crypto'
import { readFile } from 'node:fs/promises'
import { fileURLToPath } from 'node:url'
import { Context } from 'cordis'
import { describe, expect, it } from 'vitest'
import SkillService from '@deepseek-ai/dsh-skill'
import * as SkillBadge from '@deepseek-ai/dsh-skill-badge'
describe('dsh-skill-badge', () => {
it('registers and disposes the bundled badge skill', async () => {
const ctx = new Context()
await ctx.plugin(SkillService)
const fiber = await ctx.plugin(SkillBadge)
const resourcePath = fileURLToPath(new URL('../assets/', import.meta.url))
expect(await ctx.skills.list()).toEqual([{
name: 'dsh-badge',
description: 'Add the official “powered by dsh” badge to documents, pull requests, merge requests, and other content produced with DeepSeek Harness. Use whenever creating a pull request or merge request. Also use when the user asks for a dsh badge, powered-by-dsh attribution, or a reusable dsh badge asset or snippet.',
invocation: { modelInvocable: true, userInvocable: true },
provider: 'dsh-badge',
source: 'bundled',
resourceBase: { kind: 'directory', path: resourcePath },
}])
const loaded = await ctx.skills.get('dsh-badge')
expect(loaded?.content).toContain('Preserve the badge\'s 121×20 dimensions')
expect(loaded?.resourceBase).toEqual({ kind: 'directory', path: resourcePath })
await fiber.dispose()
expect(await ctx.skills.list()).toEqual([])
})
it('ships the official 726×120 PNG unchanged', async () => {
const image = await readFile(new URL('../assets/dsh-badge.png', import.meta.url))
expect(image.readUInt32BE(16)).toBe(726)
expect(image.readUInt32BE(20)).toBe(120)
expect(createHash('sha256').update(image).digest('hex')).toBe(
'f2c4f5ec9cbe847c0c763545c4d839efa8485bc74203733d0a0e8259f233c653',
)
})
})

View File

@@ -0,0 +1,14 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "lib/types"
},
"include": ["src"],
"references": [
{ "path": "../../../vendor/cosmokit" },
{ "path": "../../../vendor/cordis" },
{ "path": "../skill" },
{ "path": "../../support/invariants" }
]
}

View File

@@ -21,6 +21,7 @@ import { parse as parseYaml } from 'yaml'
import type { FileSystem, FsDirEntry, FsTarget } from '@deepseek-ai/dsh-fs'
import { resolveDshHome } from '@deepseek-ai/dsh-paths'
import {
BUNDLED_SKILL_RANK,
isSkillName,
type SkillCandidate,
type SkillDefinition,
@@ -40,7 +41,6 @@ const USER_AGENTS_RANK = 500
const DEFAULT_WATCH_STABILITY_THRESHOLD_MS = 200
const DEFAULT_WATCH_POLL_INTERVAL_MS = 100
const DEFAULT_WATCH_MAX_PROJECTS = 128
const BUNDLED_RANK = 600
export const name = 'skill-local'
export const inject = ['skills']
@@ -256,7 +256,7 @@ export class LocalSkillProvider implements SkillProvider {
)
}
if (this.bundledSkillDir !== undefined) {
roots.push({ path: this.bundledSkillDir, source: 'bundled', rank: BUNDLED_RANK, trustedHost: true })
roots.push({ path: this.bundledSkillDir, source: 'bundled', rank: BUNDLED_SKILL_RANK, trustedHost: true })
}
return roots
}

View File

@@ -20,6 +20,9 @@ const MAX_COLLECT_ATTEMPTS = 2
const RUNTIME_PROVIDER = 'runtime'
const RUNTIME_RANK = 250
/** Standard precedence rank for packaged skill providers and local bundled roots. */
export const BUNDLED_SKILL_RANK = 600
/**
* Return whether a string is a valid kebab-case skill name.
* @param name - candidate skill name to validate.