dsh-model-switch 0.4.17 → 0.4.19
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/CHANGELOG.md +21 -0
- package/PRODUCT.md +1 -1
- package/README.md +6 -2
- package/README.zh.md +6 -2
- package/lib/client.js +136 -14
- package/lib/types/client/picker/PlanReviewCard.d.ts +3 -0
- package/lib/types/client/picker/locales.d.ts +8 -0
- package/lib/types/picker/plan-goal.d.ts +77 -0
- package/package.json +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
## v0.4.19
|
|
2
|
+
|
|
3
|
+
Plan Review gains a **Set as goal and run** action: it arms the reviewed Plan as the session's goal and only then answers it, so `dsh-goal-round-driver` carries the Plan after plan mode exits.
|
|
4
|
+
|
|
5
|
+
- The goal is set before the answer, matching the card's existing commit-then-answer order; a refusal keeps the review pending and reports the Host's own wire code.
|
|
6
|
+
- An unfinished goal is replaced through `get` + `clear` + `create` rather than edited, so a new Plan starts with a fresh round cap, and the card says it replaced the previous goal.
|
|
7
|
+
- The goal face is resolved per render (`ctx.get('remote.goals', false)`) instead of listed in the static client `inject`, so a deployment that mounts no `@deepseek-ai/dsh-goal` keeps loading this plugin and the action disables itself with an explicit reason while the other three actions keep working. `@deepseek-ai/dsh-goal` is declared as an optional peer.
|
|
8
|
+
- The objective is the Plan's trimmed markdown. The plugin stores no goal state, owns no part of the goal domain, and schedules no rounds.
|
|
9
|
+
- Records the seam in `docs/seam-gap.md` (the released `remote.goals.create` exists while DSH's own goal surface deliberately omits creation) and the action in PRODUCT.md and both READMEs.
|
|
10
|
+
|
|
11
|
+
## v0.4.18
|
|
12
|
+
|
|
13
|
+
Declare official DSH `0.2.0-rc.2` compatible in `package.json#dsh.compatibility.dshReleases`.
|
|
14
|
+
|
|
15
|
+
Evidence, in the order this repository's compatibility policy requires:
|
|
16
|
+
|
|
17
|
+
- **Public API review:** the 0.2.x Host renamed the pending-question withdrawal verb (`PendingQuestion.cancel()` → `dismiss()`), fires `session.selectModel`'s deployment-default write without awaiting it, and reports a refused `ModelDirectory.select` as a returned `{ ok: false }` value instead of throwing. Each difference broke v0.4.16, and each is fixed in v0.4.17.
|
|
18
|
+
- **Tests and build:** `pnpm run check` green — `tsc` + `tsdown`, the full vitest suite, and the pack gate against a real tarball.
|
|
19
|
+
- **Lab plane:** profile composition `exit 0` with no skipped bundle, Host boot on port 3082 with the plugin's capability RPC answering, and the npm-installed build booting on port 3085 with its client bundle served.
|
|
20
|
+
- **Live desktop verification on 0.2.0-rc.2:** all three Plan Review actions exercised against a real session — Discuss withdraws the takeover and returns the composer; Reject delivers typed feedback verbatim as the answer's `custom` text; Confirm commits a different execution model, approves the plan, and restores the Main default to its pre-switch value.
|
|
21
|
+
|
|
1
22
|
## v0.4.17
|
|
2
23
|
|
|
3
24
|
First release published to the npm registry, so `dsh plugin --profile <name> add dsh-model-switch` installs prebuilt code without a git build authorization. Publishing builds `lib/` through `prepublishOnly`, and `pnpm run check` now runs its pack gate on Windows as well.
|
package/PRODUCT.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
- **Vision:** excluded. Model Switch exposes no Vision setting, does not shadow `read_image`, and does not preprocess chat attachments.
|
|
11
11
|
- **Image Router:** owns a new, uniquely named stable `generate_image` tool. It selects the configured Codex or Grok adapter/model at execution time, rejects backend-incompatible fields, and returns normalized image metadata. Existing provider-specific image tools remain available as rollback paths.
|
|
12
12
|
- **Composer Picker:** replaces the composer model seat with a suffix-grouped Model / Effort / Context / Fast / Thinking picker and submits through the official Model Directory. Variant changes preserve an effort only when the target catalog row supports it, otherwise they use the target default or omit effort. Picker changes are session-local. A submitted prompt reserves the selected runtime immediately (composer submitting, pending first turn, or running). Native Antigravity keeps its models and effort; DSH keeps LLM-provider choices and disables Agent providers. After a successful native binding, other groups stay disabled. Cancel without a binding releases the reservation; existing DSH history still cannot convert onto an External Agent. On a Host version that also persists session selection as the deployment default, the plugin restores the pre-switch Main default through the public Settings RPC with a revision fence; a concurrent Settings-page edit wins.
|
|
13
|
-
- **Plan Review:** intercepts the official `plan-review` composer takeover with a header execution-model picker and right-aligned Discuss in chat / Reject / Confirm actions. Confirm commits the selected model before answering; a refused commit leaves the review pending and retryable, while a deployment default this plugin could not restore is announced after the answer instead of holding the human's decision back. Reject carries optional human feedback as the answer's own `custom` text, which plan mode reports to the model. Discuss in chat withdraws the takeover through the Host's own verb — `dismiss()` where the Host publishes it, `cancel()` on the older generation — and names the Host when neither seam exists, so a settled review is never a dead end. The same runtime reservation applies.
|
|
13
|
+
- **Plan Review:** intercepts the official `plan-review` composer takeover with a header execution-model picker and right-aligned Discuss in chat / Reject / Set as goal and run / Confirm actions. Confirm commits the selected model before answering; a refused commit leaves the review pending and retryable, while a deployment default this plugin could not restore is announced after the answer instead of holding the human's decision back. Reject carries optional human feedback as the answer's own `custom` text, which plan mode reports to the model. **Set as goal and run** arms this Plan as the session's goal through the released `remote.goals.create` — replacing an unfinished goal with `get` + `clear` first so the new Plan receives a fresh round cap — and only then answers, so `dsh-goal-round-driver` carries the Plan after plan mode exits. The goal is set before the answer, a refusal keeps the review pending and retryable, and a deployment that mounts no goal service disables the action with an explicit reason; the plugin stores no goal state, schedules no rounds, and owns no part of the goal domain. Discuss in chat withdraws the takeover through the Host's own verb — `dismiss()` where the Host publishes it, `cancel()` on the older generation — and names the Host when neither seam exists, so a settled review is never a dead end. The same runtime reservation applies.
|
|
14
14
|
|
|
15
15
|
Model choices are capability-driven. Invalid, unavailable, or unsupported selections remain visible to configuration surfaces and fail loudly at use; routing never silently falls back.
|
|
16
16
|
|
package/README.md
CHANGED
|
@@ -79,6 +79,8 @@ Plan Review owns an execution-model draft separate from Main. **Confirm** first
|
|
|
79
79
|
|
|
80
80
|
**Reject** sends the option the asker offered, and any text typed in the card's feedback field as the answer's own `custom` text — plan mode reports that text back to the model as the reason to keep planning, so a rejection can carry what to change. **Discuss in chat** withdraws the takeover so the composer returns and the human speaks in their own words; it uses the Host's `dismiss()` where published and the older generation's `cancel()` otherwise, and names the Host when neither exists. Answering a settled review closes Confirm and Reject, while Discuss and the reload affordance stay reachable so the card always has a way back. Failures keep their wire code (`session/writer-held: …`) visible instead of a bare localized sentence.
|
|
81
81
|
|
|
82
|
+
**Set as goal and run** arms this Plan as the session's goal and only then answers it, so `dsh-goal-round-driver` keeps the Plan moving after plan mode exits. It calls the released `remote.goals.create`; when a non-complete goal already exists it clears that one first so the new Plan starts with a fresh round cap, and says so in the card. A refusal keeps the review pending with its wire code (`GOAL_AGENT_NOT_LIVE: …`), and a deployment that mounts no goal service disables the button with an explicit reason while the other three actions keep working. The objective is the Plan's full markdown, trimmed — the goal domain imposes no length limit, and the objective rides along as model-visible context every round, so a long Plan costs tokens on each continuation.
|
|
83
|
+
|
|
82
84
|

|
|
83
85
|
|
|
84
86
|
## Send-time context protection
|
|
@@ -109,7 +111,7 @@ A packed tarball installs the same build without a registry:
|
|
|
109
111
|
dsh plugin --profile web add --force ./dsh-model-switch-0.4.17.tgz
|
|
110
112
|
```
|
|
111
113
|
|
|
112
|
-
Then install only the provider adapters you use. This release was checked against official DeepSeek Harness `0.1.7-rc.2`:
|
|
114
|
+
Then install only the provider adapters you use. This release was checked against official DeepSeek Harness `0.1.7-rc.2` and verified on `0.2.0-rc.2`:
|
|
113
115
|
|
|
114
116
|
```sh
|
|
115
117
|
dsh plugin --profile web add --force \
|
|
@@ -140,6 +142,8 @@ Production profiles must use a released registry version or GitHub tag rather th
|
|
|
140
142
|
|
|
141
143
|
DSH Host peers and development dependencies accept `>=0.1.7-alpha.2`, including rc.1 and later releases. The development lockfile resolves to rc.2. Cordis accepts `>=4.0.4 <5.0.0`.
|
|
142
144
|
|
|
145
|
+
Verified releases: `0.1.7-alpha.2`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.2`. The 0.2.0 claim covers the Host's renamed question verbs, its unawaited `session.selectModel` default write, and its returned `ModelDirectory.select` refusal, each verified in the lab and on a live desktop session.
|
|
146
|
+
|
|
143
147
|
The verified releases in `package.json#dsh.compatibility.dshReleases` are evidence, not an allowlist. Review public API changes and test new Host releases before adding a verification claim.
|
|
144
148
|
|
|
145
149
|
## Development
|
|
@@ -155,7 +159,7 @@ pnpm run check
|
|
|
155
159
|
|
|
156
160
|
## Release installation (Latest)
|
|
157
161
|
|
|
158
|
-
Explicit model routing for Main, Subagent, Composer, Plan Review, and capability tools, checked on official DeepSeek Harness `0.1.7-rc.2`. The release artifact contains built Host/Client files, not sibling source or local paths.
|
|
162
|
+
Explicit model routing for Main, Subagent, Composer, Plan Review, and capability tools, checked on official DeepSeek Harness `0.1.7-rc.2` and `0.2.0-rc.2`. The release artifact contains built Host/Client files, not sibling source or local paths.
|
|
159
163
|
|
|
160
164
|
Latest installation (the asset filename must match the current latest release):
|
|
161
165
|
|
package/README.zh.md
CHANGED
|
@@ -77,6 +77,8 @@ Plan Review 拥有独立于 Main 的执行模型草稿。**确认执行**会先
|
|
|
77
77
|
|
|
78
78
|
**拒绝**会发送提问方给出的选项,并把卡片反馈框里的文字作为答复自身的 `custom` 文本一并提交 —— plan 模式会把它作为"继续规划"的理由回报给模型,所以打回时可以带上要改什么。**去聊天里说**会撤下这张卡、把输入框还给你,用你自己的话说明;它在 Host 提供 `dismiss()` 时用它,在旧代际用 `cancel()`,两者都没有时明确指出这一点。审核一旦落定,**确认执行**与**拒绝**关闭,而**去聊天里说**与"重新加载"始终可达,卡片不会变成死路。失败会保留线上错误码(如 `session/writer-held: …`),而不是只给一句本地化文案。
|
|
79
79
|
|
|
80
|
+
**设置为目标并执行** 会先把这份 Plan 设为当前会话的 goal、再答复,于是 `dsh-goal-round-driver` 能在退出计划模式后继续推进。它调用已发布的 `remote.goals.create`;若已存在一个未完成的 goal,会先 `clear` 再 `create`,让新 Plan 拿到完整轮次预算,并在替换后提示。目标设置被拒时审核保持待处理、错误带真实错误码(如 `GOAL_AGENT_NOT_LIVE: …`);部署未挂 goal 服务时该按钮禁用并给出原因,其余三个动作照常可用。objective 取计划全文(trim 后):goal 域不设长度上限,但它会作为模型可见上下文出现在每一轮续跑里,所以计划很长时每轮都花 token。
|
|
81
|
+
|
|
80
82
|

|
|
81
83
|
|
|
82
84
|
## 发送时的上下文保护
|
|
@@ -107,7 +109,7 @@ dsh plugin --profile web add --force dsh-model-switch
|
|
|
107
109
|
dsh plugin --profile web add --force ./dsh-model-switch-0.4.17.tgz
|
|
108
110
|
```
|
|
109
111
|
|
|
110
|
-
然后只安装实际使用的 Provider Adapter。此版本已在官方 DeepSeek Harness `0.1.7-rc.2`
|
|
112
|
+
然后只安装实际使用的 Provider Adapter。此版本已在官方 DeepSeek Harness `0.1.7-rc.2` 上检查,并在 `0.2.0-rc.2` 上验证:
|
|
111
113
|
|
|
112
114
|
```sh
|
|
113
115
|
dsh plugin --profile web add --force \
|
|
@@ -138,6 +140,8 @@ DeepSeek 薄适配器调用官方公开 `DeepSeekSearchProvider`,复用用户
|
|
|
138
140
|
|
|
139
141
|
DSH Host peer 和开发依赖接受 `>=0.1.7-alpha.2`,包括 rc.1 和后续版本。开发锁文件解析到 rc.2。Cordis 接受 `>=4.0.4 <5.0.0`。
|
|
140
142
|
|
|
143
|
+
已验证版本:`0.1.7-alpha.2`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.2`。0.2.0 的声明覆盖三处差异:Host 改名的提问撤下动词(`cancel()` → `dismiss()`)、`session.selectModel` 不 await 的部署默认值写入、以返回值报出的 `ModelDirectory.select` 拒绝;三者均已在 lab(3082/3085)与真实桌面会话中逐一验证。
|
|
144
|
+
|
|
141
145
|
`package.json#dsh.compatibility.dshReleases` 中的已验证版本是证据,不是允许列表。新增验证声明前要审查公开 API 变化并测试新 Host 版本。
|
|
142
146
|
|
|
143
147
|
## 开发
|
|
@@ -153,7 +157,7 @@ pnpm run check
|
|
|
153
157
|
|
|
154
158
|
## 正式版安装(Latest)
|
|
155
159
|
|
|
156
|
-
本版在官方 DeepSeek Harness `0.1.7-rc.2` 上验证了 Main、子代理、Composer 与能力路由;发布包只包含构建后的 Host/Client 产物,不包含兄弟仓库源码或本机路径。
|
|
160
|
+
本版在官方 DeepSeek Harness `0.1.7-rc.2` 与 `0.2.0-rc.2` 上验证了 Main、子代理、Composer、Plan Review 与能力路由;发布包只包含构建后的 Host/Client 产物,不包含兄弟仓库源码或本机路径。
|
|
157
161
|
|
|
158
162
|
Latest 安装命令(资产文件名必须与当前 latest Release 一致):
|
|
159
163
|
|
package/lib/client.js
CHANGED
|
@@ -3063,6 +3063,63 @@ window.__ModuleLoader__.load({
|
|
|
3063
3063
|
throw new PlanDismissalUnsupportedError("this DSH Host exposes neither PendingQuestion.dismiss() (0.2.x) nor PendingQuestion.cancel() (0.1.x)");
|
|
3064
3064
|
}
|
|
3065
3065
|
//#endregion
|
|
3066
|
+
//#region src/picker/plan-goal.ts
|
|
3067
|
+
function failure(result, fallback) {
|
|
3068
|
+
if (result.ok) return { message: fallback };
|
|
3069
|
+
const { code, message } = result.error;
|
|
3070
|
+
return {
|
|
3071
|
+
code,
|
|
3072
|
+
message: message.trim() === "" ? fallback : message
|
|
3073
|
+
};
|
|
3074
|
+
}
|
|
3075
|
+
/**
|
|
3076
|
+
* Make the plan text this session's armed goal, replacing any unfinished goal.
|
|
3077
|
+
*
|
|
3078
|
+
* Ordering mirrors the card's own commit-then-answer rule: a refusal here keeps
|
|
3079
|
+
* the Plan pending instead of approving work that no goal tracks. The replace
|
|
3080
|
+
* path clears rather than edits so a new plan receives a fresh round budget —
|
|
3081
|
+
* `edit` would inherit the rounds the previous goal already spent.
|
|
3082
|
+
*
|
|
3083
|
+
* @param remote - the released goal remote, absent when no goal package is mounted.
|
|
3084
|
+
* @param sessionId - the session that owns both the review and the goal.
|
|
3085
|
+
* @param plan - the plan markdown under review.
|
|
3086
|
+
* @returns Whether the goal now tracks this plan, or why it does not.
|
|
3087
|
+
*/
|
|
3088
|
+
async function setPlanAsGoal(remote, sessionId, plan) {
|
|
3089
|
+
if (remote === void 0) return { kind: "unsupported" };
|
|
3090
|
+
const objective = plan.trim();
|
|
3091
|
+
if (objective === "") return {
|
|
3092
|
+
kind: "failed",
|
|
3093
|
+
code: "GOAL_INVALID_OBJECTIVE",
|
|
3094
|
+
message: "goal objective must be a non-empty string"
|
|
3095
|
+
};
|
|
3096
|
+
const created = await remote.create(sessionId, { objective });
|
|
3097
|
+
if (created.ok) return { kind: "created" };
|
|
3098
|
+
if (created.error.code !== "GOAL_ALREADY_EXISTS") return {
|
|
3099
|
+
kind: "failed",
|
|
3100
|
+
...failure(created, "the goal could not be created")
|
|
3101
|
+
};
|
|
3102
|
+
const current = await remote.get(sessionId);
|
|
3103
|
+
if (!current.ok || current.value === void 0 || current.value === null) return {
|
|
3104
|
+
kind: "failed",
|
|
3105
|
+
...failure(current, "the current goal could not be read for replacement")
|
|
3106
|
+
};
|
|
3107
|
+
const cleared = await remote.clear(sessionId, {
|
|
3108
|
+
id: current.value.id,
|
|
3109
|
+
revision: current.value.revision
|
|
3110
|
+
});
|
|
3111
|
+
if (!cleared.ok) return {
|
|
3112
|
+
kind: "failed",
|
|
3113
|
+
...failure(cleared, "the current goal could not be cleared")
|
|
3114
|
+
};
|
|
3115
|
+
const retry = await remote.create(sessionId, { objective });
|
|
3116
|
+
if (retry.ok) return { kind: "replaced" };
|
|
3117
|
+
return {
|
|
3118
|
+
kind: "failed",
|
|
3119
|
+
...failure(retry, "the goal could not be created")
|
|
3120
|
+
};
|
|
3121
|
+
}
|
|
3122
|
+
//#endregion
|
|
3066
3123
|
//#region src/client/picker/RetryBoundary.tsx
|
|
3067
3124
|
/** Own retryable React error-boundary state while callers own presentation and copy. */
|
|
3068
3125
|
var RetryBoundary = class extends react.Component {
|
|
@@ -3082,7 +3139,7 @@ window.__ModuleLoader__.load({
|
|
|
3082
3139
|
};
|
|
3083
3140
|
//#endregion
|
|
3084
3141
|
//#region \0dsh-css:src/client/picker/PlanReviewCard.module.css.mjs
|
|
3085
|
-
const css = ".BylfoW_frame{padding:6px calc(var(--dsh-composer-side-clearance) + 16px) 10px;justify-content:center;display:flex}.BylfoW_card{width:100%;max-width:var(--dsh-chat-content-width);border:1px solid var(--dsw-alias-state-warn-secondary);background:var(--dsw-specific-input-major);max-height:min(60vh,520px);box-shadow:var(--dsw-shadow-lv2);color:var(--dsw-alias-label-primary);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:20px;flex-direction:column;display:flex;overflow:visible}.BylfoW_card,.BylfoW_card *{box-sizing:border-box}.BylfoW_strip{background:var(--dsw-alias-state-warn-tertiary);color:var(--dsw-alias-state-warn-primary);border-radius:20px 20px 0 0;flex-shrink:0;align-items:center;gap:8px;padding:10px 16px;font-size:13px;line-height:18px;display:flex}.BylfoW_dot{background:var(--dsw-alias-state-warn-primary);border-radius:50%;width:8px;height:8px}.BylfoW_stripTitle{flex:none;font-weight:600}.BylfoW_headerPicker{flex:0 auto;align-items:center;min-width:0;max-width:55%;margin-left:auto;display:flex}.BylfoW_headerPicker>*{min-width:0;max-width:100%}.BylfoW_body{overscroll-behavior:contain;flex:auto;min-height:0;padding:12px 16px 4px;font-size:14px;line-height:22px;overflow-y:auto}.BylfoW_footer{z-index:2;flex-direction:column;flex-shrink:0;gap:6px;padding:8px 16px 12px;display:flex;position:relative;overflow:visible}.BylfoW_feedback{min-height:0;color:var(--dsw-alias-state-error-primary);font-size:11px;line-height:16px}.BylfoW_feedback:empty{display:none}.BylfoW_feedbackRow{align-items:center;gap:8px;min-width:0;display:flex}.BylfoW_feedbackInput{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-specific-input-minor);min-width:0;height:32px;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xs-13);border-radius:8px;flex:auto;padding:0 10px}.BylfoW_feedbackInput::placeholder{color:var(--dsw-alias-label-tertiary)}.BylfoW_feedbackInput:disabled{opacity:.6}.BylfoW_bar{flex-wrap:nowrap;justify-content:space-between;align-items:center;gap:12px;min-width:0;min-height:32px;display:flex}.BylfoW_picker{flex:16rem;min-width:0;max-width:16rem}.BylfoW_pickerError{color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere;flex-wrap:wrap;align-items:center;gap:6px;font-size:12px;display:flex}.BylfoW_actions{flex-wrap:nowrap;flex:none;justify-content:flex-end;align-items:center;gap:8px;margin-left:auto;display:flex}.BylfoW_discuss,.BylfoW_keep,.BylfoW_approve,.BylfoW_recover{white-space:nowrap;height:32px;min-height:32px;padding:0 10px}.BylfoW_discuss,.BylfoW_recover{color:var(--dsw-alias-label-secondary)}.BylfoW_discuss:hover:not(:disabled),.BylfoW_recover:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.BylfoW_approve{padding:0 12px}@media (width<=720px){.BylfoW_frame{padding-right:max(10px, env(safe-area-inset-right));padding-bottom:max(10px, env(safe-area-inset-bottom));padding-left:max(10px, env(safe-area-inset-left))}.BylfoW_card{border-radius:16px}.BylfoW_strip,.BylfoW_body,.BylfoW_footer{padding-left:12px;padding-right:12px}.BylfoW_strip{flex-wrap:wrap;gap:6px}.BylfoW_headerPicker{flex:100%;max-width:100%;margin-left:0}.BylfoW_bar{justify-content:flex-end;gap:6px}.BylfoW_actions{flex:100%;justify-content:flex-end;gap:6px;min-width:0}.BylfoW_discuss,.BylfoW_keep,.BylfoW_approve,.BylfoW_recover{overflow-wrap:anywhere;white-space:normal;flex:1 1 0;min-width:0;height:auto;padding:4px;line-height:14px}.BylfoW_feedbackInput{height:auto;min-height:32px}}";
|
|
3142
|
+
const css = ".BylfoW_frame{padding:6px calc(var(--dsh-composer-side-clearance) + 16px) 10px;justify-content:center;display:flex}.BylfoW_card{width:100%;max-width:var(--dsh-chat-content-width);border:1px solid var(--dsw-alias-state-warn-secondary);background:var(--dsw-specific-input-major);max-height:min(60vh,520px);box-shadow:var(--dsw-shadow-lv2);color:var(--dsw-alias-label-primary);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:20px;flex-direction:column;display:flex;overflow:visible}.BylfoW_card,.BylfoW_card *{box-sizing:border-box}.BylfoW_strip{background:var(--dsw-alias-state-warn-tertiary);color:var(--dsw-alias-state-warn-primary);border-radius:20px 20px 0 0;flex-shrink:0;align-items:center;gap:8px;padding:10px 16px;font-size:13px;line-height:18px;display:flex}.BylfoW_dot{background:var(--dsw-alias-state-warn-primary);border-radius:50%;width:8px;height:8px}.BylfoW_stripTitle{flex:none;font-weight:600}.BylfoW_headerPicker{flex:0 auto;align-items:center;min-width:0;max-width:55%;margin-left:auto;display:flex}.BylfoW_headerPicker>*{min-width:0;max-width:100%}.BylfoW_body{overscroll-behavior:contain;flex:auto;min-height:0;padding:12px 16px 4px;font-size:14px;line-height:22px;overflow-y:auto}.BylfoW_footer{z-index:2;flex-direction:column;flex-shrink:0;gap:6px;padding:8px 16px 12px;display:flex;position:relative;overflow:visible}.BylfoW_feedback{min-height:0;color:var(--dsw-alias-state-error-primary);font-size:11px;line-height:16px}.BylfoW_feedback:empty{display:none}.BylfoW_feedbackRow{align-items:center;gap:8px;min-width:0;display:flex}.BylfoW_feedbackInput{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-specific-input-minor);min-width:0;height:32px;color:var(--dsw-alias-label-primary);font:var(--dsw-font-xs-13);border-radius:8px;flex:auto;padding:0 10px}.BylfoW_feedbackInput::placeholder{color:var(--dsw-alias-label-tertiary)}.BylfoW_feedbackInput:disabled{opacity:.6}.BylfoW_bar{flex-wrap:nowrap;justify-content:space-between;align-items:center;gap:12px;min-width:0;min-height:32px;display:flex}.BylfoW_picker{flex:16rem;min-width:0;max-width:16rem}.BylfoW_pickerError{color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere;flex-wrap:wrap;align-items:center;gap:6px;font-size:12px;display:flex}.BylfoW_actions{flex-wrap:nowrap;flex:none;justify-content:flex-end;align-items:center;gap:8px;margin-left:auto;display:flex}.BylfoW_discuss,.BylfoW_keep,.BylfoW_goalRun,.BylfoW_approve,.BylfoW_recover{white-space:nowrap;height:32px;min-height:32px;padding:0 10px}.BylfoW_discuss,.BylfoW_recover{color:var(--dsw-alias-label-secondary)}.BylfoW_discuss:hover:not(:disabled),.BylfoW_recover:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.BylfoW_approve{padding:0 12px}@media (width<=720px){.BylfoW_frame{padding-right:max(10px, env(safe-area-inset-right));padding-bottom:max(10px, env(safe-area-inset-bottom));padding-left:max(10px, env(safe-area-inset-left))}.BylfoW_card{border-radius:16px}.BylfoW_strip,.BylfoW_body,.BylfoW_footer{padding-left:12px;padding-right:12px}.BylfoW_strip{flex-wrap:wrap;gap:6px}.BylfoW_headerPicker{flex:100%;max-width:100%;margin-left:0}.BylfoW_bar{justify-content:flex-end;gap:6px}.BylfoW_actions{flex:100%;justify-content:flex-end;gap:6px;min-width:0}.BylfoW_discuss,.BylfoW_keep,.BylfoW_goalRun,.BylfoW_approve,.BylfoW_recover{overflow-wrap:anywhere;white-space:normal;flex:1 1 0;min-width:0;height:auto;padding:4px;line-height:14px}.BylfoW_feedbackInput{height:auto;min-height:32px}}";
|
|
3086
3143
|
const tagId = "dsh-model-switch/PlanReviewCard.module.css";
|
|
3087
3144
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
3088
3145
|
const tag = document.createElement("style");
|
|
@@ -3104,6 +3161,7 @@ window.__ModuleLoader__.load({
|
|
|
3104
3161
|
"feedbackRow": "BylfoW_feedbackRow",
|
|
3105
3162
|
"footer": "BylfoW_footer",
|
|
3106
3163
|
"frame": "BylfoW_frame",
|
|
3164
|
+
"goalRun": "BylfoW_goalRun",
|
|
3107
3165
|
"headerPicker": "BylfoW_headerPicker",
|
|
3108
3166
|
"keep": "BylfoW_keep",
|
|
3109
3167
|
"picker": "BylfoW_picker",
|
|
@@ -3226,11 +3284,12 @@ window.__ModuleLoader__.load({
|
|
|
3226
3284
|
...settingsUnavailableReason === void 0 ? {} : { settingsUnavailableReason },
|
|
3227
3285
|
directory: pickerDirectoryViewOrdered(snapshot, props, order, props.catalogRoutes?.() ?? {}),
|
|
3228
3286
|
t: props.t,
|
|
3287
|
+
goalRemote: props.goalRemote,
|
|
3229
3288
|
...props.resolveInteractionOperations === void 0 ? {} : { resolveInteractionOperations: props.resolveInteractionOperations },
|
|
3230
3289
|
...props.roleOf === void 0 ? {} : { roleOf: props.roleOf }
|
|
3231
3290
|
}, props.matched.key);
|
|
3232
3291
|
}
|
|
3233
|
-
function PlanReviewState({ matched, review, available, providerLock, agentLocked, lockFailed, settingsUnavailableReason, directory, t, resolveInteractionOperations, roleOf }) {
|
|
3292
|
+
function PlanReviewState({ matched, review, available, providerLock, agentLocked, lockFailed, settingsUnavailableReason, directory, t, goalRemote, resolveInteractionOperations, roleOf }) {
|
|
3234
3293
|
const { snapshot, getDirectorySnapshot, load, select } = directory;
|
|
3235
3294
|
const [execution, setExecution] = (0, react.useState)(snapshot.current ?? void 0);
|
|
3236
3295
|
const [feedback, setFeedback] = (0, react.useState)("");
|
|
@@ -3280,22 +3339,45 @@ window.__ModuleLoader__.load({
|
|
|
3280
3339
|
blocked,
|
|
3281
3340
|
error
|
|
3282
3341
|
}, available, executionAllowed);
|
|
3342
|
+
/** Approve this review after committing its execution model; a refused commit keeps the Plan pending. */
|
|
3343
|
+
const approveWith = async (model) => {
|
|
3344
|
+
if (!await approvePlanReview({
|
|
3345
|
+
select,
|
|
3346
|
+
selection: model,
|
|
3347
|
+
current: snapshot.current,
|
|
3348
|
+
answer: () => respondAnswer(matched, review.id, review.approve.label, t("plan.responseRejected"), true),
|
|
3349
|
+
onNotRestored: (switched) => {
|
|
3350
|
+
setNotice(t("plan.notRestored", { model: switched }));
|
|
3351
|
+
console.warn("dsh-model-switch: the Session model changed but the Main default was not restored", switched);
|
|
3352
|
+
}
|
|
3353
|
+
})) {
|
|
3354
|
+
const message = getDirectorySnapshot().error;
|
|
3355
|
+
throw new Error(message === null ? t("plan.modelFailed") : t("error.action", { message }));
|
|
3356
|
+
}
|
|
3357
|
+
};
|
|
3283
3358
|
const onApprove = () => {
|
|
3284
3359
|
if (execution === void 0 || !executionAllowed || !available || busy || blocked) return;
|
|
3360
|
+
settle(() => approveWith(execution));
|
|
3361
|
+
};
|
|
3362
|
+
const goal = goalRemote();
|
|
3363
|
+
const goalReason = goal === void 0 ? t("plan.goalUnsupported") : void 0;
|
|
3364
|
+
/**
|
|
3365
|
+
* Arm this plan as the session's goal first, then approve. The goal must be
|
|
3366
|
+
* set before the answer because a refusal must leave the Plan pending, and
|
|
3367
|
+
* because only an armed goal lets the round driver carry the plan after plan
|
|
3368
|
+
* mode exits.
|
|
3369
|
+
*/
|
|
3370
|
+
const onRunAsGoal = () => {
|
|
3371
|
+
if (execution === void 0 || !executionAllowed || !available || busy || blocked || goal === void 0) return;
|
|
3285
3372
|
settle(async () => {
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
onNotRestored: (model) => {
|
|
3292
|
-
setNotice(t("plan.notRestored", { model }));
|
|
3293
|
-
console.warn("dsh-model-switch: the Session model changed but the Main default was not restored", model);
|
|
3294
|
-
}
|
|
3295
|
-
})) {
|
|
3296
|
-
const message = getDirectorySnapshot().error;
|
|
3297
|
-
throw new Error(message === null ? t("plan.modelFailed") : t("error.action", { message }));
|
|
3373
|
+
const handoff = await setPlanAsGoal(goal, matched.sessionId, review.plan);
|
|
3374
|
+
if (handoff.kind === "unsupported") throw new Error(t("plan.goalUnsupported"));
|
|
3375
|
+
if (handoff.kind === "failed") {
|
|
3376
|
+
const message = handoff.code === void 0 ? handoff.message : `${handoff.code}: ${handoff.message}`;
|
|
3377
|
+
throw new Error(t("plan.goalFailed", { message }));
|
|
3298
3378
|
}
|
|
3379
|
+
if (handoff.kind === "replaced") setNotice(t("plan.goalReplaced"));
|
|
3380
|
+
await approveWith(execution);
|
|
3299
3381
|
});
|
|
3300
3382
|
};
|
|
3301
3383
|
const decline = review.decline;
|
|
@@ -3413,6 +3495,14 @@ window.__ModuleLoader__.load({
|
|
|
3413
3495
|
},
|
|
3414
3496
|
children: t("plan.keep")
|
|
3415
3497
|
}),
|
|
3498
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3499
|
+
variant: "outline",
|
|
3500
|
+
className: PlanReviewCard_module_css_default.goalRun,
|
|
3501
|
+
disabled: action.approveDisabled || goalReason !== void 0,
|
|
3502
|
+
...goalReason === void 0 ? {} : { title: goalReason },
|
|
3503
|
+
onClick: onRunAsGoal,
|
|
3504
|
+
children: t("plan.goalRun")
|
|
3505
|
+
}),
|
|
3416
3506
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
3417
3507
|
variant: "primary",
|
|
3418
3508
|
className: PlanReviewCard_module_css_default.approve,
|
|
@@ -3501,6 +3591,10 @@ window.__ModuleLoader__.load({
|
|
|
3501
3591
|
"plan.feedbackPlaceholder": "说明要改什么(可留空)",
|
|
3502
3592
|
"plan.notRestored": "执行模型已切换,但主模型默认值未能还原({model});请在「设置 → 模型」中确认默认模型。",
|
|
3503
3593
|
"plan.dismissUnsupported": "当前 DSH 版本既未提供 PendingQuestion.dismiss() 也未提供 cancel(),无法回到聊天;请直接在输入框里发送你的意见。",
|
|
3594
|
+
"plan.goalRun": "设置为目标并执行",
|
|
3595
|
+
"plan.goalFailed": "设置目标失败:{message}",
|
|
3596
|
+
"plan.goalReplaced": "已替换本会话原有的目标",
|
|
3597
|
+
"plan.goalUnsupported": "当前部署未挂载 goal 服务,无法把计划设为目标",
|
|
3504
3598
|
"plan.responseRejected": "计划答复已被另一客户端处理;已提交的模型切换无法由插件回滚。",
|
|
3505
3599
|
"plan.cancelRejected": "计划审查已被另一客户端处理,无法返回讨论。",
|
|
3506
3600
|
"markdown.copy": "复制代码",
|
|
@@ -3552,6 +3646,10 @@ window.__ModuleLoader__.load({
|
|
|
3552
3646
|
"plan.feedbackPlaceholder": "Say what to change (optional)",
|
|
3553
3647
|
"plan.notRestored": "The execution model switched, but the Main default could not be restored ({model}); confirm the default in Settings → Models.",
|
|
3554
3648
|
"plan.dismissUnsupported": "This DSH Host exposes neither PendingQuestion.dismiss() nor cancel(), so the review cannot return to chat; send your feedback as a message instead.",
|
|
3649
|
+
"plan.goalRun": "Set as goal and run",
|
|
3650
|
+
"plan.goalFailed": "Could not set the goal: {message}",
|
|
3651
|
+
"plan.goalReplaced": "Replaced this session's previous goal",
|
|
3652
|
+
"plan.goalUnsupported": "This deployment mounts no goal service, so the Plan cannot be set as a goal",
|
|
3555
3653
|
"plan.responseRejected": "Another client already handled this Plan response. A committed model change cannot be rolled back by this plugin.",
|
|
3556
3654
|
"plan.cancelRejected": "Another client already handled this Plan review, so it cannot return to discussion.",
|
|
3557
3655
|
"markdown.copy": "Copy code",
|
|
@@ -3576,6 +3674,29 @@ window.__ModuleLoader__.load({
|
|
|
3576
3674
|
}
|
|
3577
3675
|
const EMPTY_ORDER = [];
|
|
3578
3676
|
/**
|
|
3677
|
+
* Resolve the released goal remote without hard-depending on it.
|
|
3678
|
+
*
|
|
3679
|
+
* `remote.goals` exists only when the deployment mounts `@deepseek-ai/dsh-goal`,
|
|
3680
|
+
* so the capability must be looked up per render rather than injected: an
|
|
3681
|
+
* `inject` on a dotted service name would otherwise block this whole client
|
|
3682
|
+
* plugin on a deployment that does not mount the goal package. The dotted name
|
|
3683
|
+
* is read first, with the namespace object as the fallback shape.
|
|
3684
|
+
* @param ctx - client root context holding the remote namespace.
|
|
3685
|
+
* @returns The goal remote, or undefined when no goal service is mounted.
|
|
3686
|
+
*/
|
|
3687
|
+
function goalRemoteFrom(ctx) {
|
|
3688
|
+
const read = (name) => {
|
|
3689
|
+
try {
|
|
3690
|
+
return ctx.get(name, false);
|
|
3691
|
+
} catch {
|
|
3692
|
+
return;
|
|
3693
|
+
}
|
|
3694
|
+
};
|
|
3695
|
+
const nested = read("remote.goals");
|
|
3696
|
+
if (nested !== void 0 && nested !== null) return nested;
|
|
3697
|
+
return read("remote")?.goals;
|
|
3698
|
+
}
|
|
3699
|
+
/**
|
|
3579
3700
|
* Bind the optional Providers entry order as a React external store.
|
|
3580
3701
|
* @returns A subscribable order snapshot with an invalidation hook for directory changes.
|
|
3581
3702
|
*/
|
|
@@ -3709,6 +3830,7 @@ window.__ModuleLoader__.load({
|
|
|
3709
3830
|
},
|
|
3710
3831
|
subscribeMainDefaults: (listener) => mainDefaults.subscribe(listener),
|
|
3711
3832
|
getMainDefaultsSnapshot: () => mainDefaults.getSnapshot(),
|
|
3833
|
+
goalRemote: () => goalRemoteFrom(scope),
|
|
3712
3834
|
hooks: {
|
|
3713
3835
|
directory: directory.store,
|
|
3714
3836
|
providerOrder: orderStore
|
|
@@ -2,6 +2,7 @@ import type { PendingQuestion } from '@deepseek-ai/dsh-client-ui-user-questions/
|
|
|
2
2
|
import type { ConfigFormSnapshot } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
3
3
|
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
4
4
|
import type { MainSettingsView } from '../../client-contract.ts';
|
|
5
|
+
import { type GoalRemote } from '../../picker/plan-goal.ts';
|
|
5
6
|
import { type PickerDirectoryFace } from './PickerDirectory.ts';
|
|
6
7
|
import type { PickerInteractionOperations } from './popup-dismissal.ts';
|
|
7
8
|
import { type RuntimeProviderLock } from '../runtime-lock.ts';
|
|
@@ -22,6 +23,8 @@ export interface PlanReviewFace extends PickerDirectoryFace {
|
|
|
22
23
|
refreshProviderLock: () => void;
|
|
23
24
|
subscribeMainDefaults: (listener: () => void) => () => void;
|
|
24
25
|
getMainDefaultsSnapshot: () => ConfigFormSnapshot<MainSettingsView>;
|
|
26
|
+
/** Released goal remote; absent when this deployment mounts no goal service. */
|
|
27
|
+
goalRemote: () => GoalRemote | undefined;
|
|
25
28
|
/** Live catalog-group-id → card-key map from ProviderDirectory. */
|
|
26
29
|
catalogRoutes?: () => Readonly<Record<string, string>>;
|
|
27
30
|
}
|
|
@@ -44,6 +44,10 @@ export declare const zh: {
|
|
|
44
44
|
'plan.feedbackPlaceholder': string;
|
|
45
45
|
'plan.notRestored': string;
|
|
46
46
|
'plan.dismissUnsupported': string;
|
|
47
|
+
'plan.goalRun': string;
|
|
48
|
+
'plan.goalFailed': string;
|
|
49
|
+
'plan.goalReplaced': string;
|
|
50
|
+
'plan.goalUnsupported': string;
|
|
47
51
|
'plan.responseRejected': string;
|
|
48
52
|
'plan.cancelRejected': string;
|
|
49
53
|
'markdown.copy': string;
|
|
@@ -96,6 +100,10 @@ export declare const en: {
|
|
|
96
100
|
'plan.feedbackPlaceholder': string;
|
|
97
101
|
'plan.notRestored': string;
|
|
98
102
|
'plan.dismissUnsupported': string;
|
|
103
|
+
'plan.goalRun': string;
|
|
104
|
+
'plan.goalFailed': string;
|
|
105
|
+
'plan.goalReplaced': string;
|
|
106
|
+
'plan.goalUnsupported': string;
|
|
99
107
|
'plan.responseRejected': string;
|
|
100
108
|
'plan.cancelRejected': string;
|
|
101
109
|
'markdown.copy': string;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hand a reviewed plan to the Host's goal domain before its review is answered.
|
|
3
|
+
*
|
|
4
|
+
* Goal state is owned by `@deepseek-ai/dsh-goal`: this module only drives the
|
|
5
|
+
* released client remote (`ctx.remote.goals`), keeps no goal state of its own,
|
|
6
|
+
* and never schedules continuation — `dsh-goal-round-driver` owns that. The
|
|
7
|
+
* shape below mirrors the published remote face structurally so the plugin
|
|
8
|
+
* neither imports generated client modules nor hard-requires the goal package
|
|
9
|
+
* in a deployment that does not mount it.
|
|
10
|
+
*
|
|
11
|
+
* Goal creation is deliberately outside DSH's own goal surface ("Goal creation
|
|
12
|
+
* remains outside this package"), so the published `remote.goals.create` is the
|
|
13
|
+
* one seam this feature relies on; if a future Host drops it, the capability
|
|
14
|
+
* reports `unsupported` instead of guessing another path.
|
|
15
|
+
*/
|
|
16
|
+
/** Compare-and-set identity of the current goal; carried by every live view. */
|
|
17
|
+
export interface GoalRef {
|
|
18
|
+
readonly id: string;
|
|
19
|
+
readonly revision: number;
|
|
20
|
+
}
|
|
21
|
+
/** Detached live view a client reads back from the goal remote. */
|
|
22
|
+
export interface GoalView extends GoalRef {
|
|
23
|
+
readonly phase: 'active' | 'paused' | 'blocked' | 'complete';
|
|
24
|
+
readonly activation: 'armed' | 'disarmed';
|
|
25
|
+
}
|
|
26
|
+
/** Envelope every generated remote method resolves to on the wire. */
|
|
27
|
+
export type GoalRemoteResult<T> = {
|
|
28
|
+
readonly ok: true;
|
|
29
|
+
readonly value: T;
|
|
30
|
+
} | {
|
|
31
|
+
readonly ok: false;
|
|
32
|
+
readonly error: {
|
|
33
|
+
readonly code: string;
|
|
34
|
+
readonly message: string;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
/** The released `ctx.remote.goals` surface this feature uses. */
|
|
38
|
+
export interface GoalRemote {
|
|
39
|
+
/** Create and arm a goal for the session's live Agent. */
|
|
40
|
+
create(sessionId: string, request: {
|
|
41
|
+
readonly objective: string;
|
|
42
|
+
}): Promise<GoalRemoteResult<{
|
|
43
|
+
readonly ref: GoalRef;
|
|
44
|
+
}>>;
|
|
45
|
+
/** Current goal for the session, absent before the first create and after a clear. */
|
|
46
|
+
get(sessionId: string): Promise<GoalRemoteResult<GoalView | null | undefined>>;
|
|
47
|
+
/** Remove the current goal; its history stays in the session log. */
|
|
48
|
+
clear(sessionId: string, ref: GoalRef): Promise<GoalRemoteResult<unknown>>;
|
|
49
|
+
}
|
|
50
|
+
/** Outcome of setting a plan as the session's goal. */
|
|
51
|
+
export type GoalHandoff = {
|
|
52
|
+
readonly kind: 'created';
|
|
53
|
+
} | {
|
|
54
|
+
readonly kind: 'replaced';
|
|
55
|
+
}
|
|
56
|
+
/** The deployment mounts no goal service; the caller must not proceed. */
|
|
57
|
+
| {
|
|
58
|
+
readonly kind: 'unsupported';
|
|
59
|
+
} | {
|
|
60
|
+
readonly kind: 'failed';
|
|
61
|
+
readonly code?: string;
|
|
62
|
+
readonly message: string;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Make the plan text this session's armed goal, replacing any unfinished goal.
|
|
66
|
+
*
|
|
67
|
+
* Ordering mirrors the card's own commit-then-answer rule: a refusal here keeps
|
|
68
|
+
* the Plan pending instead of approving work that no goal tracks. The replace
|
|
69
|
+
* path clears rather than edits so a new plan receives a fresh round budget —
|
|
70
|
+
* `edit` would inherit the rounds the previous goal already spent.
|
|
71
|
+
*
|
|
72
|
+
* @param remote - the released goal remote, absent when no goal package is mounted.
|
|
73
|
+
* @param sessionId - the session that owns both the review and the goal.
|
|
74
|
+
* @param plan - the plan markdown under review.
|
|
75
|
+
* @returns Whether the goal now tracks this plan, or why it does not.
|
|
76
|
+
*/
|
|
77
|
+
export declare function setPlanAsGoal(remote: GoalRemote | undefined, sessionId: string, plan: string): Promise<GoalHandoff>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-model-switch",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.19",
|
|
4
4
|
"description": "Explicit model routing plus composer/Plan picker for DeepSeek Harness",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -93,7 +93,8 @@
|
|
|
93
93
|
"dshReleases": {
|
|
94
94
|
"0.1.7-alpha.2": "compatible",
|
|
95
95
|
"0.1.7-rc.1": "compatible",
|
|
96
|
-
"0.1.7-rc.2": "compatible"
|
|
96
|
+
"0.1.7-rc.2": "compatible",
|
|
97
|
+
"0.2.0-rc.2": "compatible"
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
100
|
},
|
|
@@ -118,6 +119,7 @@
|
|
|
118
119
|
"@deepseek-ai/dsh-compaction": ">=0.1.7-alpha.2",
|
|
119
120
|
"@deepseek-ai/dsh-compaction-basic": ">=0.1.7-alpha.2",
|
|
120
121
|
"@deepseek-ai/dsh-credentials": ">=0.1.7-alpha.2",
|
|
122
|
+
"@deepseek-ai/dsh-goal": ">=0.1.7-alpha.2",
|
|
121
123
|
"@deepseek-ai/dsh-launch-environment": ">=0.1.7-alpha.2",
|
|
122
124
|
"@deepseek-ai/dsh-llm": ">=0.1.7-alpha.2",
|
|
123
125
|
"@deepseek-ai/dsh-permission-presets": ">=0.1.7-alpha.2",
|
|
@@ -335,6 +337,9 @@
|
|
|
335
337
|
"@deepseek-ai/dsh-credentials": {
|
|
336
338
|
"optional": true
|
|
337
339
|
},
|
|
340
|
+
"@deepseek-ai/dsh-goal": {
|
|
341
|
+
"optional": true
|
|
342
|
+
},
|
|
338
343
|
"@deepseek-ai/dsh-client-connection": {
|
|
339
344
|
"optional": true
|
|
340
345
|
}
|