mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-10-26 16:55:08 +00:00
fix(i18n): cover nested metadata and repair locale CI regressions
This commit is contained in:
1 parent
9ce74cda96
commit
11295990b5
93 files changed
+195
-123
No files matched your search
@@ -1,5 +1,5 @@
|
||||
- listitem:
|
||||
- button "自動認可レビューを表示": 自動認可レビュー
|
||||
- text: 実験的 各ツール呼び出しの前にモデルが認可を判断する、自動レビュー権限モードを提供します。
|
||||
- text: 実験的 各ツール呼び出しの前にモデルが認可を判断する、自動認可レビュー権限モードを提供します。
|
||||
- status
|
||||
- switch "自動認可レビューを有効化"
|
||||
@@ -23,7 +23,7 @@ it('displays Japanese plugin titles and descriptions from package metadata', asy
|
||||
const title = panel.getByRole('button', { name: '自動認可レビューを表示', exact: true })
|
||||
await title.waitFor()
|
||||
const card = title.locator('xpath=ancestor::li')
|
||||
await card.getByText('各ツール呼び出しの前にモデルが認可を判断する、自動レビュー権限モードを提供します。', { exact: true }).waitFor()
|
||||
await card.getByText('各ツール呼び出しの前にモデルが認可を判断する、自動認可レビュー権限モードを提供します。', { exact: true }).waitFor()
|
||||
const expected = fileURLToPath(new URL('./expected/japanese-plugin-metadata/card.expected.md', import.meta.url))
|
||||
await compareOrRefreshGolden(expected,
|
||||
await captureStableAria(page, '[data-plugin-panel] li:has(button[aria-label="自動認可レビューを表示"])', scaffold.workspaceCwd), webSnapshotMode())
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
en: 0894bd9f35430753
|
||||
zh: 2d28090e71134edd
|
||||
/cookbook-adding-a-workspace-package/5-add-optional-plugin-display-metadata:
|
||||
en: bf6a19c236cb00e3
|
||||
zh: 4f0d62de5466112f
|
||||
en: 1238eaea376391d1
|
||||
zh: c7e606f95d8980bf
|
||||
/cookbook-adding-a-workspace-package/6-verify:
|
||||
en: 80c7fb90b1175aae
|
||||
zh: 2ba37962dbc57299
|
||||
@@ -136,7 +136,7 @@ Merge these entries into `package.json`, retaining existing runtime exports and
|
||||
}
|
||||
```
|
||||
|
||||
Keep language files together in `locale/`, with `en.json` as the discovery entry. Fields are optional; present values must be non-empty strings. English `meta.title` and `meta.description` use sentence case: capitalize only the first word, proper nouns, and product names, as in `Git worktrees` ([rule](../../.agents/skills/dsh-prose-standard/SKILL.md#required-coverage-by-prose-location)). Missing files or fields permit fallback, while malformed JSON or invalid fields produce a per-plugin diagnostic. First-party packages and plugin templates must provide `ja.json` covering every field present in `en.json` or `zh.json`, preserving placeholders; detail paths may point to the existing English document. Run `pnpm run check:i18n` to verify JSON metadata and UI dictionary completeness; these checks also run in `check:all`, CI static checks, and hygiene.
|
||||
Keep language files together in `locale/`, with `en.json` as the discovery entry. Fields are optional; present values must be non-empty strings. English `meta.title` and `meta.description` use sentence case: capitalize only the first word, proper nouns, and product names, as in `Git worktrees` ([rule](../../.agents/skills/dsh-prose-standard/SKILL.md#required-coverage-by-prose-location)). At runtime, missing files or fields permit fallback, while malformed JSON or invalid fields produce a per-plugin diagnostic. First-party packages and plugin templates must provide `ja.json` covering every field present in `en.json` or optional `zh.json`, preserving placeholders; detail paths may point to the existing English document. Subpath resources under `locale/<subpath>/` follow the same checks. English descriptions explain user-visible behavior and end with sentence punctuation. Run `pnpm run check:i18n` to verify JSON metadata and UI dictionary completeness; the JSON checks also run in `check:all`, CI static checks, and hygiene.
|
||||
|
||||
Fields fall back independently before view-specific name formatting, using the existing locale language chain first:
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ Append-only, prefix-stable, replacing, or independent behavior, including the ex
|
||||
}
|
||||
```
|
||||
|
||||
语言文件统一放在 `locale/`,并保留 `en.json` 作为发现入口。字段可选,填写时必须是非空字符串。英文 `meta.title` 和 `meta.description` 使用 sentence case:只大写首个单词、专有名词和产品名,例如 `Git worktrees`([rule](../../.agents/skills/dsh-prose-standard/SKILL.md#required-coverage-by-prose-location))。文件或字段缺失时允许回退,JSON 损坏或字段无效时显示单插件诊断。 仓库内的包和插件模板必须提供 `ja.json`,覆盖 `en.json` 或 `zh.json` 中的全部字段并保留占位符;详情路径可指向现有英文文档。运行 `pnpm run check:i18n` 检查 JSON 元数据和 UI 字典完整性;这些检查也接入 `check:all`、CI 静态检查和 hygiene。
|
||||
语言文件统一放在 `locale/`,并保留 `en.json` 作为发现入口。字段可选,填写时必须是非空字符串。英文 `meta.title` 和 `meta.description` 使用 sentence case:只大写首个单词、专有名词和产品名,例如 `Git worktrees`([rule](../../.agents/skills/dsh-prose-standard/SKILL.md#required-coverage-by-prose-location))。运行时文件或字段缺失时允许回退,JSON 损坏或字段无效时显示单插件诊断。仓库内的包和插件模板必须提供 `ja.json`,覆盖 `en.json` 或可选 `zh.json` 中的全部字段并保留占位符;详情路径可指向现有英文文档。`locale/<subpath>/` 下的子路径资源使用相同检查。英文描述面向产品用户说明可见行为,并以句末标点结束。运行 `pnpm run check:i18n` 检查 JSON 元数据和 UI 字典完整性;JSON 检查也接入 `check:all`、CI 静态检查和 hygiene。
|
||||
|
||||
各字段先独立回退,再按页面规则格式化技术名称;回退优先经过现有 locale 语言链:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "ACP server",
|
||||
"description": "Automation-only Agent Client Protocol server for driving DeepSeek Harness agents over JSON-RPC stdio"
|
||||
"description": "Run agents through JSON-RPC over standard input and output for automation."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Remote access control",
|
||||
"description": "Method-level Remote access control for non-owner Peers and the per-Peer access snapshot"
|
||||
"description": "Control which methods non-owner connections can access and retain permission snapshots for each connection."
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ export const OFFICIAL_ON_DEMAND_CATALOG: readonly OfficialBundleCatalogEntry[] =
|
||||
packageName: '@deepseek-ai/dsh-subagent-claude-code',
|
||||
meta: {
|
||||
title: { 'en': 'Claude Code subagent', 'ja': 'Claude Code \u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8', 'zh': 'Claude Code \u5B50\u667A\u80FD\u4F53' },
|
||||
description: { 'en': 'Delegate one task to Claude Code using its native authentication and settings.', 'ja': 'Claude Code \u306E\u6A19\u6E96\u306E\u8A8D\u8A3C\u3068\u8A2D\u5B9A\u3092\u4F7F\u7528\u3057\u3066\u3001\u5358\u72EC\u306E\u30BF\u30B9\u30AF\u3092\u59D4\u6D3E\u3057\u307E\u3059\u3002', 'zh': '\u4F7F\u7528 Claude Code \u539F\u751F\u8BA4\u8BC1\u548C\u8BBE\u7F6E\u59D4\u6D3E\u5355\u4E2A\u4EFB\u52A1\u3002' },
|
||||
description: { 'en': 'Delegate one task to Claude Code using its native authentication and settings.', 'ja': 'Claude Code \u306E\u30CD\u30A4\u30C6\u30A3\u30D6\u306E\u8A8D\u8A3C\u3068\u8A2D\u5B9A\u3092\u4F7F\u7528\u3057\u3066\u3001\u5358\u72EC\u306E\u30BF\u30B9\u30AF\u3092\u59D4\u6D3E\u3057\u307E\u3059\u3002', 'zh': '\u4F7F\u7528 Claude Code \u539F\u751F\u8BA4\u8BC1\u548C\u8BBE\u7F6E\u59D4\u6D3E\u5355\u4E2A\u4EFB\u52A1\u3002' },
|
||||
icon: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzYiIGhlaWdodD0iMzYiIHZpZXdCb3g9IjAgMCAzNiAzNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB4PSIxNC45ODkzIiB5PSIxNS4xODc3IiB3aWR0aD0iMTIuMjM2NSIgaGVpZ2h0PSIxMi4yMzY1IiByeD0iMiIgZmlsbD0idXJsKCNkc2hfcGx1Z2luX2FydF9SMGEpIiBmaWxsLW9wYWNpdHk9IjAuOCI+PC9yZWN0PjxyZWN0IHg9IjguODcxMDkiIHk9IjkuMDY5NyIgd2lkdGg9IjEyLjIzNjUiIGhlaWdodD0iMTIuMjM2NSIgcng9IjIiIGZpbGw9InVybCgjZHNoX3BsdWdpbl9hcnRfUjBiKSIgZmlsbC1vcGFjaXR5PSIwLjgiPjwvcmVjdD48ZGVmcz48bGluZWFyR3JhZGllbnQgaWQ9ImRzaF9wbHVnaW5fYXJ0X1IwYSIgeDE9IjIxLjEwNzUiIHkxPSIxNS4xODc3IiB4Mj0iMjEuMTA3NSIgeTI9IjI3LjQyNDMiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBzdG9wLWNvbG9yPSIjNDVFN0E0Ij48L3N0b3A+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMDU5MDlEIj48L3N0b3A+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9ImRzaF9wbHVnaW5fYXJ0X1IwYiIgeDE9IjE0Ljk4OTQiIHkxPSI5LjA2OTciIHgyPSIxNC45ODk0IiB5Mj0iMjEuMzA2MyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiM2OUI5RkYiPjwvc3RvcD48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMzMjRERTIiPjwvc3RvcD48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48L3N2Zz4K',
|
||||
},
|
||||
},
|
||||
@@ -16,7 +16,7 @@ export const OFFICIAL_ON_DEMAND_CATALOG: readonly OfficialBundleCatalogEntry[] =
|
||||
packageName: '@deepseek-ai/dsh-subagent-codex',
|
||||
meta: {
|
||||
title: { 'en': 'Codex subagent', 'ja': 'Codex \u30B5\u30D6\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8', 'zh': 'Codex \u5B50\u667A\u80FD\u4F53' },
|
||||
description: { 'en': 'Delegate one task to Codex using its native authentication and settings.', 'ja': 'Codex \u306E\u6A19\u6E96\u306E\u8A8D\u8A3C\u3068\u8A2D\u5B9A\u3092\u4F7F\u7528\u3057\u3066\u3001\u5358\u72EC\u306E\u30BF\u30B9\u30AF\u3092\u59D4\u6D3E\u3057\u307E\u3059\u3002', 'zh': '\u4F7F\u7528 Codex \u539F\u751F\u8BA4\u8BC1\u548C\u8BBE\u7F6E\u59D4\u6D3E\u5355\u4E2A\u4EFB\u52A1\u3002' },
|
||||
description: { 'en': 'Delegate one task to Codex using its native authentication and settings.', 'ja': 'Codex \u306E\u30CD\u30A4\u30C6\u30A3\u30D6\u306E\u8A8D\u8A3C\u3068\u8A2D\u5B9A\u3092\u4F7F\u7528\u3057\u3066\u3001\u5358\u72EC\u306E\u30BF\u30B9\u30AF\u3092\u59D4\u6D3E\u3057\u307E\u3059\u3002', 'zh': '\u4F7F\u7528 Codex \u539F\u751F\u8BA4\u8BC1\u548C\u8BBE\u7F6E\u59D4\u6D3E\u5355\u4E2A\u4EFB\u52A1\u3002' },
|
||||
icon: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzYiIGhlaWdodD0iMzYiIHZpZXdCb3g9IjAgMCAzNiAzNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB4PSIxNC45ODkzIiB5PSIxNS4xODc3IiB3aWR0aD0iMTIuMjM2NSIgaGVpZ2h0PSIxMi4yMzY1IiByeD0iMiIgZmlsbD0idXJsKCNkc2hfcGx1Z2luX2FydF9SMGEpIiBmaWxsLW9wYWNpdHk9IjAuOCI+PC9yZWN0PjxyZWN0IHg9IjguODcxMDkiIHk9IjkuMDY5NyIgd2lkdGg9IjEyLjIzNjUiIGhlaWdodD0iMTIuMjM2NSIgcng9IjIiIGZpbGw9InVybCgjZHNoX3BsdWdpbl9hcnRfUjBiKSIgZmlsbC1vcGFjaXR5PSIwLjgiPjwvcmVjdD48ZGVmcz48bGluZWFyR3JhZGllbnQgaWQ9ImRzaF9wbHVnaW5fYXJ0X1IwYSIgeDE9IjIxLjEwNzUiIHkxPSIxNS4xODc3IiB4Mj0iMjEuMTA3NSIgeTI9IjI3LjQyNDMiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj48c3RvcCBzdG9wLWNvbG9yPSIjNDVFN0E0Ij48L3N0b3A+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMDU5MDlEIj48L3N0b3A+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9ImRzaF9wbHVnaW5fYXJ0X1IwYiIgeDE9IjE0Ljk4OTQiIHkxPSI5LjA2OTciIHgyPSIxNC45ODk0IiB5Mj0iMjEuMzA2MyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIHN0b3AtY29sb3I9IiM2OUI5RkYiPjwvc3RvcD48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMzMjRERTIiPjwvc3RvcD48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48L3N2Zz4K',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "プラグイン管理ツール"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Plugin market indexes",
|
||||
"description": "Configured plugin market indexes for the Web Discover page and the plugin_market agent tool"
|
||||
"description": "Manage configured market indexes for plugin discovery and the plugin_market tool."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Browser provider registry",
|
||||
"description": "Exclusive named browser-use provider registration"
|
||||
"description": "Register browser automation providers by name, with one provider per name."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "ACP profile",
|
||||
"description": "The dsh ACP profile bundle: automation-only JSON-RPC stdio and process lifecycle over dsh-base"
|
||||
"description": "Provide automation-only ACP communication and process lifecycle management over dsh-base."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Headless profile",
|
||||
"description": "The dsh one-shot bundle: a direct core Agent/Session runner over dsh-base with no Host, HTTP, or browser layer"
|
||||
"description": "Run a single task directly with the core Agent/Session runner over dsh-base, without a Host, HTTP, or browser layer."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "ヘッドレスプロファイル",
|
||||
"description": "dsh-base 上で単一タスクを実行し、Host、HTTP、ブラウザのレイヤーを含みません。"
|
||||
"description": "dsh-base 上でコアの Agent/Session ランナーを直接使用して単一タスクを実行し、Host、HTTP、ブラウザのレイヤーを含みません。"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "无界面运行配置",
|
||||
"description": "在 dsh-base 上提供单次任务运行,不包含 Host、HTTP 或浏览器层。"
|
||||
"description": "在 dsh-base 上直接使用核心 Agent/Session 执行单次任务,不包含 Host、HTTP 或浏览器层。"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "SDK profile",
|
||||
"description": "The dsh SDK profile bundle: stdio JSON-RPC serving and process lifecycle over dsh-base"
|
||||
"description": "Provide JSON-RPC over standard input and output and manage the process lifecycle over dsh-base."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Web 起動設定"
|
||||
}
|
||||
}
|
||||
@@ -1096,9 +1096,9 @@ export const ja = {
|
||||
'tool.title.glob': 'Glob',
|
||||
'tool.title.webSearch': '検索',
|
||||
'tool.title.webFetch': '取得',
|
||||
'tool.autoReviewRejected': '自動レビューにより拒否されました',
|
||||
'tool.autoReviewRejected': '自動認可レビューにより拒否されました',
|
||||
'tool.autoReviewNotExecuted': 'ツールは実行されませんでした。理由: {reason}',
|
||||
'tool.autoReviewReasonFallback': '自動レビューがこの操作を承認しませんでした',
|
||||
'tool.autoReviewReasonFallback': '自動認可レビューがこの操作を承認しませんでした',
|
||||
'diff.collapseAria': '差分を折りたたむ',
|
||||
'diff.expandAria': '差分の残り{count}行を表示',
|
||||
'diff.expandRest': '… 残り{count}行',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "DeepSeek 1017 model badge",
|
||||
"description": "Temporary 1017 release badge for official DeepSeek Flash model labels"
|
||||
"description": "Add a temporary 1017 release badge to official DeepSeek Flash model names."
|
||||
}
|
||||
}
|
||||
@@ -111,11 +111,11 @@ export const accessJa = {
|
||||
'confirm.acknowledge': 'リスクを理解し、続行します',
|
||||
'confirm.cancel': 'キャンセル',
|
||||
'confirm.enable': 'フルアクセスを有効にする',
|
||||
'auto.label': '自動レビュー',
|
||||
'auto.label': '自動認可レビュー',
|
||||
'auto.badge': 'EXP',
|
||||
'auto.description': 'すべてのネイティブツール呼び出しと PTC 内部呼び出しを実験的な同一モデルでレビューしたうえで、サンドボックスなしで実行します。',
|
||||
'auto.confirm.title': '自動レビュー(実験的)を有効にしますか?',
|
||||
'auto.confirm.description': '自動レビューはサンドボックスなしで実行されます。ネイティブツール呼び出しと PTC 内部呼び出しのたびに、現在のエージェントと同じモデルが許可可否をレビューし、拒否された呼び出しはあなたが承認または却下します。この機能は実験的であり、操作を誤って許可・拒否する可能性があり、追加のトークンを消費します。',
|
||||
'auto.confirm.title': '自動認可レビュー(実験的)を有効にしますか?',
|
||||
'auto.confirm.description': '自動認可レビューはサンドボックスなしで実行されます。ネイティブツール呼び出しと PTC 内部呼び出しのたびに、現在のエージェントと同じモデルが許可可否をレビューし、拒否された呼び出しはあなたが承認または却下します。この機能は実験的であり、操作を誤って許可・拒否する可能性があり、追加のトークンを消費します。',
|
||||
'auto.confirm.acknowledge': 'これらのリスクを理解し、続行します',
|
||||
'auto.confirm.enable': '自動レビューを有効にする',
|
||||
'auto.confirm.enable': '自動認可レビューを有効にする',
|
||||
} satisfies Record<keyof typeof accessEn, string>
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Plugin discovery",
|
||||
"description": "Discover tab of the dsh web Plugins page: browse configured plugin market indexes and install their bundles"
|
||||
"description": "Browse configured plugin market indexes and install their packages."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Computer provider registry",
|
||||
"description": "Exclusive named computer-use provider registration"
|
||||
"description": "Register Computer Use providers by name, with one provider per name."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Harness development context",
|
||||
"description": "Model context naming the DeepSeek Harness checkout and Web GUI URL without letting either change the system prompt"
|
||||
"description": "Give the model the Harness source directory and Web URL without changing its system prompt."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "tmux context",
|
||||
"description": "Opt-in durable per-step context with this agent's tmux pane and window location"
|
||||
"description": "Save tmux pane and window locations for each step when needed."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Deliverable file references",
|
||||
"description": "Shared model guidance for file links and deliverables across DeepSeek Harness hosts"
|
||||
"description": "Provide shared model guidance for file links and deliverables across application environments."
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "自動認可レビュー",
|
||||
"description": "各ツール呼び出しの前にモデルが認可を判断する、自動レビュー権限モードを提供します。",
|
||||
"description": "各ツール呼び出しの前にモデルが認可を判断する、自動認可レビュー権限モードを提供します。",
|
||||
"detail": "docs/DETAIL.md"
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@
|
||||
* @module @deepseek-ai/dsh-experimental-auto-review
|
||||
*/
|
||||
|
||||
import { deniedDisplayReason } from './locales.ts'
|
||||
import type {} from '@deepseek-ai/dsh-working-directory'
|
||||
import { FiberState, type Context } from '@deepseek-ai/cordis'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
@@ -33,6 +32,7 @@ import {
|
||||
type PreToolDecision,
|
||||
type ToolExecution,
|
||||
} from '@deepseek-ai/dsh-tools'
|
||||
import { deniedDisplayReason } from './locales.ts'
|
||||
|
||||
/** Structured error name persisted for every final reviewer denial. */
|
||||
const AUTO_REVIEW_DENIED_ERROR_NAME = 'AutoReviewDeniedError'
|
||||
|
||||
@@ -14,8 +14,8 @@ export const zh = {
|
||||
|
||||
/** Japanese approval messages. */
|
||||
export const ja = {
|
||||
denied: '自動レビューがこの呼び出しを拒否しました。',
|
||||
deniedWithReason: (reason: string): string => `自動レビューがこの呼び出しを拒否しました:${reason}`,
|
||||
denied: '自動認可レビューがこの呼び出しを拒否しました。',
|
||||
deniedWithReason: (reason: string): string => `自動認可レビューがこの呼び出しを拒否しました:${reason}`,
|
||||
} satisfies typeof en
|
||||
|
||||
/**
|
||||
|
||||
@@ -967,9 +967,9 @@ describe('native review request', () => {
|
||||
? 'Auto review denied tool "probe"'
|
||||
: `Auto review denied tool "probe": ${item.expectedReason}`)
|
||||
expect(displayReasons.at(-1)).toEqual(item.expectedReason === undefined
|
||||
? { en: 'Auto review denied this call.', zh: 'Auto review 拒绝了此调用。', ja: '自動レビューがこの呼び出しを拒否しました。' }
|
||||
? { en: 'Auto review denied this call.', zh: 'Auto review 拒绝了此调用。', ja: '自動認可レビューがこの呼び出しを拒否しました。' }
|
||||
: { en: `Auto review denied this call: ${item.expectedReason}`, zh: `Auto review 拒绝了此调用:${item.expectedReason}`,
|
||||
ja: `自動レビューがこの呼び出しを拒否しました:${item.expectedReason}` })
|
||||
ja: `自動認可レビューがこの呼び出しを拒否しました:${item.expectedReason}` })
|
||||
}
|
||||
|
||||
expect(probe.runs()).toBe(2)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Stagehand browser tools",
|
||||
"description": "Experimental Stagehand browser tools with separately configured native models"
|
||||
"description": "Provide experimental Stagehand browser tools using a separately configured native model."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Claude Code mods",
|
||||
"description": "Experimental bridge: load Claude Code mods (hooks modules) and run their hook chains on DeepSeek Harness extension points"
|
||||
"description": "Load Claude Code extensions and run their hooks through Harness extension points."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Claude Code mods interface",
|
||||
"description": "Web band above the prompt for Claude Code mods: draws each session's mod tree and sends button presses back to the bridge"
|
||||
"description": "Display each session's extension tree above the input box and send button actions to the extension service."
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Machine translation of reasoning",
|
||||
"description": "Machine translation of expanded reasoning; source text is sent to the selected service",
|
||||
"description": "Machine translation of expanded reasoning; source text is sent to the selected service.",
|
||||
"detail": "docs/DETAIL.md"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "macOS computer use provider",
|
||||
"description": "macOS native provider for shared Computer Use application and window objects"
|
||||
"title": "macOS Computer Use provider",
|
||||
"description": "Provide native macOS applications and windows for the shared Computer Use service."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "macOS コンピュータ操作バックエンド",
|
||||
"description": "共通のコンピュータ操作サービスに macOS ネイティブのアプリとウィンドウのオブジェクトを提供します。"
|
||||
"title": "macOS Computer Useバックエンド",
|
||||
"description": "共通のComputer Useサービスに macOS ネイティブのアプリとウィンドウのオブジェクトを提供します。"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "macOS 电脑操作后端",
|
||||
"description": "为共享电脑操作服务提供 macOS 原生应用与窗口对象。"
|
||||
"title": "macOS Computer Use后端",
|
||||
"description": "为共享Computer Use服务提供 macOS 原生应用与窗口对象。"
|
||||
}
|
||||
}
|
||||
@@ -12,8 +12,8 @@
|
||||
en: f4d9cc48587d62a2
|
||||
zh: d1bac6c1fe7eb29e
|
||||
/deepseek-ai-dsh-cua/table-of-contents:
|
||||
en: 0eab171f6bf125ee
|
||||
zh: 1337384d6c8ee027
|
||||
en: 5db4d4fea25493b9
|
||||
zh: 65ab64fc24eb0d09
|
||||
/deepseek-ai-dsh-cua/use-this-package:
|
||||
en: 4b4000d5eafc9256
|
||||
zh: 4eeae251ec7c8ec4
|
||||
|
||||
@@ -20,7 +20,7 @@ Inspect applications, retain window objects across PTC calls, and send actions t
|
||||
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
|
||||
- [Dev Note](#dev-note)
|
||||
|
||||
Application consent supplies English, Chinese, and Japanese display text from `src/locales.ts` and uses the fixed approval presentation of User Questions and remains independent of the session tool-approval policy. Native icons accompany the prompt and permission-page observations, but remain outside saved identities and model results. System checks, saved grants and refusals, and icons use separate queries so each result can appear without waiting for the others.
|
||||
Application consent supplies English, Chinese, and Japanese display text from `src/locales.ts`. It uses the fixed approval presentation of User Questions and remains independent of the session tool-approval policy. Native icons accompany the prompt and permission-page observations, but remain outside saved identities and model results. System checks, saved grants and refusals, and icons use separate queries so each result can appear without waiting for the others.
|
||||
|
||||
-----
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ kind: "package-reference"
|
||||
- [已知限制与后续工作](#known-limitations-and-deferred-work)
|
||||
- [开发备注](#dev-note)
|
||||
|
||||
应用授权从 `src/locales.ts` 提供中英日展示文案,并使用 User Questions 的固定审批呈现,仍独立于会话的工具审批策略。本机图标用于授权提示和权限页展示,不进入保存的身份信息或模型结果。系统权限、持久授权与拒绝记录、图标分别查询,各项结果返回后即可显示。
|
||||
应用授权从 `src/locales.ts` 提供中英日展示文案。它使用 User Questions 的固定审批呈现,仍独立于会话的工具审批策略。本机图标用于授权提示和权限页展示,不进入保存的身份信息或模型结果。系统权限、持久授权与拒绝记录、图标分别查询,各项结果返回后即可显示。
|
||||
|
||||
-----
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Computer use service",
|
||||
"description": "Shared Computer Use application objects, authorization, and logged tool execution"
|
||||
"title": "Computer Use service",
|
||||
"description": "Manage application access, permissions, and logged tool execution for Computer Use."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "コンピュータ操作サービス",
|
||||
"description": "コンピュータ操作のアプリオブジェクト、認可、ログに記録されるツール実行を管理します。"
|
||||
"title": "Computer Useサービス",
|
||||
"description": "Computer Useのアプリオブジェクト、認可、ログに記録されるツール実行を管理します。"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "电脑操作服务",
|
||||
"description": "管理电脑操作的应用对象、授权和带日志的工具执行。"
|
||||
"title": "Computer Use服务",
|
||||
"description": "管理Computer Use的应用对象、授权和带日志的工具执行。"
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
/** Application consent checked before native observations and input. */
|
||||
import { applicationAccessDisplay } from './locales.ts'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import { UserQuestionError, type AskUserQuestionAnswer } from '@deepseek-ai/dsh-user-questions'
|
||||
import { z } from 'zod'
|
||||
import { applicationAccessDisplay } from './locales.ts'
|
||||
import { NativeError, type NativeClient } from './native-client.ts'
|
||||
import type { CuaAppHandle } from './types.ts'
|
||||
import type { CuaApplicationGrant, CuaApplicationId } from './application-types.ts'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Claude Code hooks",
|
||||
"description": "Bridge plugin: run a Claude Code hooks.json / settings hook config on the DeepSeek Harness interception seams"
|
||||
"description": "Run hooks from Claude Code hooks.json or settings at Harness interception points."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Codex hooks",
|
||||
"description": "Bridge plugin: run a Codex hooks.json hook config on the DeepSeek Harness interception seams"
|
||||
"description": "Run hooks from Codex hooks.json at Harness interception points."
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Custom plugin markets",
|
||||
"description": "Adds a Discover tab to Plugins for browsing and installing bundles from plugin market indexes you add",
|
||||
"description": "Adds a Discover tab to Plugins for browsing and installing bundles from plugin market indexes you add.",
|
||||
"detail": "docs/DETAIL.md"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Python PTC runtime",
|
||||
"description": "CPython subprocess implementation of the DeepSeek Harness PTC execution seam"
|
||||
"description": "Run programmatic tool-calling code in CPython subprocesses."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "All-message session titles",
|
||||
"description": "All-user-messages LLM provider plugin for DeepSeek Harness session titles"
|
||||
"description": "Generate session titles from all user messages in the session."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Session history tools",
|
||||
"description": "Workspace-authorized model-facing session history search, trace, and event read tools"
|
||||
"description": "Search session history and read trajectories and events according to workspace permissions."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Persistent terminal tools",
|
||||
"description": "Six model-facing persistent PTY tools with owner isolation and generic background-job integration"
|
||||
"description": "Provide six persistent PTY tools with isolated session ownership and background task integration."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Translation service",
|
||||
"description": "Machine translation with reusable Session results"
|
||||
"description": "Translate text and reuse translations saved in the session."
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Voice input",
|
||||
"description": "Transcribe recordings locally with SenseVoice; first use requires installing dependencies",
|
||||
"description": "Transcribe recordings locally with SenseVoice; first use requires installing dependencies.",
|
||||
"detail": "docs/DETAIL.md"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "GitHub webhooks",
|
||||
"description": "Signed GitHub HTTP webhook adapter for the DeepSeek Harness webhook runtime"
|
||||
"description": "Verify signed GitHub HTTP webhooks and forward them to the Webhook service."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Webhook runtime",
|
||||
"description": "Fire-and-forget webhook rule runtime that creates Workspace-backed DeepSeek Harness Sessions"
|
||||
"description": "Create Harness sessions in a workspace through Webhook rules without waiting for completion."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Worktree service",
|
||||
"description": "Creates a named Git worktree and changes the calling Session working directory"
|
||||
"description": "Create named Git worktrees and change the current session's working directory."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "プラグイン API 検査サービス"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Local filesystem",
|
||||
"description": "Local-filesystem implementation of the DeepSeek Harness filesystem seam (ctx.fs)"
|
||||
"description": "Access files through the local filesystem."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Text editor tools",
|
||||
"description": "Model-facing view, create, literal replace, and line insert tool over the Harness filesystem service"
|
||||
"description": "View, create, replace, and insert text through the filesystem service."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Static frontend server",
|
||||
"description": "SPA dist server for the Web shell: owns the webserver fallback seat, serving explicit index entries and static assets with traversal rejection and 404 misses"
|
||||
"description": "Serve the Web application's entry page and static files, reject paths outside their directory, and return 404 for missing resources."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Stdio language server provider",
|
||||
"description": "Generic stdio language-server provider for the DeepSeek Harness LSP capability seam (ctx.lsp) — spawns configured servers, translates JSON-RPC, and serves transient-open goToDefinition/findReferences/goToImplementation/hover queries in the host filesystem namespace"
|
||||
"description": "Connect to language servers through subprocesses and JSON-RPC, open files as needed, and run code queries."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Language server service",
|
||||
"description": "Abstract LSP capability seam (ctx.lsp) for the DeepSeek Harness — language-server provider registry keyed by branded id and extension mapping, order-independent per-query selection, normalized definition/references/implementation/hover requests and results, and the LspError taxonomy"
|
||||
"description": "Register language servers for definition, reference, implementation, and hover queries with consistent errors."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Language server tools",
|
||||
"description": "Model-facing lsp tool over the DeepSeek Harness LSP capability seam (ctx.lsp) — one read-only tool with goToDefinition/findReferences/goToImplementation/hover operations, one-based UTF-16 cursor coordinates, bounded location rendering, and hover normalization"
|
||||
"description": "Query definitions, references, implementations, and hover information using one-based UTF-16 cursor positions and bounded results."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "MCP client",
|
||||
"description": "MCP client bridge: connects to MCP servers and registers their tools on ctx.tools"
|
||||
"description": "Connect to MCP servers and make their tools available in Harness."
|
||||
}
|
||||
}
|
||||
@@ -43,8 +43,8 @@ The files below live in this skill's base directory, which the `skill` tool repo
|
||||
| Web UI: Client manifest, module loader, slot registration | `references/ui-plugin.md` |
|
||||
| Connecting an MCP server through a configuration-only bundle | `references/mcp-bundle.md` |
|
||||
| Page/panel design checks and verification without browser control | `references/verification.md` |
|
||||
| UI plugin template, including display resources | `templates/decoration/package.json`, `templates/decoration/cordis.patch.yml`, `templates/decoration/index.js`, `templates/decoration/client.js`, `templates/decoration/locale/en.json`, `templates/decoration/icon.svg` |
|
||||
| MCP bundle template, including display resources | `templates/mcp/package.json`, `templates/mcp/cordis.patch.yml`, `templates/mcp/locale/en.json`, `templates/mcp/icon.svg` |
|
||||
| UI plugin template, including display resources | `templates/decoration/package.json`, `templates/decoration/cordis.patch.yml`, `templates/decoration/index.js`, `templates/decoration/client.js`, `templates/decoration/locale/en.json`, `templates/decoration/locale/ja.json`, `templates/decoration/icon.svg` |
|
||||
| MCP bundle template, including display resources | `templates/mcp/package.json`, `templates/mcp/cordis.patch.yml`, `templates/mcp/locale/en.json`, `templates/mcp/locale/ja.json`, `templates/mcp/icon.svg` |
|
||||
| Loader patch dialect and the list of installable plugin packages | the `cordis-composition-reference` skill |
|
||||
| Choosing extension points, contexts, and state mechanisms for upgrade stability and performance | `references/practices.md` |
|
||||
| Sharing application operations between UI actions and agent tools | `references/user-actions.md` |
|
||||
@@ -16,8 +16,8 @@
|
||||
* @module dsh-sandbox/escalation
|
||||
*/
|
||||
|
||||
import { escalationDisplayReason } from './locales.ts'
|
||||
import { assertNever } from '@deepseek-ai/dsh-util-values'
|
||||
import { escalationDisplayReason } from './locales.ts'
|
||||
import type { SandboxMode } from './index.ts'
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ export const zh = {
|
||||
|
||||
/** Japanese escalation messages. */
|
||||
export const ja = {
|
||||
escalation: (mode: string, justification: string): string => `この操作に ${mode} 権限を許可しますか:${justification}`,
|
||||
escalation: (mode: string, justification: string): string => `${mode} 権限でこの操作を許可します:${justification}`,
|
||||
} satisfies typeof en
|
||||
|
||||
/**
|
||||
|
||||
@@ -89,7 +89,7 @@ describe('approveEscalation', () => {
|
||||
displayReason: {
|
||||
en: 'Allow this operation with workspace-write permissions: the user asked to write in the workspace',
|
||||
zh: '允许本次操作使用 workspace-write 权限:the user asked to write in the workspace',
|
||||
ja: 'この操作に workspace-write 権限を許可しますか:the user asked to write in the workspace',
|
||||
ja: 'workspace-write 権限でこの操作を許可します:the user asked to write in the workspace',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Scheduling tools",
|
||||
"description": "Model-facing reminder management tools (schedule_create, schedule_list, schedule_update, schedule_delete) over the Host ctx.schedule service"
|
||||
"description": "Create, view, update, and delete automated tasks."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "SDK server",
|
||||
"description": "Stdio JSON-RPC server plugin for out-of-process DeepSeek Harness SDK clients"
|
||||
"description": "Serve SDK clients in separate processes through JSON-RPC over standard input and output."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Message quotes",
|
||||
"description": "Selected-text quotation and Markdown blockquote presentation"
|
||||
"description": "Quote selected text and display it as a Markdown block quote."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Working directory tools",
|
||||
"description": "Read and change the active Session working directory"
|
||||
"description": "Read and change the current session's working directory."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Session working directories",
|
||||
"description": "Session working directories with durable changes and model context"
|
||||
"description": "Manage session working directories, save directory changes, and provide the model with working-directory context."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Local Bash execution",
|
||||
"description": "Local-subprocess implementation of the DeepSeek Harness bash executor seam"
|
||||
"description": "Run Bash commands in local subprocesses."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Local PowerShell execution",
|
||||
"description": "Local PowerShell implementation of the DeepSeek Harness bash executor seam"
|
||||
"description": "Run commands through local PowerShell."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Office skills",
|
||||
"description": "Bundled Word, PowerPoint, and Excel workflows and LibreOffice Kit operations"
|
||||
"description": "Provide built-in Word, PowerPoint, and Excel workflows and LibreOffice Kit operations."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Workspace dependencies",
|
||||
"description": "The load_workspace_dependencies tool: absolute paths into a bundled Python, Node.js, and pnpm payload"
|
||||
"description": "Provide absolute paths to the bundled Python, Node.js, and pnpm runtimes."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "SSH filesystem",
|
||||
"description": "Filesystem provider over the shared POSIX SSH helper"
|
||||
"description": "Access remote files through the shared POSIX SSH helper."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "SSH process sandbox",
|
||||
"description": "Remote POSIX sandbox argv provider over the shared SSH helper"
|
||||
"description": "Build sandbox commands for remote POSIX processes through the shared SSH helper."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "SSH connections",
|
||||
"description": "Shared OpenSSH connection and versioned POSIX remote helper"
|
||||
"description": "Share OpenSSH connections and versioned POSIX remote helpers."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "SSH subprocesses",
|
||||
"description": "Subprocess and terminal provider over the shared POSIX SSH helper"
|
||||
"description": "Provide subprocesses and terminals through the shared POSIX SSH helper."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "SQLite storage",
|
||||
"description": "SQLite storage backend (kv facet) for the DeepSeek Harness storage hub"
|
||||
"description": "Store Harness key-value data in SQLite."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "ACP subagent backend",
|
||||
"description": "Out-of-process ACP subagent backend: drives a child agent in a spawned subprocess over the Agent Client Protocol"
|
||||
"description": "Run external agents in subprocesses through ACP."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Claude Code サブエージェント",
|
||||
"description": "Claude Code の標準の認証と設定を使用して、単独のタスクを委派します。"
|
||||
"description": "Claude Code のネイティブの認証と設定を使用して、単独のタスクを委派します。"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Codex サブエージェント",
|
||||
"description": "Codex の標準の認証と設定を使用して、単独のタスクを委派します。"
|
||||
"description": "Codex のネイティブの認証と設定を使用して、単独のタスクを委派します。"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "DSH SDK subagent backend",
|
||||
"description": "Out-of-process SDK subagent backend: drives a child DeepSeek Harness runtime subprocess over stdio JSON-RPC through the TypeScript SDK client"
|
||||
"description": "Run Harness in a subprocess through the TypeScript SDK and JSON-RPC over standard input and output."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "サブエージェントのモデル選択設定"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Exa web search",
|
||||
"description": "Exa-backed search provider for the DeepSeek Harness web capability seam (ctx.web)"
|
||||
"description": "Search the Web through Exa."
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"meta": {
|
||||
"title": "Perplexity web search",
|
||||
"description": "Perplexity-backed search provider for the DeepSeek Harness web capability seam (ctx.web)"
|
||||
"description": "Search the Web through Perplexity."
|
||||
}
|
||||
}
|
||||
@@ -370,16 +370,17 @@ describe('gate graph validation', () => {
|
||||
expect(ids).toEqual([
|
||||
'rescope-vendor', 'publint', 'constraints', 'default-product-isolation', 'product-use', 'official-bundle-catalog', 'provider-data', 'package-dependencies', 'application-entrypoints',
|
||||
'dsh-package-licenses', 'node-next-types',
|
||||
'optional-dependency-imports', 'client-packages', 'installer-locales', 'locale-metadata', 'locale-dictionaries', 'client-ui-i18n', 'client-route-resolution', 'no-bare-dispatcher',
|
||||
'optional-dependency-imports', 'client-packages', 'installer-locales', 'locale-metadata', 'client-ui-i18n', 'client-route-resolution', 'no-bare-dispatcher',
|
||||
'plugin-record-callers', 'no-unknown-casts', 'no-top-level-await',
|
||||
'cordis-config', 'runtime-closure',
|
||||
])
|
||||
})
|
||||
|
||||
it('includes metadata and dictionary completeness in local and CI aggregates', () => {
|
||||
it('includes JSON resource checks in local and CI aggregates', () => {
|
||||
for (const mode of ['i18n', 'check-all', 'ci-static', 'hygiene'] as const) {
|
||||
const ids = withPnpmEntrypoint(() => gatesForMode(mode).map(gate => gate.id))
|
||||
expect(ids).toEqual(expect.arrayContaining(['installer-locales', 'locale-metadata', 'locale-dictionaries']))
|
||||
expect(ids).toEqual(expect.arrayContaining(['installer-locales', 'locale-metadata']))
|
||||
if (mode !== 'i18n') expect(ids).not.toContain('locale-dictionaries')
|
||||
}
|
||||
expect(withPnpmEntrypoint(() => gatesForMode('i18n').map(gate => gate.id)))
|
||||
.toEqual(['installer-locales', 'locale-metadata', 'locale-dictionaries'])
|
||||
|
||||
@@ -366,7 +366,7 @@ export function gatesForMode(selected: Mode): Gate[] {
|
||||
case 'doc-quick':
|
||||
return docQuickLeafGates()
|
||||
case 'i18n':
|
||||
return i18nGates()
|
||||
return i18nGates(true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,11 +389,11 @@ function ciSharedStaticGates(): Gate[] {
|
||||
]
|
||||
}
|
||||
|
||||
function i18nGates(): Gate[] {
|
||||
function i18nGates(includeDictionaries: boolean): Gate[] {
|
||||
return [
|
||||
pnpmScript('installer-locales', 'verify-installer-locales', { label: 'Windows installer locales' }),
|
||||
pnpmScript('locale-metadata', 'verify-locale-metadata', { label: 'Japanese plugin metadata' }),
|
||||
pnpmExec('locale-dictionaries', ['vitest', 'run', 'scripts/locale-dictionary-parity.spec.ts'], { label: 'locale dictionaries' }),
|
||||
...includeDictionaries ? [pnpmExec('locale-dictionaries', ['vitest', 'run', 'scripts/locale-dictionary-parity.spec.ts'], { label: 'locale dictionaries' })] : [],
|
||||
]
|
||||
}
|
||||
|
||||
@@ -403,7 +403,7 @@ function sharedHygieneGates(): Gate[] {
|
||||
label: 'optional dependency imports',
|
||||
}),
|
||||
pnpmScript('client-packages', 'verify-client-packages', { label: 'client packages' }),
|
||||
...i18nGates(),
|
||||
...i18nGates(false),
|
||||
pnpmScript('client-ui-i18n', 'verify-client-ui-i18n', { label: 'client UI i18n' }),
|
||||
pnpmScript('client-route-resolution', 'verify-client-route-resolution', { label: 'client route resolution' }),
|
||||
pnpmScript('no-bare-dispatcher', 'verify-no-bare-dispatcher', { label: 'proxy-aware dispatchers' }),
|
||||
|
||||
@@ -41,7 +41,7 @@ it.each([
|
||||
it('checks referenced detail documents', () => {
|
||||
const root = fixture()
|
||||
const directory = join(root, 'packages/demo/plugin/locale')
|
||||
const meta = { title: 'Name {name}', description: 'Description', detail: 'docs/DETAIL.md' }
|
||||
const meta = { title: 'Name {name}', description: 'Description.', detail: 'docs/DETAIL.md' }
|
||||
for (const language of ['en', 'zh', 'ja']) writeFileSync(join(directory, `${language}.json`), JSON.stringify({ meta }))
|
||||
expect(localeMetadataProblems(root).join('\n')).toContain('missing detail resource')
|
||||
mkdirSync(join(directory, '../docs'))
|
||||
@@ -73,3 +73,49 @@ it('rejects loadable plugins without any locale directory', () => {
|
||||
writeFileSync(join(directory, 'src/index.ts'), 'export function apply() {}')
|
||||
expect(localeMetadataProblems(root).join('\n')).toContain('new-plugin/locale')
|
||||
})
|
||||
|
||||
it('checks nested subpath locale resources and package-relative detail files', () => {
|
||||
const root = fixture()
|
||||
const directory = join(root, 'packages/demo/plugin/locale/tools')
|
||||
mkdirSync(directory)
|
||||
for (const language of ['en', 'zh']) writeFileSync(join(directory, `${language}.json`), JSON.stringify({ meta: { title: 'Tools', detail: 'docs/TOOLS.md' } }))
|
||||
mkdirSync(join(root, 'packages/demo/plugin/docs'))
|
||||
writeFileSync(join(root, 'packages/demo/plugin/docs/TOOLS.md'), '# Tools\n')
|
||||
expect(localeMetadataProblems(root).join('\n')).toContain('locale/tools')
|
||||
expect(localeMetadataProblems(root).join('\n')).toContain('ja.json')
|
||||
writeFileSync(join(directory, 'ja.json'), JSON.stringify({ meta: { title: 'ツール', detail: 'docs/TOOLS.md' } }))
|
||||
expect(localeMetadataProblems(root)).toEqual([])
|
||||
})
|
||||
|
||||
it.each(['../../other/README.md', 'docs\\DETAIL.md', 'docs/DETAIL.txt', '/README.md'])('rejects runtime-invalid detail path %s', (detail) => {
|
||||
const root = fixture({ meta: { title: '名前 {name}', description: '説明', detail } })
|
||||
expect(localeMetadataProblems(root).join('\n')).toMatch(/must (?:be a relative path|name a Markdown file)/u)
|
||||
})
|
||||
|
||||
it('requires sentence punctuation for English descriptions', () => {
|
||||
const root = fixture()
|
||||
const file = join(root, 'packages/demo/plugin/locale/en.json')
|
||||
writeFileSync(file, JSON.stringify({ meta: { title: 'Name {name}', description: 'Description' } }))
|
||||
expect(localeMetadataProblems(root).join('\n')).toContain('sentence punctuation')
|
||||
writeFileSync(file, JSON.stringify({ meta: { title: 'Name {name}', description: 'Description.' } }))
|
||||
expect(localeMetadataProblems(root)).toEqual([])
|
||||
})
|
||||
|
||||
it('permits missing Chinese resources for loadable plugins', () => {
|
||||
const root = fixture({ meta: { title: '名前 {name}' } })
|
||||
const directory = join(root, 'packages/demo/plugin')
|
||||
mkdirSync(join(directory, 'src'))
|
||||
writeFileSync(join(directory, 'src/index.ts'), 'export function apply() {}')
|
||||
writeFileSync(join(directory, 'package.json'), JSON.stringify({ name: '@deepseek-ai/dsh-demo' }))
|
||||
rmSync(join(directory, 'locale/zh.json'))
|
||||
expect(localeMetadataProblems(root)).toEqual([])
|
||||
})
|
||||
|
||||
it('excludes packages formally classified as test helpers', () => {
|
||||
const root = fixture()
|
||||
const directory = join(root, 'packages/test-support/llm-replay')
|
||||
mkdirSync(join(directory, 'src'), { recursive: true })
|
||||
writeFileSync(join(directory, 'src/index.ts'), 'export function apply() {}')
|
||||
writeFileSync(join(directory, 'package.json'), JSON.stringify({ name: '@deepseek-ai/dsh-llm-replay' }))
|
||||
expect(localeMetadataProblems(root)).toEqual([])
|
||||
})
|
||||
@@ -1,6 +1,8 @@
|
||||
/** Check Japanese coverage of package metadata and plugin templates without loading plugins. */
|
||||
import { existsSync, globSync, readFileSync } from 'node:fs'
|
||||
import { basename, dirname, join, resolve } from 'node:path'
|
||||
import { basename, posix, join, resolve } from 'node:path'
|
||||
import { detailPath } from '../packages/util/plugin-detail/src/document.ts'
|
||||
import { PRODUCT_PACKAGE_POLICY } from './product-package-policy.ts'
|
||||
import { collectConfigCatalog } from './gen-config-catalog.ts'
|
||||
|
||||
/** Flatten metadata strings and reject values that cannot be translated. */
|
||||
@@ -16,16 +18,14 @@ function strings(value: unknown, key = ''): Record<string, string> {
|
||||
* @returns actionable missing-file, field, placeholder and resource diagnostics.
|
||||
*/
|
||||
export function localeMetadataProblems(root: string): string[] {
|
||||
const directories = new Set(globSync('packages/**/locale/*.json', {
|
||||
const directories = new Set(globSync('packages/**/locale/**/*.json', {
|
||||
cwd: root, exclude: ['packages/**/node_modules/**', 'packages/**/lib/**', 'packages/**/tests/**'],
|
||||
}).filter(file => ['en.json', 'zh.json', 'ja.json'].includes(basename(file))).map(dirname))
|
||||
const loadable = new Set<string>()
|
||||
}).map(file => file.replaceAll('\\', '/')).filter(file => ['en.json', 'zh.json', 'ja.json'].includes(basename(file))).map(file => posix.dirname(file)))
|
||||
for (const entry of collectConfigCatalog(root)) {
|
||||
// Test-support providers are fixtures, outside the product plugin inventory.
|
||||
if (entry.dir.startsWith('packages/test-support/')) continue
|
||||
const dir = entry.dir.replaceAll('\\', '/')
|
||||
if (PRODUCT_PACKAGE_POLICY[dir]?.category === 'test') continue
|
||||
if (entry.kind !== 'config' && entry.kind !== 'no-config') continue
|
||||
const directory = join(entry.dir, 'locale')
|
||||
loadable.add(directory)
|
||||
const directory = `${dir}/locale`
|
||||
directories.add(directory)
|
||||
}
|
||||
const problems: string[] = []
|
||||
@@ -35,10 +35,18 @@ export function localeMetadataProblems(root: string): string[] {
|
||||
const read = (language: string): Record<string, string> => {
|
||||
const file = join(root, directory, `${language}.json`)
|
||||
const value: unknown = JSON.parse(readFileSync(file, 'utf8'))
|
||||
return strings(value)
|
||||
const dictionary = strings(value)
|
||||
const detail = detailPath(dictionary['meta.detail'], `${directory}/${language}.json: meta.detail`)
|
||||
const packageDir = directory.slice(0, directory.lastIndexOf('/locale'))
|
||||
if (detail !== undefined && !existsSync(resolve(root, packageDir, detail))) {
|
||||
throw new Error(`missing detail resource ${detail}`)
|
||||
}
|
||||
return dictionary
|
||||
}
|
||||
const en = read('en')
|
||||
const zh = loadable.has(directory) || existsSync(join(root, directory, 'zh.json')) ? read('zh') : {}
|
||||
const zh = existsSync(join(root, directory, 'zh.json')) ? read('zh') : {}
|
||||
const description = en['meta.description']
|
||||
if (description !== undefined && !/[.!?]$/u.test(description)) problems.push(`${directory}/en.json: meta.description must end with sentence punctuation`)
|
||||
const ja = read('ja')
|
||||
const expected = { ...zh, ...en }
|
||||
for (const key of new Set([...Object.keys(expected), ...Object.keys(ja)])) {
|
||||
@@ -47,9 +55,6 @@ export function localeMetadataProblems(root: string): string[] {
|
||||
else {
|
||||
const placeholders = (text: string): string => (text.match(/\{\w+\}/gu) ?? []).sort().join(',')
|
||||
if (placeholders(ja[key]) !== placeholders(expected[key])) problems.push(`${directory}/ja.json: ${key} changes placeholders`)
|
||||
if (key === 'meta.detail' && !existsSync(resolve(root, directory, '..', ja[key]))) {
|
||||
problems.push(`${directory}/ja.json: missing detail resource ${ja[key]}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -60,7 +65,7 @@ export function localeMetadataProblems(root: string): string[] {
|
||||
}
|
||||
|
||||
if (import.meta.filename === resolve(process.argv[1] ?? '')) {
|
||||
const problems = localeMetadataProblems(process.cwd())
|
||||
const problems = localeMetadataProblems(resolve(import.meta.dirname, '..'))
|
||||
for (const problem of problems) console.error(problem)
|
||||
if (problems.length > 0) process.exitCode = 1
|
||||
else console.log('verify-locale-metadata: all package and template metadata has complete Japanese translations.')
|
||||
|
||||
@@ -325,7 +325,7 @@
|
||||
},
|
||||
{
|
||||
"name": "present",
|
||||
"description": "Declare existing files as final deliverables for the user. Use it when the user needs a separate file, especially Office documents, spreadsheets, and slide decks; prefer your final response when that suffices. The user opens the current files; their contents are not copied.",
|
||||
"description": "Declare existing files as final deliverables for the user. Hosts may show presented files only after your turn ends, so call it once the files are final. If the user needs to review files earlier, such as before a tool call that waits for their answer, link them in your message instead. Use it when the user needs a separate file, especially Office documents, spreadsheets, and slide decks; prefer your final response when that suffices. The user opens the current files; their contents are not copied.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
Reference in new issue
Block a user