dsh-primer 0.4.5 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +6 -6
- package/README.es.md +6 -6
- package/README.hi.md +6 -6
- package/README.md +7 -7
- package/README.pt.md +6 -6
- package/SKILL.md +11 -9
- package/data/facts.json +35 -15
- package/data/seams/index.json +1526 -98
- package/data/standards.json +17 -11
- package/dist/dsh-plugin-dev.js +22 -37
- package/guide/links.md +2 -2
- package/guide/migration-0.2.md +105 -14
- package/guide/plugin-dev-guide.md +6 -6
- package/guide/quick-reference.es.md +4 -4
- package/guide/quick-reference.hi.md +4 -4
- package/guide/quick-reference.md +4 -4
- package/guide/quick-reference.pt.md +4 -4
- package/guide/quick-reference.zh-CN.md +4 -4
- package/guide/standards.md +1 -1
- package/guide/standards.zh-CN.md +1 -1
- package/guide/unfixed-issues.md +2 -2
- package/guide/version-matrix.md +65 -42
- package/package.json +13 -7
- package/references/official-docs/CLAUDE.md +1 -1
- package/references/official-docs/README.md +9 -4
- package/references/official-docs/SNAPSHOT.md +7 -5
- package/references/official-docs/docs/capability-seams.i18n.yaml +2 -2
- package/references/official-docs/docs/capability-seams.md +4 -0
- package/references/official-docs/docs/capability-seams.zh.md +4 -0
- package/references/official-docs/docs/config-catalog.md +26 -28
- package/references/official-docs/docs/config-catalog.zh.md +26 -28
- package/references/official-docs/docs/defensive-patterns/package-surface.i18n.yaml +2 -2
- package/references/official-docs/docs/defensive-patterns/package-surface.md +0 -1
- package/references/official-docs/docs/defensive-patterns/package-surface.zh.md +0 -1
- package/references/official-docs/docs/event-producer-consumer.md +1 -1
- package/references/official-docs/docs/event-producer-consumer.zh.md +1 -1
- package/references/official-docs/docs/module-graph.md +12 -17
- package/references/official-docs/docs/module-graph.zh.md +12 -17
- package/references/official-docs/docs/subsystems/computer-use.i18n.yaml +2 -2
- package/references/official-docs/docs/subsystems/computer-use.md +1 -1
- package/references/official-docs/docs/subsystems/computer-use.zh.md +1 -1
- package/references/official-docs/docs/subsystems/persistence.md +19 -0
- package/references/official-docs/docs/subsystems/persistence.zh.md +19 -0
- package/references/official-docs/docs/subsystems/ptc-runtime.i18n.yaml +4 -4
- package/references/official-docs/docs/subsystems/ptc-runtime.md +8 -48
- package/references/official-docs/docs/subsystems/ptc-runtime.zh.md +8 -48
- package/references/official-docs/docs/tool-catalog.i18n.yaml +2 -2
- package/references/official-docs/docs/tool-catalog.md +1 -1
- package/references/official-docs/docs/tool-catalog.zh.md +1 -1
- package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.i18n.yaml +4 -4
- package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.md +7 -7
- package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.zh.md +7 -7
- package/references/official-plugin-dev-skill.md +16 -12
- package/references/sources.md +2 -2
- package/scripts/check-docs-drift.mjs +121 -0
- package/scripts/check-docs-drift.ps1 +4 -1
- package/scripts/check-facts.mjs +81 -3
- package/scripts/sync-official-docs.ps1 +16 -5
- package/templates/js/README-es.md +1 -1
- package/templates/js/README-hi.md +1 -1
- package/templates/js/README-pt.md +1 -1
- package/templates/js/README-zh.md +1 -1
- package/templates/js/README.md +1 -1
- package/templates/ts/README-es.md +1 -1
- package/templates/ts/README-hi.md +1 -1
- package/templates/ts/README-pt.md +1 -1
- package/templates/ts/README-zh.md +1 -1
- package/templates/ts/README.md +1 -1
- package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/package-export-cleanup/guide.i18n.yaml +0 -16
- package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/package-export-cleanup/guide.md +0 -26
- package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/package-export-cleanup/guide.zh.md +0 -26
- package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-bootstrap-protocol/guide.i18n.yaml +0 -16
- package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-bootstrap-protocol/guide.md +0 -25
- package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-bootstrap-protocol/guide.zh.md +0 -25
- package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-inspect-output/guide.i18n.yaml +0 -16
- package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-inspect-output/guide.md +0 -48
- package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-inspect-output/guide.zh.md +0 -48
- package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-scoped-repl-default/guide.i18n.yaml +0 -16
- package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-scoped-repl-default/guide.md +0 -45
- package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/ptc-scoped-repl-default/guide.zh.md +0 -45
|
@@ -19,15 +19,13 @@ interface PtcRunRequest {
|
|
|
19
19
|
/**
|
|
20
20
|
* The program source, in the runtime's {@link ../index.ts | language}. It
|
|
21
21
|
* follows the provider's programFormat: an async function body supports
|
|
22
|
-
* top-level `await` and `return`; REPL
|
|
22
|
+
* top-level `await` and `return`; REPL and Script programs support top-level
|
|
23
23
|
* declarations, `await`, and a final expression, but not top-level `return`.
|
|
24
24
|
* The Script provider lowers top-level await; its executionInstructions and
|
|
25
25
|
* documentation define retained-binding semantics. The completion value
|
|
26
26
|
* becomes {@link PtcRunResult.value}.
|
|
27
27
|
*/
|
|
28
28
|
program: string
|
|
29
|
-
/** Discard the completion without JSON validation when true; omission preserves the completion value. */
|
|
30
|
-
discardCompletion?: boolean
|
|
31
29
|
/**
|
|
32
30
|
* Object-identity owner for optional in-memory state. Omission requests a fresh
|
|
33
31
|
* environment. Consumers must await runtime.release(owner) when the owner ends.
|
|
@@ -95,12 +93,11 @@ interface PtcRunResult {
|
|
|
95
93
|
*/
|
|
96
94
|
value?: PtcJsonValue
|
|
97
95
|
/**
|
|
98
|
-
* Captured text
|
|
99
|
-
* Each source channel preserves emission order; interleaving
|
|
96
|
+
* Captured text. Each source channel preserves emission order; interleaving
|
|
100
97
|
* across independent channels is backend-dependent. Bounded only as part of
|
|
101
98
|
* the outer result.
|
|
102
99
|
*/
|
|
103
|
-
|
|
100
|
+
logs: string[]
|
|
104
101
|
/** Present iff the run failed; see {@link PtcRunFailure} for the taxonomy. */
|
|
105
102
|
error?: PtcRunFailure
|
|
106
103
|
}
|
|
@@ -108,10 +105,10 @@ interface PtcRunResult {
|
|
|
108
105
|
|
|
109
106
|
```ts type-equiv
|
|
110
107
|
/** Source evaluation form, independent of retained program state. */
|
|
111
|
-
type PtcProgramFormat = 'function-body' | 'repl' | 'script'
|
|
108
|
+
type PtcProgramFormat = 'function-body' | 'repl' | 'script'
|
|
112
109
|
```
|
|
113
110
|
|
|
114
|
-
`programFormat` distinguishes async function bodies, REPL statements,
|
|
111
|
+
`programFormat` distinguishes async function bodies, REPL statements, and scripts. REPL and Script programs accept top-level `await`, declarations, and a final expression; top-level `return` is not supported. The Node Script provider lowers top-level await and awaits the completion value; its [declaration limitations](../../packages/ptc-runtime/ptc-runtime-node/README.md#known-limitations-and-deferred-work) apply to transformed programs. `retainsState` reports memory retention independently of source syntax. `stateOwner` is an in-process object identity for optional retained memory; distinct objects remain isolated. Consumers await `release(owner)` when that owner ends; cleanup failures reject that call. Omitted owners are one-shot, and stateless providers ignore ownership. The [persistent Node provider](../../packages/ptc-runtime/ptc-runtime-node/README.md#persistent-repl) defines reset and recovery behavior; no retained object enters the durable Session format.
|
|
115
112
|
|
|
116
113
|
## Bindings: host functions as program globals
|
|
117
114
|
|
|
@@ -153,7 +150,7 @@ interface PtcBindingNamespace {
|
|
|
153
150
|
* words, so the same namespace list works against every backend regardless
|
|
154
151
|
* of `language` — a JS-only spelling like `$tools` is rejected by design,
|
|
155
152
|
* not just by the Python backend. Names that satisfy the identifier rule but
|
|
156
|
-
* name a backend-owned slot (`RESERVED_BINDING_GLOBALS`, e.g. `
|
|
153
|
+
* name a backend-owned slot (`RESERVED_BINDING_GLOBALS`, e.g. `console`,
|
|
157
154
|
* `__dsh_main__`) are also refused everywhere; see its declaration for the
|
|
158
155
|
* exact set and why each entry is reserved.
|
|
159
156
|
*/
|
|
@@ -174,7 +171,7 @@ type PtcJsonValue = null | boolean | number | string | PtcJsonValue[] | { [key:
|
|
|
174
171
|
/**
|
|
175
172
|
* One host-side function exposed to the program as an async callable. The
|
|
176
173
|
* runtime bridges calls to it (possibly across a serialization boundary), so
|
|
177
|
-
* `args`
|
|
174
|
+
* `args` and the resolution value MUST be lossless JSON. A runtime rejects a
|
|
178
175
|
* lossy or non-cloneable value with a descriptive error rather than corrupting
|
|
179
176
|
* the run. No seam-level byte cap applies to a binding resolution. A rejection
|
|
180
177
|
* of this function surfaces inside the program as a rejection of the
|
|
@@ -185,29 +182,7 @@ type PtcBindingFunction = (args: unknown) => Promise<PtcJsonValue>
|
|
|
185
182
|
|
|
186
183
|
## Captured output and the failure taxonomy
|
|
187
184
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
```ts public-api
|
|
191
|
-
/** A stored image readable from the program's execution environment. */
|
|
192
|
-
declare class PtcImage {
|
|
193
|
-
readonly [key: string]: PtcJsonValue;
|
|
194
|
-
/** Absolute attachment file path readable in the execution world. */
|
|
195
|
-
readonly path: string;
|
|
196
|
-
/** Stored image selected when the program inspects this value. */
|
|
197
|
-
readonly attachment: Readonly<ImageAttachmentRef>;
|
|
198
|
-
/**
|
|
199
|
-
* Describe one immutable image file in the execution world.
|
|
200
|
-
* @param path - Absolute path to the stored image.
|
|
201
|
-
* @param attachment - Reference to the immutable stored image.
|
|
202
|
-
*/
|
|
203
|
-
constructor(path: string, attachment: ImageAttachmentRef);
|
|
204
|
-
}
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
```ts type-equiv
|
|
208
|
-
/** Raw text fragments and inspected images in emission order; concatenate adjacent text without separators. */
|
|
209
|
-
type PtcOutput = { type: 'text'; text: string } | { type: 'image'; attachment: ImageAttachmentRef }
|
|
210
|
-
```
|
|
185
|
+
Logs are plain strings. Each source channel preserves emission order, while interleaving across independent channels is backend-dependent because channel metadata is not part of the seam. The runtime captures the program's console and stream output, and consumers render only the text. Implementations cap the serialized outer log-array plus completion-value or failure-message payload; fixed result-envelope syntax and consumer presentation whitespace are not part of that variable-payload ledger. Overflow is an explicit failure rather than in-band value substitution.
|
|
211
186
|
|
|
212
187
|
Failure kinds are **orthogonal outcomes reported independently** (per [defensive-patterns](../defensive-patterns/general.md)): a budget expiry is not an exception, an abort is not a timeout, and a substrate death (e.g. OOM) is neither:
|
|
213
188
|
|
|
@@ -262,21 +237,6 @@ Registers one `ctx.ptcRuntime` implementation. Program, budget, abort, and subst
|
|
|
262
237
|
*/
|
|
263
238
|
release(owner: object): Promise<void>
|
|
264
239
|
|
|
265
|
-
/**
|
|
266
|
-
* Register source evaluated once when each execution environment is created.
|
|
267
|
-
* Registration must precede the first run admission; only one initializer may
|
|
268
|
-
* be registered. Current bindings are installed before initialization. Its
|
|
269
|
-
* completion is discarded; logs, timeout, cancellation and output bounds share
|
|
270
|
-
* the first run. Initialization failure discards the environment without
|
|
271
|
-
* executing the user program or rolling back external effects.
|
|
272
|
-
* @param program - Initialization source in the provider's language and format.
|
|
273
|
-
* @returns An idempotent async disposer that stops admission, cancels and drains
|
|
274
|
-
* admitted runs, and releases environments. Failed cleanup blocks execution
|
|
275
|
-
* until the disposer succeeds on retry. The caller owns this disposer.
|
|
276
|
-
* @throws When unsupported, registered twice, registered after admission, or invalid.
|
|
277
|
-
*/
|
|
278
|
-
registerEnvironmentInitializer(program: string): () => Promise<void>
|
|
279
|
-
|
|
280
240
|
/**
|
|
281
241
|
* Resolve supported options and provider defaults before execution.
|
|
282
242
|
* @param request - Program, bindings, cancellation and optional execution choices.
|
|
@@ -19,15 +19,13 @@ interface PtcRunRequest {
|
|
|
19
19
|
/**
|
|
20
20
|
* The program source, in the runtime's {@link ../index.ts | language}. It
|
|
21
21
|
* follows the provider's programFormat: an async function body supports
|
|
22
|
-
* top-level `await` and `return`; REPL
|
|
22
|
+
* top-level `await` and `return`; REPL and Script programs support top-level
|
|
23
23
|
* declarations, `await`, and a final expression, but not top-level `return`.
|
|
24
24
|
* The Script provider lowers top-level await; its executionInstructions and
|
|
25
25
|
* documentation define retained-binding semantics. The completion value
|
|
26
26
|
* becomes {@link PtcRunResult.value}.
|
|
27
27
|
*/
|
|
28
28
|
program: string
|
|
29
|
-
/** Discard the completion without JSON validation when true; omission preserves the completion value. */
|
|
30
|
-
discardCompletion?: boolean
|
|
31
29
|
/**
|
|
32
30
|
* Object-identity owner for optional in-memory state. Omission requests a fresh
|
|
33
31
|
* environment. Consumers must await runtime.release(owner) when the owner ends.
|
|
@@ -95,12 +93,11 @@ interface PtcRunResult {
|
|
|
95
93
|
*/
|
|
96
94
|
value?: PtcJsonValue
|
|
97
95
|
/**
|
|
98
|
-
* Captured text
|
|
99
|
-
* Each source channel preserves emission order; interleaving
|
|
96
|
+
* Captured text. Each source channel preserves emission order; interleaving
|
|
100
97
|
* across independent channels is backend-dependent. Bounded only as part of
|
|
101
98
|
* the outer result.
|
|
102
99
|
*/
|
|
103
|
-
|
|
100
|
+
logs: string[]
|
|
104
101
|
/** Present iff the run failed; see {@link PtcRunFailure} for the taxonomy. */
|
|
105
102
|
error?: PtcRunFailure
|
|
106
103
|
}
|
|
@@ -108,10 +105,10 @@ interface PtcRunResult {
|
|
|
108
105
|
|
|
109
106
|
```ts type-equiv
|
|
110
107
|
/** Source evaluation form, independent of retained program state. */
|
|
111
|
-
type PtcProgramFormat = 'function-body' | 'repl' | 'script'
|
|
108
|
+
type PtcProgramFormat = 'function-body' | 'repl' | 'script'
|
|
112
109
|
```
|
|
113
110
|
|
|
114
|
-
`programFormat` 区分异步函数体、REPL
|
|
111
|
+
`programFormat` 区分异步函数体、REPL 语句与脚本。REPL 与 Script 程序接受顶层 `await`、声明和末尾表达式,不支持顶层 `return`。Node Script 提供方转换顶层 await 并等待完成值;其[声明限制](../../packages/ptc-runtime/ptc-runtime-node/README.zh.md#known-limitations-and-deferred-work)适用于转换后的程序。`retainsState` 独立于源码语法报告是否保留内存。`stateOwner` 是标识可选保留内存的进程内对象身份;不同对象相互隔离。消费者在所有者结束时等待 `release(owner)`;清理失败时该调用拒绝。省略所有者时仅执行一次,无状态提供方忽略所有权。[持久 Node 提供方](../../packages/ptc-runtime/ptc-runtime-node/README.zh.md#persistent-repl)定义重置和恢复行为;保留对象不会进入持久 Session 格式。
|
|
115
112
|
|
|
116
113
|
## 绑定:宿主函数作为程序全局变量
|
|
117
114
|
|
|
@@ -153,7 +150,7 @@ interface PtcBindingNamespace {
|
|
|
153
150
|
* words, so the same namespace list works against every backend regardless
|
|
154
151
|
* of `language` — a JS-only spelling like `$tools` is rejected by design,
|
|
155
152
|
* not just by the Python backend. Names that satisfy the identifier rule but
|
|
156
|
-
* name a backend-owned slot (`RESERVED_BINDING_GLOBALS`, e.g. `
|
|
153
|
+
* name a backend-owned slot (`RESERVED_BINDING_GLOBALS`, e.g. `console`,
|
|
157
154
|
* `__dsh_main__`) are also refused everywhere; see its declaration for the
|
|
158
155
|
* exact set and why each entry is reserved.
|
|
159
156
|
*/
|
|
@@ -174,7 +171,7 @@ type PtcJsonValue = null | boolean | number | string | PtcJsonValue[] | { [key:
|
|
|
174
171
|
/**
|
|
175
172
|
* One host-side function exposed to the program as an async callable. The
|
|
176
173
|
* runtime bridges calls to it (possibly across a serialization boundary), so
|
|
177
|
-
* `args`
|
|
174
|
+
* `args` and the resolution value MUST be lossless JSON. A runtime rejects a
|
|
178
175
|
* lossy or non-cloneable value with a descriptive error rather than corrupting
|
|
179
176
|
* the run. No seam-level byte cap applies to a binding resolution. A rejection
|
|
180
177
|
* of this function surfaces inside the program as a rejection of the
|
|
@@ -185,29 +182,7 @@ type PtcBindingFunction = (args: unknown) => Promise<PtcJsonValue>
|
|
|
185
182
|
|
|
186
183
|
## 捕获的输出与失败分类体系
|
|
187
184
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
```ts public-api
|
|
191
|
-
/** A stored image readable from the program's execution environment. */
|
|
192
|
-
declare class PtcImage {
|
|
193
|
-
readonly [key: string]: PtcJsonValue;
|
|
194
|
-
/** Absolute attachment file path readable in the execution world. */
|
|
195
|
-
readonly path: string;
|
|
196
|
-
/** Stored image selected when the program inspects this value. */
|
|
197
|
-
readonly attachment: Readonly<ImageAttachmentRef>;
|
|
198
|
-
/**
|
|
199
|
-
* Describe one immutable image file in the execution world.
|
|
200
|
-
* @param path - Absolute path to the stored image.
|
|
201
|
-
* @param attachment - Reference to the immutable stored image.
|
|
202
|
-
*/
|
|
203
|
-
constructor(path: string, attachment: ImageAttachmentRef);
|
|
204
|
-
}
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
```ts type-equiv
|
|
208
|
-
/** Raw text fragments and inspected images in emission order; concatenate adjacent text without separators. */
|
|
209
|
-
type PtcOutput = { type: 'text'; text: string } | { type: 'image'; attachment: ImageAttachmentRef }
|
|
210
|
-
```
|
|
185
|
+
日志是纯字符串。每个来源通道保留自身的发出顺序;由于通道元数据不属于 seam,相互独立的通道如何交错由后端决定。运行时捕获程序的 console 与流输出,Consumer 只渲染文本。实现会对序列化后的外层日志数组,以及完成值或失败消息的组合载荷设置上限;固定的结果封装语法与 Consumer 展示空白不计入这份可变载荷计量。超限会显式失败,而不会在值中插入替代内容。
|
|
211
186
|
|
|
212
187
|
失败类型是**正交的结果,独立报告**(见 [defensive-patterns](../defensive-patterns/general.zh.md)):预算耗尽不是异常,中止不是超时,基底崩溃(如 OOM)也不是二者中的任何一个:
|
|
213
188
|
|
|
@@ -262,21 +237,6 @@ Registers one `ctx.ptcRuntime` implementation. Program, budget, abort, and subst
|
|
|
262
237
|
*/
|
|
263
238
|
release(owner: object): Promise<void>
|
|
264
239
|
|
|
265
|
-
/**
|
|
266
|
-
* Register source evaluated once when each execution environment is created.
|
|
267
|
-
* Registration must precede the first run admission; only one initializer may
|
|
268
|
-
* be registered. Current bindings are installed before initialization. Its
|
|
269
|
-
* completion is discarded; logs, timeout, cancellation and output bounds share
|
|
270
|
-
* the first run. Initialization failure discards the environment without
|
|
271
|
-
* executing the user program or rolling back external effects.
|
|
272
|
-
* @param program - Initialization source in the provider's language and format.
|
|
273
|
-
* @returns An idempotent async disposer that stops admission, cancels and drains
|
|
274
|
-
* admitted runs, and releases environments. Failed cleanup blocks execution
|
|
275
|
-
* until the disposer succeeds on retry. The caller owns this disposer.
|
|
276
|
-
* @throws When unsupported, registered twice, registered after admission, or invalid.
|
|
277
|
-
*/
|
|
278
|
-
registerEnvironmentInitializer(program: string): () => Promise<void>
|
|
279
|
-
|
|
280
240
|
/**
|
|
281
241
|
* Resolve supported options and provider defaults before execution.
|
|
282
242
|
* @param request - Program, bindings, cancellation and optional execution choices.
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
en: 8c8643ef46fd075f
|
|
73
73
|
zh: 8c8643ef46fd075f
|
|
74
74
|
/tool-schema-catalog/deepseek-ai-dsh-tool-executor-ptc/run-code:
|
|
75
|
-
en:
|
|
76
|
-
zh:
|
|
75
|
+
en: 7917e16cbc2c366f
|
|
76
|
+
zh: c39eb0420544f04a
|
|
77
77
|
/tool-schema-catalog/deepseek-ai-dsh-plan-mode:
|
|
78
78
|
en: b500b530845e26a9
|
|
79
79
|
zh: b500b530845e26a9
|
|
@@ -623,7 +623,7 @@ ask_user_question keeps the original blocking behavior by default; set `mode: ti
|
|
|
623
623
|
|
|
624
624
|
### `run_code`
|
|
625
625
|
|
|
626
|
-
Execute a TypeScript program against the available tools. Takes two required arguments: `code`, the BODY of an async function (erasable syntax only; top-level `await` and `return` work), and `description`, a short summary of what the program does. Call tools as `await tools.name(args)` per the declarations in the system prompt.
|
|
626
|
+
Execute a TypeScript program against the available tools. Takes two required arguments: `code`, the BODY of an async function (erasable syntax only; top-level `await` and `return` work), and `description`, a short summary of what the program does. Call tools as `await tools.name(args)` per the declarations in the system prompt. Only what you print or return is program output — curate it. Image-bearing subtool results are attached after the run. The program is the body of an async TypeScript function; only erasable syntax is accepted, with no enum or namespaces. Type annotations are advisory. Top-level await and return are supported. Emit output with console.log(...) or return a lossless JSON value. Only printed values and the returned value become program output. Each call runs in a fresh Node process. Node APIs are available through await import(...). Relative paths use the supplied working directory; process.env starts empty. Direct filesystem access follows this execution's sandbox policy. Each program starts in the Session's current directory. Running programs keep their initial directory. A sandbox escalation approves this complete program for one execution only. Nested tools retain their own policies and approvals. Request wider access only after evidence of a denial. Earlier effects may already have completed: inspect them before explicitly retrying. Programs are never replayed automatically.
|
|
627
627
|
|
|
628
628
|
```json
|
|
629
629
|
{
|
|
@@ -627,7 +627,7 @@ ask_user_question 默认保持原有阻塞行为;设置 `mode: timed` 后才
|
|
|
627
627
|
|
|
628
628
|
### `run_code`
|
|
629
629
|
|
|
630
|
-
针对可用工具执行 TypeScript 程序。接受两个必填参数:`code`,异步函数的函数体(仅限可擦除语法,支持顶层 `await` 和 `return`);以及 `description`,简要说明程序做什么。请按系统提示词中的声明,以 `await tools.name(args)`
|
|
630
|
+
针对可用工具执行 TypeScript 程序。接受两个必填参数:`code`,异步函数的函数体(仅限可擦除语法,支持顶层 `await` 和 `return`);以及 `description`,简要说明程序做什么。请按系统提示词中的声明,以 `await tools.name(args)` 调用工具。只有打印或返回的内容构成程序输出,请筛选这些内容。含图片的子工具结果会在运行结束后附加。程序是异步 TypeScript 函数的函数体,只接受可擦除语法,不支持 enum 或 namespace。类型标注只作提示。支持顶层 await 和 return。使用 console.log(...) 或返回无损 JSON 值来输出。只有打印值和返回值成为程序输出。每次调用在新的 Node 进程中运行,可通过 await import(...) 使用 Node API。相对路径以传入的工作目录为准;process.env 初始为空。直接文件系统访问遵循本次执行的沙箱策略。每个程序从 Session 的当前目录启动,运行中保留初始目录。沙箱提权只为本次完整程序执行授权。嵌套工具保留自身策略与审批。只有在获得拒绝证据后才请求更宽访问。先前效果可能已经发生,请在显式重试前检查。程序不会自动重放。
|
|
631
631
|
|
|
632
632
|
```json
|
|
633
633
|
{
|
package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.i18n.yaml
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
en: 207c515390c5e529
|
|
10
10
|
zh: bd4d90881efb011d
|
|
11
11
|
/native-cua-application-and-window-api/change:
|
|
12
|
-
en:
|
|
13
|
-
zh:
|
|
12
|
+
en: e5d1027faa55adba
|
|
13
|
+
zh: 4b88ad6a70977fb3
|
|
14
14
|
/native-cua-application-and-window-api/migration:
|
|
15
|
-
en:
|
|
16
|
-
zh:
|
|
15
|
+
en: 071b67613c512b84
|
|
16
|
+
zh: 7ee32d8dbcf7a0f2
|
package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.md
CHANGED
|
@@ -9,15 +9,15 @@ English | [中文](guide.zh.md)
|
|
|
9
9
|
|
|
10
10
|
## Change
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
CUA scripts use an explicit window for screenshots and pointer input. App and Window objects share the latest accessibility snapshot for their application handle. Their identifiers are `appHandle` and `windowId` respectively. Application discovery still reports the PID of a running match.
|
|
13
13
|
|
|
14
|
-
Providers supply startup capabilities
|
|
14
|
+
Providers supply startup capabilities alongside their platform guidance. The native helper reports runtime permissions and session lock state. The Host combines both in `getCapabilities()`. Human-facing permission responses carry a `darwin` or `win32` platform tag.
|
|
15
15
|
|
|
16
16
|
## Migration
|
|
17
17
|
|
|
18
|
-
1.
|
|
19
|
-
2. Replace `getAXState()` with `getAccessibilityTree()`. Replace `getAXStateAndScreenshot()` with separate tree and screenshot reads. Application and window selection does not read AX. Before using element IDs, call `getAccessibilityTree()` explicitly
|
|
18
|
+
1. After `cua.getApp(selector)`, select the target from `app.getWindows()` with `app.getWindow(windowId)`. Use `window.getScreenshot()`, `window.click()`, `window.scroll()`, and `window.drag()`. Replace `hover` with `window.mouseMove()`. On macOS, `window.click(id)` sends mouse events at the element center. Switch to `invoke(id)` for the default accessibility action, or `performAction(id, "AXShowMenu")` to request an advertised menu action.
|
|
19
|
+
2. Replace `getAXState()` with `getAccessibilityTree()`. Replace `getAXStateAndScreenshot()` with separate tree and screenshot reads. Application and window selection does not read AX. Before using element IDs, call `getAccessibilityTree()` explicitly; use `{ emit: false }` to retain the snapshot without displaying it. A screenshot does not require a successful AX read. Before coordinate input, including relative coordinates, obtain a successful AX observation covering the window or a screenshot; absolute coordinates require a screenshot. See [macOS AX read limits](../cua-ax-read-limits/guide.md) for changes to traversal defaults and configuration.
|
|
20
20
|
3. Pass the opaque string ID from the latest tree wherever you passed a numeric element index. In raw requests use `elementId` with `snapshotId`. Replace `performSecondaryAction` with `listActions(id)` and `performAction(id, exactName, argument?)`, or use `invoke(id)` for the default action. `setValue` accepts the provider’s supported JSON values. On macOS, `performAction(id, 'AXRaise')` performs the advertised raise action. Call `app.activate()` first when the application must become active.
|
|
21
|
-
4. Replace a packed chord such as `pressKey('shift+Tab')` with `pressKey('Tab', ['shift'])`. Check `(await cua.getCapabilities()).methods` before using `sendKeyEvent`. On macOS, call it inside one `run_code`
|
|
22
|
-
5. Read `dispatched
|
|
23
|
-
6.
|
|
21
|
+
4. Replace a packed chord such as `pressKey('shift+Tab')` with `pressKey('Tab', ['shift'])`. Check `(await cua.getCapabilities()).methods` before using `sendKeyEvent`. On macOS, call it inside one `run_code` to hold a key across tool calls. To request one repeat, send another down for a non-modifier key held by that execution. Returning, throwing or pausing releases any remaining keys. If your script handles unknown macOS key names as `NATIVE_ERROR`, handle `INVALID_ARGUMENT` instead. Correct the key name before retrying.
|
|
22
|
+
5. Read `dispatched` from action results, then observe the application to verify the outcome. `invoke` returns `dispatched: false` when the element has no default action. Remove reads of the old `verified` field and of `pid` on selected objects or window records. Use `listApps()` or running `findApps()` matches when you need a PID.
|
|
23
|
+
6. For a custom provider, replace `CuaBackend.description` with `capabilities` and pass `guidance` and `permissionParameters` to `installCua`. Rebuild any custom `helperPath` against the [operation schema](../../../../packages/experimental/cua/src/protocol.ts) and [tagged permission response](../../../../packages/experimental/cua/src/access-types.ts). Restart the provider, inspect its advertised methods and keyboard scopes, and open the Computer Use permission page to verify its platform controls.
|
package/references/official-docs/docs/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.zh.md
CHANGED
|
@@ -9,15 +9,15 @@ description: "迁移 CUA 脚本和自定义原生提供方,使用显式窗口
|
|
|
9
9
|
|
|
10
10
|
## 变更
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
CUA 脚本在指定窗口上截图和操作鼠标。App 和 Window 对象共享同一应用句柄最近读取的辅助功能快照。App 用 `appHandle` 标识,Window 用 `windowId` 标识。查找应用时,运行中的匹配项仍提供 PID。
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
提供方在安装时声明固定的平台能力并提供操作指引。原生 helper 返回实际的权限和会话锁定状态。Host 合并两者,作为 `getCapabilities()` 的结果。供权限页面使用的响应带有 `darwin` 或 `win32` 平台标记。
|
|
15
15
|
|
|
16
16
|
## 迁移
|
|
17
17
|
|
|
18
|
-
1.
|
|
19
|
-
2. 将 `getAXState()` 改为 `getAccessibilityTree()`,将 `getAXStateAndScreenshot()` 拆成读取树和截图两次调用。选择应用或窗口不读取 AX。使用元素 ID 前须显式调用 `getAccessibilityTree()
|
|
18
|
+
1. 调用 `cua.getApp(selector)` 后,从 `app.getWindows()` 返回的列表选定目标,再调用 `app.getWindow(windowId)`。在窗口上调用 `getScreenshot()`、`click()`、`scroll()` 和 `drag()`,将原有的 `hover` 调用改为 `window.mouseMove()`。在 macOS 上,`window.click(id)` 在元素中心发送鼠标事件。需要执行默认辅助功能动作时,改用 `invoke(id)`。需要打开控件菜单且控件声明了 `AXShowMenu` 时,调用 `performAction(id, "AXShowMenu")`。
|
|
19
|
+
2. 将 `getAXState()` 改为 `getAccessibilityTree()`,将 `getAXStateAndScreenshot()` 拆成读取树和截图两次调用。选择应用或窗口不读取 AX。使用元素 ID 前须显式调用 `getAccessibilityTree()`;使用 `{ emit: false }` 可保留快照但不显示树。截图不要求 AX 读取成功。所有坐标输入(包括相对坐标)之前都须成功读取覆盖该窗口的 AX 或取得截图;绝对坐标要求截图。[读取上限的迁移说明](../cua-ax-read-limits/guide.zh.md)列出了 macOS 默认值和配置含义的变化。
|
|
20
20
|
3. 将数字元素索引改为从最新树中取得的字符串 ID。直接发送请求时使用 `elementId` 和 `snapshotId`。原先调用 `performSecondaryAction` 的地方,先用 `listActions(id)` 取得完整动作名,再调用 `performAction(id, exactName, argument?)`。要执行默认动作,可调用 `invoke(id)`。`setValue` 接受提供方支持的 JSON 值。 在 macOS 上,`performAction(id, 'AXRaise')` 只执行元素声明的抬起窗口动作。需要把应用切到前台时先调用 `app.activate()`。
|
|
21
|
-
4. 将 `pressKey('shift+Tab')` 之类的组合键写法改为 `pressKey('Tab', ['shift'])`。调用 `sendKeyEvent` 前检查 `(await cua.getCapabilities()).methods`。在 macOS 上,同一次 `run_code`
|
|
22
|
-
5. 从动作结果读取 `dispatched`,再观察应用确认效果。元素没有默认动作时,`invoke` 返回 `dispatched: false`。移除读取旧字段 `verified` 的代码,以及对已选对象和窗口记录中 `pid`
|
|
23
|
-
6.
|
|
21
|
+
4. 将 `pressKey('shift+Tab')` 之类的组合键写法改为 `pressKey('Tab', ['shift'])`。调用 `sendKeyEvent` 前检查 `(await cua.getCapabilities()).methods`。在 macOS 上,同一次 `run_code` 中可调用此方法跨工具调用保持按键。如果需要一次重复按下,可在这次执行中对已按住的普通键再发一次 `down`。执行返回、异常退出或用户暂停时会释放仍按着的键。如果脚本用 `NATIVE_ERROR` 识别 macOS 上的未知键名,请改为处理 `INVALID_ARGUMENT`,并在重试前修正键名。
|
|
22
|
+
5. 从动作结果读取 `dispatched`,再观察应用确认效果。元素没有默认动作时,`invoke` 返回 `dispatched: false`。移除读取旧字段 `verified` 的代码,以及对已选对象和窗口记录中 `pid` 的读取。需要 PID 时,使用 `listApps()` 或 `findApps()` 返回的运行中应用记录。
|
|
23
|
+
6. 自定义提供方需将 `CuaBackend.description` 改为 `capabilities`,并向 `installCua` 传入 `guidance` 和 `permissionParameters`。如配置了 `helperPath`,请按[操作协议](../../../../packages/experimental/cua/src/protocol.ts)和[带平台标记的权限响应](../../../../packages/experimental/cua/src/access-types.ts)重新构建 helper。重启提供方,检查它声明的方法和键盘输入范围,再打开 Computer Use 权限页确认平台控件。
|
|
@@ -2,21 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
> **这是什么**:DeepSeek Harness 自带的 preset(`packages/preset/agent-preset/`)里有一整套**官方插件开发技能**,是 0.2 世代最重要的新增资料——它描述的正是"在当前 Harness 里、由 agent 自己写并安装插件"的官方流程。
|
|
4
4
|
> **本文件性质**:**要点摘录 + 原文定位**(不是逐字全文;逐字全文随官方文档副本一起在 `references/official-docs/` 之外的仓库路径,需 checkout 才能读)。凡写"官方明确"的地方都能在上游文件里逐字查到。
|
|
5
|
-
> **基线**:`
|
|
6
|
-
> **上游路径**(在 checkout 里,如 `D:\deepseek-harness`):`packages/preset/agent-preset/skills/`
|
|
5
|
+
> **基线**:`38a6a5c965aa99ab525161efb7cc5cf1fe62fced`(`dsh-v0.2.2-rc.3`,2026-11-13)。升级宿主后若与上游冲突,以上游为准。
|
|
6
|
+
> **上游路径**(在 checkout 里,如 `D:\deepseek-harness`):`packages/preset/agent-preset/skills/dsh-doc/`
|
|
7
7
|
|
|
8
|
-
## 1.
|
|
8
|
+
## 1. 一个技能:`dsh-doc`
|
|
9
|
+
|
|
10
|
+
从 `0.2.2-rc.1` 起,Creator mode 原来的四个技能(`cordis-plugin-development`、`editing-cordis-compositions`、`cordis-composition-reference`、`agent-experience`)被**合并成一个 `dsh-doc` 技能**(官方指南 `docs/upgrade-guide/v0.2.2-rc.1/dsh-doc-skill/guide.md`);rc.3 的 preset 技能目录里只有 `dsh-doc/`(43 个文件)。旧的四个名字只作历史,**不要再去 `skills/cordis-plugin-development/` 找路径**。
|
|
9
11
|
|
|
10
12
|
| 技能 | 职责 |
|
|
11
13
|
|---|---|
|
|
12
|
-
| `
|
|
13
|
-
| `
|
|
14
|
-
| `
|
|
15
|
-
| `
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
| `dsh-doc/SKILL.md` | 入口:按"运行时 inspection → 已装文档/包源码 → 声明未核实"的顺序查事实;要改宿主/插件只在用户明确要求时动手 |
|
|
15
|
+
| `dsh-doc/references/plugin-development.md` | **主流程**:bundle 的编写/安装/启用/调试;`plugin_manager` `install_bundle`;禁止手写 profile 清单与在 profile 里跑 pnpm |
|
|
16
|
+
| `dsh-doc/references/{locate-docs,host-plugin,plugin-details,configuration,ui-plugin,mcp-bundle,practices,user-actions,verification,artwork,compositions,upgrading,composition-reference,packages,tool-design}.md` | 分面参考(见 §3;`locate-docs` 讲怎么找当前版本的文档与包源码,`upgrading` 讲升级插件/组合) |
|
|
17
|
+
| `dsh-doc/templates/{decoration,mcp}/**` | 可直接复制的 UI 插件模板与 MCP bundle 模板(含多语 locale 与 icon) |
|
|
18
|
+
|
|
19
|
+
> 仓库贡献者向的 `.agents/skills/**`(如 `dsh-doc-writing`、`dsh-pre-push-checks`)不是 preset 技能、不给插件作者用,别和 `dsh-doc` 混谈。
|
|
18
20
|
|
|
19
|
-
## 2. 主流程(`
|
|
21
|
+
## 2. 主流程(`dsh-doc/SKILL.md` + `dsh-doc/references/plugin-development.md` 的硬性规定)
|
|
20
22
|
|
|
21
23
|
**安装方式(官方唯一推荐)**:在工作区用普通文件写 bundle,然后用 **`plugin_manager` 工具的 `install_bundle`**,`target` 传**绝对包目录**装进当前 profile。改动对该 profile 的**所有会话**生效并跨重启保留。
|
|
22
24
|
|
|
@@ -46,7 +48,9 @@
|
|
|
46
48
|
|
|
47
49
|
**启用随包发布但默认关闭的插件**:行 id 与原因写在随包 patch(源码 checkout 的 `packages/bundle/*/cordis.patch.yml`)里。写一个工作区 bundle,用 patch 覆盖该行为 `disabled: false`,并把它依赖的 Host 行一起插入;源码 checkout 的 `apps/cli/config/examples/<feature>/cordis.yml` 会列出这些行。**随 dsh 发布的包从 dsh 安装位置解析,所以这种 bundle 不声明对它们的依赖。**
|
|
48
50
|
|
|
49
|
-
## 3.
|
|
51
|
+
## 3. 分面参考的要点(都位于 `dsh-doc/references/`)
|
|
52
|
+
|
|
53
|
+
> 下面按旧文件里最常引用的六份(host-plugin / ui-plugin / mcp-bundle / practices / user-actions / verification)展开;rc.3 的 `dsh-doc/references/` 另有 `plugin-development`、`locate-docs`、`plugin-details`、`configuration`、`artwork`、`compositions`、`upgrading`、`composition-reference`、`packages`、`tool-design` 共 17 份参考,按 SKILL.md 的 "Read next" 表取用。
|
|
50
54
|
|
|
51
55
|
### 3.1 `host-plugin.md` — bundle 与 Host 插件
|
|
52
56
|
|
|
@@ -121,4 +125,4 @@
|
|
|
121
125
|
|
|
122
126
|
- 本文件是**索引与摘录**;机制细节(精确签名、事件 `@mode`、Config schema)永远以 **inspection** 与 `references/official-docs/docs/**` 为准。
|
|
123
127
|
- 官方这份技能覆盖"在会话里让 agent 写并安装插件";本知识库另外覆盖**对外发布**(npm/tarball/git 通道、`prepare` + `allowBuilds`、五语 README、质量门禁)与**版本迁移**([migration-0.2.md](../guide/migration-0.2.md))。
|
|
124
|
-
- 上游路径随宿主版本变化(本文件基线 `
|
|
128
|
+
- 上游路径随宿主版本变化(本文件基线 `dsh-v0.2.2-rc.3` / `38a6a5c9`);`preset/agent-presets` → `preset/agent-preset` 的改名发生在 `d1e22a7e24`,`cordis-plugin-development` → `dsh-doc` 的合并发生在 `v0.2.2-rc.1`。
|
package/references/sources.md
CHANGED
|
@@ -33,13 +33,13 @@
|
|
|
33
33
|
|
|
34
34
|
## C. 本地 checkout 文档副本(references/official-docs/)
|
|
35
35
|
|
|
36
|
-
- `docs/**`(**
|
|
36
|
+
- `docs/**`(**709 个 md**,含 352 个 `.zh.md` 双语对;2026-11-14 按**发布 tag** `dsh-v0.2.2-rc.3`(`38a6a5c965aa99ab525161efb7cc5cf1fe62fced`)重同步,不再取 master HEAD)— 教程/架构/子系统/API/cookbook/upgrade-guide/persistence-changes 全量(计数以 `references/official-docs/SNAPSHOT.md` 为准)
|
|
37
37
|
- 仓库根文件(**2026-08-14 晚新增**):`AGENTS.md`、`CLAUDE.md`(上游为 symlink→AGENTS.md,副本存其目标文本)、`BENCHMARK.md`、`CONTRIBUTING.md`/`.zh.md`/`.i18n.yaml`、`README.zh.md`/`.i18n.yaml`、`THIRD_PARTY_NOTICES.md`、`LICENSE`
|
|
38
38
|
- `packages/AGENTS.md` · `packages/README.md` · `vendor/README.md`
|
|
39
39
|
- `website-docs.ts`(站点投影清单)
|
|
40
40
|
- 上游英文 `README.md` 不进入本目录(与 KB 索引同名),线上快照在 `downloads/github/harness/README.md`
|
|
41
41
|
- 同步脚本本次加固:pathspec 全部 `:(top)` 锚定(避免 basename 全局匹配误收仓库深处 symlink);Windows 下无法解出的 symlink 按其 blob 目标文本落地;目的目录只保留范围内条目(曾因一次失败抽取残留污染,已由脚本自动修剪 107 项)。
|
|
42
|
-
- **不在站点路由表里的重要文档**(本地有副本、站上找不到):`session-format-status.md`、`upgrade-guide/**`(
|
|
42
|
+
- **不在站点路由表里的重要文档**(本地有副本、站上找不到):`session-format-status.md`、`upgrade-guide/**`(rc.3 tag 内 12 个版本目录、46 条 0.2.2 线指南;**无 index、无任何入链**)、`persistence-changes/**`、`ui-radius.md`、`web-styling.md`、`module-graph.md`、`dependency-catalog.json`、`persistence-schema.json`——清单见 [guide/links.md](../guide/links.md) §2.1。
|
|
43
43
|
- **官方自带插件开发技能不在 `docs/` 下**:在 `packages/preset/agent-preset/skills/**`(本库要点摘录见 [official-plugin-dev-skill.md](official-plugin-dev-skill.md))。
|
|
44
44
|
|
|
45
45
|
## D. 社区与生态(downloads/community/ + references/community-ecosystem.md)
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Freshness probe for the tag-pinned official-docs mirror (no checkout required).
|
|
3
|
+
//
|
|
4
|
+
// Why this exists, next to `check-docs-drift.ps1`: that script compares the
|
|
5
|
+
// upstream *branch tip* against the pinned commit, which is the right question
|
|
6
|
+
// only while the mirror tracks master. Since 0.4.6 the mirror is pinned to a
|
|
7
|
+
// **release tag** (`references/official-docs/SNAPSHOT.md` -> `Source ref`), so a
|
|
8
|
+
// branch-tip comparison is guaranteed red even with nothing to do: master is
|
|
9
|
+
// always ahead of the tag by construction.
|
|
10
|
+
//
|
|
11
|
+
// The right question for a tag pin is "is there a newer release tag than the one
|
|
12
|
+
// we mirrored?". This script asks it by version-sorting the remote `dsh-v*` tags
|
|
13
|
+
// and comparing the newest one with the pinned ref and commit. It never edits the
|
|
14
|
+
// mirror; drift is only reported.
|
|
15
|
+
//
|
|
16
|
+
// Usage:
|
|
17
|
+
// node scripts/check-docs-drift.mjs [--repo <url>] [--snapshot <path>]
|
|
18
|
+
// [--fail-on-drift] [--json]
|
|
19
|
+
// Exit codes: 0 = FRESH or report produced, 1 = DRIFT (with --fail-on-drift),
|
|
20
|
+
// 2 = probe could not run (snapshot/parse/fetch failure).
|
|
21
|
+
// In CI (when $GITHUB_OUTPUT is set) it appends `drift=yes|no|error`.
|
|
22
|
+
|
|
23
|
+
import { execFileSync } from 'node:child_process'
|
|
24
|
+
import { readFileSync, existsSync, appendFileSync } from 'node:fs'
|
|
25
|
+
import { join } from 'node:path'
|
|
26
|
+
|
|
27
|
+
const root = process.cwd()
|
|
28
|
+
const argv = process.argv.slice(2)
|
|
29
|
+
const flag = (name, fallback) => {
|
|
30
|
+
const i = argv.indexOf(name)
|
|
31
|
+
return i >= 0 ? (argv[i + 1] ?? true) : fallback
|
|
32
|
+
}
|
|
33
|
+
const asJson = argv.includes('--json')
|
|
34
|
+
const failOnDrift = argv.includes('--fail-on-drift')
|
|
35
|
+
const repo = flag('--repo', 'https://github.com/deepseek-ai/deepseek-harness.git')
|
|
36
|
+
const snapshotPath = join(root, flag('--snapshot', 'references/official-docs/SNAPSHOT.md'))
|
|
37
|
+
|
|
38
|
+
const emit = (driftState) => {
|
|
39
|
+
if (process.env.GITHUB_OUTPUT) {
|
|
40
|
+
appendFileSync(process.env.GITHUB_OUTPUT, `drift=${driftState}\n`)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const fail2 = (message) => {
|
|
45
|
+
if (asJson) console.log(JSON.stringify({ state: 'error', message }))
|
|
46
|
+
else console.log(`ERROR: ${message}`)
|
|
47
|
+
emit('error')
|
|
48
|
+
process.exit(2)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!existsSync(snapshotPath)) fail2(`snapshot not found: ${snapshotPath}`)
|
|
52
|
+
const snapshot = readFileSync(snapshotPath, 'utf8')
|
|
53
|
+
const pinnedCommit = /^\|\s*Source commit\s*\|\s*`([0-9a-f]{40})`\s*\|/m.exec(snapshot)?.[1]
|
|
54
|
+
const pinnedRef = /^\|\s*Source ref\s*\|\s*`([^`]+)`\s*\|/m.exec(snapshot)?.[1]
|
|
55
|
+
if (!pinnedCommit) fail2(`cannot parse the pinned "Source commit" from ${snapshotPath}`)
|
|
56
|
+
if (!pinnedRef) fail2(`cannot parse the pinned "Source ref" from ${snapshotPath}`)
|
|
57
|
+
|
|
58
|
+
let result
|
|
59
|
+
if (/^dsh-v/.test(pinnedRef)) {
|
|
60
|
+
// Tag pin: the newest release tag is the freshness authority.
|
|
61
|
+
let newest
|
|
62
|
+
try {
|
|
63
|
+
const out = execFileSync('git', ['ls-remote', '--tags', '--refs', '--sort=-v:refname', repo, 'refs/tags/dsh-v*'], {
|
|
64
|
+
encoding: 'utf8',
|
|
65
|
+
timeout: 60_000,
|
|
66
|
+
})
|
|
67
|
+
newest = out
|
|
68
|
+
.split('\n')
|
|
69
|
+
.map((line) => /^([0-9a-f]{40})\trefs\/tags\/(.+)$/.exec(line))
|
|
70
|
+
.filter(Boolean)
|
|
71
|
+
.map((m) => ({ sha: m[1], tag: m[2] }))[0]
|
|
72
|
+
} catch (error) {
|
|
73
|
+
fail2(`cannot reach upstream ${repo}: ${error.message.split('\n')[0]}`)
|
|
74
|
+
}
|
|
75
|
+
if (!newest) fail2(`no dsh-v* tags found at ${repo}`)
|
|
76
|
+
const fresh = newest.tag === pinnedRef && newest.sha === pinnedCommit
|
|
77
|
+
result = {
|
|
78
|
+
state: fresh ? 'fresh' : 'drift',
|
|
79
|
+
mode: 'tag',
|
|
80
|
+
pinnedRef,
|
|
81
|
+
pinnedCommit,
|
|
82
|
+
upstreamRef: newest.tag,
|
|
83
|
+
upstreamCommit: newest.sha,
|
|
84
|
+
}
|
|
85
|
+
if (!fresh && newest.tag === pinnedRef) {
|
|
86
|
+
result.message = `the pinned tag ${pinnedRef} now points to ${newest.sha}, not the mirrored ${pinnedCommit}`
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
// Legacy branch pin (e.g. origin/master): compare the branch tip.
|
|
90
|
+
const branch = pinnedRef.replace(/^origin\//, '')
|
|
91
|
+
let tip
|
|
92
|
+
try {
|
|
93
|
+
const out = execFileSync('git', ['ls-remote', repo, `refs/heads/${branch}`], { encoding: 'utf8', timeout: 60_000 })
|
|
94
|
+
tip = /^([0-9a-f]{40})\t/.exec(out)?.[1]
|
|
95
|
+
} catch (error) {
|
|
96
|
+
fail2(`cannot reach upstream ${repo}: ${error.message.split('\n')[0]}`)
|
|
97
|
+
}
|
|
98
|
+
if (!tip) fail2(`cannot resolve ${branch} at ${repo}`)
|
|
99
|
+
const fresh = tip === pinnedCommit
|
|
100
|
+
result = { state: fresh ? 'fresh' : 'drift', mode: 'branch', pinnedRef, pinnedCommit, upstreamRef: branch, upstreamCommit: tip }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (result.state === 'fresh') {
|
|
104
|
+
if (asJson) console.log(JSON.stringify(result))
|
|
105
|
+
else {
|
|
106
|
+
console.log(`pinned (SNAPSHOT.md): ${result.pinnedRef} @ ${result.pinnedCommit}`)
|
|
107
|
+
console.log('FRESH: references/official-docs is pinned to the newest official release tag')
|
|
108
|
+
}
|
|
109
|
+
emit('no')
|
|
110
|
+
process.exit(0)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (asJson) console.log(JSON.stringify(result))
|
|
114
|
+
else {
|
|
115
|
+
console.log(`pinned (SNAPSHOT.md): ${result.pinnedRef} @ ${result.pinnedCommit}`)
|
|
116
|
+
console.log(`upstream: ${result.upstreamRef} @ ${result.upstreamCommit}`)
|
|
117
|
+
console.log(`DRIFT: ${result.message ?? 'a newer official release tag exists than the one mirrored'}`)
|
|
118
|
+
console.log(`Action: run pwsh -File scripts/sync-official-docs.ps1 -Ref ${result.upstreamRef} to refresh the mirror (do not hand-edit it).`)
|
|
119
|
+
}
|
|
120
|
+
emit('yes')
|
|
121
|
+
process.exit(failOnDrift ? 1 : 0)
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
# dsh-plugin-guide official-docs freshness probe.
|
|
1
|
+
# dsh-plugin-guide official-docs freshness probe (LEGACY branch-tip probe).
|
|
2
|
+
# NOTE: since 0.4.6 the mirror is pinned to a release tag (`Source ref` in SNAPSHOT.md);
|
|
3
|
+
# comparing the master tip is then always "drift". Use `node scripts/check-docs-drift.mjs`
|
|
4
|
+
# (also what CI runs) for tag pinning; keep this script for a branch-pinned snapshot.
|
|
2
5
|
# Purpose: detect drift between the KB mirror (references/official-docs) and the
|
|
3
6
|
# upstream deepseek-harness repository WITHOUT a local checkout. It compares the
|
|
4
7
|
# upstream branch tip SHA (git ls-remote) against the pinned "Source commit" SHA
|