dsh-ctxlift 0.1.3 → 0.2.3
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 +64 -32
- package/CONTRIBUTING.md +3 -2
- package/README.md +16 -9
- package/README.zh-CN.md +13 -8
- package/dsh-ctxlift.png +0 -0
- package/lib/client.js +104 -16
- package/lib/config.d.ts +8 -9
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +29 -35
- package/lib/config.js.map +1 -1
- package/lib/engine/cache-invalidation.d.ts +19 -0
- package/lib/engine/cache-invalidation.d.ts.map +1 -0
- package/lib/engine/cache-invalidation.js +26 -0
- package/lib/engine/cache-invalidation.js.map +1 -0
- package/lib/engine/coordinator.d.ts +25 -2
- package/lib/engine/coordinator.d.ts.map +1 -1
- package/lib/engine/coordinator.js +136 -60
- package/lib/engine/coordinator.js.map +1 -1
- package/lib/engine/files.d.ts +11 -4
- package/lib/engine/files.d.ts.map +1 -1
- package/lib/engine/files.js +38 -10
- package/lib/engine/files.js.map +1 -1
- package/lib/index.d.ts +6 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +26 -13
- package/lib/index.js.map +1 -1
- package/lib/remote.d.ts +6 -8
- package/lib/remote.d.ts.map +1 -1
- package/lib/remote.js +9 -36
- package/lib/remote.js.map +1 -1
- package/locale/en.json +5 -1
- package/locale/zh.json +5 -1
- package/package.json +18 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,54 +1,86 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
本项目所有值得记录的变更都记录在这个文件中。
|
|
4
|
+
|
|
5
|
+
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
|
|
6
|
+
本项目遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.2.3] - 2026-11-14
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- `tools/result` 监听器签名错误。事件的真实签名是 `(exec, result)`,工具名在 `exec.name`;旧代码把它当单参事件对象读 `event.tool.name`,该字段不存在,判断恒为 false。结果是改完 `AGENTS.md` / `CLAUDE.md` 后渲染缓存不失效,注入的仍是旧内容。工具清单同时改为官方 `dsh-tool-fs` 的 `write` / `edit` / `apply_patch`,删掉并不存在的 `ops_replace`。
|
|
15
|
+
- `remote.getGlobalInfo` 硬编码 `'auto'`,忽略用户的 `globalPreference`。偏好设为 `claude` 且两份文件都存在时,Web 端编辑器显示 `AGENTS.md`,引擎实际加载 `CLAUDE.md`。
|
|
16
|
+
- `resolveWorkspaceDir` 的 `catch {}` 吞掉 `workingDirectory.ensure` 抛出的 `AbortError`,取消信号失效。改为只对该错误继续向上传播,其余异常仍静默回退。
|
|
17
|
+
|
|
18
|
+
## [0.2.2] - 2026-11-13
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- reject 守卫:决策被拒绝时不再对空 messages 崩溃,对齐官方 agent-instructions 的类型契约
|
|
23
|
+
- 逐条消息去重:增量 delta 消息不再被整轮去重误伤,四层截断对增量消息同样生效
|
|
24
|
+
|
|
25
|
+
## [0.2.1] - 2026-10-31
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- 正式插件图标「漂游灯笼」,体积压缩至 196 KiB
|
|
30
|
+
- package.json 声明 icon 字段并加入发布白名单
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- 未选中的历史参考图归档至 archive-icons
|
|
35
|
+
|
|
36
|
+
## [0.2.0] - 2026-10-31
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- 缓存失效:写文件仅清渲染缓存,不再回滚动态配置
|
|
41
|
+
- 存储与传输解耦:落盘逻辑下沉为独立领域函数,RPC 层变薄适配器
|
|
42
|
+
- 配置解析统一:volatile 访问器与裸对象统一收敛到 resolveConfig
|
|
43
|
+
- 渲染缓存指纹升级为内容摘要复合签名,等长文本修改也能正确感知
|
|
44
|
+
|
|
45
|
+
### Removed
|
|
46
|
+
|
|
47
|
+
- 无调用者的 getAgentsHomeDir 导出
|
|
48
|
+
- 构建脚本手工复制默认值,改为复用单一事实来源
|
|
4
49
|
|
|
5
50
|
## [0.1.3] - 2026-10-29
|
|
6
51
|
|
|
7
|
-
###
|
|
52
|
+
### Fixed
|
|
8
53
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
- 新增专项测试与全量回归:在 `test/files.test.mjs` 中新增主目录寻根截断与主目录排除 `~/CLAUDE.md` 的专项断言,全套 16 项测试与 E2E 验收 100% 绿色通过。
|
|
54
|
+
- 主目录边界隔离:寻根算法到 os.homedir() 强制中止,禁止把主目录当项目根
|
|
55
|
+
- 工作目录为主目录时排除 ~/CLAUDE.md,仅加载全局指令
|
|
12
56
|
|
|
13
57
|
## [0.1.2] - 2026-10-28
|
|
14
58
|
|
|
15
|
-
###
|
|
59
|
+
### Fixed
|
|
16
60
|
|
|
17
|
-
- 修复上游
|
|
18
|
-
- 新增专项单测:严密断言注入消息的 `source.changes` 严格为数组且支持 `.flatMap()`。
|
|
61
|
+
- 修复上游 flatMap 崩溃:合成消息强制提供 changes 数组
|
|
19
62
|
|
|
20
63
|
## [0.1.1] - 2026-10-28
|
|
21
64
|
|
|
22
|
-
###
|
|
65
|
+
### Added
|
|
23
66
|
|
|
24
|
-
-
|
|
25
|
-
-
|
|
67
|
+
- 全局指令编辑器只读选择语义:点击未创建文件显示空白草稿,不自动创建
|
|
68
|
+
- 保存时自动创建缺失文件并刷新选中状态
|
|
26
69
|
|
|
27
|
-
###
|
|
70
|
+
### Changed
|
|
28
71
|
|
|
29
|
-
-
|
|
30
|
-
- 前端 Store 状态闭环:保存成功后链式触发目标项刷新,防止保存后跳回默认选项。
|
|
31
|
-
- 完善 CI 工作流与测试断言:覆盖缺失文件空内容只读呈现与保存自动创建的专项单测及 E2E 验证。
|
|
72
|
+
- switchGlobalFilename 纯只读化,返回存在性、内容与字节数
|
|
32
73
|
|
|
33
74
|
## [0.1.0] - 2026-10-27
|
|
34
75
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
### 新增
|
|
38
|
-
|
|
39
|
-
- 四层独立截断策略:全局(`globalPolicy`)、项目根 `CLAUDE.md`(`projectClaudePolicy`)、项目根 `AGENTS.md`(`projectAgentsPolicy`)、子目录(`subdirectoriesPolicy`),每层支持 `unlimited` / `truncate` / `disabled`。
|
|
40
|
-
- 全局文件偏好:`auto` / `agents` / `claude` / `both`,打破官方硬编码 `USER_GLOBAL_FILE='AGENTS.md'` 的限制。
|
|
41
|
-
- 浏览器内在线编辑全局指令文件(`AGENTS.md` / `CLAUDE.md`),经 RPC 服务原子落盘。
|
|
42
|
-
- 按官方范式重构:`Config` Schema(schemastery,全字段 volatile、无默认值)、`InstructionsGuardService extends TypertRemoteService` + `@Remote`、`ctx.plugin` 挂载、`scripts/build-client.mjs` 生成 ModuleLoader 客户端产物、`configForms.whileServed + plugins.bundle.config` 配置面板。
|
|
43
|
-
- 配置写入统一为官方 `{op:'set'|'unset'}` 通道,宿主持久化回写 `cordis.patch.yml` 并带 revision 冲突保护。
|
|
44
|
-
|
|
45
|
-
### 修复
|
|
76
|
+
### Added
|
|
46
77
|
|
|
47
|
-
-
|
|
48
|
-
-
|
|
78
|
+
- 四层独立截断策略:全局、项目 CLAUDE.md、项目 AGENTS.md、子目录,各层支持 unlimited / truncate / disabled
|
|
79
|
+
- 全局文件偏好:auto / agents / claude / both
|
|
80
|
+
- 浏览器内在线编辑全局指令文件,经 RPC 原子落盘
|
|
81
|
+
- 配置面板与客户端产物遵循官方范式
|
|
49
82
|
|
|
50
|
-
###
|
|
83
|
+
### Fixed
|
|
51
84
|
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
- 冷装 / 热装 / 热卸载验收通过。
|
|
85
|
+
- 插件装配但未激活的三个根因:缺 Config Schema、客户端产物非 ModuleLoader 形态、错误的手写注册
|
|
86
|
+
- 保存内容强校验,拒绝非字符串载荷
|
package/CONTRIBUTING.md
CHANGED
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
- Node >= 20,pnpm >= 9
|
|
8
8
|
- 克隆后 `pnpm install`(会安装 dev 与 peer 依赖)
|
|
9
|
-
- `pnpm typecheck` / `pnpm build` / `pnpm test` 分别对应类型检查、构建(tsc + build-client
|
|
10
|
-
- 隔离环境全功能验收:`
|
|
9
|
+
- `pnpm typecheck` / `pnpm build` / `pnpm test` 分别对应类型检查、构建(tsc + build-client)与单测(21 项,含图标规范)
|
|
10
|
+
- 隔离环境全功能验收:`pnpm test:e2e`(6 大区 10 项指标)
|
|
11
|
+
- 实机验收套件:`node test/verify-real-instance.mjs`(5 大域 12 项断言,含 RPC 原子落盘、SHA-1 复合指纹、ModuleLoader 契约)
|
|
11
12
|
|
|
12
13
|
## 提交规范
|
|
13
14
|
|
package/README.md
CHANGED
|
@@ -24,6 +24,7 @@ The official `agent-instructions` plugin shares one global byte budget across al
|
|
|
24
24
|
- Global file preference: `auto` / `agents` / `claude` / `both` — breaks the official hardcoded `USER_GLOBAL_FILE='AGENTS.md'` limit and supports a global `CLAUDE.md` (or both files at once).
|
|
25
25
|
- In-browser editor for global instruction files (`AGENTS.md` / `CLAUDE.md`) with atomic writes through an RPC service. Missing files open as clean empty drafts with zero disk side effects and are created automatically on save.
|
|
26
26
|
- Onion-skin replacement of the official `agent-instructions` messages on every agent step, so your policies take effect in real sessions.
|
|
27
|
+
- Official drifting lantern plugin icon: 512x512 Retina transparent PNG under 200 KiB, strictly complying with DSH 256 KiB `MAX_ICON_BYTES` limit and auto-converted by host to Base64 data URL.
|
|
27
28
|
- Home directory boundary isolation: project root traversal stops at `os.homedir()` and never treats the home directory as a project root, preventing unintended loading of `~/CLAUDE.md` when starting sessions from the user home.
|
|
28
29
|
|
|
29
30
|
## Install
|
|
@@ -65,14 +66,18 @@ src/
|
|
|
65
66
|
├── index.ts Host entry: exports { name, inject, Config, apply };
|
|
66
67
|
│ assembles the coordinator and mounts the RPC service via ctx.plugin
|
|
67
68
|
├── config.ts Config Schema (schemastery, all fields volatile, no defaults);
|
|
68
|
-
│ DEFAULT_CONFIG + resolveConfig
|
|
69
|
-
├── remote.ts InstructionsGuardService extends TypertRemoteService,
|
|
70
|
-
│ @Remote('getGlobalInfo'|'saveGlobalContent'|'switchGlobalFilename')
|
|
71
|
-
└── engine/
|
|
72
|
-
|
|
69
|
+
│ DEFAULT_CONFIG + resolveConfig (natively unwraps volatile accessors)
|
|
70
|
+
├── remote.ts InstructionsGuardService extends TypertRemoteService, a thin RPC
|
|
71
|
+
│ adapter: @Remote('getGlobalInfo'|'saveGlobalContent'|'switchGlobalFilename')
|
|
72
|
+
└── engine/
|
|
73
|
+
├── render.ts UTF-8-safe truncation and granular instruction rendering
|
|
74
|
+
├── files.ts discovery, home boundary isolation, and atomic persistence
|
|
75
|
+
│ (saveGlobalInstructionFile keeps fs out of the RPC layer)
|
|
76
|
+
└── coordinator.ts agent/pre-step onion-skin replacement, invalidateCache(),
|
|
77
|
+
SHA-1 composite cache signature (workspaceDir + path + length + digest)
|
|
73
78
|
scripts/
|
|
74
|
-
└── build-client.mjs Generates lib/client.js as a window.__ModuleLoader__.load bundle
|
|
75
|
-
|
|
79
|
+
└── build-client.mjs Generates lib/client.js as a window.__ModuleLoader__.load bundle;
|
|
80
|
+
reuses DEFAULT_CONFIG from lib/config.js as the single source of truth
|
|
76
81
|
locale/ zh.json / en.json
|
|
77
82
|
```
|
|
78
83
|
|
|
@@ -83,6 +88,7 @@ Key contracts (verified against DSH source):
|
|
|
83
88
|
- Host RPC endpoints are discovered automatically from the `TypertRemoteService` subclass mounted via `ctx.plugin(...)`.
|
|
84
89
|
- The client bundle must explicitly `ctx.remote.$mount(...)` its descriptors — the host only mounts the built-in official contributions.
|
|
85
90
|
- The client needs `inject: ['slots', 'locale', 'configForms', 'remote']`.
|
|
91
|
+
- Cache invalidation is explicit: `tools/result` calls `coordinator.invalidateCache()`, never `updateConfig(...)`, so dynamic volatile config is never reverted to the startup closure value.
|
|
86
92
|
|
|
87
93
|
## Development
|
|
88
94
|
|
|
@@ -90,8 +96,9 @@ Key contracts (verified against DSH source):
|
|
|
90
96
|
pnpm install # installs dev + peer dependencies
|
|
91
97
|
pnpm typecheck # tsc --noEmit
|
|
92
98
|
pnpm build # tsc into lib/, scripts/build-client.mjs generates lib/client.js
|
|
93
|
-
pnpm test # node --test test/*.test.mjs (
|
|
94
|
-
|
|
99
|
+
pnpm test # node --test test/*.test.mjs (21 unit tests, including icon contract)
|
|
100
|
+
pnpm test:e2e # isolated full-function acceptance (6 areas, 10 criteria)
|
|
101
|
+
node test/verify-real-instance.mjs # real-instance suite (5 domains, 12 assertions)
|
|
95
102
|
```
|
|
96
103
|
|
|
97
104
|
## Compatibility
|
package/README.zh-CN.md
CHANGED
|
@@ -65,14 +65,17 @@ src/
|
|
|
65
65
|
├── index.ts Host 入口:导出 { name, inject, Config, apply };
|
|
66
66
|
│ 组装 coordinator 并通过 ctx.plugin 挂载 RPC 服务
|
|
67
67
|
├── config.ts Config Schema(schemastery,全字段 volatile、无默认值);
|
|
68
|
-
│ DEFAULT_CONFIG + resolveConfig
|
|
69
|
-
├── remote.ts InstructionsGuardService
|
|
68
|
+
│ DEFAULT_CONFIG + resolveConfig(原生解包 volatile 访问器)
|
|
69
|
+
├── remote.ts InstructionsGuardService 纯 RPC 薄适配器;
|
|
70
70
|
│ @Remote('getGlobalInfo'|'saveGlobalContent'|'switchGlobalFilename')
|
|
71
|
-
└── engine/
|
|
72
|
-
|
|
71
|
+
└── engine/
|
|
72
|
+
├── render.ts UTF-8 安全截断与分层指令渲染
|
|
73
|
+
├── files.ts 文件发现、主目录边界隔离,以及原子落盘
|
|
74
|
+
│ (saveGlobalInstructionFile 让 fs 远离 RPC 层)
|
|
75
|
+
└── coordinator.ts agent/pre-step 洋葱圈替换、invalidateCache()、SHA-1 复合指纹
|
|
73
76
|
scripts/
|
|
74
|
-
└── build-client.mjs 生成 lib/client.js(window.__ModuleLoader__.load
|
|
75
|
-
|
|
77
|
+
└── build-client.mjs 生成 lib/client.js(window.__ModuleLoader__.load 形态);
|
|
78
|
+
直接复用 lib/config.js 的 DEFAULT_CONFIG 作为单一事实来源
|
|
76
79
|
locale/ zh.json / en.json
|
|
77
80
|
```
|
|
78
81
|
|
|
@@ -83,6 +86,7 @@ locale/ zh.json / en.json
|
|
|
83
86
|
- 宿主 RPC 端点由 `ctx.plugin(TypertRemoteService 子类)` 自动发现。
|
|
84
87
|
- 客户端 bundle 必须显式 `ctx.remote.$mount(...)` 自己的描述符——宿主只挂载内置官方贡献。
|
|
85
88
|
- 客户端需要 `inject: ['slots', 'locale', 'configForms', 'remote']`。
|
|
89
|
+
- 缓存失效显式化:`tools/result` 只调用 `coordinator.invalidateCache()`,绝不再用启动闭包值回滚动态 volatile 配置。
|
|
86
90
|
|
|
87
91
|
## 开发
|
|
88
92
|
|
|
@@ -90,8 +94,9 @@ locale/ zh.json / en.json
|
|
|
90
94
|
pnpm install # 安装 dev + peer 依赖
|
|
91
95
|
pnpm typecheck # tsc --noEmit
|
|
92
96
|
pnpm build # tsc 输出 lib/,scripts/build-client.mjs 生成 lib/client.js
|
|
93
|
-
pnpm test # node --test test/*.test.mjs(
|
|
94
|
-
|
|
97
|
+
pnpm test # node --test test/*.test.mjs(21 项单测,含图标规范测试)
|
|
98
|
+
pnpm test:e2e # 隔离环境全功能验收(6 大区 10 项指标)
|
|
99
|
+
node test/verify-real-instance.mjs # 实机验收套件(5 大域 12 项断言)
|
|
95
100
|
```
|
|
96
101
|
|
|
97
102
|
## 兼容性
|
package/dsh-ctxlift.png
ADDED
|
Binary file
|
package/lib/client.js
CHANGED
|
@@ -12,8 +12,8 @@ window.__ModuleLoader__.load({
|
|
|
12
12
|
var PKG = "dsh-ctxlift";
|
|
13
13
|
var LAYERS = ["globalPolicy","projectClaudePolicy","projectAgentsPolicy","subdirectoriesPolicy"];
|
|
14
14
|
var DEFAULTS = {"globalPreference":"auto","globalPolicy":{"mode":"unlimited","maxBytes":131072},"projectClaudePolicy":{"mode":"truncate","maxBytes":65536},"projectAgentsPolicy":{"mode":"truncate","maxBytes":65536},"subdirectoriesPolicy":{"mode":"truncate","maxBytes":32768}};
|
|
15
|
-
var ZH = {"panel.title":"工作区指令精细化截断与全局管理","panel.description":"独立精细控制全局指令、项目根目录 CLAUDE.md 与 AGENTS.md 的截断策略,杜绝原生一刀切丢弃,并支持在 Web 端直接查看与编辑全局守则。","pref.title":"全局指令文件偏好","pref.description":"打破官方硬编码限制,支持全局使用 CLAUDE.md 或两者合并注入","pref.auto":"自动探测 (存在优先)","pref.claude":"全局仅使用 CLAUDE.md","pref.agents":"全局仅使用 AGENTS.md","pref.both":"两者同时载入 (AGENTS + CLAUDE)","policy.globalPolicy.title":"全局指令 (Global)","policy.globalPolicy.desc":"生效于所有会话与项目的全局工作守则(~/.dsh/)","policy.projectClaudePolicy.title":"项目根目录 CLAUDE.md","policy.projectClaudePolicy.desc":"项目专属指令核心记忆库","policy.projectAgentsPolicy.title":"项目根目录 AGENTS.md","policy.projectAgentsPolicy.desc":"项目专属代理规范库","policy.subdirectoriesPolicy.title":"子目录指令 (Subdirectories)","policy.subdirectoriesPolicy.desc":"深层子目录中的局部指令文件","policy.mode.unlimited":"不截断 (完整保留)","policy.mode.truncate":"截断 (按字节上限)","policy.mode.disabled":"禁用 (不注入)","policy.bytes":"字节","editor.title":"全局指令文件在线编辑器","editor.size":"大小: {n} 字节","editor.dirty":"未保存草稿","editor.save":"保存更改","editor.saving":"保存中...","editor.saved":"已保存","editor.error":"保存或加载异常: {msg}","editor.confirmSwitch":"当前有未保存的修改,切换文件将丢弃未保存的草稿,是否继续?","editor.placeholder":"在 ~/.dsh/{file} 中输入全局指令内容...","state.loading":"加载中...","state.readOnly":"当前环境只读,无法修改配置","toast.saved":"配置已保存","toast.rejected":"保存被拒绝,配置已被服务端更新"};
|
|
16
|
-
var EN = {"panel.title":"Granular Workspace Instructions","panel.description":"Fine-grained truncation control over global instructions, project CLAUDE.md and AGENTS.md, plus a web editor for global instruction files.","pref.title":"Global Instruction Preference","pref.description":"Breaks the official hard-coded limit: global CLAUDE.md or both files can be injected","pref.auto":"Auto detect (existing wins)","pref.claude":"Global CLAUDE.md only","pref.agents":"Global AGENTS.md only","pref.both":"Load both (AGENTS + CLAUDE)","policy.globalPolicy.title":"Global Instructions","policy.globalPolicy.desc":"Global working rules effective in all sessions (~/.dsh/)","policy.projectClaudePolicy.title":"Project root CLAUDE.md","policy.projectClaudePolicy.desc":"Project-specific instruction memory","policy.projectAgentsPolicy.title":"Project root AGENTS.md","policy.projectAgentsPolicy.desc":"Project-specific agent rules","policy.subdirectoriesPolicy.title":"Subdirectory Instructions","policy.subdirectoriesPolicy.desc":"Local instruction files in deeper subdirectories","policy.mode.unlimited":"Unlimited (full)","policy.mode.truncate":"Truncate (byte budget)","policy.mode.disabled":"Disabled (not injected)","policy.bytes":"bytes","editor.title":"Global Instruction Editor","editor.size":"Size: {n} bytes","editor.dirty":"Unsaved draft","editor.save":"Save changes","editor.saving":"Saving...","editor.saved":"Saved","editor.error":"Save/load error: {msg}","editor.confirmSwitch":"Unsaved changes exist. Switching files will discard the draft. Continue?","editor.placeholder":"Type global instruction content in ~/.dsh/{file}...","state.loading":"Loading...","state.readOnly":"Read-only environment, cannot modify configuration","toast.saved":"Configuration saved","toast.rejected":"Save rejected, configuration was updated on the server"};
|
|
15
|
+
var ZH = {"panel.title":"工作区指令精细化截断与全局管理","panel.description":"独立精细控制全局指令、项目根目录 CLAUDE.md 与 AGENTS.md 的截断策略,杜绝原生一刀切丢弃,并支持在 Web 端直接查看与编辑全局守则。","pref.title":"全局指令文件偏好","pref.description":"打破官方硬编码限制,支持全局使用 CLAUDE.md 或两者合并注入","pref.auto":"自动探测 (存在优先)","pref.claude":"全局仅使用 CLAUDE.md","pref.agents":"全局仅使用 AGENTS.md","pref.both":"两者同时载入 (AGENTS + CLAUDE)","policy.globalPolicy.title":"全局指令 (Global)","policy.globalPolicy.desc":"生效于所有会话与项目的全局工作守则(~/.dsh/)","policy.projectClaudePolicy.title":"项目根目录 CLAUDE.md","policy.projectClaudePolicy.desc":"项目专属指令核心记忆库","policy.projectAgentsPolicy.title":"项目根目录 AGENTS.md","policy.projectAgentsPolicy.desc":"项目专属代理规范库","policy.subdirectoriesPolicy.title":"子目录指令 (Subdirectories)","policy.subdirectoriesPolicy.desc":"深层子目录中的局部指令文件","policy.mode.unlimited":"不截断 (完整保留)","policy.mode.truncate":"截断 (按字节上限)","policy.mode.disabled":"禁用 (不注入)","policy.bytes":"字节","editor.title":"全局指令文件在线编辑器","editor.size":"大小: {n} 字节","editor.dirty":"未保存草稿","editor.save":"保存更改","editor.saving":"保存中...","editor.saved":"已保存","editor.error":"保存或加载异常: {msg}","editor.confirmSwitch":"当前有未保存的修改,切换文件将丢弃未保存的草稿,是否继续?","editor.placeholder":"在 ~/.dsh/{file} 中输入全局指令内容...","state.loading":"加载中...","state.readOnly":"当前环境只读,无法修改配置","toast.saved":"配置已保存","toast.rejected":"保存被拒绝,配置已被服务端更新","config.sectionTitle":"指令截断与全局策略","config.dirty":"配置有未保存修改","config.save":"保存配置","config.reset":"放弃修改"};
|
|
16
|
+
var EN = {"panel.title":"Granular Workspace Instructions","panel.description":"Fine-grained truncation control over global instructions, project CLAUDE.md and AGENTS.md, plus a web editor for global instruction files.","pref.title":"Global Instruction Preference","pref.description":"Breaks the official hard-coded limit: global CLAUDE.md or both files can be injected","pref.auto":"Auto detect (existing wins)","pref.claude":"Global CLAUDE.md only","pref.agents":"Global AGENTS.md only","pref.both":"Load both (AGENTS + CLAUDE)","policy.globalPolicy.title":"Global Instructions","policy.globalPolicy.desc":"Global working rules effective in all sessions (~/.dsh/)","policy.projectClaudePolicy.title":"Project root CLAUDE.md","policy.projectClaudePolicy.desc":"Project-specific instruction memory","policy.projectAgentsPolicy.title":"Project root AGENTS.md","policy.projectAgentsPolicy.desc":"Project-specific agent rules","policy.subdirectoriesPolicy.title":"Subdirectory Instructions","policy.subdirectoriesPolicy.desc":"Local instruction files in deeper subdirectories","policy.mode.unlimited":"Unlimited (full)","policy.mode.truncate":"Truncate (byte budget)","policy.mode.disabled":"Disabled (not injected)","policy.bytes":"bytes","editor.title":"Global Instruction Editor","editor.size":"Size: {n} bytes","editor.dirty":"Unsaved draft","editor.save":"Save changes","editor.saving":"Saving...","editor.saved":"Saved","editor.error":"Save/load error: {msg}","editor.confirmSwitch":"Unsaved changes exist. Switching files will discard the draft. Continue?","editor.placeholder":"Type global instruction content in ~/.dsh/{file}...","state.loading":"Loading...","state.readOnly":"Read-only environment, cannot modify configuration","toast.saved":"Configuration saved","toast.rejected":"Save rejected, configuration was updated on the server","config.sectionTitle":"Instruction & Policy Settings","config.dirty":"Unsaved config changes","config.save":"Save Configuration","config.reset":"Discard Changes"};
|
|
17
17
|
|
|
18
18
|
var localeCtx = null;
|
|
19
19
|
function t(key, params) {
|
|
@@ -265,26 +265,89 @@ window.__ModuleLoader__.load({
|
|
|
265
265
|
|
|
266
266
|
var dirty = draft !== base;
|
|
267
267
|
|
|
268
|
-
|
|
268
|
+
function normalizeConfig(c) {
|
|
269
|
+
var raw = c || {};
|
|
270
|
+
var res = {
|
|
271
|
+
globalPreference: typeof raw.globalPreference === "string" ? raw.globalPreference : DEFAULTS.globalPreference
|
|
272
|
+
};
|
|
273
|
+
for (var i = 0; i < LAYERS.length; i++) {
|
|
274
|
+
res[LAYERS[i]] = policyOf(raw, LAYERS[i]);
|
|
275
|
+
}
|
|
276
|
+
return res;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
var serverConfig = React.useMemo(function () {
|
|
280
|
+
return normalizeConfig(config);
|
|
281
|
+
}, [config]);
|
|
282
|
+
|
|
283
|
+
var configDraftPair = React.useState(null);
|
|
284
|
+
var configDraft = configDraftPair[0];
|
|
285
|
+
var setConfigDraft = configDraftPair[1];
|
|
286
|
+
|
|
287
|
+
var currentConfig = configDraft || serverConfig;
|
|
288
|
+
|
|
289
|
+
var configDirty = React.useMemo(function () {
|
|
290
|
+
if (!configDraft) return false;
|
|
291
|
+
if (configDraft.globalPreference !== serverConfig.globalPreference) return true;
|
|
292
|
+
for (var i = 0; i < LAYERS.length; i++) {
|
|
293
|
+
var l = LAYERS[i];
|
|
294
|
+
if (configDraft[l].mode !== serverConfig[l].mode) return true;
|
|
295
|
+
if (configDraft[l].maxBytes !== serverConfig[l].maxBytes) return true;
|
|
296
|
+
}
|
|
297
|
+
return false;
|
|
298
|
+
}, [configDraft, serverConfig]);
|
|
299
|
+
|
|
300
|
+
var setPreferenceDraft = function (pref) {
|
|
301
|
+
setConfigDraft(function (prev) {
|
|
302
|
+
var baseConfig = prev || serverConfig;
|
|
303
|
+
return Object.assign({}, baseConfig, { globalPreference: pref });
|
|
304
|
+
});
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
var writePolicyDraft = function (layer, next) {
|
|
308
|
+
setConfigDraft(function (prev) {
|
|
309
|
+
var baseConfig = prev || serverConfig;
|
|
310
|
+
var updated = Object.assign({}, baseConfig);
|
|
311
|
+
updated[layer] = { mode: next.mode, maxBytes: next.maxBytes };
|
|
312
|
+
return updated;
|
|
313
|
+
});
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
var saveConfig = function () {
|
|
317
|
+
if (!configDirty || busy || !writable) return;
|
|
318
|
+
var ops = [];
|
|
319
|
+
if (currentConfig.globalPreference !== serverConfig.globalPreference) {
|
|
320
|
+
ops.push({ op: "set", path: ["globalPreference"], value: currentConfig.globalPreference });
|
|
321
|
+
}
|
|
322
|
+
for (var i = 0; i < LAYERS.length; i++) {
|
|
323
|
+
var l = LAYERS[i];
|
|
324
|
+
if (currentConfig[l].mode !== serverConfig[l].mode || currentConfig[l].maxBytes !== serverConfig[l].maxBytes) {
|
|
325
|
+
ops.push({ op: "set", path: [l], value: currentConfig[l] });
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (ops.length === 0) {
|
|
329
|
+
setConfigDraft(null);
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
269
332
|
setBusy(true);
|
|
270
333
|
setNote(null);
|
|
271
334
|
props.mutate(ops, snapshot.revision).then(function (landed) {
|
|
272
335
|
setBusy(false);
|
|
273
|
-
|
|
336
|
+
if (landed) {
|
|
337
|
+
setConfigDraft(null);
|
|
338
|
+
setNote(t("toast.saved"));
|
|
339
|
+
} else {
|
|
340
|
+
setNote(t("toast.rejected"));
|
|
341
|
+
}
|
|
274
342
|
});
|
|
275
|
-
}, [props.mutate, snapshot.revision]);
|
|
276
|
-
|
|
277
|
-
var setPreference = function (pref) {
|
|
278
|
-
applyOps([{ op: "set", path: ["globalPreference"], value: pref }], t("toast.saved"));
|
|
279
343
|
};
|
|
280
344
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
applyOps([{ op: "set", path: [layer], value: next }], t("toast.saved"));
|
|
345
|
+
var resetConfig = function () {
|
|
346
|
+
setConfigDraft(null);
|
|
284
347
|
};
|
|
285
348
|
|
|
286
349
|
var renderPolicyRow = function (layer) {
|
|
287
|
-
var policy =
|
|
350
|
+
var policy = currentConfig[layer];
|
|
288
351
|
var rowKey = "policy." + layer;
|
|
289
352
|
return e(
|
|
290
353
|
"div",
|
|
@@ -305,7 +368,7 @@ window.__ModuleLoader__.load({
|
|
|
305
368
|
disabled: busy || !writable,
|
|
306
369
|
style: L.select,
|
|
307
370
|
onChange: function (event) {
|
|
308
|
-
|
|
371
|
+
writePolicyDraft(layer, { mode: event.target.value, maxBytes: policy.maxBytes });
|
|
309
372
|
}
|
|
310
373
|
},
|
|
311
374
|
e("option", { value: "unlimited" }, t("policy.mode.unlimited")),
|
|
@@ -326,7 +389,7 @@ window.__ModuleLoader__.load({
|
|
|
326
389
|
onChange: function (event) {
|
|
327
390
|
var next = Number(event.target.value);
|
|
328
391
|
if (!Number.isFinite(next) || next < 128) return;
|
|
329
|
-
|
|
392
|
+
writePolicyDraft(layer, { mode: policy.mode, maxBytes: Math.floor(next) });
|
|
330
393
|
}
|
|
331
394
|
}),
|
|
332
395
|
e("span", { style: L.hint }, t("policy.bytes"))
|
|
@@ -366,6 +429,31 @@ window.__ModuleLoader__.load({
|
|
|
366
429
|
e("h3", { style: { margin: "0", fontSize: "15px", fontWeight: "600", color: "var(--dsw-alias-label-primary)" } }, t("panel.title")),
|
|
367
430
|
e("p", { style: L.hint }, t("panel.description")),
|
|
368
431
|
|
|
432
|
+
e(
|
|
433
|
+
"div",
|
|
434
|
+
{ style: { display: "flex", justifyContent: "space-between", alignItems: "center", flexWrap: "wrap", gap: "8px", marginTop: "4px" } },
|
|
435
|
+
e("span", { style: L.title }, t("config.sectionTitle")),
|
|
436
|
+
e(
|
|
437
|
+
"div",
|
|
438
|
+
{ style: { display: "flex", alignItems: "center", gap: "8px" } },
|
|
439
|
+
configDirty ? e("span", { style: L.warn }, t("config.dirty")) : null,
|
|
440
|
+
configDirty
|
|
441
|
+
? e("button", {
|
|
442
|
+
type: "button",
|
|
443
|
+
disabled: busy || !writable,
|
|
444
|
+
style: L.select,
|
|
445
|
+
onClick: resetConfig
|
|
446
|
+
}, t("config.reset"))
|
|
447
|
+
: null,
|
|
448
|
+
e(P.Button, {
|
|
449
|
+
variant: "primary",
|
|
450
|
+
size: "sm",
|
|
451
|
+
disabled: busy || !configDirty || !writable,
|
|
452
|
+
onClick: saveConfig
|
|
453
|
+
}, t("config.save"))
|
|
454
|
+
)
|
|
455
|
+
),
|
|
456
|
+
|
|
369
457
|
e(
|
|
370
458
|
"div",
|
|
371
459
|
{ style: L.row },
|
|
@@ -378,10 +466,10 @@ window.__ModuleLoader__.load({
|
|
|
378
466
|
e(
|
|
379
467
|
"select",
|
|
380
468
|
{
|
|
381
|
-
value:
|
|
469
|
+
value: currentConfig.globalPreference,
|
|
382
470
|
disabled: busy || !writable,
|
|
383
471
|
style: L.select,
|
|
384
|
-
onChange: function (event) {
|
|
472
|
+
onChange: function (event) { setPreferenceDraft(event.target.value); }
|
|
385
473
|
},
|
|
386
474
|
e("option", { value: "auto" }, t("pref.auto")),
|
|
387
475
|
e("option", { value: "claude" }, t("pref.claude")),
|
package/lib/config.d.ts
CHANGED
|
@@ -120,12 +120,8 @@ export declare const Config: Schema<Schemastery.ObjectS<NoInfer<{
|
|
|
120
120
|
* 所以读取一律走 readVolatile,这里的类型只是"用户写下的形状"。
|
|
121
121
|
*/
|
|
122
122
|
export type Config = GranularInstructionsConfig;
|
|
123
|
-
/**
|
|
124
|
-
* 校验并合并默认配置,保证每个字段类型健全
|
|
125
|
-
*/
|
|
126
|
-
export declare function resolveConfig(rawConfig?: Partial<GranularInstructionsConfig>): GranularInstructionsConfig;
|
|
127
123
|
/** volatile 字段在宿主里是带 get() 的访问器,单测里也可能直接传裸值 */
|
|
128
|
-
interface VolatileRef<T> {
|
|
124
|
+
export interface VolatileRef<T> {
|
|
129
125
|
get(): T;
|
|
130
126
|
}
|
|
131
127
|
/**
|
|
@@ -134,9 +130,12 @@ interface VolatileRef<T> {
|
|
|
134
130
|
*/
|
|
135
131
|
export declare function readVolatile<T>(value: VolatileRef<T> | T | undefined): T | undefined;
|
|
136
132
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
133
|
+
* 校验并合并默认配置,保证每个字段类型健全。
|
|
134
|
+
* 深模块设计:原生吸收 volatile 访问器或普通对象,调用方无需在外部手动解包。
|
|
135
|
+
*/
|
|
136
|
+
export declare function resolveConfig(rawConfig?: unknown): GranularInstructionsConfig;
|
|
137
|
+
/**
|
|
138
|
+
* 兼容旧入口:统一委托给具备深层解包能力的 resolveConfig
|
|
139
139
|
*/
|
|
140
|
-
export declare
|
|
141
|
-
export {};
|
|
140
|
+
export declare const resolvePluginConfig: typeof resolveConfig;
|
|
142
141
|
//# sourceMappingURL=config.d.ts.map
|
package/lib/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,MAAM,MAAM,0BAA0B,CAAC;AAE9C,kBAAkB;AAClB,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAAC;AAEjE,iBAAiB;AACjB,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEzE,eAAe;AACf,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,IAAI,EAAE,YAAY,CAAC;IACnB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,aAAa;AACb,MAAM,WAAW,0BAA0B;IACzC;;;;;;OAMG;IACH,gBAAgB,EAAE,oBAAoB,CAAC;IACvC,gBAAgB;IAChB,YAAY,EAAE,gBAAgB,CAAC;IAC/B,yBAAyB;IACzB,mBAAmB,EAAE,gBAAgB,CAAC;IACtC,yBAAyB;IACzB,mBAAmB,EAAE,gBAAgB,CAAC;IACtC,gBAAgB;IAChB,oBAAoB,EAAE,gBAAgB,CAAC;CACxC;AAED,qCAAqC;AACrC,eAAO,MAAM,cAAc,EAAE,0BAkB5B,CAAC;AAKF;;;;GAIG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAkBjB,CAAC;AAEH;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,0BAA0B,CAAC;AAEhD
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,MAAM,MAAM,0BAA0B,CAAC;AAE9C,kBAAkB;AAClB,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAAC;AAEjE,iBAAiB;AACjB,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEzE,eAAe;AACf,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,IAAI,EAAE,YAAY,CAAC;IACnB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,aAAa;AACb,MAAM,WAAW,0BAA0B;IACzC;;;;;;OAMG;IACH,gBAAgB,EAAE,oBAAoB,CAAC;IACvC,gBAAgB;IAChB,YAAY,EAAE,gBAAgB,CAAC;IAC/B,yBAAyB;IACzB,mBAAmB,EAAE,gBAAgB,CAAC;IACtC,yBAAyB;IACzB,mBAAmB,EAAE,gBAAgB,CAAC;IACtC,gBAAgB;IAChB,oBAAoB,EAAE,gBAAgB,CAAC;CACxC;AAED,qCAAqC;AACrC,eAAO,MAAM,cAAc,EAAE,0BAkB5B,CAAC;AAKF;;;;GAIG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAkBjB,CAAC;AAEH;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,0BAA0B,CAAC;AAEhD,+CAA+C;AAC/C,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,GAAG,IAAI,CAAC,CAAC;CACV;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,GAAG,CAAC,GAAG,SAAS,CAKpF;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,0BAA0B,CAwC7E;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,sBAAgB,CAAC"}
|
package/lib/config.js
CHANGED
|
@@ -57,57 +57,51 @@ export const Config = Schema.object({
|
|
|
57
57
|
}).required(false).volatile()
|
|
58
58
|
});
|
|
59
59
|
/**
|
|
60
|
-
*
|
|
60
|
+
* 解开一个 volatile 字段:有 get() 就调用,否则原样返回。
|
|
61
|
+
* 单测与 headless 宿主可能传裸值,两种形态都要认。
|
|
62
|
+
*/
|
|
63
|
+
export function readVolatile(value) {
|
|
64
|
+
if (value && typeof value === 'object' && typeof value.get === 'function') {
|
|
65
|
+
return value.get();
|
|
66
|
+
}
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 校验并合并默认配置,保证每个字段类型健全。
|
|
71
|
+
* 深模块设计:原生吸收 volatile 访问器或普通对象,调用方无需在外部手动解包。
|
|
61
72
|
*/
|
|
62
73
|
export function resolveConfig(rawConfig) {
|
|
63
74
|
if (!rawConfig || typeof rawConfig !== 'object') {
|
|
64
75
|
return structuredClone(DEFAULT_CONFIG);
|
|
65
76
|
}
|
|
66
|
-
const
|
|
77
|
+
const raw = rawConfig;
|
|
78
|
+
const resolvePolicy = (rawPolicyInput, fallback) => {
|
|
79
|
+
const policy = readVolatile(rawPolicyInput);
|
|
67
80
|
if (!policy || typeof policy !== 'object') {
|
|
68
81
|
return { ...fallback };
|
|
69
82
|
}
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
|
|
83
|
+
const rawMode = readVolatile(policy.mode);
|
|
84
|
+
const mode = VALID_MODES.includes(rawMode) ? rawMode : fallback.mode;
|
|
85
|
+
const rawMaxBytes = readVolatile(policy.maxBytes);
|
|
86
|
+
const maxBytes = typeof rawMaxBytes === 'number' && rawMaxBytes > 0
|
|
87
|
+
? Math.floor(rawMaxBytes)
|
|
73
88
|
: fallback.maxBytes;
|
|
74
89
|
return { mode, maxBytes };
|
|
75
90
|
};
|
|
76
|
-
const
|
|
77
|
-
|
|
91
|
+
const rawPref = readVolatile(raw.globalPreference);
|
|
92
|
+
const globalPreference = VALID_PREFERENCES.includes(rawPref)
|
|
93
|
+
? rawPref
|
|
78
94
|
: DEFAULT_CONFIG.globalPreference;
|
|
79
95
|
return {
|
|
80
96
|
globalPreference,
|
|
81
|
-
globalPolicy: resolvePolicy(
|
|
82
|
-
projectClaudePolicy: resolvePolicy(
|
|
83
|
-
projectAgentsPolicy: resolvePolicy(
|
|
84
|
-
subdirectoriesPolicy: resolvePolicy(
|
|
97
|
+
globalPolicy: resolvePolicy(raw.globalPolicy, DEFAULT_CONFIG.globalPolicy),
|
|
98
|
+
projectClaudePolicy: resolvePolicy(raw.projectClaudePolicy, DEFAULT_CONFIG.projectClaudePolicy),
|
|
99
|
+
projectAgentsPolicy: resolvePolicy(raw.projectAgentsPolicy, DEFAULT_CONFIG.projectAgentsPolicy),
|
|
100
|
+
subdirectoriesPolicy: resolvePolicy(raw.subdirectoriesPolicy, DEFAULT_CONFIG.subdirectoriesPolicy)
|
|
85
101
|
};
|
|
86
102
|
}
|
|
87
103
|
/**
|
|
88
|
-
*
|
|
89
|
-
* 单测与 headless 宿主可能传裸值,两种形态都要认。
|
|
104
|
+
* 兼容旧入口:统一委托给具备深层解包能力的 resolveConfig
|
|
90
105
|
*/
|
|
91
|
-
export
|
|
92
|
-
if (value && typeof value === 'object' && typeof value.get === 'function') {
|
|
93
|
-
return value.get();
|
|
94
|
-
}
|
|
95
|
-
return value;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* 把宿主交给 apply 的原始配置解开成普通对象,再交给 resolveConfig 归一。
|
|
99
|
-
* 这是引擎唯一入口,保证四处 policy 都拿到确定的值。
|
|
100
|
-
*/
|
|
101
|
-
export function resolvePluginConfig(rawConfig) {
|
|
102
|
-
if (!rawConfig || typeof rawConfig !== 'object') {
|
|
103
|
-
return resolveConfig();
|
|
104
|
-
}
|
|
105
|
-
return resolveConfig({
|
|
106
|
-
globalPreference: readVolatile(rawConfig.globalPreference),
|
|
107
|
-
globalPolicy: readVolatile(rawConfig.globalPolicy),
|
|
108
|
-
projectClaudePolicy: readVolatile(rawConfig.projectClaudePolicy),
|
|
109
|
-
projectAgentsPolicy: readVolatile(rawConfig.projectAgentsPolicy),
|
|
110
|
-
subdirectoriesPolicy: readVolatile(rawConfig.subdirectoriesPolicy)
|
|
111
|
-
});
|
|
112
|
-
}
|
|
106
|
+
export const resolvePluginConfig = resolveConfig;
|
|
113
107
|
//# sourceMappingURL=config.js.map
|
package/lib/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,MAAM,MAAM,0BAA0B,CAAC;AA2C9C,qCAAqC;AACrC,MAAM,CAAC,MAAM,cAAc,GAA+B;IACxD,gBAAgB,EAAE,MAAM;IACxB,YAAY,EAAE;QACZ,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,MAAM;KACjB;IACD,mBAAmB,EAAE;QACnB,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,KAAK;KAChB;IACD,mBAAmB,EAAE;QACnB,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,KAAK;KAChB;IACD,oBAAoB,EAAE;QACpB,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,KAAK;KAChB;CACF,CAAC;AAEF,MAAM,WAAW,GAAmB,CAAC,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;AAC1E,MAAM,iBAAiB,GAA2B,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAEvF;;;;GAIG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAClC,gBAAgB,EAAE,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE;IAC5E,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC;QAC1B,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC/C,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;KACpD,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE;IAC7B,mBAAmB,EAAE,MAAM,CAAC,MAAM,CAAC;QACjC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC/C,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;KACpD,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE;IAC7B,mBAAmB,EAAE,MAAM,CAAC,MAAM,CAAC;QACjC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC/C,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;KACpD,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE;IAC7B,oBAAoB,EAAE,MAAM,CAAC,MAAM,CAAC;QAClC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC/C,QAAQ,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;KACpD,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE;CAC9B,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 渲染缓存失效判定:哪些工具执行结果会让 AGENTS.md/CLAUDE.md 的内容可能变化。
|
|
3
|
+
*
|
|
4
|
+
* tools/result 事件的真实签名是 (exec, result),工具名在 exec.name 上
|
|
5
|
+
* (dsh-tools/lib/types/events.d.ts:48 + contracts.d.ts 的 ToolExecution.name)。
|
|
6
|
+
* 旧实现读 event.tool.name 这类不存在的字段,判断恒为 false,缓存永不失效。
|
|
7
|
+
*/
|
|
8
|
+
/** 会改动工作区指令文件的工具。取自官方 dsh-tool-fs 注册清单。 */
|
|
9
|
+
export declare const FILE_WRITE_TOOLS: ReadonlySet<string>;
|
|
10
|
+
/**
|
|
11
|
+
* 判断一次工具执行是否应触发指令渲染缓存失效。
|
|
12
|
+
*
|
|
13
|
+
* @param exec - tools/result 的第一个参数(ToolExecution 快照)
|
|
14
|
+
* @returns 命中写工具时为 true;空输入或未知工具为 false
|
|
15
|
+
*/
|
|
16
|
+
export declare function shouldInvalidateCache(exec: {
|
|
17
|
+
name?: unknown;
|
|
18
|
+
} | undefined | null): boolean;
|
|
19
|
+
//# sourceMappingURL=cache-invalidation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-invalidation.d.ts","sourceRoot":"","sources":["../../src/engine/cache-invalidation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,2CAA2C;AAC3C,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAI/C,CAAA;AAEF;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAI1F"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 渲染缓存失效判定:哪些工具执行结果会让 AGENTS.md/CLAUDE.md 的内容可能变化。
|
|
3
|
+
*
|
|
4
|
+
* tools/result 事件的真实签名是 (exec, result),工具名在 exec.name 上
|
|
5
|
+
* (dsh-tools/lib/types/events.d.ts:48 + contracts.d.ts 的 ToolExecution.name)。
|
|
6
|
+
* 旧实现读 event.tool.name 这类不存在的字段,判断恒为 false,缓存永不失效。
|
|
7
|
+
*/
|
|
8
|
+
/** 会改动工作区指令文件的工具。取自官方 dsh-tool-fs 注册清单。 */
|
|
9
|
+
export const FILE_WRITE_TOOLS = new Set([
|
|
10
|
+
'write',
|
|
11
|
+
'edit',
|
|
12
|
+
'apply_patch',
|
|
13
|
+
]);
|
|
14
|
+
/**
|
|
15
|
+
* 判断一次工具执行是否应触发指令渲染缓存失效。
|
|
16
|
+
*
|
|
17
|
+
* @param exec - tools/result 的第一个参数(ToolExecution 快照)
|
|
18
|
+
* @returns 命中写工具时为 true;空输入或未知工具为 false
|
|
19
|
+
*/
|
|
20
|
+
export function shouldInvalidateCache(exec) {
|
|
21
|
+
if (exec === undefined || exec === null)
|
|
22
|
+
return false;
|
|
23
|
+
const name = exec.name;
|
|
24
|
+
return typeof name === 'string' && FILE_WRITE_TOOLS.has(name);
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=cache-invalidation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-invalidation.js","sourceRoot":"","sources":["../../src/engine/cache-invalidation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,2CAA2C;AAC3C,MAAM,CAAC,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC;IAC3D,OAAO;IACP,MAAM;IACN,aAAa;CACd,CAAC,CAAA;AAEF;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAA2C;IAC/E,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,KAAK,CAAA;IACrD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;IACtB,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;AAC/D,CAAC"}
|