mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
docs: replace nonexistent repository references
This commit is contained in:
@@ -2,5 +2,5 @@
|
|||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# 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:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-21-mandatory-app-attribution-headers.md
|
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-21-mandatory-app-attribution-headers.md
|
||||||
2026-06-21-mandatory-app-attribution-headers.md: 12482ca80d19e5cd1e62b8860865db6cccea61ab
|
2026-06-21-mandatory-app-attribution-headers.md: 39050a53ec76e8c5a6cac4d8e31fa15b992c406e
|
||||||
2026-06-21-mandatory-app-attribution-headers.zh.md: 43f356887948b88d34ba41d46ed1cd2f1c89a1e2
|
2026-06-21-mandatory-app-attribution-headers.zh.md: bfd6aa2540022f68cf9f69ccc2c12b3bc0978960
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ The provider-neutral identity is owned by `dsh-llm` (`packages/llm/llm/src/attri
|
|||||||
|
|
||||||
- product token for `User-Agent`: `deepseek-harness` (continuity with the pre-Agent Note wire value and the repo/org identity)
|
- product token for `User-Agent`: `deepseek-harness` (continuity with the pre-Agent Note wire value and the repo/org identity)
|
||||||
- version: read from the owning package's manifest via `createRequire`, never a hand-copied constant
|
- version: read from the owning package's manifest via `createRequire`, never a hand-copied constant
|
||||||
- app URL: `https://github.com/deepseek-ai/deepseek-harness-sdk` - the planned public home, which must exist before release
|
- app URL: `https://github.com/deepseek-ai/deepseek-harness` - the repository home
|
||||||
|
|
||||||
The default is mandatory and non-empty. White-label deployments pass their own `AppIdentity` to `attributionHeaders(identity)` - the override hook is the function parameter, with no deployment config plumbing until a consumer needs it - and omission falls back to the harness default rather than suppressing attribution. There is no per-request API for the model, user prompt, session id, cwd, user email, API key owner, or local machine identity to influence these fields.
|
The default is mandatory and non-empty. White-label deployments pass their own `AppIdentity` to `attributionHeaders(identity)` - the override hook is the function parameter, with no deployment config plumbing until a consumer needs it - and omission falls back to the harness default rather than suppressing attribution. There is no per-request API for the model, user prompt, session id, cwd, user email, API key owner, or local machine identity to influence these fields.
|
||||||
|
|
||||||
@@ -77,8 +77,6 @@ The landed contract:
|
|||||||
|
|
||||||
**Providers see that traffic comes from the harness.** That is the point, but it means deployments that previously blended into generic SDK traffic become identifiable. Mitigation: send only static public product data and let forks/white-label deployments pass their own `AppIdentity`.
|
**Providers see that traffic comes from the harness.** That is the point, but it means deployments that previously blended into generic SDK traffic become identifiable. Mitigation: send only static public product data and let forks/white-label deployments pass their own `AppIdentity`.
|
||||||
|
|
||||||
**The app URL points at a repository that does not exist yet.** `deepseek-ai/deepseek-harness-sdk` is the planned public home; until it is created the URL is a dangling promise that blocks release.
|
|
||||||
|
|
||||||
**Header support differs by client library.** The hand-rolled adapter sets headers directly; the pi-ai-backed adapter depends on pi-ai continuing to honor `StreamOptions.headers` (merged last over provider defaults). The wire-level mock-server tests are the guard: if a pi-ai upgrade stops delivering the header, the suite goes red. This is useful pressure on the abstraction: a provider adapter that cannot set mandatory headers cannot fully implement the harness LLM contract.
|
**Header support differs by client library.** The hand-rolled adapter sets headers directly; the pi-ai-backed adapter depends on pi-ai continuing to honor `StreamOptions.headers` (merged last over provider defaults). The wire-level mock-server tests are the guard: if a pi-ai upgrade stops delivering the header, the suite goes red. This is useful pressure on the abstraction: a provider adapter that cannot set mandatory headers cannot fully implement the harness LLM contract.
|
||||||
|
|
||||||
**OpenRouter rankings do not benefit yet.** `User-Agent` is the correct baseline for provider-neutral HTTP identity, but it will not create OpenRouter app pages or rankings because OpenRouter requires `HTTP-Referer` for that product feature. That is deliberate: public app marketplace participation is a separate product decision, not a prerequisite for mandatory request attribution.
|
**OpenRouter rankings do not benefit yet.** `User-Agent` is the correct baseline for provider-neutral HTTP identity, but it will not create OpenRouter app pages or rankings because OpenRouter requires `HTTP-Referer` for that product feature. That is deliberate: public app marketplace participation is a separate product decision, not a prerequisite for mandatory request attribution.
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ OpenRouter 应用归属刻意未实现。`HTTP-Referer`、`X-OpenRouter-Title`
|
|||||||
|
|
||||||
- `User-Agent` 的产品 token:`deepseek-harness`(与 Agent Note 之前的线路值及仓库/组织身份保持连续性)
|
- `User-Agent` 的产品 token:`deepseek-harness`(与 Agent Note 之前的线路值及仓库/组织身份保持连续性)
|
||||||
- 版本:通过 `createRequire` 从所属包的 manifest(元数据清单)读取,绝不手动复制常量
|
- 版本:通过 `createRequire` 从所属包的 manifest(元数据清单)读取,绝不手动复制常量
|
||||||
- 应用 URL:`https://github.com/deepseek-ai/deepseek-harness-sdk`——计划中的公开主页,且必须在发布前实际存在
|
- 应用 URL:`https://github.com/deepseek-ai/deepseek-harness`——仓库主页
|
||||||
|
|
||||||
默认值是强制的且非空。白标部署通过向 `attributionHeaders(identity)` 传入自己的 `AppIdentity` 来覆盖——覆盖钩子就是函数参数,在有消费方需要之前不做部署配置管道——省略时回退到 harness 默认值而非抑制归属。没有逐请求 API 允许模型、用户提示词、会话 id、cwd、用户邮箱、API key 所有者或本地机器身份影响这些字段。
|
默认值是强制的且非空。白标部署通过向 `attributionHeaders(identity)` 传入自己的 `AppIdentity` 来覆盖——覆盖钩子就是函数参数,在有消费方需要之前不做部署配置管道——省略时回退到 harness 默认值而非抑制归属。没有逐请求 API 允许模型、用户提示词、会话 id、cwd、用户邮箱、API key 所有者或本地机器身份影响这些字段。
|
||||||
|
|
||||||
@@ -77,8 +77,6 @@ OpenRouter 应用归属刻意未实现。`HTTP-Referer`、`X-OpenRouter-Title`
|
|||||||
|
|
||||||
**提供方看到流量来自 harness。** 这正是目的,但意味着此前混在通用 SDK 流量中的部署变得可识别。缓解措施:仅发送静态公开产品数据,并允许 fork/白标部署传入自己的 `AppIdentity`。
|
**提供方看到流量来自 harness。** 这正是目的,但意味着此前混在通用 SDK 流量中的部署变得可识别。缓解措施:仅发送静态公开产品数据,并允许 fork/白标部署传入自己的 `AppIdentity`。
|
||||||
|
|
||||||
**应用 URL 指向一个尚不存在的仓库。** `deepseek-ai/deepseek-harness-sdk` 是计划中的公开主页;在它创建之前,该 URL 是一个阻塞发布的悬空承诺。
|
|
||||||
|
|
||||||
**不同客户端库的头部支持有差异。** 手写适配器直接设置头部;基于 pi-ai 的适配器依赖 pi-ai 继续尊重 `StreamOptions.headers`(最后合并覆盖提供方默认值)。线路级 mock 服务器测试是守卫:如果 pi-ai 升级后不再投递该头部,套件会变红。这对抽象施加了有益的压力:一个无法设置强制头部的提供方适配器不能完整实现 harness 的 LLM 约定。
|
**不同客户端库的头部支持有差异。** 手写适配器直接设置头部;基于 pi-ai 的适配器依赖 pi-ai 继续尊重 `StreamOptions.headers`(最后合并覆盖提供方默认值)。线路级 mock 服务器测试是守卫:如果 pi-ai 升级后不再投递该头部,套件会变红。这对抽象施加了有益的压力:一个无法设置强制头部的提供方适配器不能完整实现 harness 的 LLM 约定。
|
||||||
|
|
||||||
**OpenRouter 排名尚未受益。** `User-Agent` 是提供方无关的 HTTP 身份的正确基线,但它不会创建 OpenRouter 应用页面或排名,因为 OpenRouter 要求 `HTTP-Referer` 来实现该产品功能。这是有意为之:公开应用市场参与是一个独立的产品决策,不是强制请求归属的前提。
|
**OpenRouter 排名尚未受益。** `User-Agent` 是提供方无关的 HTTP 身份的正确基线,但它不会创建 OpenRouter 应用页面或排名,因为 OpenRouter 要求 `HTTP-Referer` 来实现该产品功能。这是有意为之:公开应用市场参与是一个独立的产品决策,不是强制请求归属的前提。
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# 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:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-07-13-documentation-site-projection.md
|
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-07-13-documentation-site-projection.md
|
||||||
2026-07-13-documentation-site-projection.md: d9af915754fa6a1df51a27d18d412597472aaa73
|
2026-07-13-documentation-site-projection.md: 309dbd96c5f1ca87d137cdc3839acfc5c5aa22f2
|
||||||
2026-07-13-documentation-site-projection.zh.md: 7d7b4752b8f27d55aae8426a7dc001ce4340e661
|
2026-07-13-documentation-site-projection.zh.md: b01965fb1b46ab618b5b8bcb748bb5a8940d6e69
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ Canonical Markdown remains in the repository tier that owns it. Product-facing g
|
|||||||
|
|
||||||
Locale home projections retain only the canonical YAML frontmatter. The repository-facing body can keep its H1 and bilingual source links, while the VitePress home theme owns the rendered hero and features and the site navigation owns locale switching.
|
Locale home projections retain only the canonical YAML frontmatter. The repository-facing body can keep its H1 and bilingual source links, while the VitePress home theme owns the rendered hero and features and the site navigation owns locale switching.
|
||||||
|
|
||||||
The projector parses Markdown links without reserializing the document. A link to another published source becomes a site-relative route; a link to an unpublished repository file becomes a source link under the public `deepseek-ai/deepseek-harness-sdk` home; a repository image is copied into the generated tree and referenced from there ([why](2026-08-06-doc-site-carries-its-images.md)). Missing relative targets fail projection. Unit tests pin these transformations, and `docs:check` runs the projector tests plus a production VitePress build as part of `doc-sync` and the parallel documentation gates.
|
The projector parses Markdown links without reserializing the document. A link to another published source becomes a site-relative route; a link to an unpublished repository file becomes a source link under the `deepseek-ai/deepseek-harness` repository home; a repository image is copied into the generated tree and referenced from there ([why](2026-08-06-doc-site-carries-its-images.md)). Missing relative targets fail projection. Unit tests pin these transformations, and `docs:check` runs the projector tests plus a production VitePress build as part of `doc-sync` and the parallel documentation gates.
|
||||||
|
|
||||||
`verify-public-repository-links` rejects internal repository remotes from tracked files. Public source links use the public home, while work tracking stays in repository metadata and source carries a TODO only when the local boundary matters to maintainers.
|
`verify-public-repository-links` rejects references to the unavailable legacy repository from tracked files. Source and edit links use the current repository home.
|
||||||
|
|
||||||
`website/AGENTS.md` is the only maintained Markdown file in the website subtree. The projector test enumerates tracked and unignored files and rejects any other website Markdown, so site-specific locale, route, API, or generated source copies cannot bypass the publication manifest.
|
`website/AGENTS.md` is the only maintained Markdown file in the website subtree. The projector test enumerates tracked and unignored files and rejects any other website Markdown, so site-specific locale, route, API, or generated source copies cannot bypass the publication manifest.
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ Status: implemented
|
|||||||
|
|
||||||
各 locale 的首页投影只保留权威 YAML frontmatter。面向仓库的正文可以保留其 H1 和双语源文件链接,而 VitePress 首页主题负责渲染 hero 与功能区,网站导航负责切换 locale。
|
各 locale 的首页投影只保留权威 YAML frontmatter。面向仓库的正文可以保留其 H1 和双语源文件链接,而 VitePress 首页主题负责渲染 hero 与功能区,网站导航负责切换 locale。
|
||||||
|
|
||||||
投影器解析 Markdown 链接,但不会重新序列化文档。指向另一个已发布源文件的链接会变成站内相对路由;指向未发布仓库文件的链接会变成公开 `deepseek-ai/deepseek-harness-sdk` 主页下的源文件链接;仓库图片会被拷贝进生成树并从那里引用([原因](2026-08-06-doc-site-carries-its-images.md))。相对目标不存在时,投影会失败。单元测试会锁定这些转换行为,`docs:check` 则运行投影器测试和 VitePress 生产构建,并将二者纳入 `doc-sync` 和并行文档门禁。
|
投影器解析 Markdown 链接,但不会重新序列化文档。指向另一个已发布源文件的链接会变成站内相对路由;指向未发布仓库文件的链接会变成 `deepseek-ai/deepseek-harness` 仓库主页下的源文件链接;仓库图片会被拷贝进生成树并从那里引用([原因](2026-08-06-doc-site-carries-its-images.md))。相对目标不存在时,投影会失败。单元测试会锁定这些转换行为,`docs:check` 则运行投影器测试和 VitePress 生产构建,并将二者纳入 `doc-sync` 和并行文档门禁。
|
||||||
|
|
||||||
`verify-public-repository-links` 会拒绝已跟踪文件中的内部仓库远程链接。公开源文件链接使用公开主页,而工作跟踪留在仓库元数据中;只有本地边界对维护者有意义时,源文件才保留 TODO。
|
`verify-public-repository-links` 会拒绝已跟踪文件中指向不可用旧仓库的引用。源文件链接和编辑链接使用当前仓库主页。
|
||||||
|
|
||||||
`website/AGENTS.md` 是网站子树中唯一维护的 Markdown 文件。投影器测试会枚举所有已跟踪文件和未被忽略的未跟踪文件,并拒绝网站中的任何其他 Markdown,因此网站专用的 locale、路由、API 或生成源文件副本无法绕过发布 manifest。
|
`website/AGENTS.md` 是网站子树中唯一维护的 Markdown 文件。投影器测试会枚举所有已跟踪文件和未被忽略的未跟踪文件,并拒绝网站中的任何其他 Markdown,因此网站专用的 locale、路由、API 或生成源文件副本无法绕过发布 manifest。
|
||||||
|
|
||||||
|
|||||||
@@ -85,14 +85,14 @@ describe('dsh badge assembled snapshot', () => {
|
|||||||
|
|
||||||
- Local PNG: [\`dsh-badge.png\`](dsh-badge.png), 726×120 source image; render at 121×20
|
- 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\`
|
- 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\`
|
- Project URL: \`https://github.com/deepseek-ai/deepseek-harness\`
|
||||||
|
|
||||||
## Markdown
|
## Markdown
|
||||||
|
|
||||||
Use this linked badge in Markdown:
|
Use this linked badge in Markdown:
|
||||||
|
|
||||||
\`\`\`markdown
|
\`\`\`markdown
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
If attribution should not be linked, use:
|
If attribution should not be linked, use:
|
||||||
@@ -124,14 +124,14 @@ describe('dsh badge assembled snapshot', () => {
|
|||||||
|
|
||||||
- Local PNG: [\`dsh-badge.png\`](dsh-badge.png), 726×120 source image; render at 121×20
|
- 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\`
|
- 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\`
|
- Project URL: \`https://github.com/deepseek-ai/deepseek-harness\`
|
||||||
|
|
||||||
## Markdown
|
## Markdown
|
||||||
|
|
||||||
Use this linked badge in Markdown:
|
Use this linked badge in Markdown:
|
||||||
|
|
||||||
\`\`\`markdown
|
\`\`\`markdown
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
If attribution should not be linked, use:
|
If attribution should not be linked, use:
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# 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:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/01-first-plugin.md
|
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/01-first-plugin.md
|
||||||
01-first-plugin.md: 448034b54107d5620673052ad388feecc22fe1e1
|
01-first-plugin.md: 79df2f42df1f34a7ef32cc81607e1b926a1854ae
|
||||||
01-first-plugin.zh.md: a1838be61f8099831d59afa266fe40ce6bd165bf
|
01-first-plugin.zh.md: 87cd7a96843d69d68fb95662e59bbfb9ebfc2a37
|
||||||
|
|||||||
@@ -92,4 +92,4 @@ One caveat worth knowing early: a config entry whose module cannot be **resolved
|
|||||||
|
|
||||||
Next: [Lifecycle and effects](02-lifecycle-and-effects.md) — what happens when a plugin unloads.
|
Next: [Lifecycle and effects](02-lifecycle-and-effects.md) — what happens when a plugin unloads.
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -92,4 +92,4 @@ export function apply(ctx: Context) {
|
|||||||
|
|
||||||
下一章:[生命周期与 effect](02-lifecycle-and-effects.md):插件卸载时会发生什么。
|
下一章:[生命周期与 effect](02-lifecycle-and-effects.md):插件卸载时会发生什么。
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# 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:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/02-lifecycle-and-effects.md
|
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/02-lifecycle-and-effects.md
|
||||||
02-lifecycle-and-effects.md: 3e88c6f1e1fb1bc825fb74434520993c855010c3
|
02-lifecycle-and-effects.md: 8e75708eb0cba1aceb7fa3dae5ae334995eb113f
|
||||||
02-lifecycle-and-effects.zh.md: 3cceecfb8334f2ed2ec9942fa876a0e51e1b315f
|
02-lifecycle-and-effects.zh.md: bc4489e702ab58b5d1efd8a72fc693ee48af2624
|
||||||
|
|||||||
@@ -95,4 +95,4 @@ One ordering caveat: disposers start in reverse registration order, but multiple
|
|||||||
|
|
||||||
Next: [Services](03-services.md) — how plugins share capabilities.
|
Next: [Services](03-services.md) — how plugins share capabilities.
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -95,4 +95,4 @@ PENDING → LOADING → ACTIVE → UNLOADING → DISPOSED
|
|||||||
|
|
||||||
下一章:[服务](03-services.md):插件如何共享功能。
|
下一章:[服务](03-services.md):插件如何共享功能。
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# 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:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/03-services.md
|
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/03-services.md
|
||||||
03-services.md: 3f2273ba4061912640e409d7b4deb4cd1b45684f
|
03-services.md: 32007284be99ef46b4621089c9b3a80317e77189
|
||||||
03-services.zh.md: 657271aba6c0b2e824c79fa822e29c8a6dcf4275
|
03-services.zh.md: d82be29aa69686b8dc10cc6a45a658683c017cbd
|
||||||
|
|||||||
@@ -95,4 +95,4 @@ Service names live in one flat namespace per application. Prefix or namespace yo
|
|||||||
|
|
||||||
Next: [Events](04-events.md) — communication without a shared service.
|
Next: [Events](04-events.md) — communication without a shared service.
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -95,4 +95,4 @@ export function apply(ctx: Context) {
|
|||||||
|
|
||||||
下一章:[事件](04-events.md):无需共享服务即可通信。
|
下一章:[事件](04-events.md):无需共享服务即可通信。
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# 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:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/04-events.md
|
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/04-events.md
|
||||||
04-events.md: 0302adf7c81b802b406f5f6737539ccf3eb970f9
|
04-events.md: db911b9a06d7304d73030a2020de3d465fde2f9c
|
||||||
04-events.zh.md: ae41e757c06a46ef70c250c94a124546769e0112
|
04-events.zh.md: e0357b2c04785d52a54f839d1b8ff3ecccb027ed
|
||||||
|
|||||||
@@ -141,4 +141,4 @@ The harness uses waterfalls for decisions that cooperating plugins may wrap or a
|
|||||||
|
|
||||||
Next: [Configuration](05-config.md) — plugin options from `cordis.yml`.
|
Next: [Configuration](05-config.md) — plugin options from `cordis.yml`.
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -141,4 +141,4 @@ harness 使用 waterfall 处理协作插件可以包装或回答的决策:[`ag
|
|||||||
|
|
||||||
下一章:[配置](05-config.md):来自 `cordis.yml` 的插件选项。
|
下一章:[配置](05-config.md):来自 `cordis.yml` 的插件选项。
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# 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:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/05-config.md
|
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/05-config.md
|
||||||
05-config.md: ad73a732242e4015b2976e6fb193ff464e148dfa
|
05-config.md: 2357f663135d6fc78a65f9d0952e0bc3f5eefae4
|
||||||
05-config.zh.md: edb3c4113288dfa80e899fb2e5eb21a67d929ca6
|
05-config.zh.md: fbd94d179494ad0b6f73baff2ca525c786cc9e33
|
||||||
|
|||||||
@@ -81,4 +81,4 @@ The loader used in this repo supports a `!!js` tag for config values that must b
|
|||||||
|
|
||||||
Next: [Composition and HMR](06-composition-and-hmr.md) — treating `cordis.yml` as the application.
|
Next: [Composition and HMR](06-composition-and-hmr.md) — treating `cordis.yml` as the application.
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -81,4 +81,4 @@ ValidationError: invalid config:
|
|||||||
|
|
||||||
下一章:[组合与 HMR(热模块替换)](06-composition-and-hmr.md):将 `cordis.yml` 视为应用。
|
下一章:[组合与 HMR(热模块替换)](06-composition-and-hmr.md):将 `cordis.yml` 视为应用。
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# 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:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/06-composition-and-hmr.md
|
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/06-composition-and-hmr.md
|
||||||
06-composition-and-hmr.md: 490e3de3a98dd823190deefd47e1b6f2f8ba71b5
|
06-composition-and-hmr.md: 87ea26014657ae8c8199e1ebb486556c827d96ca
|
||||||
06-composition-and-hmr.zh.md: 4aefb5ecd036929590ab373a2883d90779997b4b
|
06-composition-and-hmr.zh.md: 830f55de7c1be351fe701cb068197543602619a7
|
||||||
|
|||||||
@@ -110,4 +110,4 @@ needs-timer is PENDING — a required service is missing
|
|||||||
|
|
||||||
Next: [Into the harness](07-into-the-harness.md) — the same patterns against real harness services.
|
Next: [Into the harness](07-into-the-harness.md) — the same patterns against real harness services.
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -110,4 +110,4 @@ needs-timer is PENDING — a required service is missing
|
|||||||
|
|
||||||
下一章:[进入 harness](07-into-the-harness.md):把相同模式用于真实的 harness 服务。
|
下一章:[进入 harness](07-into-the-harness.md):把相同模式用于真实的 harness 服务。
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# 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:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/07-into-the-harness.md
|
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/07-into-the-harness.md
|
||||||
07-into-the-harness.md: 41a30f032ac02d8e9e3b17ac8d9cd13e9973e36a
|
07-into-the-harness.md: 2d3c23f9f7f7fc6bd6cabd4e7e68ebfc46e20665
|
||||||
07-into-the-harness.zh.md: 159cede00d453796f6a2cacae184229d71e17f87
|
07-into-the-harness.zh.md: 45dc0ee6f07ab3b0275499cd4ab0c436eebdddef
|
||||||
|
|||||||
@@ -104,4 +104,4 @@ Where to go next:
|
|||||||
- The generated `cordis-surface` regions on the [subsystem pages](../subsystems/core.md) — everything you can inject and listen to, each on its owning page.
|
- The generated `cordis-surface` regions on the [subsystem pages](../subsystems/core.md) — everything you can inject and listen to, each on its owning page.
|
||||||
- [Architecture](../architecture.md) — the system map these plugins live in.
|
- [Architecture](../architecture.md) — the system map these plugins live in.
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -104,4 +104,4 @@ logger 会先触发:`tools/result` 在结果物化过程中发出,发生在
|
|||||||
- [子系统页面](../subsystems/core.md)上生成的 `cordis-surface` 区块:可以注入和监听的所有内容,各在其所属页面上。
|
- [子系统页面](../subsystems/core.md)上生成的 `cordis-surface` 区块:可以注入和监听的所有内容,各在其所属页面上。
|
||||||
- [架构](../architecture.md):这些插件所处的系统地图。
|
- [架构](../architecture.md):这些插件所处的系统地图。
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# 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:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/index.md
|
# pnpm run verify-translation-pairing --write docs/cordis-tutorial/index.md
|
||||||
index.md: cf61fec07acd2022591cd858ba4146b6a4ae1a3d
|
index.md: fb700344e6d07d3864655009d2edac15ee9eede8
|
||||||
index.zh.md: 775bf2fce2138b9edd91f5ee46b93b8c4eb4559e
|
index.zh.md: a68e931d81e745164d8f9a5dc7ec9aec4cd0e590
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ If you want the condensed concept reference instead of a walkthrough, read the [
|
|||||||
You need a clone of this repository with dependencies installed — the [quick start](../user/guide/quickstart.md) covers prerequisites. No API key is needed for this tutorial; every example runs keylessly.
|
You need a clone of this repository with dependencies installed — the [quick start](../user/guide/quickstart.md) covers prerequisites. No API key is needed for this tutorial; every example runs keylessly.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/deepseek-ai/deepseek-harness-sdk.git
|
git clone https://github.com/deepseek-ai/deepseek-harness.git
|
||||||
cd deepseek-harness
|
cd deepseek-harness
|
||||||
pnpm install
|
pnpm install
|
||||||
```
|
```
|
||||||
@@ -55,4 +55,4 @@ The examples use three TypeScript features beyond ordinary modern JavaScript:
|
|||||||
|
|
||||||
Chapter 5 also uses an `interface` to describe a configuration object's fields and a generic type such as `Schema<Config>` to say which object fields a schema validates. You can copy those declarations as shown; the surrounding text explains what each one connects.
|
Chapter 5 also uses an `interface` to describe a configuration object's fields and a generic type such as `Schema<Config>` to say which object fields a schema validates. You can copy those declarations as shown; the surrounding text explains what each one connects.
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Cordis 是 DeepSeek Harness SDK 底层的插件框架:它是一个小型运行
|
|||||||
你需要克隆本仓库并安装依赖,具体前置条件见[快速入门](../user/guide/quickstart.md)。本教程不需要 API 密钥;所有示例均可在无密钥环境中运行。
|
你需要克隆本仓库并安装依赖,具体前置条件见[快速入门](../user/guide/quickstart.md)。本教程不需要 API 密钥;所有示例均可在无密钥环境中运行。
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/deepseek-ai/deepseek-harness-sdk.git
|
git clone https://github.com/deepseek-ai/deepseek-harness.git
|
||||||
cd deepseek-harness
|
cd deepseek-harness
|
||||||
pnpm install
|
pnpm install
|
||||||
```
|
```
|
||||||
@@ -55,4 +55,4 @@ node --import tsx ../../vendor/cordis/bin.js
|
|||||||
|
|
||||||
第 5 章还会使用 `interface` 描述配置对象的字段,并使用 `Schema<Config>` 这类泛型表示 schema 校验哪些对象字段。你可以直接照写这些声明;周围的正文会解释每项声明连接了什么。
|
第 5 章还会使用 `interface` 描述配置对象的字段,并使用 `Schema<Config>` 这类泛型表示 schema 校验哪些对象字段。你可以直接照写这些声明;周围的正文会解释每项声明连接了什么。
|
||||||
|
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# 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:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write docs/subsystems/llm-streaming.md
|
# pnpm run verify-translation-pairing --write docs/subsystems/llm-streaming.md
|
||||||
llm-streaming.md: 8ae4e8b376b4c4221e6179eb719fcf162f3031e4
|
llm-streaming.md: 17f984166906914c49b2c330bdf57b3cecdbd013
|
||||||
llm-streaming.zh.md: 7d244ab882521a90217873fc3cdee12cd5232db8
|
llm-streaming.zh.md: 6519710dad8a174418bcc97f1bc4b36296ab969e
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ interface AppIdentity {
|
|||||||
product: string
|
product: string
|
||||||
/** Product version; sourced from package metadata, never hand-copied. */
|
/** Product version; sourced from package metadata, never hand-copied. */
|
||||||
version: string
|
version: string
|
||||||
/** Public home URL of the app, used as the `User-Agent` comment. */
|
/** Repository home URL of the app, used as the `User-Agent` comment. */
|
||||||
url: string
|
url: string
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ interface AppIdentity {
|
|||||||
product: string
|
product: string
|
||||||
/** Product version; sourced from package metadata, never hand-copied. */
|
/** Product version; sourced from package metadata, never hand-copied. */
|
||||||
version: string
|
version: string
|
||||||
/** Public home URL of the app, used as the `User-Agent` comment. */
|
/** Repository home URL of the app, used as the `User-Agent` comment. */
|
||||||
url: string
|
url: string
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# 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:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write docs/user/guide/python-sdk.md
|
# pnpm run verify-translation-pairing --write docs/user/guide/python-sdk.md
|
||||||
python-sdk.md: c48bc95c9334cfd16a925d12726c20b2f968c753
|
python-sdk.md: 0713de6f96c110624d5f5a8f2ccf56dd4ce01096
|
||||||
python-sdk.zh.md: dc31c391a180a742c7dc10807f6ed2ef8d11927d
|
python-sdk.zh.md: f8fa877b407a43c643fda405e1059fb487182761
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ python -m pip install deepseek-harness-sdk
|
|||||||
A source build additionally requires Git, Node.js ^22.19 or >= 24, Corepack-enabled pnpm 11, and `uv`. The following commands build the runtime for the current supported host platform, build both wheels, and install them into the active virtual environment:
|
A source build additionally requires Git, Node.js ^22.19 or >= 24, Corepack-enabled pnpm 11, and `uv`. The following commands build the runtime for the current supported host platform, build both wheels, and install them into the active virtual environment:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/deepseek-ai/deepseek-harness-sdk.git deepseek-harness
|
git clone https://github.com/deepseek-ai/deepseek-harness.git deepseek-harness
|
||||||
cd deepseek-harness
|
cd deepseek-harness
|
||||||
python -m pip install uv==0.11.23
|
python -m pip install uv==0.11.23
|
||||||
corepack enable
|
corepack enable
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ python -m pip install deepseek-harness-sdk
|
|||||||
从源码构建还需要 Git、Node.js ^22.19 或 >= 24、通过 Corepack 启用的 pnpm 11,以及 `uv`。以下命令为当前受支持的宿主平台构建运行时和两个 wheel 包,并将它们安装进当前虚拟环境:
|
从源码构建还需要 Git、Node.js ^22.19 或 >= 24、通过 Corepack 启用的 pnpm 11,以及 `uv`。以下命令为当前受支持的宿主平台构建运行时和两个 wheel 包,并将它们安装进当前虚拟环境:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/deepseek-ai/deepseek-harness-sdk.git deepseek-harness
|
git clone https://github.com/deepseek-ai/deepseek-harness.git deepseek-harness
|
||||||
cd deepseek-harness
|
cd deepseek-harness
|
||||||
python -m pip install uv==0.11.23
|
python -m pip install uv==0.11.23
|
||||||
corepack enable
|
corepack enable
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# 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:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write docs/user/guide/quickstart.md
|
# pnpm run verify-translation-pairing --write docs/user/guide/quickstart.md
|
||||||
quickstart.md: 635c0dffd6119f95c1951a441691f87f04396b4a
|
quickstart.md: e93e5a430f0cb345728581cd6fa3175ffd20b7d1
|
||||||
quickstart.zh.md: d0921382bcb0844fa0260c51546622c582867e68
|
quickstart.zh.md: 69cde830bb802ef19cc1204685395b957a0e02e3
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ pnpm -v
|
|||||||
## Step 1: install and configure the API key
|
## Step 1: install and configure the API key
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/deepseek-ai/deepseek-harness-sdk.git
|
git clone https://github.com/deepseek-ai/deepseek-harness.git
|
||||||
cd deepseek-harness
|
cd deepseek-harness
|
||||||
pnpm install
|
pnpm install
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ pnpm -v
|
|||||||
## 第一步:安装并配置 API 密钥
|
## 第一步:安装并配置 API 密钥
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/deepseek-ai/deepseek-harness-sdk.git
|
git clone https://github.com/deepseek-ai/deepseek-harness.git
|
||||||
cd deepseek-harness
|
cd deepseek-harness
|
||||||
pnpm install
|
pnpm install
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
# 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:
|
# after editing either side, bring the other along and re-record with:
|
||||||
# pnpm run verify-translation-pairing --write examples/mcp-memory/README.md
|
# pnpm run verify-translation-pairing --write examples/mcp-memory/README.md
|
||||||
README.md: 58da672030eaf2ddf70ee92d506de300efcd9650
|
README.md: 7e7de76f4123481b78898b8d62228e4821f3ebc9
|
||||||
README.zh.md: 0a2f109f9458ec7e1aba50e7fc9b6fd0fca15dbd
|
README.zh.md: 3473af862011725844ede95dc9460dd91534b484
|
||||||
|
|||||||
@@ -30,18 +30,6 @@ dsh web --patch "$PWD/examples/mcp-memory/memorix.cordis.yml"
|
|||||||
|
|
||||||
Replace the filename with `mcp-reference-memory.cordis.yml` or `engram.cordis.yml`. The path may point to a copied file anywhere on disk. No memory server is present in the shipped composition, so omitting `--patch` keeps all three disabled.
|
Replace the filename with `mcp-reference-memory.cordis.yml` or `engram.cordis.yml`. The path may point to a copied file anywhere on disk. No memory server is present in the shipped composition, so omitting `--patch` keeps all three disabled.
|
||||||
|
|
||||||
Without a repository checkout, download the selected overlay directly:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mkdir -p "${DSH_HOME:-$HOME/.dsh}"
|
|
||||||
curl --fail --location \
|
|
||||||
--output "${DSH_HOME:-$HOME/.dsh}/memory.cordis.yml" \
|
|
||||||
https://raw.githubusercontent.com/deepseek-ai/deepseek-harness-sdk/master/examples/mcp-memory/memorix.cordis.yml
|
|
||||||
dsh web --patch "${DSH_HOME:-$HOME/.dsh}/memory.cordis.yml"
|
|
||||||
```
|
|
||||||
|
|
||||||
Replace `memorix.cordis.yml` in the URL with either of the other filenames to select it. Review a downloaded overlay before running it: Cordis configuration can contain executable `!!js` expressions.
|
|
||||||
|
|
||||||
To keep the selection across runs, merge the chosen file's single `insert` patch into a user patch layer — `$DSH_HOME/profiles/<name>/cordis.patch.yml` for one profile, or `$DSH_HOME/cordis.patch.yml` for every profile on the machine. Do not copy over an existing file: it may already contain unrelated user patches.
|
To keep the selection across runs, merge the chosen file's single `insert` patch into a user patch layer — `$DSH_HOME/profiles/<name>/cordis.patch.yml` for one profile, or `$DSH_HOME/cordis.patch.yml` for every profile on the machine. Do not copy over an existing file: it may already contain unrelated user patches.
|
||||||
|
|
||||||
## Provider setup
|
## Provider setup
|
||||||
|
|||||||
@@ -30,18 +30,6 @@ dsh web --patch "$PWD/examples/mcp-memory/memorix.cordis.yml"
|
|||||||
|
|
||||||
请将文件名替换为 `mcp-reference-memory.cordis.yml` 或 `engram.cordis.yml`。该路径可以指向磁盘任意位置的一份复制文件。交付组合不包含任何记忆服务器,因此不传 `--patch` 就会让这三项全部保持关闭。
|
请将文件名替换为 `mcp-reference-memory.cordis.yml` 或 `engram.cordis.yml`。该路径可以指向磁盘任意位置的一份复制文件。交付组合不包含任何记忆服务器,因此不传 `--patch` 就会让这三项全部保持关闭。
|
||||||
|
|
||||||
如果本地没有仓库 checkout,可直接下载所选 overlay:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mkdir -p "${DSH_HOME:-$HOME/.dsh}"
|
|
||||||
curl --fail --location \
|
|
||||||
--output "${DSH_HOME:-$HOME/.dsh}/memory.cordis.yml" \
|
|
||||||
https://raw.githubusercontent.com/deepseek-ai/deepseek-harness-sdk/master/examples/mcp-memory/memorix.cordis.yml
|
|
||||||
dsh web --patch "${DSH_HOME:-$HOME/.dsh}/memory.cordis.yml"
|
|
||||||
```
|
|
||||||
|
|
||||||
若要选择另外任一配置,请将 URL 中的 `memorix.cordis.yml` 替换为对应文件名。运行下载的 overlay 前,请先审阅其内容:Cordis 配置可以包含可执行的 `!!js` 表达式。
|
|
||||||
|
|
||||||
如果要跨次运行保留所选配置,请将对应文件中的单个 `insert` patch 合并到用户 patch 层:只对一个 profile 生效则写入 `$DSH_HOME/profiles/<name>/cordis.patch.yml`,对本机所有 profile 生效则写入 `$DSH_HOME/cordis.patch.yml`。不要覆盖已有文件,其中可能已经包含无关的用户 patch。
|
如果要跨次运行保留所选配置,请将对应文件中的单个 `insert` patch 合并到用户 patch 层:只对一个 profile 生效则写入 `$DSH_HOME/profiles/<name>/cordis.patch.yml`,对本机所有 profile 生效则写入 `$DSH_HOME/cordis.patch.yml`。不要覆盖已有文件,其中可能已经包含无关的用户 patch。
|
||||||
|
|
||||||
## 提供方设置
|
## 提供方设置
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export interface AppIdentity {
|
|||||||
product: string
|
product: string
|
||||||
/** Product version; sourced from package metadata, never hand-copied. */
|
/** Product version; sourced from package metadata, never hand-copied. */
|
||||||
version: string
|
version: string
|
||||||
/** Public home URL of the app, used as the `User-Agent` comment. */
|
/** Repository home URL of the app, used as the `User-Agent` comment. */
|
||||||
url: string
|
url: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,8 +40,7 @@ export interface AppIdentity {
|
|||||||
export const APP_IDENTITY: AppIdentity = {
|
export const APP_IDENTITY: AppIdentity = {
|
||||||
product: 'deepseek-harness',
|
product: 'deepseek-harness',
|
||||||
version,
|
version,
|
||||||
// TODO(public-home): Ensure this public source repository exists before release.
|
url: 'https://github.com/deepseek-ai/deepseek-harness',
|
||||||
url: 'https://github.com/deepseek-ai/deepseek-harness-sdk',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ describe('APP_IDENTITY', () => {
|
|||||||
expect(APP_IDENTITY).toEqual({
|
expect(APP_IDENTITY).toEqual({
|
||||||
product: 'deepseek-harness',
|
product: 'deepseek-harness',
|
||||||
version: manifest.version,
|
version: manifest.version,
|
||||||
url: 'https://github.com/deepseek-ai/deepseek-harness-sdk',
|
url: 'https://github.com/deepseek-ai/deepseek-harness',
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -29,7 +29,7 @@ describe('APP_IDENTITY', () => {
|
|||||||
describe('userAgent', () => {
|
describe('userAgent', () => {
|
||||||
it('renders product/version with the +url comment', () => {
|
it('renders product/version with the +url comment', () => {
|
||||||
expect(userAgent()).toBe(
|
expect(userAgent()).toBe(
|
||||||
`deepseek-harness/${manifest.version} (+https://github.com/deepseek-ai/deepseek-harness-sdk)`,
|
`deepseek-harness/${manifest.version} (+https://github.com/deepseek-ai/deepseek-harness)`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ Add the official “powered by dsh” badge without recreating or restyling it.
|
|||||||
|
|
||||||
- Local PNG: [`dsh-badge.png`](dsh-badge.png), 726×120 source image; render at 121×20
|
- 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`
|
- 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`
|
- Project URL: `https://github.com/deepseek-ai/deepseek-harness`
|
||||||
|
|
||||||
## Markdown
|
## Markdown
|
||||||
|
|
||||||
Use this linked badge in Markdown:
|
Use this linked badge in Markdown:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
[](https://github.com/deepseek-ai/deepseek-harness-sdk)
|
[](https://github.com/deepseek-ai/deepseek-harness)
|
||||||
```
|
```
|
||||||
|
|
||||||
If attribution should not be linked, use:
|
If attribution should not be linked, use:
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ describe('rewriteMarkdown', () => {
|
|||||||
repositoryRef: 'abc123',
|
repositoryRef: 'abc123',
|
||||||
})).toBe(
|
})).toBe(
|
||||||
'[B](./reference/b.md#part) '
|
'[B](./reference/b.md#part) '
|
||||||
+ '[source](https://github.com/deepseek-ai/deepseek-harness-sdk/blob/abc123/packages/tool.ts#L2) '
|
+ '[source](https://github.com/deepseek-ai/deepseek-harness/blob/abc123/packages/tool.ts#L2) '
|
||||||
+ '[web](https://example.com)\n',
|
+ '[web](https://example.com)\n',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -130,7 +130,7 @@ describe('rewriteMarkdown', () => {
|
|||||||
pages,
|
pages,
|
||||||
repoRoot: root,
|
repoRoot: root,
|
||||||
repositoryRef: 'abc123',
|
repositoryRef: 'abc123',
|
||||||
})).toBe('\n')
|
})).toBe('\n')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('hands an image to the placer and uses the URL it returns', () => {
|
it('hands an image to the placer and uses the URL it returns', () => {
|
||||||
@@ -209,7 +209,7 @@ describe('rewriteMarkdown', () => {
|
|||||||
repositoryRef: 'abc123',
|
repositoryRef: 'abc123',
|
||||||
})).toBe(
|
})).toBe(
|
||||||
'[title](./reference/b.md "b.md") '
|
'[title](./reference/b.md "b.md") '
|
||||||
+ '[escaped](https://github.com/deepseek-ai/deepseek-harness-sdk/blob/abc123/docs/x(y).md)\n',
|
+ '[escaped](https://github.com/deepseek-ai/deepseek-harness/blob/abc123/docs/x(y).md)\n',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { gfm } from 'micromark-extension-gfm'
|
|||||||
import type { Nodes } from 'mdast'
|
import type { Nodes } from 'mdast'
|
||||||
import { docsPages, type DocsLocale, type DocsPage } from '../website/docs.ts'
|
import { docsPages, type DocsLocale, type DocsPage } from '../website/docs.ts'
|
||||||
|
|
||||||
const REPOSITORY_URL = 'https://github.com/deepseek-ai/deepseek-harness-sdk'
|
const REPOSITORY_URL = 'https://github.com/deepseek-ai/deepseek-harness'
|
||||||
const root = resolve(import.meta.dirname, '..')
|
const root = resolve(import.meta.dirname, '..')
|
||||||
const generatedRoot = resolve(root, 'website/.generated')
|
const generatedRoot = resolve(root, 'website/.generated')
|
||||||
|
|
||||||
@@ -209,7 +209,7 @@ function githubTarget(
|
|||||||
image: boolean,
|
image: boolean,
|
||||||
): string {
|
): string {
|
||||||
const path = repoPath(absPath, repoRoot)
|
const path = repoPath(absPath, repoRoot)
|
||||||
if (image) return `https://raw.githubusercontent.com/deepseek-ai/deepseek-harness-sdk/${repositoryRef}/${path}${suffix}`
|
if (image) return `https://raw.githubusercontent.com/deepseek-ai/deepseek-harness/${repositoryRef}/${path}${suffix}`
|
||||||
const kind = lstatSync(absPath).isDirectory() ? 'tree' : 'blob'
|
const kind = lstatSync(absPath).isDirectory() ? 'tree' : 'blob'
|
||||||
const lineSuffix = line === undefined ? suffix : `#L${line}`
|
const lineSuffix = line === undefined ? suffix : `#L${line}`
|
||||||
return `${REPOSITORY_URL}/${kind}/${repositoryRef}/${path}${lineSuffix}`
|
return `${REPOSITORY_URL}/${kind}/${repositoryRef}/${path}${lineSuffix}`
|
||||||
|
|||||||
@@ -1,60 +1,45 @@
|
|||||||
import { describe, expect, it } from 'vitest'
|
import { describe, expect, it } from 'vitest'
|
||||||
import { findInternalRepositoryReferences } from './verify-public-repository-links.ts'
|
import { findUnavailableRepositoryReferences } from './verify-public-repository-links.ts'
|
||||||
|
|
||||||
describe('public repository link policy', () => {
|
describe('repository link policy', () => {
|
||||||
it('rejects encoded and case-varied internal identities without blocking public repositories', () => {
|
it('rejects encoded and case-varied references to the unavailable repository', () => {
|
||||||
const internalOwner = ['deepseek', 'harness'].join('-')
|
const unavailableOwner = ['deepseek', 'ai'].join('-')
|
||||||
const internalRepository = [internalOwner, internalOwner].join('/')
|
const unavailableName = ['deepseek', 'harness', 'sdk'].join('-')
|
||||||
const encodedRepository = internalRepository.replaceAll('-', '%2D').replace('/', '%2F')
|
const unavailableRepository = `${unavailableOwner}/${unavailableName}`
|
||||||
const htmlEncodedRepository = internalRepository.replace('/', '/')
|
const encodedRepository = unavailableRepository.replaceAll('-', '%2D').replace('/', '%2F')
|
||||||
const jsonEscapedRepository = internalRepository.replace('/', '\\/')
|
const htmlEncodedRepository = unavailableRepository.replace('/', '/')
|
||||||
const unicodeEscapedRepository = internalRepository.replace('/', String.raw`\u002f`)
|
const jsonEscapedRepository = unavailableRepository.replace('/', '\\/')
|
||||||
|
const unicodeEscapedRepository = unavailableRepository.replace('/', String.raw`\u002f`)
|
||||||
const source = [
|
const source = [
|
||||||
'https://github.com/deepseek-ai/deepseek-harness-sdk',
|
'https://github.com/deepseek-ai/deepseek-harness',
|
||||||
`https://github.com/${internalOwner}/cordis`,
|
`https://github.com/${unavailableRepository.toUpperCase()}/issues/1`,
|
||||||
`https://github.com/${internalRepository.toUpperCase()}/issues/1`,
|
|
||||||
`https://github.com/${encodedRepository}/issues/2`,
|
`https://github.com/${encodedRepository}/issues/2`,
|
||||||
`https://github.com/${htmlEncodedRepository}/issues/3`,
|
`https://github.com/${htmlEncodedRepository}/issues/3`,
|
||||||
`"https:\\/\\/github.com\\/${jsonEscapedRepository}\\/issues\\/4"`,
|
`"https:\\/\\/github.com\\/${jsonEscapedRepository}\\/issues\\/4"`,
|
||||||
`"https:\\/\\/github.com\\/${unicodeEscapedRepository}\\/issues\\/5"`,
|
`"https:\\/\\/github.com\\/${unicodeEscapedRepository}\\/issues\\/5"`,
|
||||||
`${internalOwner.toUpperCase()}#6`,
|
`https://github.com/${unavailableOwner}/cordis`,
|
||||||
|
`https://github.com/example/${unavailableName}`,
|
||||||
].join('\n')
|
].join('\n')
|
||||||
|
|
||||||
expect(findInternalRepositoryReferences('subject.md', source)).toEqual([
|
expect(findUnavailableRepositoryReferences('subject.md', source)).toEqual([
|
||||||
|
{ file: 'subject.md', line: 2 },
|
||||||
{ file: 'subject.md', line: 3 },
|
{ file: 'subject.md', line: 3 },
|
||||||
{ file: 'subject.md', line: 4 },
|
{ file: 'subject.md', line: 4 },
|
||||||
{ file: 'subject.md', line: 5 },
|
{ file: 'subject.md', line: 5 },
|
||||||
{ file: 'subject.md', line: 6 },
|
{ file: 'subject.md', line: 6 },
|
||||||
{ file: 'subject.md', line: 7 },
|
|
||||||
{ file: 'subject.md', line: 8 },
|
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('allows only the exact audited trusted-publishing repository declarations', () => {
|
it('preserves frozen archived Agent Notes', () => {
|
||||||
const internalOwner = ['deepseek', 'harness'].join('-')
|
const unavailableRepository = ['deepseek-ai', 'deepseek-harness-sdk'].join('/')
|
||||||
const internalRepository = [internalOwner, internalOwner].join('/')
|
|
||||||
const repositoryUrl = `git+https://github.com/${internalRepository}.git`
|
|
||||||
const manifestLine = ` "url": "${repositoryUrl}",`
|
|
||||||
const constraintLine = `const repositoryUrl = '${repositoryUrl}'`
|
|
||||||
const allowedDeclarations = [
|
|
||||||
['native/landlock-run/packages/entry/package.json', manifestLine],
|
|
||||||
['native/landlock-run/packages/linux-arm64/package.json', manifestLine],
|
|
||||||
['native/landlock-run/packages/linux-x64/package.json', manifestLine],
|
|
||||||
['scripts/check-workspace-constraints.ts', constraintLine],
|
|
||||||
] as const
|
|
||||||
|
|
||||||
for (const [file, source] of allowedDeclarations) {
|
expect(findUnavailableRepositoryReferences(
|
||||||
expect(findInternalRepositoryReferences(file, source)).toEqual([])
|
'.agents/notes/archived/process/historical-record.md',
|
||||||
}
|
`https://github.com/${unavailableRepository}`,
|
||||||
|
)).toEqual([])
|
||||||
const wrongFile = 'native/landlock-run/package.json'
|
expect(findUnavailableRepositoryReferences(
|
||||||
expect(findInternalRepositoryReferences(wrongFile, manifestLine)).toEqual([{ file: wrongFile, line: 1 }])
|
'.agents/notes/implemented/process/active-record.md',
|
||||||
|
`https://github.com/${unavailableRepository}`,
|
||||||
const manifestFile = 'native/landlock-run/packages/entry/package.json'
|
)).toEqual([{ file: '.agents/notes/implemented/process/active-record.md', line: 1 }])
|
||||||
const wrongField = ` "homepage": "${repositoryUrl}",`
|
|
||||||
expect(findInternalRepositoryReferences(manifestFile, wrongField)).toEqual([{ file: manifestFile, line: 1 }])
|
|
||||||
|
|
||||||
const encodedLine = manifestLine.replace('github.com/', 'github.com\\/')
|
|
||||||
expect(findInternalRepositoryReferences(manifestFile, encodedLine)).toEqual([{ file: manifestFile, line: 1 }])
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/** Reject tracked files that expose the internal repository identity outside audited publishing declarations. */
|
/** Reject tracked files that reference an unavailable legacy repository. */
|
||||||
|
|
||||||
import { execFileSync } from 'node:child_process'
|
import { execFileSync } from 'node:child_process'
|
||||||
import { existsSync, lstatSync, readFileSync, readlinkSync } from 'node:fs'
|
import { existsSync, lstatSync, readFileSync, readlinkSync } from 'node:fs'
|
||||||
@@ -6,22 +6,13 @@ import { resolve } from 'node:path'
|
|||||||
import { pathToFileURL } from 'node:url'
|
import { pathToFileURL } from 'node:url'
|
||||||
|
|
||||||
const root = resolve(import.meta.dirname, '..')
|
const root = resolve(import.meta.dirname, '..')
|
||||||
const internalOwner = ['deepseek', 'harness'].join('-')
|
const unavailableOwner = ['deepseek', 'ai'].join('-')
|
||||||
const internalRepository = [internalOwner, internalOwner].join('/')
|
const unavailableRepositoryName = ['deepseek', 'harness', 'sdk'].join('-')
|
||||||
const internalIssueShorthand = `${internalOwner}#`
|
const unavailableRepository = `${unavailableOwner}/${unavailableRepositoryName}`
|
||||||
const trustedPublishingRepositoryUrl = `git+https://github.com/${internalRepository}.git`
|
const archivedAgentNotePrefix = '.agents/notes/archived/'
|
||||||
|
|
||||||
/** Exact declarations that intentionally expose the source repository for trusted publishing. */
|
|
||||||
const allowedInternalRepositoryLineByFile: Readonly<Record<string, string>> = {
|
|
||||||
'native/landlock-run/packages/entry/package.json': `"url": "${trustedPublishingRepositoryUrl}",`,
|
|
||||||
'native/landlock-run/packages/linux-arm64/package.json': `"url": "${trustedPublishingRepositoryUrl}",`,
|
|
||||||
'native/landlock-run/packages/linux-x64/package.json': `"url": "${trustedPublishingRepositoryUrl}",`,
|
|
||||||
'scripts/check-workspace-constraints.ts': `const repositoryUrl = '${trustedPublishingRepositoryUrl}'`,
|
|
||||||
}
|
|
||||||
|
|
||||||
const namedReferenceCharacters: Readonly<Record<string, string>> = {
|
const namedReferenceCharacters: Readonly<Record<string, string>> = {
|
||||||
hyphen: '-',
|
hyphen: '-',
|
||||||
num: '#',
|
|
||||||
sol: '/',
|
sol: '/',
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,8 +31,8 @@ function canonicalReferenceText(source: string): string {
|
|||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** One tracked reference to the internal repository. */
|
/** One tracked reference to the unavailable repository. */
|
||||||
export interface InternalRepositoryReference {
|
export interface UnavailableRepositoryReference {
|
||||||
/** Repository-relative file path. */
|
/** Repository-relative file path. */
|
||||||
file: string
|
file: string
|
||||||
/** One-based source line. */
|
/** One-based source line. */
|
||||||
@@ -49,20 +40,18 @@ export interface InternalRepositoryReference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locate unaudited internal-repository references in one text file.
|
* Locate unavailable-repository references in one active text file.
|
||||||
* @param file - Repository-relative path used in diagnostics.
|
* @param file - Repository-relative path used in diagnostics.
|
||||||
* @param source - Text to inspect.
|
* @param source - Text to inspect.
|
||||||
* @returns every matching source line.
|
* @returns every matching source line, excluding frozen archived Agent Notes.
|
||||||
*/
|
*/
|
||||||
export function findInternalRepositoryReferences(file: string, source: string): InternalRepositoryReference[] {
|
export function findUnavailableRepositoryReferences(file: string, source: string): UnavailableRepositoryReference[] {
|
||||||
const references: InternalRepositoryReference[] = []
|
if (file.startsWith(archivedAgentNotePrefix)) return []
|
||||||
|
|
||||||
|
const references: UnavailableRepositoryReference[] = []
|
||||||
for (const [index, line] of source.split('\n').entries()) {
|
for (const [index, line] of source.split('\n').entries()) {
|
||||||
const canonicalLine = canonicalReferenceText(line)
|
const canonicalLine = canonicalReferenceText(line)
|
||||||
const isAllowedPublishingDeclaration = line.trim() === allowedInternalRepositoryLineByFile[file]
|
if (canonicalLine.includes(unavailableRepository)) references.push({ file, line: index + 1 })
|
||||||
if (!isAllowedPublishingDeclaration
|
|
||||||
&& (canonicalLine.includes(internalRepository) || canonicalLine.includes(internalIssueShorthand))) {
|
|
||||||
references.push({ file, line: index + 1 })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return references
|
return references
|
||||||
}
|
}
|
||||||
@@ -73,8 +62,8 @@ function trackedFiles(repoRoot: string): string[] {
|
|||||||
.filter(file => file !== '')
|
.filter(file => file !== '')
|
||||||
}
|
}
|
||||||
|
|
||||||
function scanRepository(repoRoot: string): InternalRepositoryReference[] {
|
function scanRepository(repoRoot: string): UnavailableRepositoryReference[] {
|
||||||
const references: InternalRepositoryReference[] = []
|
const references: UnavailableRepositoryReference[] = []
|
||||||
for (const file of trackedFiles(repoRoot)) {
|
for (const file of trackedFiles(repoRoot)) {
|
||||||
const path = resolve(repoRoot, file)
|
const path = resolve(repoRoot, file)
|
||||||
if (!existsSync(path)) continue
|
if (!existsSync(path)) continue
|
||||||
@@ -82,7 +71,7 @@ function scanRepository(repoRoot: string): InternalRepositoryReference[] {
|
|||||||
if (!stat.isFile() && !stat.isSymbolicLink()) continue
|
if (!stat.isFile() && !stat.isSymbolicLink()) continue
|
||||||
const source = stat.isSymbolicLink() ? readlinkSync(path) : readFileSync(path, 'utf8')
|
const source = stat.isSymbolicLink() ? readlinkSync(path) : readFileSync(path, 'utf8')
|
||||||
if (source.includes('\0')) continue
|
if (source.includes('\0')) continue
|
||||||
references.push(...findInternalRepositoryReferences(file, source))
|
references.push(...findUnavailableRepositoryReferences(file, source))
|
||||||
}
|
}
|
||||||
return references
|
return references
|
||||||
}
|
}
|
||||||
@@ -92,9 +81,9 @@ const isMain = invokedPath !== undefined && import.meta.url === pathToFileURL(re
|
|||||||
if (isMain) {
|
if (isMain) {
|
||||||
const references = scanRepository(root)
|
const references = scanRepository(root)
|
||||||
if (references.length === 0) {
|
if (references.length === 0) {
|
||||||
console.log('verify-public-repository-links: tracked files expose no unexpected internal repository identity.')
|
console.log('verify-public-repository-links: tracked files reference no unavailable repository.')
|
||||||
} else {
|
} else {
|
||||||
console.error('verify-public-repository-links: unexpected internal repository references found:')
|
console.error('verify-public-repository-links: unavailable repository references found:')
|
||||||
for (const reference of references) console.error(` ${reference.file}:${String(reference.line)}`)
|
for (const reference of references) console.error(` ${reference.file}:${String(reference.line)}`)
|
||||||
process.exitCode = 1
|
process.exitCode = 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,14 +94,14 @@ const sharedTheme: Pick<DefaultTheme.Config, 'search' | 'socialLinks' | 'editLin
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
socialLinks: [
|
socialLinks: [
|
||||||
{ icon: 'github', link: 'https://github.com/deepseek-ai/deepseek-harness-sdk' },
|
{ icon: 'github', link: 'https://github.com/deepseek-ai/deepseek-harness' },
|
||||||
],
|
],
|
||||||
editLink: {
|
editLink: {
|
||||||
pattern: ({ frontmatter }: PageData) => {
|
pattern: ({ frontmatter }: PageData) => {
|
||||||
const data: unknown = frontmatter
|
const data: unknown = frontmatter
|
||||||
const editSource: unknown = typeof data === 'object' && data !== null ? Reflect.get(data, 'editSource') : undefined
|
const editSource: unknown = typeof data === 'object' && data !== null ? Reflect.get(data, 'editSource') : undefined
|
||||||
if (typeof editSource !== 'string') throw new Error('Projected documentation page has no editSource frontmatter.')
|
if (typeof editSource !== 'string') throw new Error('Projected documentation page has no editSource frontmatter.')
|
||||||
return `https://github.com/deepseek-ai/deepseek-harness-sdk/edit/master/${editSource}`
|
return `https://github.com/deepseek-ai/deepseek-harness/edit/master/${editSource}`
|
||||||
},
|
},
|
||||||
text: '在 GitHub 上编辑此页',
|
text: '在 GitHub 上编辑此页',
|
||||||
},
|
},
|
||||||
@@ -161,7 +161,7 @@ export default withMermaid({
|
|||||||
const data: unknown = frontmatter
|
const data: unknown = frontmatter
|
||||||
const editSource: unknown = typeof data === 'object' && data !== null ? Reflect.get(data, 'editSource') : undefined
|
const editSource: unknown = typeof data === 'object' && data !== null ? Reflect.get(data, 'editSource') : undefined
|
||||||
if (typeof editSource !== 'string') throw new Error('Projected documentation page has no editSource frontmatter.')
|
if (typeof editSource !== 'string') throw new Error('Projected documentation page has no editSource frontmatter.')
|
||||||
return `https://github.com/deepseek-ai/deepseek-harness-sdk/edit/master/${editSource}`
|
return `https://github.com/deepseek-ai/deepseek-harness/edit/master/${editSource}`
|
||||||
},
|
},
|
||||||
text: 'Edit this page on GitHub',
|
text: 'Edit this page on GitHub',
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user