@starwish-ai/xingyuan-dsh 0.6.5 → 0.6.7
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 +96 -0
- package/README.en-US.md +13 -7
- package/README.md +10 -6
- package/lib/domain.js +15 -2
- package/lib/index.js +23 -4
- package/lib/preset/prompts.js +20 -12
- package/lib/preset/tools.js +156 -7
- package/lib/routes/api.js +6 -19
- package/lib/store.js +33 -1
- package/lib/tab-policy.js +2 -0
- package/lib/types/domain.d.ts +17 -3
- package/lib/types/pref-policy.d.ts +24 -1
- package/lib/types/preset/prompts.d.ts +1 -1
- package/lib/types/preset/tools.d.ts +2 -2
- package/lib/types/store.d.ts +14 -1
- package/lib/types/tab-policy.d.ts +3 -1
- package/lib/types/ui-settings.d.ts +2 -2
- package/lib/ui-settings.js +5 -8
- package/package.json +41 -41
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,102 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.6.7] - 2026-09-29
|
|
9
|
+
|
|
10
|
+
Close the parity gap that the host's newly shipped practice rule
|
|
11
|
+
(`dsh-agent-preset/skills/cordis-plugin-development/references/user-actions.md`,
|
|
12
|
+
"one operation, two callers") exposes: three things you could only do on a page now have
|
|
13
|
+
agent-facing equivalents over the same business layer. Model tool count 45 → 49.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- `set_wish_category_color` — set or clear a category's default color, the same write path the
|
|
17
|
+
wish page's 分类管理 panel uses (empty color key clears the override, falling back to the
|
|
18
|
+
wish's own color or the automatic hash).
|
|
19
|
+
- `clear_all_memories` — clear the whole memory store. This is a locked destructive category:
|
|
20
|
+
it always confirms regardless of the write-confirmation switches, and an empty store replies
|
|
21
|
+
without asking.
|
|
22
|
+
- `get_xingyuan_settings` / `update_xingyuan_settings` — read every preference, and change the
|
|
23
|
+
four non-authorization ones (memory injection limit, confirmation-card language, tab
|
|
24
|
+
visibility mode, per-tab hidden list). Writes go through the host settings form on the
|
|
25
|
+
bundle's own row and are **read back and compared**: if the host did not accept them the tool
|
|
26
|
+
fails with `pref_write_rejected` rather than reporting a change that never happened.
|
|
27
|
+
- The `xingyuan` service gained `uiPrefs()` and `setPrefs(patch)` alongside `prefs()`.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
- Category-color writes moved out of `routes/api.ts` into `store.setCategoryColor`, so the page
|
|
31
|
+
action and the chat tool share one validation and one serialized read-modify-write queue.
|
|
32
|
+
Previously the route only truncated the category name, so `name: ''` persisted a ghost
|
|
33
|
+
override keyed by the empty string that could never be cleared from the UI; names are now
|
|
34
|
+
validated (`bad_category_name`) on both paths. Category existence (wishes ∪ color overrides)
|
|
35
|
+
likewise has one implementation, `store.categoryExists`.
|
|
36
|
+
- Rejected preference writes never half-apply: out-of-range limits (`bad_memory_limit`), unknown
|
|
37
|
+
tab ids (`unknown_tab`) and empty patches (`missing_field`) all fail before anything is written.
|
|
38
|
+
- Documentation: AGENTS.md §5.5 confirmation matrix, §6 tool list, §8 configuration table and
|
|
39
|
+
the §5.10 self-audit against the 0.2.0-rc.1 skills now record the closed gap; both READMEs
|
|
40
|
+
state the UI/chat parity.
|
|
41
|
+
|
|
42
|
+
### Security
|
|
43
|
+
- `update_xingyuan_settings` deliberately does **not** accept `confirmWrites` or `confirmOps`.
|
|
44
|
+
Loosening the write-confirmation policy is an authorization change and stays user-only per
|
|
45
|
+
the same official rule; a test asserts those keys are absent from the tool's parameters.
|
|
46
|
+
|
|
47
|
+
## [0.6.6] - 2026-09-29
|
|
48
|
+
|
|
49
|
+
Adapt to the dsh `0.2.0-rc.1` host line while keeping `0.1.7-rc.1` supported. Upgrading the
|
|
50
|
+
host had made the plugin disappear completely: the compatibility gate introduced in
|
|
51
|
+
0.1.7-rc.1 evaluates only the peers a package *declares*, and `^0.1.7-rc.1` does not admit
|
|
52
|
+
`0.2.0-rc.1`, so dsh skipped the whole bundle — reproduced with
|
|
53
|
+
`dsh --profile web --dump-config`, which printed
|
|
54
|
+
`skipping profile bundle "@starwish-ai/xingyuan-dsh" … is incompatible with dsh 0.2.0-rc.1`.
|
|
55
|
+
Preset, chat cards, session-view tabs, the settings page and the standalone `/xingyuan/*`
|
|
56
|
+
pages all vanished; the SQLite data stayed intact.
|
|
57
|
+
|
|
58
|
+
### Added
|
|
59
|
+
- `test/host-baseline.test.ts` — two new gates: every supported host version line
|
|
60
|
+
(`SUPPORTED_DSH_VERSIONS`) must be admitted by **all** dsh peers under the host's own
|
|
61
|
+
predicate (`semver.satisfies(line, range, {includePrerelease: true})`), the pinned
|
|
62
|
+
devDependency must be one of those lines, and an unverified next generation
|
|
63
|
+
(`0.3.0-rc.1`) must still be refused. Widening support therefore stays a deliberate,
|
|
64
|
+
verified act instead of a silent over-promise.
|
|
65
|
+
- `test/prompts.test.ts` — a gate that the reminder guide and the capabilities section
|
|
66
|
+
contain no host-version-specific assertion.
|
|
67
|
+
- AGENTS.md §5.10 — self-audit against the skills shipped with 0.2.0-rc.1 (the new
|
|
68
|
+
`references/user-actions.md` "one operation, two callers" rule and the `agent-experience`
|
|
69
|
+
skill), recording three UI-only actions that still lack tool equivalents as deliberate,
|
|
70
|
+
documented deviations rather than shipping half-implementations.
|
|
71
|
+
|
|
72
|
+
### Changed
|
|
73
|
+
- peerDependencies: all 16 `@deepseek-ai/dsh-*` entries now admit two host lines
|
|
74
|
+
(`^0.1.7-rc.1 || ^0.2.0-rc.1`) — this is exactly what the gate reads.
|
|
75
|
+
- devDependencies: host baseline moved to `0.2.0-rc.1`. `cordis 4.0.4`,
|
|
76
|
+
`cordis-plugin-loader 1.0.5` and `schemastery 3.18.4` are unchanged in that release.
|
|
77
|
+
- Reminder guidance (`REMINDER_GUIDE` plus the capabilities line) no longer states a fixed
|
|
78
|
+
capability. The host rewrote its schedule subsystem in 0.2.0 — one-shot/session-local
|
|
79
|
+
timers became Host-wide durable reminders with `daily`/`weekly`/`cron`, a
|
|
80
|
+
`schedule_update` tool, its own storage domain and `every_seconds` lowered to a 60 s
|
|
81
|
+
minimum — and because this package supports both host lines, any "periodic reminders are
|
|
82
|
+
impossible" sentence would now be a false statement to users. The guide instead tells the
|
|
83
|
+
model to read the timing parameters `schedule_create` actually accepts and to answer
|
|
84
|
+
accordingly.
|
|
85
|
+
- Documentation: AGENTS.md header gains the 0.2.0-rc.1 delta notes; §10 decision 7 and §11
|
|
86
|
+
are rewritten on the new schedule facts; the transcriptView note now reflects per-host
|
|
87
|
+
defaults (web defaults to `detailed` from 0.2.0, Desktop `standard`, and only `verbose`
|
|
88
|
+
avoids folding completed turns); §4's upgrade checklist gained the schedule row's changed
|
|
89
|
+
plugin shape; the troubleshooting table gained the observed symptom and its remedy.
|
|
90
|
+
|
|
91
|
+
### Fixed
|
|
92
|
+
- The plugin being unusable on dsh 0.2.0-rc.1. **No business-code change was required**:
|
|
93
|
+
package-by-package byte comparison between 0.1.7-rc.1 and 0.2.0-rc.1 showed that every
|
|
94
|
+
host seam this plugin touches is unchanged — session format is still v4, the v3→v4
|
|
95
|
+
migration edge still preserves ignorable plugin events (so the session-log self-repair
|
|
96
|
+
boundary stands), `retainedBy.mainView` and `projectionValues.agentPreset` are unchanged,
|
|
97
|
+
`dsh-host-webserver` / `dsh-settings` / `dsh-storage` / `dsh-storage-domain` /
|
|
98
|
+
`dsh-system-prompt` / `dsh-user-questions` / `dsh-client-ui-slots` /
|
|
99
|
+
`dsh-client-ui-renderer` / `dsh-client-store` / `dsh-session-format-catalog` and the
|
|
100
|
+
`dsh-agent-preset` implementation are byte-identical, and no changed package removed a
|
|
101
|
+
symbol this package imports. Verified with `pnpm typecheck`, `pnpm build` and the full
|
|
102
|
+
suite (25 files / 293 tests) against the new baseline.
|
|
103
|
+
|
|
8
104
|
## [0.6.5] - 2026-09-24
|
|
9
105
|
|
|
10
106
|
First stable line on the dsh 0.1.7 host contract. This release re-verifies the plugin
|
package/README.en-US.md
CHANGED
|
@@ -16,8 +16,12 @@ XingYuan is a wish & habit-building companion, shipped as a DeepSeek Harness plu
|
|
|
16
16
|
- **Micro-actions**: break an overwhelming goal into 3–7 tiny steps and walk through them guided
|
|
17
17
|
- **Growth system**: levels Lv.1–Lv.10, streak bonuses, stat cards, 30-day bar chart
|
|
18
18
|
- **Session view tabs**: Today / Wishes / Tasks / Calendar / Growth / Memory — buttons call action endpoints directly; shown only in XingYuan-preset sessions by default, switchable to always show/hide and per-tab in Settings
|
|
19
|
-
- **Memory**: important memories injected into context (limit configurable), full CRUD
|
|
19
|
+
- **Memory**: important memories injected into context (limit configurable), full CRUD and clear-all
|
|
20
20
|
- **Charts**: 15 chart types rendered as cards
|
|
21
|
+
- **Parity between UI and chat**: anything you can do on a page — check in, claim, delete, rename or
|
|
22
|
+
recolor a category, clear memories, adjust preferences — you can also ask the assistant to do,
|
|
23
|
+
through the same business layer with the same result; loosening the write-confirmation policy
|
|
24
|
+
stays user-only (Settings page) by design
|
|
21
25
|
- **Safe writes**: write confirmation is per-category (create / check-in / undo / claim / edit / save memory); deletion always confirms and cannot be turned off; defaults match previous versions
|
|
22
26
|
- **Theming**: light/dark follows the app theme
|
|
23
27
|
|
|
@@ -25,10 +29,12 @@ Tools are only mounted on sessions using the XingYuan preset; other sessions are
|
|
|
25
29
|
|
|
26
30
|
## Install
|
|
27
31
|
|
|
28
|
-
> Requires DeepSeek Harness `0.1.7-rc.1` (peer dependencies
|
|
29
|
-
>
|
|
30
|
-
> subsystem, so on older hosts this plugin's client half does not activate at all,
|
|
31
|
-
>
|
|
32
|
+
> Requires DeepSeek Harness `0.1.7-rc.1` **or** `0.2.0-rc.1` (peer dependencies admit both
|
|
33
|
+
> version lines, including the host's client-half packages; 0.1.7 rewrote the settings
|
|
34
|
+
> subsystem, so on older hosts this plugin's client half does not activate at all, and
|
|
35
|
+
> since rc.1 dsh refuses to load a whole bundle whose peer range does not match — this
|
|
36
|
+
> package's "every supported line is admitted" claim is locked by a test). Scheduled
|
|
37
|
+
> reminder capabilities differ between the two host versions and are not hardcoded here.
|
|
32
38
|
> Check the upgrade notes in [AGENTS.md](./AGENTS.md) before bumping dsh).
|
|
33
39
|
|
|
34
40
|
```sh
|
|
@@ -55,8 +61,8 @@ that directory — copy the profile file too if you want them on a new machine.
|
|
|
55
61
|
| Coach style | Gentle / humorous / strict |
|
|
56
62
|
| User profile | Nickname, occupation, interests |
|
|
57
63
|
| Write confirmation | Master switch + per-category toggles (create / check-in / undo / claim / edit / save memory); deletion always confirms and cannot be turned off |
|
|
58
|
-
| Memory injection limit | Max memories injected per turn |
|
|
59
|
-
| Tab visibility | Three modes (follow session / always show / always hide) plus per-tab toggles; defaults to follow session |
|
|
64
|
+
| Memory injection limit | Max memories injected per turn (also settable by saying "use 20 memories" in chat) |
|
|
65
|
+
| Tab visibility | Three modes (follow session / always show / always hide) plus per-tab toggles; defaults to follow session. These four non-authorization preferences are also adjustable in chat |
|
|
60
66
|
| Confirm card language | Language of the in-chat confirmation card (Chinese / English; the platform does not expose UI language to plugins, defaults to Chinese) |
|
|
61
67
|
|
|
62
68
|
## Development
|
package/README.md
CHANGED
|
@@ -18,8 +18,11 @@
|
|
|
18
18
|
- **成长体系**:等级 Lv.1–Lv.10、连续加成、统计卡与近 30 天柱状图
|
|
19
19
|
- **会话视图页**:今日 / 愿望 / 任务 / 日历 / 成长 / 记忆 六个标签页,页面按钮直连动作接口;
|
|
20
20
|
默认仅星愿预设的会话显示,可在设置里切换「始终显示 / 始终隐藏」并按标签勾选
|
|
21
|
-
-
|
|
21
|
+
- **记忆**:重要记忆自动注入上下文(上限可配),支持增删改查与一键清空
|
|
22
22
|
- **图表**:15 种统计图表自动渲染为卡片
|
|
23
|
+
- **页面与对话同权**:页面上能做的(打卡 / 领取 / 删除 / 分类改名与配色 / 清空记忆 /
|
|
24
|
+
调整偏好)都能直接在对话里说,走同一份业务收口,结果与回显一致;
|
|
25
|
+
放宽安全策略的开关(写操作二次确认)例外,只能由本人在设置页改
|
|
23
26
|
- **安全确认**:写操作二次确认按类目细化(创建 / 打卡 / 取消打卡 / 领取 / 修改 / 保存记忆),删除始终确认不可关闭;默认与此前版本一致
|
|
24
27
|
- **主题适配**:深浅色跟随应用主题
|
|
25
28
|
|
|
@@ -27,9 +30,10 @@
|
|
|
27
30
|
|
|
28
31
|
## 安装
|
|
29
32
|
|
|
30
|
-
> 需要 DeepSeek Harness `0.1.7-rc.1`(peer
|
|
31
|
-
> 0.1.7 重写了设置子系统,更早的宿主上本插件的 client
|
|
32
|
-
> dsh 会按 peer
|
|
33
|
+
> 需要 DeepSeek Harness `0.1.7-rc.1` 或 `0.2.0-rc.1`(peer 依赖同时 admit 这两条版本线,
|
|
34
|
+
> 含 client 半侧的宿主包;0.1.7 重写了设置子系统,更早的宿主上本插件的 client 半侧不会激活;
|
|
35
|
+
> rc.1 起 dsh 会按 peer 范围**整包拒绝加载**不匹配的插件,本包的「每条线都放行」由测试锁死。
|
|
36
|
+
> 两版宿主的定时提醒能力不同,插件不把能力写死。升级 dsh 前先核对 [AGENTS.md](./AGENTS.md)
|
|
33
37
|
> 的升级要点)。
|
|
34
38
|
|
|
35
39
|
```sh
|
|
@@ -58,8 +62,8 @@ dsh plugin --profile web add @starwish-ai/xingyuan-dsh
|
|
|
58
62
|
| 教练风格 | 温柔 / 幽默 / 严格 |
|
|
59
63
|
| 用户画像 | 昵称、职业、兴趣 |
|
|
60
64
|
| 写操作二次确认 | 总开关 + 六个类目明细(创建 / 打卡 / 取消打卡 / 领取 / 修改 / 保存记忆)是否确认;删除始终确认、不可关闭 |
|
|
61
|
-
| 记忆注入上限 |
|
|
62
|
-
| 标签页显示 | 三态模式(跟随会话 / 始终显示 / 始终隐藏)+
|
|
65
|
+
| 记忆注入上限 | 每次注入上下文的记忆条数上限(也可在对话里直接说「设成 20 条」) |
|
|
66
|
+
| 标签页显示 | 三态模式(跟随会话 / 始终显示 / 始终隐藏)+ 六个标签逐个勾选;默认跟随会话(后四项偏好均可在对话里调整) |
|
|
63
67
|
| 确认卡语言 | 对话中确认卡的显示语言(中文 / English;平台不向插件暴露界面语言,默认中文) |
|
|
64
68
|
|
|
65
69
|
## 开发
|
package/lib/domain.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { randomUUID } from 'node:crypto';
|
|
9
9
|
import { domainTable, defineDomain } from '@deepseek-ai/dsh-storage-domain';
|
|
10
10
|
import { z } from 'zod';
|
|
11
|
+
import { TAB_VISIBILITY_DEFAULTS } from './tab-policy.js';
|
|
11
12
|
export const DOMAIN_VERSION = 1;
|
|
12
13
|
/** 教练风格。 */
|
|
13
14
|
export const COACH_STYLES = ['gentle', 'strict', 'humorous'];
|
|
@@ -155,12 +156,24 @@ function guardDomain(domain) {
|
|
|
155
156
|
close: () => domain.close(),
|
|
156
157
|
};
|
|
157
158
|
}
|
|
158
|
-
/**
|
|
159
|
-
|
|
159
|
+
/**
|
|
160
|
+
* 由已打开领域构造服务句柄(bundle 入口组装用)。
|
|
161
|
+
*
|
|
162
|
+
* 后两个参数默认「读缺省 / 写即抛」:单测与探针桩只需领域读写,偏好写入缺席时
|
|
163
|
+
* 必须响亮失败而不是静默成功——否则「工具说改好了」就没有反证渠道了。
|
|
164
|
+
*/
|
|
165
|
+
export function makeXingyuanStore(domain, readPrefs, readUiPrefs = () => ({
|
|
166
|
+
tabVisibilityMode: TAB_VISIBILITY_DEFAULTS.tabVisibilityMode,
|
|
167
|
+
hiddenTabs: [...TAB_VISIBILITY_DEFAULTS.hiddenTabs],
|
|
168
|
+
}), writePrefs = async () => {
|
|
169
|
+
throw new Error('偏好写入未接线:本服务句柄未绑定宿主 settings 表单');
|
|
170
|
+
}) {
|
|
160
171
|
return {
|
|
161
172
|
spec: xingyuanDomainSpec,
|
|
162
173
|
domain: guardDomain(domain),
|
|
163
174
|
prefs: readPrefs,
|
|
175
|
+
uiPrefs: readUiPrefs,
|
|
176
|
+
setPrefs: writePrefs,
|
|
164
177
|
newId: () => randomUUID(),
|
|
165
178
|
checkinKey: (taskId, date) => `${taskId}|${date}`,
|
|
166
179
|
};
|
package/lib/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import z from '@deepseek-ai/schemastery';
|
|
2
2
|
import { storageBackendServiceKey } from '@deepseek-ai/dsh-storage';
|
|
3
3
|
import { makeXingyuanStore, xingyuanDomainSpec } from './domain.js';
|
|
4
|
+
import { SETTINGS_ENTRY_ID } from './pref-policy.js';
|
|
4
5
|
import { PrefSettingsFields, readPrefSettings } from './pref-settings.js';
|
|
6
|
+
import { normalizeHiddenTabs } from './tab-policy.js';
|
|
5
7
|
import { registerXingyuanRoutes } from './routes/index.js';
|
|
6
8
|
import { repairSessionLogs } from './session-log-repair.js';
|
|
7
9
|
import { sweepOrphans } from './consistency-sweep.js';
|
|
@@ -48,11 +50,28 @@ export async function apply(ctx, config) {
|
|
|
48
50
|
await domain.close();
|
|
49
51
|
});
|
|
50
52
|
// 偏好读取 thunk:每次调用现取 volatile 引用的当前值。它由领域服务持有,
|
|
51
|
-
// preset 层经 ctx.xingyuan.prefs() 读取。偏好挂在常驻主行上,故不存在
|
|
53
|
+
// preset 层经 ctx.xingyuan.prefs() / .uiPrefs() 读取。偏好挂在常驻主行上,故不存在
|
|
52
54
|
// 「整页可见而数据缺席」的时序问题(来龙去脉见 src/pref-settings.ts 头注)。
|
|
53
55
|
const readPrefs = () => readPrefSettings(config);
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
const readUiPrefs = () => ({
|
|
57
|
+
tabVisibilityMode: config.tabVisibilityMode.get(),
|
|
58
|
+
hiddenTabs: normalizeHiddenTabs(config.hiddenTabs.get()),
|
|
59
|
+
});
|
|
60
|
+
// 本插件自带「设置 → 星愿」整页,关掉宿主对这一行的自动生成页;
|
|
61
|
+
// 同一处捕获 settings 表单引用供对话侧写偏好使用(ctx.inject 的回调在后续微任务才跑,
|
|
62
|
+
// 故只能在回调里取值、在调用时判空——异步间隙访问 ctx.* 会命中 inactive context)。
|
|
63
|
+
let settingsForms;
|
|
64
|
+
ctx.inject(['settings'], (inv) => {
|
|
65
|
+
settingsForms = inv.settings;
|
|
66
|
+
inv.effect(() => inv.settings.configure({ auto: false }, ctx.fiber));
|
|
67
|
+
});
|
|
68
|
+
// 偏好唯一写路径:宿主按行 id 把 volatile 字段落到 profile 补丁(与设置页 configForms
|
|
69
|
+
// 同一个表单实例、同一份存储)。这里不做校验也不承诺成功——调用方须读回比对(§5.8)。
|
|
70
|
+
const writePrefs = async (patch) => {
|
|
71
|
+
if (settingsForms === undefined)
|
|
72
|
+
throw new Error('settings 表单未就绪,无法写入偏好');
|
|
73
|
+
await settingsForms.update(SETTINGS_ENTRY_ID, patch);
|
|
74
|
+
};
|
|
56
75
|
// 领域打开后才 provide:注入方(preset 子树)由 cordis inject 语义等待本行
|
|
57
76
|
// 激活完成,早于 provide 的读侧会拿到 undefined
|
|
58
77
|
const opened = await storageDomain.open(xingyuanDomainSpec);
|
|
@@ -61,7 +80,7 @@ export async function apply(ctx, config) {
|
|
|
61
80
|
return;
|
|
62
81
|
}
|
|
63
82
|
domain = opened;
|
|
64
|
-
ctx.provide('xingyuan', makeXingyuanStore(opened, readPrefs));
|
|
83
|
+
ctx.provide('xingyuan', makeXingyuanStore(opened, readPrefs, readUiPrefs, writePrefs));
|
|
65
84
|
// 路由注册经 ctx.effect 挂载:register 返回的 disposer 在卸载/HMR 时注销 /xingyuan
|
|
66
85
|
// 前缀——否则重激活会因重复 (kind,path) 抛错,旧 handler 还会服务已关闭的领域
|
|
67
86
|
ctx.effect(() => registerXingyuanRoutes(webServer, ctx.xingyuan, config));
|
package/lib/preset/prompts.js
CHANGED
|
@@ -34,8 +34,8 @@ const CAPABILITIES = `# 能力范围
|
|
|
34
34
|
- 图表统计(内部工具 generate_chart):打卡趋势、完成率、状态分布、愿望分类、打卡排行、愿望进度、打卡日历等 15 种
|
|
35
35
|
- 成长统计:get_growth_stats 查询等级/经验/连续打卡/达成数量
|
|
36
36
|
- 数据汇总(内部工具 batch_query_user_data):一次性获取全部愿望/任务数据
|
|
37
|
-
-
|
|
38
|
-
-
|
|
37
|
+
- 用户配置:教练风格、用户画像、偏好读取与调整(写操作确认策略除外,只能用户本人在设置页改)
|
|
38
|
+
- 定时提醒:宿主原生 schedule_* 工具,一次性与周期能力随宿主版本,判定见「定时提醒指南」
|
|
39
39
|
|
|
40
40
|
## 界面入口(主动告知用户)
|
|
41
41
|
会话顶部有视图标签页,无需通过对话即可直接查看与操作:
|
|
@@ -115,7 +115,7 @@ const PATTERNS = `# 处理模式
|
|
|
115
115
|
适用场景:用户删除内容(删除任务、删除愿望、删除记忆)
|
|
116
116
|
处理步骤:
|
|
117
117
|
1. 向用户复述要删除的对象(名称+影响范围),不自行询问确认(删除始终由系统弹卡确认)
|
|
118
|
-
2. 执行删除(delete_task/delete_wish/batch_delete_tasks/delete_memory)→ 系统确认卡确认后自动执行
|
|
118
|
+
2. 执行删除(delete_task/delete_wish/batch_delete_tasks/delete_memory/clear_all_memories)→ 系统确认卡确认后自动执行
|
|
119
119
|
3. 确认删除结果,按"标准回复模板-删除"生成回复
|
|
120
120
|
|
|
121
121
|
示例:
|
|
@@ -352,6 +352,7 @@ const MEMORY_GUIDE = `# 记忆操作指南
|
|
|
352
352
|
- 用户要求修改已保存的信息 → update_memory
|
|
353
353
|
- 用户询问之前提到的信息 → search_memory / get_memory / get_all_memories
|
|
354
354
|
- 用户要求删除已保存的信息 → delete_memory(不可恢复,会弹系统确认)
|
|
355
|
+
- 用户要求把记住的信息**全部**清掉 → clear_all_memories(同样弹确认;先看清条数再动手)
|
|
355
356
|
- 不确定键名时 → search_memory
|
|
356
357
|
|
|
357
358
|
## 常用键名参考
|
|
@@ -367,10 +368,15 @@ const CONFIG_GUIDE = `# 用户配置指南
|
|
|
367
368
|
- 用户设置/修改教练风格 → update_coach_style(免确认直接执行)
|
|
368
369
|
- 用户询问画像信息 → get_profile
|
|
369
370
|
- 用户完善画像(昵称/职业/兴趣等) → update_profile(免确认直接执行)
|
|
371
|
+
- 用户问「现在是怎么设置的/注入多少条记忆/标签页只显示星愿吗」 → get_xingyuan_settings
|
|
372
|
+
- 用户要求调整记忆注入条数、确认卡语言、标签页显隐 → update_xingyuan_settings(免确认,只传被点名的项)
|
|
373
|
+
- 用户要求关掉或放宽「写操作二次确认」 → **不代改**:这是安全策略,只能由用户本人在「设置 → 星愿 → 写操作确认」里改,说明入口后停下
|
|
370
374
|
|
|
371
375
|
## 注意事项
|
|
372
376
|
- 教练风格(温柔/严格/幽默)影响后续所有回复的语气与措辞,修改后一句话告知用户当前风格
|
|
373
|
-
-
|
|
377
|
+
- 画像信息优先从用户对话中提取,已提供的信息不重复询问
|
|
378
|
+
- 偏好改动即时生效、无需重启;回复按工具回包报**实际生效值**,越界或未知取值会被直接拒绝,此时如实转述可选区间而不是猜
|
|
379
|
+
- 用户把标签页全部隐藏后又想找回:入口在「设置 → 星愿 → 标签页显示」(页面上的开关始终可达)`;
|
|
374
380
|
const CHART_GUIDE = `# 图表展示指南(均为内部能力,通过 generate_chart 生成)
|
|
375
381
|
|
|
376
382
|
## 选型速查(chartKey 必须精确一致,选错会得到错误图表)
|
|
@@ -410,18 +416,20 @@ const CHART_GUIDE = `# 图表展示指南(均为内部能力,通过 generate
|
|
|
410
416
|
- 图表卡自动渲染;文字回复聚焦结论(趋势/占比/排行)与建议,基于工具返回 subtitle 与数据要点概括,不得只说"已生成图表"`;
|
|
411
417
|
const REMINDER_GUIDE = `# 定时提醒指南
|
|
412
418
|
|
|
413
|
-
##
|
|
414
|
-
|
|
415
|
-
-
|
|
416
|
-
|
|
419
|
+
## 能力判定(先看参数,别凭记忆断言)
|
|
420
|
+
提醒走宿主原生 schedule_* 工具,能做什么随宿主版本不同。**动手前看 schedule_create 本次实际接受的参数**:
|
|
421
|
+
- 有 daily / weekly / cron / every_seconds → 周期提醒可以做,直接设(weekly 的 weekdays 用 ISO 序号:周一 1 …… 周日 7;这些参数还各自要本地时刻与时区,时区给 IANA 名如 Asia/Shanghai)
|
|
422
|
+
- 只有 at / after_seconds → 本环境只支持一次性提醒。如实说明并给替代方案:「我会在每次对话开始给你今日待打卡概览,也可以随时问“今天有什么任务”」
|
|
423
|
+
两种情况都只填用户要的**那一种**时间参数;参数表里标了必填的其余字段(如标题)一并填满。
|
|
417
424
|
|
|
418
425
|
## 何时使用
|
|
419
|
-
- 「明天下午3点提醒我开会」「10分钟后提醒我喝水」→ schedule_create
|
|
426
|
+
- 「明天下午3点提醒我开会」「10分钟后提醒我喝水」→ schedule_create(提醒正文写清,绝对时间或「延后多少秒」二选一)
|
|
427
|
+
- 「每天早上9点提醒我打卡」「每周一三五提醒我锻炼」→ 参数支持时按 daily / weekly 设;不支持时退化为一次性提醒,并说明周期做不到
|
|
420
428
|
|
|
421
429
|
## 注意事项
|
|
422
|
-
-
|
|
423
|
-
-
|
|
424
|
-
- 查看已设提醒 → schedule_list;取消 → schedule_delete
|
|
430
|
+
- 口语时间须换算并在复述里说全(时间、内容、是否重复三样,如"好的,明天下午3点(2026-08-26 15:00)我会提醒你开会")
|
|
431
|
+
- 提醒的存活范围与送达次数由宿主决定,不得向用户承诺「关掉会话也不会丢」或「一定只送达一次」
|
|
432
|
+
- 查看已设提醒 → schedule_list;取消 → schedule_delete;改时间或正文 → schedule_update(本环境没有该工具时删除后重建);ID 一律取列表真实值`;
|
|
425
433
|
const STYLE_TONES = {
|
|
426
434
|
gentle: '当前教练风格:温柔型——暖心鼓励为主,肯定每一点进步,建议措辞柔和。',
|
|
427
435
|
strict: '当前教练风格:严格型——直接鞭策、少客套,明确指出拖延与差距,督促立即行动。',
|
package/lib/preset/tools.js
CHANGED
|
@@ -4,11 +4,13 @@ import { CATEGORY_COLOR_KEYS } from '../category-color.js';
|
|
|
4
4
|
import { addDays, calculateOpportunityDates, findFirstUncheckedOpportunityDate, todayIso } from '../opportunity.js';
|
|
5
5
|
import { confirmAction } from './hitl.js';
|
|
6
6
|
import { unclaimedNoteLine } from './prompts.js';
|
|
7
|
+
import { CONFIRM_LANGS, CONFIRM_OPS, MEMORY_LIMIT_MAX, MEMORY_LIMIT_MIN } from '../pref-policy.js';
|
|
8
|
+
import { TAB_IDS, TAB_VISIBILITY_MODES } from '../tab-policy.js';
|
|
7
9
|
import { buildChart, CHART_KEYS } from './charts.js';
|
|
8
10
|
import { growthSummary } from '../growth.js';
|
|
9
11
|
import { MICRO_STEPS_MAX, MICRO_STEPS_MIN, completeMicroStep, restartMicroAction, startMicroAction } from '../micro.js';
|
|
10
12
|
import { removeTaskCompletely, removeWishCompletely } from '../cascade.js';
|
|
11
|
-
import { allMemories, anchorOf, cancelCheckIn, checkinCountIndex, checkedDatesOf, claimTask, createTask, createWish, CYCLE_LABELS, CYCLE_LABELS_EN, deleteMemory, freshTask, freshWish, freshWishes, freshWishesWithTasks, isClaimed, mutateGlobal, performCheckIn, planForDay, planForRange, renameCategory, saveMemory, searchMemories, updateProfileGlobal, updateTask, updateWish, ToolError, validateCategoryName, validateEstimatedDate, validateTaskName, validateWishTitle, } from '../store.js';
|
|
13
|
+
import { allMemories, anchorOf, cancelCheckIn, categoryExists, checkinCountIndex, checkedDatesOf, claimTask, clearMemories, createTask, createWish, CYCLE_LABELS, CYCLE_LABELS_EN, deleteMemory, freshTask, freshWish, freshWishes, freshWishesWithTasks, isClaimed, mutateGlobal, performCheckIn, planForDay, planForRange, renameCategory, saveMemory, searchMemories, setCategoryColor, updateProfileGlobal, updateTask, updateWish, ToolError, validateCategoryName, validateColorKey, validateEstimatedDate, validateTaskName, validateWishTitle, } from '../store.js';
|
|
12
14
|
export const inject = ['tools', 'xingyuan', 'userQuestions'];
|
|
13
15
|
const STATUS_LABELS = {
|
|
14
16
|
pending: '待领取',
|
|
@@ -245,6 +247,21 @@ const CANCEL_CHECKIN_NOTE = '无需事先询问用户,直接调用即可;结
|
|
|
245
247
|
/** 分类颜色白名单(schema enum 与展示色共用同一事实源)。 */
|
|
246
248
|
const COLOR_KEY_ENUM = CATEGORY_COLOR_KEYS;
|
|
247
249
|
const COLOR_KEY_NOTE = `可选值:${CATEGORY_COLOR_KEYS.join('/')}(不传则按分类名自动配色)`;
|
|
250
|
+
/** 确认类目的中文标签(工具回包呈现用;键集由类型系统强制与 CONFIRM_OPS 对齐)。 */
|
|
251
|
+
const CONFIRM_OP_LABELS = {
|
|
252
|
+
create: '创建',
|
|
253
|
+
checkin: '打卡',
|
|
254
|
+
cancelCheckin: '取消打卡',
|
|
255
|
+
claim: '领取',
|
|
256
|
+
update: '修改',
|
|
257
|
+
memorySave: '记忆保存',
|
|
258
|
+
};
|
|
259
|
+
/** 标签页显隐三态的说法(与设置页同口径,回包不出现内部词)。 */
|
|
260
|
+
const TAB_MODE_LABELS = {
|
|
261
|
+
follow: '仅星愿会话显示',
|
|
262
|
+
show: '任何会话都显示',
|
|
263
|
+
hide: '任何会话都不显示',
|
|
264
|
+
};
|
|
248
265
|
/**
|
|
249
266
|
* 写操作确认门闩(分层模型见 AGENTS.md §10 决策 8):
|
|
250
267
|
* 总开关关闭 → 可配类目一律不弹(一键静音);开启 → 按类目明细决定。
|
|
@@ -559,11 +576,8 @@ export function registerTools(ctx, config) {
|
|
|
559
576
|
timeoutMs: 600_000,
|
|
560
577
|
async execute(args, exec) {
|
|
561
578
|
// 校验先于确认:分类不存在(无同名愿望且无颜色覆盖)直接报错,不让用户白确认
|
|
562
|
-
//
|
|
563
|
-
|
|
564
|
-
const exists = [...store.domain.table('wishes').entries()].some(([, w]) => w.categoryName === args.oldName)
|
|
565
|
-
|| store.domain.global.get().categoryColors?.[args.oldName] !== undefined;
|
|
566
|
-
if (!exists)
|
|
579
|
+
// 一次。存在性口径与配色工具共用 store.categoryExists(纯覆盖分类也是合法对象)。
|
|
580
|
+
if (!categoryExists(store, args.oldName))
|
|
567
581
|
throw new ToolError(`分类「${args.oldName}」不存在`);
|
|
568
582
|
// 新名口径先于确认:store.renameCategory 逐条落库,非法新名会在中途被写路径闸门
|
|
569
583
|
// 拒掉,留下「部分愿望已改名、颜色覆盖键未迁移」的半改状态且无回滚
|
|
@@ -581,6 +595,38 @@ export function registerTools(ctx, config) {
|
|
|
581
595
|
: `已将分类「${args.oldName}」改名为「${args.newName}」,该分类下没有愿望。`;
|
|
582
596
|
},
|
|
583
597
|
}));
|
|
598
|
+
ctx.tools.register(defineTool({
|
|
599
|
+
name: 'set_wish_category_color',
|
|
600
|
+
description: '设置分类颜色。何时使用:用户要求给某个愿望分类换颜色(如「把学习分类改成蓝色」),或要求恢复自动配色时调用。与愿望页「分类管理」面板同一写路径:改的是**分类默认色**,该分类下没有单独指定颜色的愿望都会跟着变。分类名不确定时先调 list_wish_categories;色键不确定时先调 list_wish_category_color_keys(22 选 1)。',
|
|
601
|
+
parameters: {
|
|
602
|
+
categoryName: { type: 'string', required: true, description: '分类名称,须与现有分类完全一致(区分大小写)。2-6个中文字符' },
|
|
603
|
+
colorKey: { type: 'string', required: true, description: `颜色标识,取值见 list_wish_category_color_keys(如 blue)。${CLEARABLE_NOTE}示例:blue` },
|
|
604
|
+
},
|
|
605
|
+
output: TEXT_OUTPUT,
|
|
606
|
+
timeoutMs: 600_000,
|
|
607
|
+
async execute(args, exec) {
|
|
608
|
+
// 校验与存在性判定都在写之前:分类不存在时不让用户白确认一次,
|
|
609
|
+
// 非法色键同样先过一遍口径(store 内还会校验,两半侧同源不另写规则)
|
|
610
|
+
if (!categoryExists(store, args.categoryName))
|
|
611
|
+
throw new ToolError(`分类「${args.categoryName}」不存在`);
|
|
612
|
+
if (args.colorKey.trim() !== '')
|
|
613
|
+
validateColorKey(args.colorKey);
|
|
614
|
+
if (confirmGate(config, 'update')) {
|
|
615
|
+
const clearing = args.colorKey.trim() === '';
|
|
616
|
+
const approved = await confirmAction(ctx, exec, bi(clearing
|
|
617
|
+
? `确定清除分类「${args.categoryName}」的颜色设置,恢复自动配色吗?`
|
|
618
|
+
: `确定把分类「${args.categoryName}」的颜色设为「${args.colorKey}」吗?该分类下未单独指定颜色的愿望都会跟着变。`, clearing
|
|
619
|
+
? `Clear the color of category “${args.categoryName}” and fall back to automatic coloring?`
|
|
620
|
+
: `Set category “${args.categoryName}” to color “${args.colorKey}”? Wishes in it without an explicit color will follow.`));
|
|
621
|
+
if (!approved)
|
|
622
|
+
return '已取消颜色设置。';
|
|
623
|
+
}
|
|
624
|
+
const applied = await setCategoryColor(store, args.categoryName, args.colorKey);
|
|
625
|
+
return applied === null
|
|
626
|
+
? `已清除分类「${args.categoryName}」的颜色设置,恢复自动配色。`
|
|
627
|
+
: `已把分类「${args.categoryName}」的颜色设为 ${applied}。`;
|
|
628
|
+
},
|
|
629
|
+
}));
|
|
584
630
|
ctx.tools.register(defineTool({
|
|
585
631
|
name: 'delete_wish',
|
|
586
632
|
description: `删除愿望。何时使用:删除单个愿望及其关联的所有任务时调用,适用于愿望已完成、取消或误创建的场景。${DELETE_NOTE}回复时向用户说明影响范围。`,
|
|
@@ -1221,6 +1267,24 @@ export function registerTools(ctx, config) {
|
|
|
1221
1267
|
return `已删除:「${args.key}」`;
|
|
1222
1268
|
},
|
|
1223
1269
|
}));
|
|
1270
|
+
ctx.tools.register(defineTool({
|
|
1271
|
+
name: 'clear_all_memories',
|
|
1272
|
+
description: `【清空全部用户信息】使用场景:用户明确要求把已保存的记忆**全部**删掉(如"把你记住我的都删了""清空记忆")时使用。只删单条请改用 delete_memory。${DELETE_NOTE}条数不确定时先用 get_all_memories 看一眼。`,
|
|
1273
|
+
parameters: {},
|
|
1274
|
+
output: TEXT_OUTPUT,
|
|
1275
|
+
timeoutMs: 600_000,
|
|
1276
|
+
async execute(_args, exec) {
|
|
1277
|
+
const count = allMemories(store).length;
|
|
1278
|
+
if (count === 0)
|
|
1279
|
+
return '当前没有已保存的信息,无需清空。';
|
|
1280
|
+
// 删除类目为锁定项:不受 confirmWrites / confirmOps 影响,始终确认(ADR-0001)
|
|
1281
|
+
const approved = await confirmAction(ctx, exec, bi(`确定清空全部 ${count} 条已保存的信息吗?清空后不可恢复,之后我只能重新认识你。`, `Clear all ${count} saved memories? This cannot be undone — I'll have to learn about you again.`));
|
|
1282
|
+
if (!approved)
|
|
1283
|
+
return '已取消清空。';
|
|
1284
|
+
const cleared = await clearMemories(store);
|
|
1285
|
+
return `已清空 ${cleared} 条信息。`;
|
|
1286
|
+
},
|
|
1287
|
+
}));
|
|
1224
1288
|
// ===== 用户配置(教练风格/画像,免确认)=====
|
|
1225
1289
|
ctx.tools.register(defineTool({
|
|
1226
1290
|
name: 'get_coach_config',
|
|
@@ -1281,6 +1345,91 @@ export function registerTools(ctx, config) {
|
|
|
1281
1345
|
return '已更新用户画像。';
|
|
1282
1346
|
},
|
|
1283
1347
|
}));
|
|
1348
|
+
ctx.tools.register(defineTool({
|
|
1349
|
+
name: 'get_xingyuan_settings',
|
|
1350
|
+
description: '读取星愿偏好设置。何时使用:用户问「现在是怎么设置的」「记忆注入多少条」「确认卡是中文还是英文」「标签页是不是只在星愿会话显示」,或在改设置前要先看当前值时使用。返回写操作确认策略(只读)、记忆注入上限、确认卡语言与标签页显隐。',
|
|
1351
|
+
parameters: {},
|
|
1352
|
+
output: TEXT_OUTPUT,
|
|
1353
|
+
isConcurrencySafe: () => true,
|
|
1354
|
+
async execute() {
|
|
1355
|
+
const prefs = store.prefs();
|
|
1356
|
+
const ui = store.uiPrefs();
|
|
1357
|
+
const on = CONFIRM_OPS.filter((key) => prefs.confirmOps[key]).map((key) => CONFIRM_OP_LABELS[key]);
|
|
1358
|
+
return [
|
|
1359
|
+
`写操作确认:${prefs.confirmWrites ? '开' : '关(仅删除类仍始终确认)'}`,
|
|
1360
|
+
prefs.confirmWrites ? ` 需确认的类目:${on.length > 0 ? on.join('、') : '无'}` : undefined,
|
|
1361
|
+
` 删除(愿望/任务/记忆、含批量与清空):始终确认,不可关闭`,
|
|
1362
|
+
`记忆注入上限:${prefs.memoryInjectLimit} 条`,
|
|
1363
|
+
`确认卡语言:${prefs.confirmLang}`,
|
|
1364
|
+
`标签页显示:${TAB_MODE_LABELS[ui.tabVisibilityMode]}${ui.hiddenTabs.length > 0 ? `;已勾掉:${ui.hiddenTabs.join('、')}` : ''}`,
|
|
1365
|
+
].filter((line) => line !== undefined).join('\n');
|
|
1366
|
+
},
|
|
1367
|
+
}));
|
|
1368
|
+
ctx.tools.register(defineTool({
|
|
1369
|
+
name: 'update_xingyuan_settings',
|
|
1370
|
+
description: '修改星愿偏好设置(部分更新:只传用户明确提到的项,未提及不传)。可改四项:memoryInjectLimit(记忆注入条数上限)、confirmLang(对话确认卡语言)、tabVisibilityMode(会话视图标签页显隐)、hiddenTabs(勾掉哪几页)。**写操作确认策略 confirmWrites / confirmOps 不在其中**——那是放宽安全策略,只能由用户本人在「设置 → 星愿」里改,本工具不接受也不提供绕过。何时使用:用户明确要求调整上述偏好(如「以后注入的记忆少一点,设成 20 条」「标签页一直显示」)。改完把新值如实回给用户。',
|
|
1371
|
+
parameters: {
|
|
1372
|
+
memoryInjectLimit: { type: 'integer', description: `每次对话自动注入上下文的记忆条数,${MEMORY_LIMIT_MIN}-${MEMORY_LIMIT_MAX} 的整数。越界直接拒绝、不会静默夹取,请如实告知用户可填区间` },
|
|
1373
|
+
confirmLang: { type: 'string', enum: CONFIRM_LANGS, description: '对话内确认卡的语言:zh 中文 / en 英文。宿主不向插件暴露界面语言,此项独立选择' },
|
|
1374
|
+
tabVisibilityMode: { type: 'string', enum: TAB_VISIBILITY_MODES, description: '会话视图标签页显隐:follow 仅星愿预设的会话显示(默认)/ show 任何会话都显示 / hide 任何会话都不显示' },
|
|
1375
|
+
hiddenTabs: { type: 'array', items: { type: 'string' }, description: `在「显示」前提下被单独勾掉的标签 id,取值 ${TAB_IDS.join(' / ')};传空数组表示六页全显示,不传则保持现状。未知 id 直接拒绝。注意 hide 或勾掉当前正看着的页面时,界面会自动回到 Chat,需在回复里提示用户` },
|
|
1376
|
+
},
|
|
1377
|
+
output: TEXT_OUTPUT,
|
|
1378
|
+
async execute(args) {
|
|
1379
|
+
const patch = {};
|
|
1380
|
+
if (args.memoryInjectLimit !== undefined) {
|
|
1381
|
+
const limit = args.memoryInjectLimit;
|
|
1382
|
+
if (limit < MEMORY_LIMIT_MIN || limit > MEMORY_LIMIT_MAX) {
|
|
1383
|
+
throw new ToolError(`记忆注入上限须为 ${MEMORY_LIMIT_MIN}-${MEMORY_LIMIT_MAX} 的整数(收到 ${limit})`, 'bad_memory_limit', { limit });
|
|
1384
|
+
}
|
|
1385
|
+
patch.memoryInjectLimit = limit;
|
|
1386
|
+
}
|
|
1387
|
+
if (args.confirmLang !== undefined)
|
|
1388
|
+
patch.confirmLang = args.confirmLang;
|
|
1389
|
+
if (args.tabVisibilityMode !== undefined)
|
|
1390
|
+
patch.tabVisibilityMode = args.tabVisibilityMode;
|
|
1391
|
+
if (args.hiddenTabs !== undefined) {
|
|
1392
|
+
const unknown = args.hiddenTabs.filter((tab) => !TAB_IDS.includes(tab));
|
|
1393
|
+
if (unknown.length > 0) {
|
|
1394
|
+
throw new ToolError(`未知标签 id:${unknown.join('、')};可选值为 ${TAB_IDS.join(' / ')}`, 'unknown_tab', { tabs: unknown });
|
|
1395
|
+
}
|
|
1396
|
+
patch.hiddenTabs = args.hiddenTabs;
|
|
1397
|
+
}
|
|
1398
|
+
if (Object.keys(patch).length === 0) {
|
|
1399
|
+
throw new ToolError('没有要修改的偏好项:至少传一个字段(可先调 get_xingyuan_settings 看当前值)', 'missing_field');
|
|
1400
|
+
}
|
|
1401
|
+
await store.setPrefs(patch);
|
|
1402
|
+
// 写后读回比对:宿主可能拒绝(行缺席 / 字段非 volatile / 表单不可写),
|
|
1403
|
+
// 而「工具说改好了、实际没改」是比报错更糟的结果
|
|
1404
|
+
const prefs = store.prefs();
|
|
1405
|
+
const ui = store.uiPrefs();
|
|
1406
|
+
const mismatch = [];
|
|
1407
|
+
if (patch.memoryInjectLimit !== undefined && prefs.memoryInjectLimit !== patch.memoryInjectLimit) {
|
|
1408
|
+
mismatch.push(`memoryInjectLimit=${prefs.memoryInjectLimit}`);
|
|
1409
|
+
}
|
|
1410
|
+
if (patch.confirmLang !== undefined && prefs.confirmLang !== patch.confirmLang) {
|
|
1411
|
+
mismatch.push(`confirmLang=${prefs.confirmLang}`);
|
|
1412
|
+
}
|
|
1413
|
+
if (patch.tabVisibilityMode !== undefined && ui.tabVisibilityMode !== patch.tabVisibilityMode) {
|
|
1414
|
+
mismatch.push(`tabVisibilityMode=${ui.tabVisibilityMode}`);
|
|
1415
|
+
}
|
|
1416
|
+
if (patch.hiddenTabs !== undefined) {
|
|
1417
|
+
const wanted = [...new Set(patch.hiddenTabs)].sort().join(',');
|
|
1418
|
+
if (ui.hiddenTabs.slice().sort().join(',') !== wanted)
|
|
1419
|
+
mismatch.push(`hiddenTabs=${ui.hiddenTabs.join(',')}`);
|
|
1420
|
+
}
|
|
1421
|
+
if (mismatch.length > 0) {
|
|
1422
|
+
throw new ToolError(`偏好写入未被宿主接受,当前值未变(${mismatch.join(';')})。请到「设置 → 星愿」检查该行是否可写`, 'pref_write_rejected', { mismatch });
|
|
1423
|
+
}
|
|
1424
|
+
return [
|
|
1425
|
+
patch.memoryInjectLimit !== undefined ? `记忆注入上限:${prefs.memoryInjectLimit} 条` : undefined,
|
|
1426
|
+
patch.confirmLang !== undefined ? `确认卡语言:${prefs.confirmLang}` : undefined,
|
|
1427
|
+
patch.tabVisibilityMode !== undefined || patch.hiddenTabs !== undefined
|
|
1428
|
+
? `标签页显示:${TAB_MODE_LABELS[ui.tabVisibilityMode]}${ui.hiddenTabs.length > 0 ? `;已勾掉:${ui.hiddenTabs.join('、')}` : ''}`
|
|
1429
|
+
: undefined,
|
|
1430
|
+
].filter((line) => line !== undefined).join(';') + '。(已生效,无需重启)';
|
|
1431
|
+
},
|
|
1432
|
+
}));
|
|
1284
1433
|
// ===== 图表(内部)=====
|
|
1285
1434
|
ctx.tools.register(defineTool({
|
|
1286
1435
|
name: 'generate_chart',
|
|
@@ -1457,7 +1606,7 @@ export function registerTools(ctx, config) {
|
|
|
1457
1606
|
const done = result.state.steps.filter((s) => s.completed).length;
|
|
1458
1607
|
const skipped = result.state.steps.filter((s) => s.skipped).length;
|
|
1459
1608
|
if (result.finished) {
|
|
1460
|
-
return `「${task.name}」微行动全部完成(完成 ${done} 步、跳过 ${skipped}
|
|
1609
|
+
return `「${task.name}」微行动全部完成(完成 ${done} 步、跳过 ${skipped} 步)。\n🎉 计划走完了——现在可以打卡这个任务,告诉我或去「今日」页点打卡都行。`;
|
|
1461
1610
|
}
|
|
1462
1611
|
const next = result.state.steps.find((s) => s.stepNumber === result.state.currentStepNumber);
|
|
1463
1612
|
return `第 ${args.stepNumber} 步已${args.action === 'complete' ? '完成 ✓' : '跳过 ↷'}(${done}/${result.state.steps.length} 完成)。下一步 第 ${result.state.currentStepNumber} 步:${next?.instruction ?? ''}`;
|
package/lib/routes/api.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { allMemories, anchorOf, checkedDatesOf, checkinCountIndex, clearMemories, createTask, createWish, cancelCheckIn, claimTask, deleteMemory, freshTask, freshWish, freshWishes, isClaimed, monthRange, performCheckIn, planForDay, planForRange, renameCategory, saveMemory, searchMemories, updateProfileGlobal, updateTask, validateCategoryName,
|
|
1
|
+
import { allMemories, anchorOf, checkedDatesOf, checkinCountIndex, clearMemories, createTask, createWish, cancelCheckIn, claimTask, deleteMemory, freshTask, freshWish, freshWishes, isClaimed, monthRange, performCheckIn, planForDay, planForRange, renameCategory, saveMemory, searchMemories, setCategoryColor, updateProfileGlobal, updateTask, validateCategoryName, } from '../store.js';
|
|
2
2
|
import { addDays, calculateOpportunityDates, findFirstUncheckedOpportunityDate, isIsoDate, todayIso } from '../opportunity.js';
|
|
3
3
|
import { LEVEL_CONFIGS, growthSummary } from '../growth.js';
|
|
4
4
|
import { getMicroAction } from '../micro.js';
|
|
5
|
-
import { mutateGlobal } from '../store.js';
|
|
6
5
|
import { removeTaskCompletely, removeWishCompletely } from '../cascade.js';
|
|
7
6
|
import { ActionError, HttpError } from './errors.js';
|
|
8
7
|
const MEMORY_CATEGORIES = ['personal', 'preference', 'habit', 'event', 'other'];
|
|
@@ -531,17 +530,6 @@ async function actionUpdateTask(deps, body) {
|
|
|
531
530
|
return { ok: true, task: taskView(store, task) };
|
|
532
531
|
}
|
|
533
532
|
// ===== 分类管理 =====
|
|
534
|
-
async function setCategoryOverride(deps, name, colorKey) {
|
|
535
|
-
// 读-改-写整体进串行队列:并发改不同分类颜色互不覆盖
|
|
536
|
-
await mutateGlobal(deps.store, (global) => {
|
|
537
|
-
const overrides = { ...(global.categoryColors ?? {}) };
|
|
538
|
-
if (colorKey === null)
|
|
539
|
-
delete overrides[name];
|
|
540
|
-
else
|
|
541
|
-
overrides[name] = colorKey;
|
|
542
|
-
return { ...global, categoryColors: Object.keys(overrides).length > 0 ? overrides : undefined };
|
|
543
|
-
});
|
|
544
|
-
}
|
|
545
533
|
async function actionCategoryRename(deps, body) {
|
|
546
534
|
requireFields(body, ['oldName', 'newName']);
|
|
547
535
|
const oldName = clampStr(body.oldName, 6);
|
|
@@ -554,10 +542,9 @@ async function actionCategoryRename(deps, body) {
|
|
|
554
542
|
}
|
|
555
543
|
async function actionCategoryColor(deps, body) {
|
|
556
544
|
requireFields(body, ['name']);
|
|
557
|
-
const
|
|
558
|
-
//
|
|
559
|
-
|
|
560
|
-
const colorKey =
|
|
561
|
-
|
|
562
|
-
return { ok: true, name, colorKey };
|
|
545
|
+
const rawColor = typeof body.colorKey === 'string' ? body.colorKey : null;
|
|
546
|
+
// 与对话侧 set_wish_category_color 同一写路径(store 收口):空白色键 = 清除覆盖,
|
|
547
|
+
// 分类名与色键的校验也在那一处,两半侧不再各写一份口径
|
|
548
|
+
const colorKey = await setCategoryColor(deps.store, clampStr(body.name, 6), rawColor);
|
|
549
|
+
return { ok: true, name: clampStr(body.name, 6), colorKey };
|
|
563
550
|
}
|
package/lib/store.js
CHANGED
|
@@ -655,7 +655,39 @@ export async function renameCategory(store, oldName, newName) {
|
|
|
655
655
|
});
|
|
656
656
|
return renamed;
|
|
657
657
|
}
|
|
658
|
-
/**
|
|
658
|
+
/**
|
|
659
|
+
* 分类是否存在:同名愿望 ∪ 颜色覆盖键。改名与配色两条路径共用这一口径——
|
|
660
|
+
* 「零愿望但设过色」的纯覆盖分类在页面分类面板里是合法对象,工具面不得当它不存在。
|
|
661
|
+
*/
|
|
662
|
+
export function categoryExists(store, name) {
|
|
663
|
+
for (const [, wish] of store.domain.table('wishes').entries()) {
|
|
664
|
+
if (wish.categoryName === name)
|
|
665
|
+
return true;
|
|
666
|
+
}
|
|
667
|
+
return store.domain.global.get().categoryColors?.[name] !== undefined;
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* 设置或清除分类颜色覆盖(页面 `category-color` 动作与 `set_wish_category_color`
|
|
671
|
+
* 工具的唯一写路径)。`colorKey` 为 null 或空白 = 清除覆盖,恢复跟随愿望显式色/哈希兜底。
|
|
672
|
+
* 分类名与色键都在此处过一遍口径:页面历史上靠 clamp 兜着,空串会写出一个键为 ''
|
|
673
|
+
* 的幽灵覆盖,从此在分类面板里阴魂不散。读-改-写整体进串行队列,并发改不同分类互不覆盖。
|
|
674
|
+
*
|
|
675
|
+
* @returns 生效的色键(null = 已清除),供调用方如实回显。
|
|
676
|
+
*/
|
|
677
|
+
export async function setCategoryColor(store, name, colorKey) {
|
|
678
|
+
const category = validateCategoryName(name);
|
|
679
|
+
const trimmed = colorKey?.trim() ?? '';
|
|
680
|
+
const color = trimmed === '' ? null : validateColorKey(trimmed);
|
|
681
|
+
await mutateGlobal(store, (global) => {
|
|
682
|
+
const overrides = { ...(global.categoryColors ?? {}) };
|
|
683
|
+
if (color === null)
|
|
684
|
+
delete overrides[category];
|
|
685
|
+
else
|
|
686
|
+
overrides[category] = color;
|
|
687
|
+
return { ...global, categoryColors: Object.keys(overrides).length > 0 ? overrides : undefined };
|
|
688
|
+
});
|
|
689
|
+
return color;
|
|
690
|
+
}
|
|
659
691
|
export function allMemories(store) {
|
|
660
692
|
const list = [];
|
|
661
693
|
for (const [, memory] of store.domain.table('memories').entries())
|
package/lib/tab-policy.js
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
*/
|
|
13
13
|
/** 六个会话视图标签的稳定业务名(与 slot entry id 的 xy- 前缀解耦,配置文件里可读)。 */
|
|
14
14
|
export const TAB_IDS = ['today', 'wishes', 'tasks', 'calendar', 'growth', 'memory'];
|
|
15
|
+
/** 显隐模式取值(主行 Config 的 schema 枚举、设置页选项与工具参数三方同源)。 */
|
|
16
|
+
export const TAB_VISIBILITY_MODES = ['follow', 'show', 'hide'];
|
|
15
17
|
/**
|
|
16
18
|
* 星愿 preset 身份:宿主会话投影值 `agentPreset` 的取值,与 bundle 补丁里
|
|
17
19
|
* `preset-xingyuan` 声明行的 `config.id` 是同一串纯字符串(对拍见 test/preset-declaration.test.ts)。
|
package/lib/types/domain.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Domain, type DomainTableSpec } from '@deepseek-ai/dsh-storage-domain';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import type { PrefSettings } from './pref-policy.js';
|
|
3
|
+
import type { PrefPatch, PrefSettings, UiSettings } from './pref-policy.js';
|
|
4
4
|
export declare const DOMAIN_VERSION = 1;
|
|
5
5
|
/** 教练风格。 */
|
|
6
6
|
export declare const COACH_STYLES: readonly ["gentle", "strict", "humorous"];
|
|
@@ -101,6 +101,15 @@ export interface XingyuanStore {
|
|
|
101
101
|
readonly domain: Domain<typeof xingyuanDomainSpec>;
|
|
102
102
|
/** 对话偏好:bundle 主行 volatile Config 的当前解析值(非领域数据),每次调用现取。 */
|
|
103
103
|
prefs(): PrefSettings;
|
|
104
|
+
/** 界面偏好(标签页显隐)的当前解析值,同样每次现取。 */
|
|
105
|
+
uiPrefs(): UiSettings;
|
|
106
|
+
/**
|
|
107
|
+
* 偏好写入的唯一路径(bundle 主行经宿主 settings 表单落到 profile 补丁)。
|
|
108
|
+
* 调用方(对话工具)负责参数校验;本方法只负责落盘,**不承诺成功**——
|
|
109
|
+
* 宿主可能拒绝(行缺席 / 非 volatile 字段 / 无写权限),调用方须再读
|
|
110
|
+
* {@link prefs} / {@link uiPrefs} 比对,未生效即如实报错,不得静默当作改成了。
|
|
111
|
+
*/
|
|
112
|
+
setPrefs(patch: PrefPatch): Promise<void>;
|
|
104
113
|
newId(): string;
|
|
105
114
|
checkinKey(taskId: string, date: string): string;
|
|
106
115
|
}
|
|
@@ -119,6 +128,11 @@ export declare class RecordInvalidError extends Error {
|
|
|
119
128
|
readonly code = "invalid_record";
|
|
120
129
|
constructor(message: string);
|
|
121
130
|
}
|
|
122
|
-
/**
|
|
123
|
-
|
|
131
|
+
/**
|
|
132
|
+
* 由已打开领域构造服务句柄(bundle 入口组装用)。
|
|
133
|
+
*
|
|
134
|
+
* 后两个参数默认「读缺省 / 写即抛」:单测与探针桩只需领域读写,偏好写入缺席时
|
|
135
|
+
* 必须响亮失败而不是静默成功——否则「工具说改好了」就没有反证渠道了。
|
|
136
|
+
*/
|
|
137
|
+
export declare function makeXingyuanStore(domain: Domain<typeof xingyuanDomainSpec>, readPrefs: () => PrefSettings, readUiPrefs?: () => UiSettings, writePrefs?: (patch: PrefPatch) => Promise<void>): XingyuanStore;
|
|
124
138
|
export {};
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* locale 服务是浏览器专属 seam,工具执行期读不到;故确认卡语言只能由用户在此
|
|
21
21
|
* 显式选择,不能自动跟随界面语言。
|
|
22
22
|
*/
|
|
23
|
-
import type { TabVisibilityMode } from './tab-policy.js';
|
|
23
|
+
import type { TabId, TabVisibilityMode } from './tab-policy.js';
|
|
24
24
|
/**
|
|
25
25
|
* 偏好落在哪一条 profile 行上:dsh 0.1.7 起「可编辑设置 = 该行的 Config schema 里
|
|
26
26
|
* 标了 `.volatile()` 的字段」,客户端经 `ctx.configForms.get(SETTINGS_ENTRY_ID)` 读写,
|
|
@@ -81,6 +81,29 @@ export interface PrefSettings {
|
|
|
81
81
|
export declare const PREF_DEFAULTS: PrefSettings;
|
|
82
82
|
/** 脏值容错:非 zh/en 一律回落 zh(与 tab-policy 的显隐脏值容错同口径)。 */
|
|
83
83
|
export declare function normalizeConfirmLang(value: unknown): ConfirmLang;
|
|
84
|
+
/**
|
|
85
|
+
* 界面偏好的当前解析值(标签页显隐)。与 {@link PrefSettings} 同挂主行 volatile 字段,
|
|
86
|
+
* 分两组只为让「对话侧读什么」在类型上如实;脏值收敛走 tab-policy.normalizeHiddenTabs。
|
|
87
|
+
*/
|
|
88
|
+
export interface UiSettings {
|
|
89
|
+
/** 三态:follow 仅星愿会话显示 / show 所有会话显示 / hide 全部隐藏。 */
|
|
90
|
+
tabVisibilityMode: TabVisibilityMode;
|
|
91
|
+
/** 在「显示」前提下被勾掉的单个标签(空 = 六个全显示)。 */
|
|
92
|
+
hiddenTabs: TabId[];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 偏好写入的合法载荷(对话 + 界面两组里**可由对话侧发起**的那几项)。
|
|
96
|
+
*
|
|
97
|
+
* 刻意不含 `confirmWrites` / `confirmOps`:它们是「放宽安全策略」的开关,按宿主官方
|
|
98
|
+
* 实践(dsh-agent-preset skills/references/user-actions.md:授予或确认权限的动作保持
|
|
99
|
+
* 用户专属)只能由用户在设置页亲自改,工具面不接受、也不提供绕过路径。
|
|
100
|
+
*/
|
|
101
|
+
export interface PrefPatch {
|
|
102
|
+
memoryInjectLimit?: number;
|
|
103
|
+
confirmLang?: ConfirmLang;
|
|
104
|
+
tabVisibilityMode?: TabVisibilityMode;
|
|
105
|
+
hiddenTabs?: readonly string[];
|
|
106
|
+
}
|
|
84
107
|
/**
|
|
85
108
|
* 解析「记忆注入上限」输入:非整数、非数字、空串一律返回 undefined(拒绝);
|
|
86
109
|
* 越界值夹取到 [MIN,MAX] 且 clamped 置 true(调用方据此给出行内提示并回显)。
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 提示词移植:PromptTemplateManager 全量段落 → dsh systemPrompt 分节注册。
|
|
3
3
|
* 渠道适配:无微信版(Web 图表卡自动渲染);emitUiCardsBlock 移除(工具成功即发事件);
|
|
4
|
-
*
|
|
4
|
+
* 提醒指南对宿主能力保持中立(宿主 schedule 的一次性/周期口径随版本变,判定交给工具参数)。
|
|
5
5
|
*/
|
|
6
6
|
import type { Context } from '@deepseek-ai/cordis';
|
|
7
7
|
import type { XingyuanStore } from '../domain.js';
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* - 写确认:总开关(confirmWrites)开启时按类目明细(confirmOps)弹卡——创建/打卡/取消打卡
|
|
8
8
|
* 默认确认,领取/修改/记忆保存默认免确认但可在设置开启;删除(含批量)始终确认;教练风格与画像免确认;
|
|
9
9
|
* - 业务事实:写操作成功即发 xingyuan/* 会话事件驱动卡片(可回放);
|
|
10
|
-
* -
|
|
11
|
-
*
|
|
10
|
+
* - 提醒:不自造包装工具,直接用宿主原生 schedule_*;其能力随宿主版本而不同,
|
|
11
|
+
* 判定与如实告知的口径集中在提示词的「定时提醒指南」,本层不断言能力边界。
|
|
12
12
|
*/
|
|
13
13
|
import type { Context } from '@deepseek-ai/cordis';
|
|
14
14
|
import type { XingyuanStore } from '../domain.js';
|
package/lib/types/store.d.ts
CHANGED
|
@@ -162,7 +162,20 @@ export declare function planForDay(store: XingyuanStore, date: string): DayPlan;
|
|
|
162
162
|
* (分类管理面板允许存在零愿望的纯覆盖分类)。
|
|
163
163
|
*/
|
|
164
164
|
export declare function renameCategory(store: XingyuanStore, oldName: string, newName: string): Promise<Wish[]>;
|
|
165
|
-
/**
|
|
165
|
+
/**
|
|
166
|
+
* 分类是否存在:同名愿望 ∪ 颜色覆盖键。改名与配色两条路径共用这一口径——
|
|
167
|
+
* 「零愿望但设过色」的纯覆盖分类在页面分类面板里是合法对象,工具面不得当它不存在。
|
|
168
|
+
*/
|
|
169
|
+
export declare function categoryExists(store: XingyuanStore, name: string): boolean;
|
|
170
|
+
/**
|
|
171
|
+
* 设置或清除分类颜色覆盖(页面 `category-color` 动作与 `set_wish_category_color`
|
|
172
|
+
* 工具的唯一写路径)。`colorKey` 为 null 或空白 = 清除覆盖,恢复跟随愿望显式色/哈希兜底。
|
|
173
|
+
* 分类名与色键都在此处过一遍口径:页面历史上靠 clamp 兜着,空串会写出一个键为 ''
|
|
174
|
+
* 的幽灵覆盖,从此在分类面板里阴魂不散。读-改-写整体进串行队列,并发改不同分类互不覆盖。
|
|
175
|
+
*
|
|
176
|
+
* @returns 生效的色键(null = 已清除),供调用方如实回显。
|
|
177
|
+
*/
|
|
178
|
+
export declare function setCategoryColor(store: XingyuanStore, name: string, colorKey: string | null): Promise<string | null>;
|
|
166
179
|
export declare function allMemories(store: XingyuanStore): MemoryRecord[];
|
|
167
180
|
/** 记忆存取。 */
|
|
168
181
|
export declare function saveMemory(store: XingyuanStore, key: string, value: string, category: MemoryRecord['category'], importance: MemoryRecord['importance']): Promise<void>;
|
|
@@ -13,8 +13,10 @@
|
|
|
13
13
|
/** 六个会话视图标签的稳定业务名(与 slot entry id 的 xy- 前缀解耦,配置文件里可读)。 */
|
|
14
14
|
export declare const TAB_IDS: readonly ["today", "wishes", "tasks", "calendar", "growth", "memory"];
|
|
15
15
|
export type TabId = (typeof TAB_IDS)[number];
|
|
16
|
+
/** 显隐模式取值(主行 Config 的 schema 枚举、设置页选项与工具参数三方同源)。 */
|
|
17
|
+
export declare const TAB_VISIBILITY_MODES: readonly ["follow", "show", "hide"];
|
|
16
18
|
/** 显隐模式:跟随会话 / 始终显示 / 始终隐藏。 */
|
|
17
|
-
export type TabVisibilityMode =
|
|
19
|
+
export type TabVisibilityMode = typeof TAB_VISIBILITY_MODES[number];
|
|
18
20
|
/**
|
|
19
21
|
* 会话列表快照里星愿要读的最小事实面——按「本插件用到什么」收窄,不是宿主类型的复刻:
|
|
20
22
|
* 宿主增删其它字段都不影响本视图,代价是**我们读的字段被撤除时编译期不会报错**
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import z from '@deepseek-ai/schemastery';
|
|
15
15
|
/**
|
|
16
|
-
* 界面偏好字段表。schemastery 无 z.enum,枚举用 const+union
|
|
17
|
-
*
|
|
16
|
+
* 界面偏好字段表。schemastery 无 z.enum,枚举用 const+union 表达(与 pref-settings
|
|
17
|
+
* 的 confirmLang 同形);默认值与 tab-policy 的 TAB_VISIBILITY_DEFAULTS 同源(测试对拍)。
|
|
18
18
|
*/
|
|
19
19
|
export declare const UiSettingsFields: {
|
|
20
20
|
/** 显隐三态:follow 星愿会话才显示 / show 任何会话都显示 / hide 任何会话不显示。 */
|
package/lib/ui-settings.js
CHANGED
|
@@ -12,18 +12,15 @@
|
|
|
12
12
|
* 它们出现在 host Config 里只是为了让宿主把它们投影成表单。
|
|
13
13
|
*/
|
|
14
14
|
import z from '@deepseek-ai/schemastery';
|
|
15
|
-
import { TAB_VISIBILITY_DEFAULTS } from './tab-policy.js';
|
|
15
|
+
import { TAB_VISIBILITY_DEFAULTS, TAB_VISIBILITY_MODES } from './tab-policy.js';
|
|
16
16
|
/**
|
|
17
|
-
* 界面偏好字段表。schemastery 无 z.enum,枚举用 const+union
|
|
18
|
-
*
|
|
17
|
+
* 界面偏好字段表。schemastery 无 z.enum,枚举用 const+union 表达(与 pref-settings
|
|
18
|
+
* 的 confirmLang 同形);默认值与 tab-policy 的 TAB_VISIBILITY_DEFAULTS 同源(测试对拍)。
|
|
19
19
|
*/
|
|
20
20
|
export const UiSettingsFields = {
|
|
21
21
|
/** 显隐三态:follow 星愿会话才显示 / show 任何会话都显示 / hide 任何会话不显示。 */
|
|
22
|
-
tabVisibilityMode: z.union(
|
|
23
|
-
|
|
24
|
-
z.const('show'),
|
|
25
|
-
z.const('hide'),
|
|
26
|
-
]).default(TAB_VISIBILITY_DEFAULTS.tabVisibilityMode).volatile(),
|
|
22
|
+
tabVisibilityMode: z.union(TAB_VISIBILITY_MODES.map((mode) => z.const(mode)))
|
|
23
|
+
.default(TAB_VISIBILITY_DEFAULTS.tabVisibilityMode).volatile(),
|
|
27
24
|
/**
|
|
28
25
|
* 在「显示」前提下被勾掉的单个标签(空数组 = 六个全显示;脏值容错忽略)。
|
|
29
26
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starwish-ai/xingyuan-dsh",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.7",
|
|
4
4
|
"description": "星愿 XingYuan for DeepSeek Harness: 对话创建愿望/任务、机会日打卡、微行动、记忆与图表的 Agent Preset 组合包",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -97,22 +97,22 @@
|
|
|
97
97
|
},
|
|
98
98
|
"peerDependencies": {
|
|
99
99
|
"@deepseek-ai/cordis": "^4.0.4",
|
|
100
|
-
"@deepseek-ai/dsh-agent-preset": "^0.1.7-rc.1",
|
|
101
|
-
"@deepseek-ai/dsh-api-session-controller": "^0.1.7-rc.1",
|
|
102
|
-
"@deepseek-ai/dsh-client-locale": "^0.1.7-rc.1",
|
|
103
|
-
"@deepseek-ai/dsh-client-ui-chat": "^0.1.7-rc.1",
|
|
104
|
-
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.7-rc.1",
|
|
105
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.1.7-rc.1",
|
|
106
|
-
"@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.7-rc.1",
|
|
107
|
-
"@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.1",
|
|
108
|
-
"@deepseek-ai/dsh-schedule": "^0.1.7-rc.1",
|
|
109
|
-
"@deepseek-ai/dsh-session": "^0.1.7-rc.1",
|
|
110
|
-
"@deepseek-ai/dsh-settings": "^0.1.7-rc.1",
|
|
111
|
-
"@deepseek-ai/dsh-storage": "^0.1.7-rc.1",
|
|
112
|
-
"@deepseek-ai/dsh-storage-domain": "^0.1.7-rc.1",
|
|
113
|
-
"@deepseek-ai/dsh-system-prompt": "^0.1.7-rc.1",
|
|
114
|
-
"@deepseek-ai/dsh-tools": "^0.1.7-rc.1",
|
|
115
|
-
"@deepseek-ai/dsh-user-questions": "^0.1.7-rc.1",
|
|
100
|
+
"@deepseek-ai/dsh-agent-preset": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
101
|
+
"@deepseek-ai/dsh-api-session-controller": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
102
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
103
|
+
"@deepseek-ai/dsh-client-ui-chat": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
104
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
105
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
106
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
107
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
108
|
+
"@deepseek-ai/dsh-schedule": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
109
|
+
"@deepseek-ai/dsh-session": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
110
|
+
"@deepseek-ai/dsh-settings": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
111
|
+
"@deepseek-ai/dsh-storage": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
112
|
+
"@deepseek-ai/dsh-storage-domain": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
113
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
114
|
+
"@deepseek-ai/dsh-tools": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
115
|
+
"@deepseek-ai/dsh-user-questions": "^0.1.7-rc.1 || ^0.2.0-rc.1",
|
|
116
116
|
"@deepseek-ai/schemastery": "*",
|
|
117
117
|
"react": "^18.2.0",
|
|
118
118
|
"zod": "^4.4.3"
|
|
@@ -150,30 +150,30 @@
|
|
|
150
150
|
"@deepseek-ai/cordis": "4.0.4",
|
|
151
151
|
"@deepseek-ai/cordis-plugin-include": "1.0.9",
|
|
152
152
|
"@deepseek-ai/cordis-plugin-loader": "1.0.5",
|
|
153
|
-
"@deepseek-ai/dsh-agent": "0.
|
|
154
|
-
"@deepseek-ai/dsh-agent-preset": "0.
|
|
155
|
-
"@deepseek-ai/dsh-api-remotes": "0.
|
|
156
|
-
"@deepseek-ai/dsh-api-session-controller": "0.
|
|
157
|
-
"@deepseek-ai/dsh-attachment": "0.
|
|
158
|
-
"@deepseek-ai/dsh-client-locale": "0.
|
|
159
|
-
"@deepseek-ai/dsh-client-store": "0.
|
|
160
|
-
"@deepseek-ai/dsh-client-ui-chat": "0.
|
|
161
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.
|
|
162
|
-
"@deepseek-ai/dsh-client-ui-renderer": "0.
|
|
163
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.
|
|
164
|
-
"@deepseek-ai/dsh-client-ui-settings-plugins": "0.
|
|
165
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.
|
|
166
|
-
"@deepseek-ai/dsh-host-webserver": "0.
|
|
167
|
-
"@deepseek-ai/dsh-llm": "0.
|
|
168
|
-
"@deepseek-ai/dsh-schedule": "0.
|
|
169
|
-
"@deepseek-ai/dsh-session": "0.
|
|
170
|
-
"@deepseek-ai/dsh-session-format-catalog": "0.
|
|
171
|
-
"@deepseek-ai/dsh-settings": "0.
|
|
172
|
-
"@deepseek-ai/dsh-storage": "0.
|
|
173
|
-
"@deepseek-ai/dsh-storage-domain": "0.
|
|
174
|
-
"@deepseek-ai/dsh-system-prompt": "0.
|
|
175
|
-
"@deepseek-ai/dsh-tools": "0.
|
|
176
|
-
"@deepseek-ai/dsh-user-questions": "0.
|
|
153
|
+
"@deepseek-ai/dsh-agent": "0.2.0-rc.1",
|
|
154
|
+
"@deepseek-ai/dsh-agent-preset": "0.2.0-rc.1",
|
|
155
|
+
"@deepseek-ai/dsh-api-remotes": "0.2.0-rc.1",
|
|
156
|
+
"@deepseek-ai/dsh-api-session-controller": "0.2.0-rc.1",
|
|
157
|
+
"@deepseek-ai/dsh-attachment": "0.2.0-rc.1",
|
|
158
|
+
"@deepseek-ai/dsh-client-locale": "0.2.0-rc.1",
|
|
159
|
+
"@deepseek-ai/dsh-client-store": "0.2.0-rc.1",
|
|
160
|
+
"@deepseek-ai/dsh-client-ui-chat": "0.2.0-rc.1",
|
|
161
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.2.0-rc.1",
|
|
162
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.2.0-rc.1",
|
|
163
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.1",
|
|
164
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "0.2.0-rc.1",
|
|
165
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.1",
|
|
166
|
+
"@deepseek-ai/dsh-host-webserver": "0.2.0-rc.1",
|
|
167
|
+
"@deepseek-ai/dsh-llm": "0.2.0-rc.1",
|
|
168
|
+
"@deepseek-ai/dsh-schedule": "0.2.0-rc.1",
|
|
169
|
+
"@deepseek-ai/dsh-session": "0.2.0-rc.1",
|
|
170
|
+
"@deepseek-ai/dsh-session-format-catalog": "0.2.0-rc.1",
|
|
171
|
+
"@deepseek-ai/dsh-settings": "0.2.0-rc.1",
|
|
172
|
+
"@deepseek-ai/dsh-storage": "0.2.0-rc.1",
|
|
173
|
+
"@deepseek-ai/dsh-storage-domain": "0.2.0-rc.1",
|
|
174
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.0-rc.1",
|
|
175
|
+
"@deepseek-ai/dsh-tools": "0.2.0-rc.1",
|
|
176
|
+
"@deepseek-ai/dsh-user-questions": "0.2.0-rc.1",
|
|
177
177
|
"@deepseek-ai/schemastery": "3.18.4",
|
|
178
178
|
"@types/js-yaml": "^4.0.9",
|
|
179
179
|
"@types/node": "^24.0.0",
|