@qlzt/dsh-tool-goal 0.0.0-stage → 0.2.1-alpha.2

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DeepSeek
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,79 @@
1
+ # Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
2
+ # section, a hash of its English and Chinese blocks outside code blocks and generated regions.
3
+ # After editing either side, bring the other along and re-record with:
4
+ # pnpm run verify-translation-pairing --write packages/goal/tool-goal/README.md
5
+ /:
6
+ en: 1965bb8d690c2163
7
+ zh: ccbb80e24190cb70
8
+ /deepseek-ai-dsh-tool-goal:
9
+ en: 942b1a25c527fe81
10
+ zh: f688d651470c7c5a
11
+ /deepseek-ai-dsh-tool-goal/summary:
12
+ en: e949bc54b6e81b98
13
+ zh: 728896898f55353f
14
+ /deepseek-ai-dsh-tool-goal/table-of-contents:
15
+ en: d152484eb41ac6b4
16
+ zh: 09388d293f9be9cb
17
+ /deepseek-ai-dsh-tool-goal/use-this-package:
18
+ en: 0a5939086aa67be0
19
+ zh: c97e18432e623631
20
+ /deepseek-ai-dsh-tool-goal/use-this-package/tools:
21
+ en: 1f9ad059567a448a
22
+ zh: d3f70b470e9317c4
23
+ /deepseek-ai-dsh-tool-goal/use-this-package/configure-it:
24
+ en: e3f5e8d634a488b7
25
+ zh: 04dcf916aa2114d2
26
+ /deepseek-ai-dsh-tool-goal/use-this-package/authority-rules:
27
+ en: a00f0dac577c3e9e
28
+ zh: 5dedb3dfcce449bc
29
+ /deepseek-ai-dsh-tool-goal/understand-the-implementation:
30
+ en: 4e9fdb5a89f4baa3
31
+ zh: 50d182467ae1f3a7
32
+ /deepseek-ai-dsh-tool-goal/understand-the-implementation/design:
33
+ en: a30f36299c8107f7
34
+ zh: 65e6e1e19aeb5281
35
+ /deepseek-ai-dsh-tool-goal/understand-the-implementation/source-map:
36
+ en: 4d5c648787409868
37
+ zh: b4938bfe660f18aa
38
+ /deepseek-ai-dsh-tool-goal/understand-the-implementation/tool-output:
39
+ en: 79e54f40e0bfbe2b
40
+ zh: 895f7ba22749bc07
41
+ /deepseek-ai-dsh-tool-goal/further-exploration:
42
+ en: 870f9cbbc201e7f1
43
+ zh: 6fa3e87efd10940b
44
+ /deepseek-ai-dsh-tool-goal/model-experience:
45
+ en: 215e7ba838619b7b
46
+ zh: a311da3843709f90
47
+ /deepseek-ai-dsh-tool-goal/model-experience/system-prompt:
48
+ en: cf78b9dd5596495f
49
+ zh: bd44560f8c2435e8
50
+ /deepseek-ai-dsh-tool-goal/model-experience/system-prompt/what-the-model-sees:
51
+ en: c4ddc481746664fc
52
+ zh: f86e0ba3bb0043be
53
+ /deepseek-ai-dsh-tool-goal/model-experience/system-prompt/what-the-model-sees/goal-policy:
54
+ en: 452e35a67b130e54
55
+ zh: ad6030b6cb0eaabc
56
+ /deepseek-ai-dsh-tool-goal/model-experience/system-prompt/token-effect:
57
+ en: 0ca47969efda70ab
58
+ zh: bfb6dd046182bcfe
59
+ /deepseek-ai-dsh-tool-goal/model-experience/system-prompt/kv-cache-effect:
60
+ en: 1228efe95b389486
61
+ zh: 0eb2e21c6ab3bc33
62
+ /deepseek-ai-dsh-tool-goal/model-experience/tool-schemas-and-results:
63
+ en: cadc497841430a21
64
+ zh: af4cc374d7d16917
65
+ /deepseek-ai-dsh-tool-goal/model-experience/tool-schemas-and-results/what-the-model-sees:
66
+ en: a935557ea8afce8e
67
+ zh: 3e2b8208d0a22672
68
+ /deepseek-ai-dsh-tool-goal/model-experience/tool-schemas-and-results/token-effect:
69
+ en: 636b06a2958786bd
70
+ zh: 4bb09f24ef382b3b
71
+ /deepseek-ai-dsh-tool-goal/model-experience/tool-schemas-and-results/kv-cache-effect:
72
+ en: c2d2e98ce08fb40e
73
+ zh: 54d278190a1a9ed5
74
+ /deepseek-ai-dsh-tool-goal/known-limitations-and-deferred-work:
75
+ en: c9b0f788467a5062
76
+ zh: 1a94e89fbb2e1e41
77
+ /deepseek-ai-dsh-tool-goal/known-limitations-and-deferred-work/dev-note:
78
+ en: 47101daa04549489
79
+ zh: 1a3babd48193c068
package/README.md CHANGED
@@ -1,3 +1,162 @@
1
- # Temporary Holding Version
1
+ ---
2
+ description: "The model-facing goal tools for users and maintainers choosing, composing, or debugging get_goal, create_goal, and update_goal."
3
+ kind: "package-reference"
4
+ ---
2
5
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
6
+ # @deepseek-ai/dsh-tool-goal
7
+
8
+ English | [中文](README.zh.md)
9
+
10
+ ## Summary
11
+
12
+ `dsh-tool-goal` lets a model read persisted goals and infer and create a long-running goal from a direct human request. Creating, editing, pausing, or resuming requires that direct request in a top-level agent turn; completing or blocking also works in an autonomous goal round. Updates require the exact goal id and revision returned by a prior read. `resume` rearms active-but-disarmed or blocked goals, while users resume durable paused goals through Web or `/goal resume`. Autonomous blocking requires the same condition for a configurable threshold of three consecutive rounds by default.
13
+
14
+ ## Table of Contents
15
+
16
+ - [Use this package](#use-this-package)
17
+ - [Understand the implementation](#understand-the-implementation)
18
+ - [Further Exploration](#further-exploration)
19
+ - [Model Experience](#model-experience)
20
+ - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
21
+ - [Dev Note](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## Use this package
27
+
28
+ Mount `dsh-tool-goal` beside the goal service when the model should create and update persisted goals itself. The tools are the model-facing half of the goal surface; the `/goal` command is the human-facing half, and the continuation driver uses the same tools to complete or block goals at the end of autonomous rounds.
29
+
30
+ ### Tools
31
+
32
+ All three tools return the same compact JSON — `{ goal: null }` when no goal is current, otherwise the goal's id, revision, objective, phase, rounds started, round cap, optional blocker reason, and whether continuation is armed — matching what Native callers already render.
33
+
34
+ | Tool | What it does |
35
+ |---|---|
36
+ | `get_goal()` | Reads the current goal, or `null` when none is current |
37
+ | `create_goal(objective, max_goal_rounds?)` | Creates one goal from a direct top-level human turn |
38
+ | `update_goal(goal_id, revision, action, objective?, max_goal_rounds?, blocked_reason?)` | `edit`, `pause`, `resume`, `complete`, or `blocked` on the exact goal revision |
39
+
40
+ Call `get_goal` before `update_goal` and copy the exact `goal_id` and `revision`; all calls are exclusive, so a model-ordered batch observes earlier mutations and their new revisions. Replacements belong only to `edit`; `blocked_reason` is required only for `blocked` and is persisted with the stable code `model-reported`. Strict-schema empty-string and zero fillers count as omitted, while meaningful values remain limited to their action.
41
+
42
+ ### Configure it
43
+
44
+ ```yaml
45
+ - id: tool-goal
46
+ name: '@deepseek-ai/dsh-tool-goal'
47
+ config:
48
+ blockedAfterConsecutiveRounds: 3
49
+ ```
50
+
51
+ The value must be a positive safe integer. It supplies both the hard lower bound on model self-blocking and the number named in model guidance. The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-tool-goal) is the exhaustive source for every accepted field.
52
+
53
+ ### Authority rules
54
+
55
+ The tools execute only for the exact live calling agent inside its active driver with an open turn. `create`, `edit`, `pause`, and `resume` additionally require a direct human message in a runtime-root agent's current turn — a subagent or a non-human producer cannot create or edit goals. `resume` rejects a durable paused goal before the goal service runs; that state belongs to the user-facing resume path. `complete` and `blocked` also accept the exact current goal round: a goal-sourced round may complete the goal immediately, but a blocked call is mechanically rejected until the configured number of consecutive rounds has passed — the model judges whether the same condition actually persisted and must describe it in `blocked_reason`. A direct human request may stop a goal immediately.
56
+
57
+ An autonomous round that successfully reports `complete` or `blocked` also ends the physical turn after that step, and the model receives a closing instruction to write the final message to the user. Direct-human mutations never trigger that stop: the assistant may acknowledge the change and the loop keeps concurrent human steering available.
58
+
59
+ -----
60
+
61
+ <a id="understand-the-implementation"></a>
62
+ ## Understand the implementation
63
+
64
+ <details>
65
+ <summary>Implementation internals — click to expand</summary>
66
+
67
+ This section explains how the tools enforce authority and render output; the observable contract is covered in [Use this package](#use-this-package).
68
+
69
+ ### Design
70
+
71
+ - **Authority at execution.** Every call resolves the exact live agent, its inherited `AgentRegistry` initiator, running status, and an open turn; `create`, `edit`, `pause`, and `resume` additionally require an accepted `{ kind: 'user' }` message or steering event in a runtime-root agent's current turn. A durable paused goal fails the `resume` action with `GOAL_TOOL_RESUME_PAUSED`; the user-facing command or Web control owns that transition. Durable fork lineage does not demote a resumed root; live subagent ownership does.
72
+ - **Host attestation of human input.** `{ kind: 'user' }` is assigned by `Agent.followup()` and `steer()` when their caller omits a source, so plugins, schedulers, and other non-human producers must pass their own source rather than inheriting human authority.
73
+ - **System-prompt guidance with the configured threshold.** The package registers one `tool:goal` system-prompt section whose fixed text interpolates `blockedAfterConsecutiveRounds`; the same value is the hard lower bound enforced at execution.
74
+ - **Wrap-up context for terminal rounds.** A successful autonomous `complete` or `blocked` defers a closing `<goal_complete>` or `<goal_blocked>` instruction so the model addresses the user once before the turn ends; direct-human mutations never defer this context.
75
+
76
+ ### Source map
77
+
78
+ | File | Role |
79
+ |---|---|
80
+ | [`src/index.ts`](src/index.ts) | Plugin entry: tool registration, config, system-prompt section, result rendering |
81
+ | [`src/authority.ts`](src/authority.ts) | Execution-time authority checks and goal-round acceptance |
82
+ | [`src/wrapup.ts`](src/wrapup.ts) | Closing-message instruction for terminal autonomous updates |
83
+
84
+ ### Tool output
85
+
86
+ All three tools share one canonical output: the compact JSON `{ goal: null }` or `{ goal: { id, revision, objective, phase, roundsStarted, maxGoalRounds, blockedReason? }, activation }`. `activation` in a result is a live observation and never becomes replay authority. UI clients receive pure generic cards — read for `get_goal`, other for mutations.
87
+
88
+ </details>
89
+
90
+ -----
91
+
92
+ <a id="further-exploration"></a>
93
+ ## Further Exploration
94
+
95
+ The tools are the model-facing half of the goal surface; read these pages for the state they mutate and the policy they defer to.
96
+
97
+ - [Goal service](../goal/README.md) — the goal state and lifecycle the tools mutate.
98
+ - [Goal group map](../README.md) — the goal packages and how they compose.
99
+ - [Generated tool catalog](../../../docs/tool-catalog.md#deepseek-aidsh-tool-goal) — the exact schemas the model receives.
100
+ - [Goal-tool Agent Note](../../../.agents/notes/implemented/feature/2026-07-19-model-facing-goal-tools.md) — the authority split and UX decisions.
101
+
102
+ -----
103
+
104
+ <a id="model-experience"></a>
105
+ ## Model Experience
106
+
107
+ ### System prompt
108
+
109
+ #### What the model sees
110
+
111
+ A fixed goal policy allows inferring goal intent in any language, explains rearming after resume/fork, and limits completion/blocking claims; creation scope and read-before-update refs live in the tool definitions. Durable paused resume is rejected at execution with `GOAL_TOOL_RESUME_PAUSED`; the user-facing goal control owns that transition. The configured threshold is interpolated into that guidance.
112
+
113
+ ##### Goal policy
114
+
115
+ ```markdown
116
+ create_goal may infer goal intent from a direct human request in any language. After session resume or fork, an active goal is disarmed: when a human asks to continue or resume in any wording or language, use update_goal action resume to rearm it. Mark complete only when the objective is actually achieved. Mark blocked only after the same blocking condition persists for at least 3 consecutive goal rounds, and report that concrete condition in blocked_reason; difficulty, uncertainty, or useful remaining work is not blocked.
117
+ ```
118
+
119
+ #### Token effect
120
+
121
+ Small fixed input cost on every request where this plugin's prompt registration is in scope.
122
+
123
+ #### KV Cache effect
124
+
125
+ Prefix-stable while the plugin scope, configured threshold, and guidance text are unchanged. Activation, disposal, or configuration changes may invalidate reuse from this prompt section.
126
+
127
+ ### Tool schemas and results
128
+
129
+ #### What the model sees
130
+
131
+ The generated [`get_goal`, `create_goal`, and `update_goal` schemas](../../../docs/tool-catalog.md#deepseek-aidsh-tool-goal). Successful results are compact JSON. A mutation appends the goal domain's durable `goal/change` event without queuing model context. `activation` in a result is a live observation and never becomes replay authority.
132
+
133
+ #### Token effect
134
+
135
+ Fixed schema cost plus one compact result per call. The durable mutation adds no separate model-visible context.
136
+
137
+ #### KV Cache effect
138
+
139
+ Schemas are prefix-stable while their definitions and visibility are unchanged. Calls and results append after the reusable request prefix without invalidating earlier entries.
140
+
141
+ ## Known Limitations and Deferred Work
142
+
143
+ <a id="known-limitations-and-deferred-work"></a>
144
+
145
+
146
+ These limits define when the goal tools are a poor fit or need special care. They are current package constraints, not a task backlog.
147
+
148
+ - **Semantic intent remains model judgment** — execution can prove that the current turn contains a direct human message, not whether the request is substantial enough to merit a goal.
149
+ - **Same-condition blocking remains model judgment** — the runtime enforces distinct admitted-round count, not semantic equivalence of obstacles; an independent evaluator is deferred.
150
+ - **No scheduling or direct human rendering** — these tools mutate state only; the same-session driver and `dsh-command-goal` are independent consumers of the same domain.
151
+ - **Goal-round authority requires a driver** — the autonomous `complete`/`blocked` path is dormant unless a continuation driver admits goal-sourced user turns; mounting this tool package alone does not create them.
152
+ - **Prompt registration is independent of filtering** — a scope may hide the tools while retaining their guidance unless the deployment scopes both registrations together.
153
+
154
+ <a id="dev-note"></a>
155
+ ### Dev Note
156
+
157
+ <details>
158
+ <summary>Working context for maintainers — click to expand</summary>
159
+
160
+ This Dev Note is working context for maintainers; it is explicitly non-authoritative. Open question: whether the goal-policy section should be independently scoped from the tool registrations, so a scope cannot hide the tools while keeping the guidance.
161
+
162
+ </details>
package/README.zh.md ADDED
@@ -0,0 +1,162 @@
1
+ ---
2
+ description: "面向选择、组合或排查 get_goal、create_goal 与 update_goal 的用户与维护者的模型侧 goal 工具说明。"
3
+ kind: "package-reference"
4
+ ---
5
+
6
+ # @deepseek-ai/dsh-tool-goal
7
+
8
+ [English](README.md) | 中文
9
+
10
+ ## 概述
11
+
12
+ `dsh-tool-goal` 让模型读取持久 goal,并根据人类直接请求推断和创建长期 goal。创建、编辑、暂停或恢复要求该直接请求出现在顶层 agent(智能体)轮次中;完成或阻塞也可以在自主 Goal Round 中执行。更新必须使用先前读取到的精确 goal id 和 revision。`resume` 会重新启用 active-but-disarmed 或 blocked 的 goal,而持久的 paused goal 由用户通过 Web 或 `/goal resume` 恢复。自主阻塞要求同一条件持续达到可配置阈值,默认是连续三个 Round。
13
+
14
+ ## 目录
15
+
16
+ - [使用本包](#use-this-package)
17
+ - [理解实现](#understand-the-implementation)
18
+ - [进一步探索](#further-exploration)
19
+ - [模型体验](#model-experience)
20
+ - [已知限制与延期工作](#known-limitations-and-deferred-work)
21
+ - [开发备注](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## 使用本包
27
+
28
+ 当模型需要自行创建和更新持久 goal 时,把 `dsh-tool-goal` 挂在 goal 服务旁边。这些工具是 goal 表面面向模型的一半;`/goal` 命令是面向人类的一半,续行驱动器在自主 Round 结束时使用同一套工具完成或阻塞 goal。
29
+
30
+ ### 工具
31
+
32
+ 三个工具都返回相同的紧凑 JSON——没有当前 goal 时为 `{ goal: null }`,否则返回 goal 的 id、revision、目标、phase、已开始 Round、Round 上限、可选的 blocker reason 与续行是否已启用——与 Native 调用方已经渲染的内容一致。
33
+
34
+ | 工具 | 作用 |
35
+ |---|---|
36
+ | `get_goal()` | 读取当前 goal;没有当前 goal 时返回 `null` |
37
+ | `create_goal(objective, max_goal_rounds?)` | 根据人类直接发起的顶层轮次创建一个 goal |
38
+ | `update_goal(goal_id, revision, action, objective?, max_goal_rounds?, blocked_reason?)` | 对精确 goal revision 执行 `edit`、`pause`、`resume`、`complete` 或 `blocked` |
39
+
40
+ 在 `update_goal` 之前调用 `get_goal`,并复制精确的 `goal_id` 与 `revision`;所有调用都互斥,因此模型排序的批次能观察到更早变更及其新 revision。替换值只属于 `edit`;`blocked_reason` 只有在 `blocked` 时才必填,并以稳定代码 `model-reported` 持久化。严格 schema 下的空字符串和零填充值视为省略,而有意义的值仍限定到各自 action。
41
+
42
+ ### 配置
43
+
44
+ ```yaml
45
+ - id: tool-goal
46
+ name: '@deepseek-ai/dsh-tool-goal'
47
+ config:
48
+ blockedAfterConsecutiveRounds: 3
49
+ ```
50
+
51
+ 该值必须是正的安全整数。它既提供模型自行报告阻塞的硬下限,也决定模型指引中指明的数值。生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-tool-goal)是每个受支持字段的穷尽式真源。
52
+
53
+ ### 权限规则
54
+
55
+ 工具只为活跃驱动器内、处于开放轮次中的精确活跃调用 agent 执行。`create`、`edit`、`pause` 和 `resume` 还要求运行时根 agent 的当前轮次中存在人类直接消息——subagent 或非人类生产方不能创建或编辑 goal。`resume` 会在 goal 服务执行前拒绝持久的 paused goal;该状态只属于面向用户的恢复路径。`complete` 和 `blocked` 还接受完全一致的当前 Goal Round:来源为 goal 的 Round 可以立即完成 goal,但 `blocked` 调用在达到配置的连续 Round 数量之前会被机械拒绝——模型判断同一条件是否确实持续,并必须在 `blocked_reason` 中说明。人类直接请求可以立即停止 goal。
56
+
57
+ 成功报告 `complete` 或 `blocked` 的自主 Round 还会在该步骤后结束物理轮次,模型会收到一条结束指令,要求向用户写出最终消息。人类直接变更绝不会触发这种停止:assistant 可以确认变更,循环仍可接收并发的人类 steering(中途引导)。
58
+
59
+ -----
60
+
61
+ <a id="understand-the-implementation"></a>
62
+ ## 理解实现
63
+
64
+ <details>
65
+ <summary>实现细节——点击展开</summary>
66
+
67
+ 本节解释工具如何强制执行权限并渲染输出;可观察约定已在[使用本包](#use-this-package)中说明。
68
+
69
+ ### 设计
70
+
71
+ - **执行时权限。** 每次调用都解析精确活跃 agent、其继承的 `AgentRegistry` initiator、running 状态与开放轮次;`create`、`edit`、`pause` 和 `resume` 还要求运行时根 agent 的当前轮次中存在已接受的 `{ kind: 'user' }` 消息或 steering 事件。持久的 paused goal 会让 `resume` 以 `GOAL_TOOL_RESUME_PAUSED` 失败;面向用户的命令或 Web 控件拥有该转换。持久 fork 谱系不会降低已恢复根 agent 的等级;活跃 subagent 所有权会降低。
72
+ - **人类输入的宿主证明。** `Agent.followup()` 与 `steer()` 会在调用方省略 source 时分配 `{ kind: 'user' }`,因此插件、调度器与其他非人类生产方必须传入自己的 source,不能继承人类权限。
73
+ - **带配置阈值的系统提示词指引。** 本包注册一个 `tool:goal` 系统提示词章节,其固定文本插入 `blockedAfterConsecutiveRounds`;同一数值就是执行时强制执行的硬下限。
74
+ - **终局 Round 的结束上下文。** 成功的自主 `complete` 或 `blocked` 会延后一条 `<goal_complete>` 或 `<goal_blocked>` 结束指令,让模型在轮次结束前向用户做一次交代;人类直接变更绝不会延后该上下文。
75
+
76
+ ### 源码地图
77
+
78
+ | 文件 | 职责 |
79
+ |---|---|
80
+ | [`src/index.ts`](src/index.ts) | 插件入口:工具注册、配置、系统提示词章节、结果渲染 |
81
+ | [`src/authority.ts`](src/authority.ts) | 执行时权限检查与 Goal Round 接受 |
82
+ | [`src/wrapup.ts`](src/wrapup.ts) | 终局自主更新的结束消息指令 |
83
+
84
+ ### 工具输出
85
+
86
+ 三个工具共用一种规范输出:紧凑 JSON `{ goal: null }`,或 `{ goal: { id, revision, objective, phase, roundsStarted, maxGoalRounds, blockedReason? }, activation }`。结果中的 `activation` 是实时观察值,绝不会成为回放权限依据。UI 客户端收到纯通用卡片——`get_goal` 为 read,变更使用 other。
87
+
88
+ </details>
89
+
90
+ -----
91
+
92
+ <a id="further-exploration"></a>
93
+ ## 进一步探索
94
+
95
+ 这些工具是 goal 表面面向模型的一半;如需了解它们变更的状态及其所遵循的策略,请阅读以下页面。
96
+
97
+ - [goal 服务](../goal/README.zh.md)——工具变更的 goal 状态与生命周期。
98
+ - [goal 组地图](../README.zh.md)——goal 各包及其组合方式。
99
+ - [生成的工具目录](../../../docs/tool-catalog.zh.md#deepseek-aidsh-tool-goal)——模型接收的精确 schema。
100
+ - [goal 工具 Agent Note](../../../.agents/notes/implemented/feature/2026-07-19-model-facing-goal-tools.zh.md)——权限拆分与 UX 决策。
101
+
102
+ -----
103
+
104
+ <a id="model-experience"></a>
105
+ ## 模型体验
106
+
107
+ ### 系统提示词
108
+
109
+ #### 模型看到的内容
110
+
111
+ 固定 goal 策略允许以任意语言推断 goal 意图,解释会话 resume/fork 后如何重新启用续行,并限制完成/阻塞声明;创建范围和更新前读取 ref 由工具定义说明。持久 paused 的 resume 会在执行时以 `GOAL_TOOL_RESUME_PAUSED` 拒绝;面向用户的 goal 控件拥有该转换。配置的阈值会插入该指引。
112
+
113
+ ##### Goal 策略
114
+
115
+ ```markdown
116
+ create_goal may infer goal intent from a direct human request in any language. After session resume or fork, an active goal is disarmed: when a human asks to continue or resume in any wording or language, use update_goal action resume to rearm it. Mark complete only when the objective is actually achieved. Mark blocked only after the same blocking condition persists for at least 3 consecutive goal rounds, and report that concrete condition in blocked_reason; difficulty, uncertainty, or useful remaining work is not blocked.
117
+ ```
118
+
119
+ #### Token 影响
120
+
121
+ 此插件的提示词注册位于请求范围内时,每次请求都会产生少量固定输入成本。
122
+
123
+ #### KV Cache 影响
124
+
125
+ 插件范围、配置阈值和指引文本不变时,前缀保持稳定。启用、dispose(资源释放)或配置变更可能使此提示词章节的复用失效。
126
+
127
+ ### 工具 schema 与结果
128
+
129
+ #### 模型看到的内容
130
+
131
+ 生成的 [`get_goal`、`create_goal` 和 `update_goal` schema](../../../docs/tool-catalog.zh.md#deepseek-aidsh-tool-goal)。成功结果是紧凑 JSON。变更会追加 goal 领域的持久 `goal/change` 事件,而不会将模型上下文加入队列。结果中的 `activation` 是实时观察值,绝不会成为回放权限依据。
132
+
133
+ #### Token 影响
134
+
135
+ 固定 schema 成本,加上每次调用的一条紧凑结果。持久变更不会增加单独的模型可见上下文。
136
+
137
+ #### KV Cache 影响
138
+
139
+ schema 的定义与可见性不变时,前缀保持稳定。调用和结果会追加到可复用请求前缀之后,不会使更早条目失效。
140
+
141
+ ## 已知限制与延期工作
142
+
143
+ <a id="known-limitations-and-deferred-work"></a>
144
+
145
+
146
+ 这些限制说明 goal 工具何时不合适或需要特别注意。它们是当前包约束,不是任务积压。
147
+
148
+ - **语义意图仍由模型判断**——执行只能证明当前轮次包含一条人类直接发送的消息,无法证明请求是否足够重大而值得创建 goal。
149
+ - **阻塞条件是否相同仍由模型判断**——运行时强制统计互不重复的已准入 Goal Round,而不判断障碍在语义上是否等价;独立评估器的实现暂缓。
150
+ - **不负责调度或直接面向人类呈现**——这些工具只变更状态;同会话驱动器与 `dsh-command-goal` 是同一领域的独立消费方。
151
+ - **Goal Round 权限需要驱动器**——除非续行驱动器准入 goal 来源的用户轮次,否则自主 `complete`/`blocked` 路径不会启用;只挂载这个包不会创建这些轮次。
152
+ - **提示词注册与过滤相互独立**——某个范围可能隐藏工具,却保留指引,除非部署将两项注册限定在同一范围。
153
+
154
+ <a id="dev-note"></a>
155
+ ### 开发备注
156
+
157
+ <details>
158
+ <summary>维护者的工作上下文——点击展开</summary>
159
+
160
+ 本开发备注是维护者的工作上下文,明确不具权威性。开放问题:goal 策略章节是否应与工具注册独立限定范围,避免某个范围隐藏工具却保留指引。
161
+
162
+ </details>
package/lib/index.js ADDED
@@ -0,0 +1,379 @@
1
+ import z from "@deepseek-ai/schemastery";
2
+ import { GoalId } from "@qlzt/dsh-goal";
3
+ import { HarnessError, boundContextSummary, createUserMessage } from "@qlzt/dsh-llm";
4
+ import { defineTool } from "@qlzt/dsh-tools";
5
+ //#region lib/types/authority.js
6
+ /** Execution-time authority checks for the model-facing goal tools. */
7
+ /** Throw one structured tool-policy failure. */
8
+ function reject(message, code = "GOAL_TOOL_AUTHORITY_REQUIRED") {
9
+ throw new HarnessError(message, code);
10
+ }
11
+ /** Resolve the immutable event cut and open-turn boundary without copying the turn suffix. */
12
+ function openTurnEvents(ctx, agent) {
13
+ const events = agent.session.snapshotEvents();
14
+ const boundary = ctx.sessionProjections.stateOf(agent.session, "turnBoundary");
15
+ if (boundary === void 0 || boundary.openTurnStartSeq === null) reject("goal tools require an open model turn", "GOAL_TOOL_DRIVER_REQUIRED");
16
+ return {
17
+ events,
18
+ openTurnStartSeq: boundary.openTurnStartSeq
19
+ };
20
+ }
21
+ /**
22
+ * Resolve and authenticate the calling agent and its driver boundary.
23
+ * @param ctx - Context carrying the live agent registry.
24
+ * @param exec - Tool execution metadata supplied by the registry.
25
+ * @returns The authenticated agent, immutable event cut, and open-turn boundary.
26
+ */
27
+ function goalToolExecution(ctx, exec) {
28
+ const agent = exec.agent;
29
+ if (agent === void 0) return reject("goal tools require a calling agent", "GOAL_TOOL_AGENT_REQUIRED");
30
+ if (ctx.agents.get(agent.id) !== agent || agent.status !== "running" || ctx.agents.currentInitiator() !== agent) return reject("goal tools require the exact live calling agent inside its active driver", "GOAL_TOOL_DRIVER_REQUIRED");
31
+ return {
32
+ agent,
33
+ ...openTurnEvents(ctx, agent)
34
+ };
35
+ }
36
+ /** Whether the captured open turn contains an event accepted by `predicate`. */
37
+ function someOpenTurnEvent(execution, predicate) {
38
+ for (let seq = execution.openTurnStartSeq + 1; seq < execution.events.length; seq += 1) {
39
+ const event = execution.events[seq];
40
+ if (event !== void 0 && predicate(event)) return true;
41
+ }
42
+ return false;
43
+ }
44
+ /**
45
+ * Whether host-attested human input appears in the current root-agent turn.
46
+ * An omitted `Agent.followup()` / `steer()` source resolves to `user`, so non-human
47
+ * producers must supply their own source rather than inheriting this authority.
48
+ */
49
+ function hasDirectHumanInput(ctx, execution) {
50
+ if (!ctx.agents.roots().includes(execution.agent)) return false;
51
+ return someOpenTurnEvent(execution, (event) => event.type === "user/message" && event.data.source.kind === "user");
52
+ }
53
+ /** Whether this turn is the current goal's exact admitted round. */
54
+ function isMatchingGoalRound(execution, goal) {
55
+ return someOpenTurnEvent(execution, (event) => event.type === "user/message" && event.data.source.kind === "goal" && event.data.source.goalId === goal.id && event.data.source.revision === goal.revision && event.data.source.round === goal.roundsStarted);
56
+ }
57
+ /**
58
+ * Require authority originating in a human message accepted by a runtime root.
59
+ * @param ctx - Context carrying the live agent graph.
60
+ * @param execution - Authenticated current tool execution.
61
+ */
62
+ function requireDirectHuman(ctx, execution) {
63
+ if (hasDirectHumanInput(ctx, execution)) return;
64
+ reject("this goal operation requires a direct human turn on a top-level agent");
65
+ }
66
+ /**
67
+ * Resolve completion authority from either direct human input or the exact goal round.
68
+ * @param ctx - Context carrying live agents and goal state.
69
+ * @param execution - Authenticated current tool execution.
70
+ * @returns The direct-human or exact-goal-round authority grant.
71
+ */
72
+ function completionAuthority(ctx, execution) {
73
+ if (hasDirectHumanInput(ctx, execution)) return { kind: "direct-human" };
74
+ const goal = ctx.goals.get(execution.agent);
75
+ if (goal !== void 0 && isMatchingGoalRound(execution, goal)) return {
76
+ kind: "goal-round",
77
+ goal
78
+ };
79
+ return reject("complete and blocked require a direct human turn or the current goal round");
80
+ }
81
+ //#endregion
82
+ //#region lib/types/wrapup.js
83
+ /**
84
+ * Render the closing-message instruction injected after an autonomous goal
85
+ * round reports `complete` or `blocked`, replacing the former hard turn stop
86
+ * so the model still addresses the user once before the turn ends.
87
+ * @param objective - the terminal goal's objective, echoed for grounding.
88
+ * @param blockedReason - the validated report for `blocked`; omitted for `complete`.
89
+ * @returns a fresh one-block context for `ToolRunContext.deferContext()`.
90
+ */
91
+ function renderWrapupContext(objective, blockedReason) {
92
+ const heading = `Objective: ${JSON.stringify(objective)}\n`;
93
+ return [{
94
+ type: "text",
95
+ text: blockedReason === void 0 ? "<goal_complete>\n" + heading + "The goal is marked complete and this autonomous run is ending. Write the closing message to the user now: state the outcome, summarize what was done and how it was verified, and point to the concrete results (files, commits, or other artifacts). Report only what earlier rounds and tool results in this session actually establish; when a detail is not in the session, say so instead of inventing it. Note anything the user should review or do next. Address the user directly. Do not call any more tools in this run; further work waits for the user's next instruction.\n</goal_complete>" : "<goal_blocked>\n" + heading + `Blocked: ${JSON.stringify(blockedReason)}\nThe goal is marked blocked and this autonomous run is ending. Write the closing message to the user now: state what has been completed so far, describe the concrete blocking condition and what you tried, and say exactly what you need from the user to continue. Report only what earlier rounds and tool results in this session actually establish; when a detail is not in the session, say so instead of inventing it. Address the user directly. Do not call any more tools in this run; further work waits for the user's next instruction.
96
+ </goal_blocked>`
97
+ }];
98
+ }
99
+ //#endregion
100
+ //#region lib/types/index.js
101
+ /**
102
+ * Model-facing `get_goal`, `create_goal`, and `update_goal` tools over the
103
+ * persisted same-session goal domain.
104
+ * @module @qlzt/dsh-tool-goal
105
+ */
106
+ const name = "tool-goal";
107
+ const inject = [
108
+ "agents",
109
+ "goals",
110
+ "tools",
111
+ "systemPrompt",
112
+ "sessionProjections"
113
+ ];
114
+ /** Schemastery config for the goal-tool policy. */
115
+ const Config = z.object({ blockedAfterConsecutiveRounds: z.number().step(1).min(1).default(3) });
116
+ const UPDATE_ACTIONS = [
117
+ "edit",
118
+ "pause",
119
+ "resume",
120
+ "complete",
121
+ "blocked"
122
+ ];
123
+ const CREATE_DESCRIPTION = "Create a persisted goal that keeps this session working across automatic continuation rounds. Use it when the direct human request is a long-running objective, even if the user did not say \"goal\"; not for single-turn work.";
124
+ const GET_DESCRIPTION = "Read the current session goal, including the id and revision that update_goal requires.";
125
+ const GOAL_VALUE_SCHEMA = { oneOf: [{
126
+ type: "object",
127
+ additionalProperties: false,
128
+ properties: { goal: {
129
+ type: "null",
130
+ required: true
131
+ } }
132
+ }, {
133
+ type: "object",
134
+ additionalProperties: false,
135
+ properties: {
136
+ goal: {
137
+ type: "object",
138
+ additionalProperties: false,
139
+ required: true,
140
+ properties: {
141
+ id: {
142
+ type: "string",
143
+ required: true
144
+ },
145
+ revision: {
146
+ type: "integer",
147
+ required: true
148
+ },
149
+ objective: {
150
+ type: "string",
151
+ required: true
152
+ },
153
+ phase: {
154
+ type: "string",
155
+ required: true,
156
+ enum: [
157
+ "active",
158
+ "paused",
159
+ "blocked",
160
+ "complete"
161
+ ]
162
+ },
163
+ roundsStarted: {
164
+ type: "integer",
165
+ required: true
166
+ },
167
+ maxGoalRounds: {
168
+ type: "integer",
169
+ required: true
170
+ },
171
+ blockedReason: {
172
+ type: "object",
173
+ additionalProperties: false,
174
+ properties: {
175
+ code: {
176
+ type: "string",
177
+ required: true
178
+ },
179
+ message: {
180
+ type: "string",
181
+ required: true
182
+ }
183
+ }
184
+ }
185
+ }
186
+ },
187
+ activation: {
188
+ type: "string",
189
+ required: true,
190
+ enum: ["armed", "disarmed"]
191
+ }
192
+ }
193
+ }] };
194
+ /** Render policy guidance with its deployment-selected blocked threshold. */
195
+ function guidance(blockedAfter) {
196
+ return `create_goal may infer goal intent from a direct human request in any language. After session resume or fork, an active goal is disarmed: when a human asks to continue or resume in any wording or language, use update_goal action resume to rearm it. Mark complete only when the objective is actually achieved. Mark blocked only after the same blocking condition persists for at least ${blockedAfter} consecutive goal rounds, and report that concrete condition in blocked_reason; difficulty, uncertainty, or useful remaining work is not blocked.`;
197
+ }
198
+ /** Validate config even when apply is called directly outside Loader normalization. */
199
+ function resolveConfig(config) {
200
+ const blockedAfter = config.blockedAfterConsecutiveRounds ?? 3;
201
+ if (!Number.isSafeInteger(blockedAfter) || blockedAfter < 1) throw new TypeError("blockedAfterConsecutiveRounds must be a positive safe integer");
202
+ return { blockedAfterConsecutiveRounds: blockedAfter };
203
+ }
204
+ /** Whether optional text is meaningful rather than a strict-schema empty filler. */
205
+ function hasText(value) {
206
+ return value !== void 0 && value !== "";
207
+ }
208
+ /** Whether an optional round cap is meaningful rather than a strict-schema zero filler. */
209
+ function hasRoundCap(value) {
210
+ return value !== void 0 && value !== 0;
211
+ }
212
+ /** Build the exact compare-and-set ref from model arguments. */
213
+ function goalRef(goalId, revision) {
214
+ if (goalId.length === 0 || goalId !== goalId.trim() || !Number.isSafeInteger(revision) || revision < 1) throw new HarnessError("goal_id must be non-empty and revision must be a positive safe integer", "GOAL_TOOL_INVALID_UPDATE");
215
+ return {
216
+ id: GoalId(goalId),
217
+ revision
218
+ };
219
+ }
220
+ /** Stable compact model result; activation is an observation, not replay state. */
221
+ function goalValue(goal) {
222
+ if (goal === void 0) return { goal: null };
223
+ return {
224
+ goal: {
225
+ id: goal.id,
226
+ revision: goal.revision,
227
+ objective: goal.objective,
228
+ phase: goal.phase,
229
+ roundsStarted: goal.roundsStarted,
230
+ maxGoalRounds: goal.maxGoalRounds,
231
+ ...goal.blockedReason === void 0 ? {} : { blockedReason: {
232
+ code: goal.blockedReason.code,
233
+ message: goal.blockedReason.message
234
+ } }
235
+ },
236
+ activation: goal.activation
237
+ };
238
+ }
239
+ /** Reusable canonical output declaration for all three goal controls. */
240
+ const GOAL_OUTPUT = {
241
+ schema: GOAL_VALUE_SCHEMA,
242
+ render: (_args, value) => [{
243
+ type: "text",
244
+ text: JSON.stringify(value)
245
+ }]
246
+ };
247
+ /** Generic, args-only pending presentation shared by the goal tools. */
248
+ function present(title, kind, rawInput) {
249
+ return {
250
+ card: "generic",
251
+ title,
252
+ kind,
253
+ ...rawInput === void 0 ? {} : { rawInput }
254
+ };
255
+ }
256
+ /** Register the three Codex-shaped goal tools and their shared policy section. */
257
+ function apply(ctx, config) {
258
+ const resolved = resolveConfig(config);
259
+ ctx.systemPrompt.section({
260
+ name: "tool:goal",
261
+ order: ctx.systemPrompt.getSectionOrder("TOOL_GOAL"),
262
+ text: guidance(resolved.blockedAfterConsecutiveRounds)
263
+ });
264
+ ctx.tools.register(defineTool({
265
+ name: "get_goal",
266
+ description: GET_DESCRIPTION,
267
+ parameters: {},
268
+ output: GOAL_OUTPUT,
269
+ execute(_args, exec) {
270
+ const execution = goalToolExecution(ctx, exec);
271
+ return Promise.resolve(goalValue(ctx.goals.get(execution.agent)));
272
+ },
273
+ presentCall: () => present("Read current goal", "read")
274
+ }));
275
+ ctx.tools.register(defineTool({
276
+ name: "create_goal",
277
+ description: CREATE_DESCRIPTION,
278
+ parameters: {
279
+ objective: {
280
+ type: "string",
281
+ required: true,
282
+ description: "The concrete completion objective inferred from the direct human request."
283
+ },
284
+ max_goal_rounds: {
285
+ type: "number",
286
+ description: "Optional positive safe-integer limit on automatic continuation rounds."
287
+ }
288
+ },
289
+ output: GOAL_OUTPUT,
290
+ execute(args, exec) {
291
+ const execution = goalToolExecution(ctx, exec);
292
+ requireDirectHuman(ctx, execution);
293
+ const goal = ctx.goals.create(execution.agent, {
294
+ objective: args.objective,
295
+ ...args.max_goal_rounds === void 0 ? {} : { maxGoalRounds: args.max_goal_rounds }
296
+ });
297
+ return Promise.resolve(goalValue(goal));
298
+ },
299
+ presentCall: (args) => present("Create goal", "other", args.objective)
300
+ }));
301
+ ctx.tools.register(defineTool({
302
+ name: "update_goal",
303
+ description: "Update the current goal.",
304
+ parameters: {
305
+ goal_id: {
306
+ type: "string",
307
+ required: true,
308
+ description: "Exact id returned by get_goal."
309
+ },
310
+ revision: {
311
+ type: "number",
312
+ required: true,
313
+ description: "Exact positive revision returned by get_goal."
314
+ },
315
+ action: {
316
+ type: "string",
317
+ required: true,
318
+ enum: UPDATE_ACTIONS,
319
+ description: "edit, pause, and resume require a direct top-level human request. complete and blocked are also allowed during an automatic continuation of this goal; blocked is rejected before the configured minimum round count."
320
+ },
321
+ objective: {
322
+ type: "string",
323
+ description: "Replacement objective; valid only with action edit."
324
+ },
325
+ max_goal_rounds: {
326
+ type: "number",
327
+ description: "Replacement cap; valid only with action edit."
328
+ },
329
+ blocked_reason: {
330
+ type: "string",
331
+ description: "Required only with action blocked: the concrete condition that persisted across rounds and blocks progress."
332
+ }
333
+ },
334
+ output: GOAL_OUTPUT,
335
+ execute(args, exec) {
336
+ const execution = goalToolExecution(ctx, exec);
337
+ const ref = goalRef(args.goal_id, args.revision);
338
+ const replacements = {
339
+ ...hasText(args.objective) ? { objective: args.objective } : {},
340
+ ...hasRoundCap(args.max_goal_rounds) ? { maxGoalRounds: args.max_goal_rounds } : {}
341
+ };
342
+ if (args.action === "edit") {
343
+ requireDirectHuman(ctx, execution);
344
+ if (hasText(args.blocked_reason)) throw new HarnessError("blocked_reason is valid only with action blocked", "GOAL_TOOL_INVALID_UPDATE");
345
+ const goal = ctx.goals.edit(execution.agent, ref, replacements);
346
+ return Promise.resolve(goalValue(goal));
347
+ }
348
+ if (args.action === "pause" || args.action === "resume") {
349
+ requireDirectHuman(ctx, execution);
350
+ if (hasText(args.objective) || hasRoundCap(args.max_goal_rounds) || hasText(args.blocked_reason)) throw new HarnessError("objective and max_goal_rounds are valid only with action edit; blocked_reason is valid only with action blocked", "GOAL_TOOL_INVALID_UPDATE");
351
+ const current = ctx.goals.get(execution.agent);
352
+ if (args.action === "resume" && current?.id === ref.id && current.revision === ref.revision && current.phase === "paused") throw new HarnessError("the model cannot resume a paused goal; the user must resume it", "GOAL_TOOL_RESUME_PAUSED");
353
+ const goal = args.action === "pause" ? ctx.goals.pause(execution.agent, ref) : ctx.goals.resume(execution.agent, ref);
354
+ return Promise.resolve(goalValue(goal));
355
+ }
356
+ const authority = completionAuthority(ctx, execution);
357
+ if (hasText(args.objective) || hasRoundCap(args.max_goal_rounds)) throw new HarnessError("objective and max_goal_rounds are valid only with action edit", "GOAL_TOOL_INVALID_UPDATE");
358
+ if (args.action === "complete" && hasText(args.blocked_reason)) throw new HarnessError("blocked_reason is valid only with action blocked", "GOAL_TOOL_INVALID_UPDATE");
359
+ if (args.action === "blocked" && (args.blocked_reason === void 0 || args.blocked_reason.trim().length === 0)) throw new HarnessError("blocked_reason is required with action blocked", "GOAL_TOOL_INVALID_UPDATE");
360
+ if (args.action === "blocked" && authority.kind === "goal-round" && authority.goal.roundsStarted < resolved.blockedAfterConsecutiveRounds) throw new HarnessError(`blocked requires at least ${resolved.blockedAfterConsecutiveRounds} consecutive goal rounds; current round is ${authority.goal.roundsStarted}`, "GOAL_TOOL_BLOCK_THRESHOLD");
361
+ const goal = args.action === "complete" ? ctx.goals.complete(execution.agent, ref) : ctx.goals.block(execution.agent, ref, {
362
+ code: "model-reported",
363
+ message: args.blocked_reason
364
+ });
365
+ if (authority.kind === "goal-round") exec.deferContext(createUserMessage({
366
+ content: args.action === "complete" ? renderWrapupContext(goal.objective) : renderWrapupContext(goal.objective, args.blocked_reason),
367
+ source: {
368
+ kind: "tool-goal",
369
+ form: "notice",
370
+ summary: boundContextSummary(`${args.action}: ${goal.objective}`)
371
+ }
372
+ }));
373
+ return Promise.resolve(goalValue(goal));
374
+ },
375
+ presentCall: (args) => present(`${args.action === "blocked" ? "Mark" : args.action.charAt(0).toUpperCase() + args.action.slice(1)} goal`, "other", hasText(args.blocked_reason) ? args.blocked_reason : hasText(args.objective) ? args.objective : hasRoundCap(args.max_goal_rounds) ? args.max_goal_rounds : args.goal_id)
376
+ }));
377
+ }
378
+ //#endregion
379
+ export { Config, apply, inject, name };
@@ -0,0 +1,40 @@
1
+ /** Execution-time authority checks for the model-facing goal tools. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ import type { Agent } from '@qlzt/dsh-agent';
4
+ import type { GoalView } from '@qlzt/dsh-goal';
5
+ import type { SessionEvent, SessionSeq } from '@qlzt/dsh-session';
6
+ import type { ToolRunContext } from '@qlzt/dsh-tools';
7
+ /** The calling agent plus the immutable event cut and open-turn start seq used for authority checks. */
8
+ export interface GoalToolExecution {
9
+ readonly agent: Agent;
10
+ readonly events: readonly SessionEvent[];
11
+ readonly openTurnStartSeq: SessionSeq;
12
+ }
13
+ /** Hard authority granted to one state-changing call. */
14
+ export type GoalToolAuthority = {
15
+ readonly kind: 'direct-human';
16
+ } | {
17
+ readonly kind: 'goal-round';
18
+ readonly goal: GoalView;
19
+ };
20
+ /**
21
+ * Resolve and authenticate the calling agent and its driver boundary.
22
+ * @param ctx - Context carrying the live agent registry.
23
+ * @param exec - Tool execution metadata supplied by the registry.
24
+ * @returns The authenticated agent, immutable event cut, and open-turn boundary.
25
+ */
26
+ export declare function goalToolExecution(ctx: Context, exec: ToolRunContext): GoalToolExecution;
27
+ /**
28
+ * Require authority originating in a human message accepted by a runtime root.
29
+ * @param ctx - Context carrying the live agent graph.
30
+ * @param execution - Authenticated current tool execution.
31
+ */
32
+ export declare function requireDirectHuman(ctx: Context, execution: GoalToolExecution): void;
33
+ /**
34
+ * Resolve completion authority from either direct human input or the exact goal round.
35
+ * @param ctx - Context carrying live agents and goal state.
36
+ * @param execution - Authenticated current tool execution.
37
+ * @returns The direct-human or exact-goal-round authority grant.
38
+ */
39
+ export declare function completionAuthority(ctx: Context, execution: GoalToolExecution): GoalToolAuthority;
40
+ //# sourceMappingURL=authority.d.ts.map
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Model-facing `get_goal`, `create_goal`, and `update_goal` tools over the
3
+ * persisted same-session goal domain.
4
+ * @module @qlzt/dsh-tool-goal
5
+ */
6
+ import type { Context } from '@deepseek-ai/cordis';
7
+ import z from '@deepseek-ai/schemastery';
8
+ import type { ContextFormed } from '@qlzt/dsh-llm';
9
+ declare module '@qlzt/dsh-llm' {
10
+ interface MessageSourceMap {
11
+ 'tool-goal': {
12
+ kind: 'tool-goal';
13
+ } & ContextFormed;
14
+ }
15
+ }
16
+ export declare const name = "tool-goal";
17
+ export declare const inject: string[];
18
+ /** Model policy and hard lower bounds for goal-state updates. */
19
+ export interface Config {
20
+ /** Minimum admitted goal rounds before the model may self-report `blocked`. */
21
+ blockedAfterConsecutiveRounds?: number;
22
+ }
23
+ /** Schemastery config for the goal-tool policy. */
24
+ export declare const Config: z<Config>;
25
+ /** Register the three Codex-shaped goal tools and their shared policy section. */
26
+ export declare function apply(ctx: Context, config: Config): void;
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,12 @@
1
+ /** Model-visible wrap-up instruction for a terminal autonomous goal update. */
2
+ import type { ContentBlock } from '@qlzt/dsh-llm';
3
+ /**
4
+ * Render the closing-message instruction injected after an autonomous goal
5
+ * round reports `complete` or `blocked`, replacing the former hard turn stop
6
+ * so the model still addresses the user once before the turn ends.
7
+ * @param objective - the terminal goal's objective, echoed for grounding.
8
+ * @param blockedReason - the validated report for `blocked`; omitted for `complete`.
9
+ * @returns a fresh one-block context for `ToolRunContext.deferContext()`.
10
+ */
11
+ export declare function renderWrapupContext(objective: string, blockedReason?: string): ContentBlock[];
12
+ //# sourceMappingURL=wrapup.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,56 @@
1
1
  {
2
2
  "name": "@qlzt/dsh-tool-goal",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "description": "Model-facing same-session goal tools with execution-time authority checks",
4
+ "version": "0.2.1-alpha.2",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://gitee.com/zsping1989/deepseek-harness.git",
11
+ "directory": "packages/goal/tool-goal"
12
+ },
13
+ "type": "module",
14
+ "main": "lib/index.js",
15
+ "types": "lib/types/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./lib/types/index.d.ts",
19
+ "default": "./lib/index.js"
20
+ },
21
+ "./src/*": "./src/*",
22
+ "./package.json": "./package.json"
23
+ },
24
+ "files": [
25
+ "lib/index.js",
26
+ "lib/types/**/*.d.ts"
27
+ ],
28
+ "license": "MIT",
29
+ "peerDependencies": {
30
+ "@qlzt/dsh-agent": "0.2.1-alpha.2",
31
+ "@qlzt/dsh-goal": "0.2.1-alpha.2",
32
+ "@qlzt/dsh-llm": "0.2.1-alpha.2",
33
+ "@qlzt/dsh-session": "0.2.1-alpha.2",
34
+ "@qlzt/dsh-system-prompt": "0.2.1-alpha.2",
35
+ "@qlzt/dsh-tools": "0.2.1-alpha.2",
36
+ "@deepseek-ai/cordis": "~4.0.5-alpha.1",
37
+ "@qlzt/dsh-session-projection": "0.2.1-alpha.2"
38
+ },
39
+ "dependencies": {
40
+ "@deepseek-ai/schemastery": "~3.18.5-alpha.1"
41
+ },
42
+ "devDependencies": {
43
+ "@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.1",
44
+ "@deepseek-ai/dsh-agent": "0.2.1-alpha.2",
45
+ "@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-alpha.2",
46
+ "@deepseek-ai/dsh-agent-loop": "0.2.1-alpha.2",
47
+ "@deepseek-ai/dsh-goal": "0.2.1-alpha.2",
48
+ "@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
49
+ "@deepseek-ai/dsh-session": "0.2.1-alpha.2",
50
+ "@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.2",
51
+ "@deepseek-ai/dsh-tools": "0.2.1-alpha.2",
52
+ "@deepseek-ai/cordis": "~4.0.5-alpha.1",
53
+ "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.2"
54
+ },
55
+ "dsh": {}
56
+ }