@wenaixi/dsh-ponytail 5.3.2 → 5.4.0
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 +30 -1
- package/README.md +75 -109
- package/README.zh-CN.md +124 -0
- package/lib/client.js +9 -5
- package/lib/ponytail-commands.d.ts +29 -3
- package/lib/ponytail-commands.d.ts.map +1 -1
- package/lib/ponytail-commands.js +123 -19
- package/lib/ponytail-commands.js.map +1 -1
- package/lib/ponytail-instructions.d.ts +7 -1
- package/lib/ponytail-instructions.d.ts.map +1 -1
- package/lib/ponytail-instructions.js +45 -1
- package/lib/ponytail-instructions.js.map +1 -1
- package/lib/ponytail-remote.d.ts.map +1 -1
- package/lib/ponytail-remote.js.map +1 -1
- package/lib/ponytail-state.d.ts +24 -0
- package/lib/ponytail-state.d.ts.map +1 -1
- package/lib/ponytail-state.js +150 -6
- package/lib/ponytail-state.js.map +1 -1
- package/lib/ponytail.d.ts.map +1 -1
- package/lib/ponytail.js +27 -45
- package/lib/ponytail.js.map +1 -1
- package/locale/en.json +4 -3
- package/locale/zh.json +4 -3
- package/package.json +12 -5
- package/AGENTS.md +0 -32
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
## [Unreleased]
|
|
2
|
+
|
|
3
|
+
## [5.4.0] - 2026-10-09
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- 模式切换零缓存破坏机制(对齐官方 `renderCatalogUpdate` 范式,ADR-0012):
|
|
8
|
+
- 顶层 SystemPrompt(`order: 50`)在会话生命周期内绝对锁定初始 `baselineMode`,会话期间前缀文本逐字节完全恒定,100% 保护历史 KV Cache / Prompt Cache 命中率;
|
|
9
|
+
- 模式切换(会话内命令切档或全局默认档变更)统一通过 `agent/pre-step` 瀑布流拦截点在当前最新轮次用户消息末尾追加一次带有 `<system-reminder>` 的更新通知(`renderModeUpdate`),后续未切档轮次幂等稳定,绝不重复追加;
|
|
10
|
+
- 状态管理器引入 `SessionModeState`,支持访问序 LRU 淘汰(上限 100 会话)与 `explicitlySet` 显式设置意图守卫,全局修改不覆盖用户显式锁定的会话,新会话以新全局档纯净启动。
|
|
11
|
+
- 轮次拦截生命周期深模块 `TurnCoordinator`(ADR-0013):
|
|
12
|
+
- 完整封装消息纯文本提取、指令语法解析、下游 waterfall 穿透、变动对比、原地替换/追加与发射标记落盘 7 步调用流;
|
|
13
|
+
- 严格捍卫不断链、KV Cache 零破坏、单通知幂等、发射标记收敛时机、多会话隔离与只读安全 6 大不变量;
|
|
14
|
+
- 宿主入口 `src/ponytail.ts` 消除 90+ 行底层消息拼接胶水代码,大幅提升 Locality 与 Leverage。
|
|
15
|
+
- 提示词引擎唯一生产出口收敛 `renderPromptSection`(ADR-0013):
|
|
16
|
+
- 扩展方法签名,在模块内部自洽接管会话基线锁定与无会话降级判定,修复名存实亡的单出口裂痕;
|
|
17
|
+
- 坚决杜绝类内部内存模板缓存,严守 ADR-0003 同步直读铁律。
|
|
18
|
+
- 存储适配器全虚拟化 `StateStorageAdapter`(ADR-0013):
|
|
19
|
+
- 扩展 `PonytailStorage` 契约,支持会话状态持久化映射解耦;
|
|
20
|
+
- 导出 `createMemoryStorage` 纯内存适配器,使单元测试物理零触碰磁盘,彻底消除测试脏文件残留与并发竞争。
|
|
21
|
+
- 行为测试套件扩充至 **107 项全绿**:
|
|
22
|
+
- 新增 C27(TurnCoordinator 端到端拦截与幂等性)、C28(会话事件兜底通道)与 C29(内存存储适配器纯内存隔离)回归锁。
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- 技能描述语言控件的「跟随宿主(自动)」段改为常驻:此前该段按「补丁是否已写 `skillDescriptionLang`」条件追加,用户手动锁过一次中文或英文后该段消失,无法再切回跟随宿主,只能在中英之间横跳。「跟随宿主」是三态之一而非一次性占位选项,因此三段恒定、选中值只反映配置态。
|
|
27
|
+
- 清理 `src/ponytail-remote.ts` 与 `src/ponytail.ts` 中的死导入(`readdirSync`、`dirname`、`join`、`parseYaml`),精简依赖树。
|
|
28
|
+
|
|
1
29
|
## [5.3.2] - 2026-10-06
|
|
2
30
|
|
|
3
31
|
### Documentation
|
|
@@ -255,7 +283,8 @@
|
|
|
255
283
|
|
|
256
284
|
- 首个 DSH 移植版本:单一插件包,`dsh.bundle.patch` 挂载,`PONYTAIL_DEFAULT_MODE` 三级回退(`review` 不可作默认),全部文案中文化,触发词兼容中英文。
|
|
257
285
|
|
|
258
|
-
[Unreleased]: https://github.com/Wenaixi/dsh-ponytail/compare/v5.
|
|
286
|
+
[Unreleased]: https://github.com/Wenaixi/dsh-ponytail/compare/v5.4.0...HEAD
|
|
287
|
+
[5.4.0]: https://github.com/Wenaixi/dsh-ponytail/compare/v5.3.2...v5.4.0
|
|
259
288
|
[5.3.2]: https://github.com/Wenaixi/dsh-ponytail/compare/v5.3.1...v5.3.2
|
|
260
289
|
[5.3.1]: https://github.com/Wenaixi/dsh-ponytail/compare/v5.3.0...v5.3.1
|
|
261
290
|
[5.3.0]: https://github.com/Wenaixi/dsh-ponytail/compare/v5.2.0...v5.3.0
|
package/README.md
CHANGED
|
@@ -1,160 +1,126 @@
|
|
|
1
1
|
# dsh-ponytail
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
[English](./README.md) | [简体中文](./README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@wenaixi/dsh-ponytail)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
8
|
+
[](https://nodejs.org)
|
|
9
|
+
[](https://pnpm.io)
|
|
6
10
|
|
|
7
11
|
<p align="center">
|
|
8
|
-
|
|
12
|
+
<img src="./assets/logo.png" alt="@wenaixi/dsh-ponytail" width="128" height="128"><br/>
|
|
9
13
|
<em>The best code is the code you never wrote.</em>
|
|
10
14
|
</p>
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-111111?style=flat-square" alt="MIT"/></a>
|
|
14
|
-
<a href="https://www.npmjs.com/package/@wenaixi/dsh-ponytail"><img src="https://img.shields.io/npm/v/@wenaixi/dsh-ponytail?color=111111&style=flat-square" alt="npm"/></a>
|
|
15
|
-
</p>
|
|
16
|
+
A DeepSeek Harness (DSH) port of [DietrichGebert/ponytail](https://github.com/DietrichGebert/ponytail), maintained independently (ADR-0010). Injects the 7-rung ladder directly into system prompts, provides 6 specialized skills, and registers zero tools.
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
<a href="CHANGELOG.md">Changelog</a> ·
|
|
19
|
-
<a href="https://github.com/DietrichGebert/ponytail">上游</a> ·
|
|
20
|
-
<a href="https://www.npmjs.com/package/@wenaixi/dsh-ponytail">npm</a>
|
|
21
|
-
</p>
|
|
18
|
+
## What it is
|
|
22
19
|
|
|
23
|
-
|
|
20
|
+
A counter-weight to LLM boilerplate and over-engineering: deletion over addition, boring over clever, and fewest files possible. Challenge requirements before writing code (YAGNI), prioritize existing functions and standard libraries, and solve in one line when possible.
|
|
24
21
|
|
|
25
|
-
|
|
22
|
+
Features a **Zero Cache Miss Architecture** (ADR-0012): session baseline is locked permanently, and dynamic intensity switches take effect via turn-end reminders, leaving historical prompt / KV cache 100% untouched across long conversations. Ships as a pure `dsh.bundle`, writes zero garbage to your home root, uninstalls cleanly, and rebuilds itself through HMR.
|
|
26
23
|
|
|
27
|
-
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
Needs the DSH runtime (`npm i -g @deepseek-ai/dsh`). Node and pnpm floors are in the badges above. Examples use the `web` profile; substitute your own profile name.
|
|
28
27
|
|
|
29
28
|
```bash
|
|
29
|
+
# Install (automatic HMR reload)
|
|
30
30
|
dsh plugin --profile web add @wenaixi/dsh-ponytail
|
|
31
|
-
dsh plugin --profile web remove @wenaixi/dsh-ponytail
|
|
32
|
-
dsh --profile web --dump-config | grep -A2 ponytail
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
`WARN missing peer @deepseek-ai/...` 是正常的,peer 由 DSH 运行时提供。看到 `Packages: +2 Done` 就是装好了。
|
|
36
|
-
|
|
37
|
-
若插件卡片只有包名、没有标题描述图标,说明包的 `exports` 没放行 `./package.json` 与 `./locale/*.json`。这是 DSH 读取展示元信息的硬约束,与安装本身无关。
|
|
38
31
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
支持完全零配置热安装。`dsh plugin add` 将插件包登记至 `package.json` 与 bundle 列表后,宿主 HMR 会自动重载 Loader 树并挂载配置卡片:
|
|
32
|
+
# Remove
|
|
33
|
+
dsh plugin --profile web remove @wenaixi/dsh-ponytail
|
|
42
34
|
|
|
43
|
-
|
|
44
|
-
dsh
|
|
35
|
+
# Inspect composed patch tree
|
|
36
|
+
dsh --profile web --dump-config | grep -A2 ponytail
|
|
45
37
|
```
|
|
46
38
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
说明:
|
|
50
|
-
- 首次安装无需重启宿主,刷新浏览器即可。
|
|
51
|
-
- 原地更新已安装版本时,宿主受条目指纹冻结机制限制,建议重启宿主或通过卸载后重新安装加载新产物。
|
|
52
|
-
|
|
53
|
-
## 用法
|
|
39
|
+
## Usage
|
|
54
40
|
|
|
55
41
|
```
|
|
56
|
-
/ponytail
|
|
57
|
-
/ponytail lite
|
|
58
|
-
/ponytail ultra
|
|
59
|
-
/ponytail off
|
|
60
|
-
/ponytail default lite
|
|
61
|
-
stop ponytail
|
|
42
|
+
/ponytail Switch to full mode (all 7 rungs active)
|
|
43
|
+
/ponytail lite Do the bare minimum
|
|
44
|
+
/ponytail ultra Challenge the requirement itself first
|
|
45
|
+
/ponytail off Disable injection
|
|
46
|
+
/ponytail default lite Persist default across sessions
|
|
47
|
+
stop ponytail Equivalent to off (exact match)
|
|
62
48
|
```
|
|
63
49
|
|
|
64
|
-
|
|
50
|
+
Intensity levels reset on each new session according to `env > Profile patch > fallback full`. Therefore, `/ponytail <level>` is session-scoped. To persist across restarts and new sessions, use `/ponytail default <level>`.
|
|
65
51
|
|
|
66
|
-
|
|
52
|
+
### Zero Cache Miss Architecture
|
|
67
53
|
|
|
68
|
-
|
|
69
|
-
| --- | --- |
|
|
70
|
-
| `/ponytail-review` | 只看 diff,找能删的东西 |
|
|
71
|
-
| `/ponytail-audit` | 全仓审计,按可删收益排序 |
|
|
72
|
-
| `/ponytail-debt` | 收割 `ponytail:` 注释列成待办 |
|
|
73
|
-
| `/ponytail-gain` | 收益看板 |
|
|
74
|
-
| `/ponytail-help` | 速查卡 |
|
|
54
|
+
When switching intensity levels within an ongoing session or updating global default configurations, the top-level SystemPrompt baseline remains **strictly byte-identical and static**.
|
|
75
55
|
|
|
76
|
-
|
|
56
|
+
Mode transitions take effect dynamically by appending an incremental system notification (`<system-reminder>`) at the end of the current turn's user message (aligned with the official `dsh-tool-skill` catalog update pattern, ADR-0012). This **100% protects historical KV Cache / Prompt Cache** across all multi-turn conversation history, eliminating costly prefill recalculations and latency spikes.
|
|
77
57
|
|
|
78
|
-
|
|
79
|
-
dsh --profile web '<任务>'
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## 技能正文与描述语言
|
|
83
|
-
|
|
84
|
-
技能正文是上游 DietrichGebert/ponytail v4.10.3 的英文原文,按 tag 逐文件取回。两处内容对 DSH
|
|
85
|
-
不适用,已就地改写为真实落点:`ponytail-gain` 的数据来源指向 `assets/*.svg`(本仓无上游的
|
|
86
|
-
`benchmarks/`),`ponytail-help` 的配置与更新章节改为 profile 补丁与 `dsh plugin`。
|
|
58
|
+
## Skills
|
|
87
59
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
`
|
|
92
|
-
|
|
60
|
+
| Skill | Description |
|
|
61
|
+
|---|---|
|
|
62
|
+
| `/ponytail` | Core mode: 7-rung ladder, lazy senior dev mindset |
|
|
63
|
+
| `/ponytail-review` | Over-engineering code review: hunt for code that can be deleted |
|
|
64
|
+
| `/ponytail-audit` | Whole-repo complexity audit, ranked by deletion yield |
|
|
65
|
+
| `/ponytail-debt` | Harvest `ponytail:` comments into an actionable debt ledger |
|
|
66
|
+
| `/ponytail-gain` | Minimal metrics dashboard showing code reduction benchmarks |
|
|
67
|
+
| `/ponytail-help` | Quick reference card for modes, commands, and skills |
|
|
93
68
|
|
|
94
|
-
|
|
95
|
-
超长会在模型目录里被截断,`verify.mjs` 对两册都断言。
|
|
69
|
+
## Skill Bodies and Description Languages
|
|
96
70
|
|
|
97
|
-
|
|
71
|
+
Skill bodies are retrieved directly from upstream DietrichGebert/ponytail v4.10.3 in verbatim English. Two host-incompatible details are tailored for DSH: `ponytail-gain` data sources point to `assets/*.svg` (as upstream `benchmarks/` is excluded), and `ponytail-help` configuration and update sections reference profile patches and `dsh plugin`.
|
|
98
72
|
|
|
99
|
-
|
|
73
|
+
Model catalog views and configuration forms share the exact same description string, governed by `skillDescriptionLang` (three-state: explicit Chinese `zh` / explicit English `en` / unconfigured `auto`). When unconfigured, it follows the host's `locale.preference` (English triggers English alignment; others default to Chinese). Explicit selection locks the language. Canonical descriptions reside in `skills/descriptions.zh.json` and `skills/descriptions.en.json`, served live via `ctx.remote.ponytail.snapshot()`.
|
|
100
74
|
|
|
101
|
-
|
|
75
|
+
## Configuration Panel
|
|
102
76
|
|
|
103
|
-
|
|
77
|
+
The card detail view provides an embedded settings panel: intensity level control, independent toggle switches for all 6 skills, a one-click reset button, and a 3-tier priority diagnostic chain displaying environment variables, profile patches, and built-in fallbacks with their active hit states.
|
|
104
78
|
|
|
105
|
-
|
|
106
|
-
| --- | --- | --- |
|
|
107
|
-
| `ctx.configForms.get('ponytail')` | 默认档、技能启用列表,写入自带 revision 冲突检测 | `profiles/<name>/cordis.patch.yml` |
|
|
108
|
-
| `ctx.remote.ponytail.snapshot()` | 当前生效等级、三级诊断链,只读 | 不落盘,按需拉取 |
|
|
79
|
+
The level segmented control reflects only the actual persisted configuration. When `defaultMode` is not configured in the patch, the control highlights the appended `unset` segment. The currently active runtime level is displayed distinctly in the diagnostic header text.
|
|
109
80
|
|
|
110
|
-
|
|
81
|
+
Configuration reads and writes use two official DSH channels:
|
|
111
82
|
|
|
112
|
-
|
|
83
|
+
| Channel | Scope | Target |
|
|
84
|
+
|---|---|---|
|
|
85
|
+
| `ctx.configForms.get('ponytail')` | Default level & disabled skills with revision conflict checking | `profiles/<name>/cordis.patch.yml` |
|
|
86
|
+
| `ctx.remote.ponytail.snapshot()` | Active runtime level & 3-tier diagnostic chain (read-only) | In-memory RPC |
|
|
113
87
|
|
|
114
|
-
|
|
115
|
-
| --- | --- | --- |
|
|
116
|
-
| 新装 | 否,刷新浏览器即可 | 宿主检测到新增条目,投递新的产物指纹 |
|
|
117
|
-
| 更新 | 是 | 条目 `rev` 在进程启动时算好就冻结,运行中替换文件不触发重算 |
|
|
118
|
-
| 卸载 | 否,但补丁条目要手工删 | `dsh plugin remove` 清 `package.json`、bundles 与物理包,不删 `cordis.patch.yml` 的条目 |
|
|
88
|
+
Profiles lacking a full UI service bundle (headless, CLI) fall back gracefully to `profiles/<name>/ponytail/config.json`. Legacy configurations from `$DSH_HOME/ponytail/config.json` are migrated once into profile patches upon initial boot and renamed to `.imported`.
|
|
119
89
|
|
|
120
|
-
|
|
90
|
+
## Upstream Mapping
|
|
121
91
|
|
|
122
|
-
|
|
92
|
+
The six hooks from upstream `hooks/` are consolidated into a single DSH Cordis plugin:
|
|
123
93
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
上游 `hooks/` 的六个 Hook 合并进单一 DSH 插件:
|
|
127
|
-
|
|
128
|
-
| 上游 | DSH 侧 |
|
|
129
|
-
| --- | --- |
|
|
94
|
+
| Upstream | DSH Implementation |
|
|
95
|
+
|---|---|
|
|
130
96
|
| `ponytail-config.js` | `src/ponytail-config.ts` |
|
|
131
|
-
| `ponytail-instructions.js` | `src/ponytail-instructions.ts
|
|
132
|
-
| `ponytail-state.js` | `src/ponytail-state.ts
|
|
133
|
-
| `ponytail-activate.js` | `src/ponytail.ts`
|
|
134
|
-
| `ponytail-mode-tracker.js` | `src/ponytail-commands.ts`
|
|
135
|
-
| `ponytail-subagent.js` | `src/ponytail.ts`
|
|
97
|
+
| `ponytail-instructions.js` | `src/ponytail-instructions.ts` (single entrypoint `renderPromptSection`) |
|
|
98
|
+
| `ponytail-state.js` | `src/ponytail-state.ts` (flag file I/O, session baseline manager, reload) |
|
|
99
|
+
| `ponytail-activate.js` | `src/ponytail.ts` (`agent/created` hook) |
|
|
100
|
+
| `ponytail-mode-tracker.js` | `src/ponytail-commands.ts` (`createCommandDispatcher`) |
|
|
101
|
+
| `ponytail-subagent.js` | `src/ponytail.ts` (`agent/created`, `PONYTAIL_SUBAGENT_MATCHER`) |
|
|
136
102
|
|
|
137
|
-
|
|
103
|
+
Prompts are injected via `systemPrompt.section('ponytail')` at `order: 50`, positioned neatly between `persona` (0) and tools (100). When switched to `off`, prompt rendering overhead is zero. Flags and configurations are scoped per profile directory, ensuring full multi-instance isolation.
|
|
138
104
|
|
|
139
|
-
##
|
|
105
|
+
## Development
|
|
140
106
|
|
|
141
107
|
```bash
|
|
142
108
|
pnpm typecheck # tsc --noEmit
|
|
143
|
-
pnpm build # tsc
|
|
144
|
-
node scripts/verify.mjs #
|
|
145
|
-
node scripts/docs-verify.mjs #
|
|
146
|
-
node scripts/behavior.test.mjs #
|
|
109
|
+
pnpm build # tsc into lib/, scripts/build-client.mjs generates lib/client.js
|
|
110
|
+
node scripts/verify.mjs # Static contract gates: artifacts, skills, zero tools, slots, locales
|
|
111
|
+
node scripts/docs-verify.mjs # Documentation and version consistency gates
|
|
112
|
+
node scripts/behavior.test.mjs # Behavioral test suite (107 tests pass)
|
|
147
113
|
|
|
148
|
-
dsh --profile web --patch ./cordis.patch.yml --dump-config #
|
|
149
|
-
pnpm dsh web --patch ./cordis.patch.yml #
|
|
114
|
+
dsh --profile web --patch ./cordis.patch.yml --dump-config # Verify patch parsing
|
|
115
|
+
pnpm dsh web --patch ./cordis.patch.yml # Hot reload dev runner
|
|
150
116
|
```
|
|
151
117
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
发布只走 tag 触发的 CI。严禁本地 `npm publish`,push 与打 tag 都需要明确授权。
|
|
118
|
+
## License
|
|
155
119
|
|
|
156
|
-
|
|
120
|
+
MIT. Full text in [LICENSE](./LICENSE).
|
|
157
121
|
|
|
158
|
-
##
|
|
122
|
+
## Credits
|
|
159
123
|
|
|
160
|
-
[
|
|
124
|
+
- Upstream [DietrichGebert/ponytail](https://github.com/DietrichGebert/ponytail)
|
|
125
|
+
- [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) for the plugin architecture and runtime
|
|
126
|
+
- [dsh-plugin-dev](https://github.com/Wenaixi/dsh-plugin-dev) for DSH plugin development patterns and architectural guidelines
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# dsh-ponytail
|
|
2
|
+
|
|
3
|
+
[English](./README.md) | [简体中文](./README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@wenaixi/dsh-ponytail)
|
|
6
|
+
[](./LICENSE)
|
|
7
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
8
|
+
[](https://nodejs.org)
|
|
9
|
+
[](https://pnpm.io)
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<img src="./assets/logo.png" alt="@wenaixi/dsh-ponytail" width="128" height="128"><br/>
|
|
13
|
+
<em>最优秀的代码,就是你从未写出的代码。</em>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
[DietrichGebert/ponytail](https://github.com/DietrichGebert/ponytail) 的 DeepSeek Harness (DSH) 移植版,独立维护(ADR-0010)。把著名的七阶梯子直接注入系统提示词,提供 6 个原生技能,不注册任何模型 tool。
|
|
17
|
+
|
|
18
|
+
## 是什么
|
|
19
|
+
|
|
20
|
+
对抗 AI 样板代码与过度工程的解药:删减优于新增,平实优于精巧,文件越少越好。动手写代码前先质疑需求是否该存在(YAGNI),优先复用标准库与现有代码,能写一行就绝不写五十行。
|
|
21
|
+
|
|
22
|
+
具备**全场景零缓存破坏架构**(ADR-0012):会话初始基线终身锁定,动态切档通过当前轮次末尾追加系统提醒生效,长对话历史 Prompt Cache / KV 缓存 **100% 保持命中**。以纯净 `dsh.bundle` 交付,不往用户目录写垃圾文件,卸载干净,HMR 自动热重载。
|
|
23
|
+
|
|
24
|
+
## 安装
|
|
25
|
+
|
|
26
|
+
需要 DSH 运行时(`npm i -g @deepseek-ai/dsh`),Node 与 pnpm 的版本要求见上方徽章。示例以 `web` profile 为例,换成你自己的 profile 名字即可。
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# 安装(自动触发 HMR 热重载)
|
|
30
|
+
dsh plugin --profile web add @wenaixi/dsh-ponytail
|
|
31
|
+
|
|
32
|
+
# 卸载
|
|
33
|
+
dsh plugin --profile web remove @wenaixi/dsh-ponytail
|
|
34
|
+
|
|
35
|
+
# 检查合成配置树
|
|
36
|
+
dsh --profile web --dump-config | grep -A2 ponytail
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 用法
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
/ponytail 切到 full(七阶梯子全开)
|
|
43
|
+
/ponytail lite 只做最低限度
|
|
44
|
+
/ponytail ultra 先挑战需求本身
|
|
45
|
+
/ponytail off 关闭注入
|
|
46
|
+
/ponytail default lite 跨会话持久化
|
|
47
|
+
stop ponytail 同 off,整句匹配
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
等级在每次会话启动时按 `env > Profile 补丁 > 内置兜底 full` 重置,所以 `/ponytail <档>` 只在本会话有效,跨会话要写 `/ponytail default <档>`。
|
|
51
|
+
|
|
52
|
+
### 零缓存破坏特性 (Prompt Cache Friendly)
|
|
53
|
+
|
|
54
|
+
会话内切档或全局改配置时,顶层系统提示词基线严格保持静态恒定,切换指令通过当前轮次用户消息末尾的 `<system-reminder>` 增量追加生效(对齐官方技能目录更新范式,ADR-0012),**100% 保护长对话的历史 Prompt Cache / KV 缓存**,零重算延迟,零多余 Token 消耗。
|
|
55
|
+
|
|
56
|
+
## 包含技能
|
|
57
|
+
|
|
58
|
+
| 技能 | 作用 |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `/ponytail` | 核心模式:七阶梯子、懒人资深工程师守则 |
|
|
61
|
+
| `/ponytail-review` | 猎杀复杂度代码评审:只看 diff,找能删的东西 |
|
|
62
|
+
| `/ponytail-audit` | 全仓过度设计审计:按可删收益排序 |
|
|
63
|
+
| `/ponytail-debt` | 收割 `ponytail:` 注释列成待办台账 |
|
|
64
|
+
| `/ponytail-gain` | 精简收益看板:实测代码缩减比例 |
|
|
65
|
+
| `/ponytail-help` | 模式、命令与技能速查卡 |
|
|
66
|
+
|
|
67
|
+
## 技能正文与描述语言
|
|
68
|
+
|
|
69
|
+
技能正文是上游 DietrichGebert/ponytail v4.10.3 的英文原文,按 tag 逐文件取回。两处内容对 DSH 不适用,已就地改写为真实落点:`ponytail-gain` 的数据来源指向 `assets/*.svg`(本仓无上游的 `benchmarks/`),`ponytail-help` 的配置与更新章节改为 profile 补丁与 `dsh plugin`。
|
|
70
|
+
|
|
71
|
+
模型目录与配置面板看到的是同一个描述字符串,语言由 `skillDescriptionLang` 决定(三态:显式中文 `zh` / 显式英文 `en` / 未配置 `auto`)。未配置时跟随宿主语言 `locale.preference` 的显式选择(仅英文触发对齐,其余兜底中文);显式选择即锁定。两套描述的真源是 `skills/descriptions.zh.json` 与 `skills/descriptions.en.json`,经 `ctx.remote.ponytail.snapshot()` 下发。
|
|
72
|
+
|
|
73
|
+
## 配置面板
|
|
74
|
+
|
|
75
|
+
已安装插件的卡片详情内嵌配置面板:运行等级、6 个技能的独立开关、一键恢复默认,外加一条三级优先级诊断链,逐行显示环境变量、Profile 补丁、内置兜底各自的值与生效状态。
|
|
76
|
+
|
|
77
|
+
等级控件只显示补丁里真实配置的档。补丁没写 `defaultMode` 时选中末尾追加的「未设置」段,「当前生效」由诊断链顶部的文字给出。
|
|
78
|
+
|
|
79
|
+
读写走两条官方通道:
|
|
80
|
+
|
|
81
|
+
| 通道 | 内容 | 落点 |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| `ctx.configForms.get('ponytail')` | 默认档、技能启用列表,写入自带 revision 冲突检测 | `profiles/<name>/cordis.patch.yml` |
|
|
84
|
+
| `ctx.remote.ponytail.snapshot()` | 当前生效等级、三级诊断链,只读 | In-memory RPC |
|
|
85
|
+
|
|
86
|
+
无 Profile 上下文的组合(headless、CLI)没有 Settings 服务,配置读写回退到 `profiles/<name>/ponytail/config.json`。从旧版本升级时,全局的 `$DSH_HOME/ponytail/config.json` 首次启动时一次性导入 Profile 补丁,旧文件随后被改名 `.imported`。
|
|
87
|
+
|
|
88
|
+
## 上游映射
|
|
89
|
+
|
|
90
|
+
上游 `hooks/` 的六个 Hook 合并进单一 DSH 插件:
|
|
91
|
+
|
|
92
|
+
| 上游 | DSH 侧 |
|
|
93
|
+
|---|---|
|
|
94
|
+
| `ponytail-config.js` | `src/ponytail-config.ts` |
|
|
95
|
+
| `ponytail-instructions.js` | `src/ponytail-instructions.ts` (单一出口 `renderPromptSection`) |
|
|
96
|
+
| `ponytail-state.js` | `src/ponytail-state.ts` (flag 文件存取、会话基线管理、重载) |
|
|
97
|
+
| `ponytail-activate.js` | `src/ponytail.ts` (`agent/created` 钩子) |
|
|
98
|
+
| `ponytail-mode-tracker.js` | `src/ponytail-commands.ts` (`createCommandDispatcher`) |
|
|
99
|
+
| `ponytail-subagent.js` | `src/ponytail.ts` (`agent/created`, `PONYTAIL_SUBAGENT_MATCHER`) |
|
|
100
|
+
|
|
101
|
+
提示词经 `systemPrompt.section('ponytail')` 注入,`order: 50` 落在 persona(0) 与工具(100) 之间。切换到 `off` 时,提示词生成零成本。标志文件与配置同源持久化在当前 profile 内,同机多实例互不干扰。
|
|
102
|
+
|
|
103
|
+
## 开发与门禁
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
pnpm typecheck # tsc --noEmit
|
|
107
|
+
pnpm build # tsc 出 lib/,再由 build-client.mjs 生成 lib/client.js
|
|
108
|
+
node scripts/verify.mjs # 静态门禁:产物、技能、零 tool、UI 落点、locale 键集
|
|
109
|
+
node scripts/docs-verify.mjs # 版本策略与双语文档一致性
|
|
110
|
+
node scripts/behavior.test.mjs # 行为测试 (107 项全通)
|
|
111
|
+
|
|
112
|
+
dsh --profile web --patch ./cordis.patch.yml --dump-config # 验证补丁解析
|
|
113
|
+
pnpm dsh web --patch ./cordis.patch.yml # 热重载联调
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## 协议
|
|
117
|
+
|
|
118
|
+
MIT,详见 [LICENSE](./LICENSE)。
|
|
119
|
+
|
|
120
|
+
## 致谢
|
|
121
|
+
|
|
122
|
+
- 上游 [DietrichGebert/ponytail](https://github.com/DietrichGebert/ponytail)
|
|
123
|
+
- [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 的插件架构与运行底座
|
|
124
|
+
- [dsh-plugin-dev](https://github.com/Wenaixi/dsh-plugin-dev) 提供的 DSH 插件开发架构规范与权威开发指南
|
package/lib/client.js
CHANGED
|
@@ -12,8 +12,8 @@ window.__ModuleLoader__.load({
|
|
|
12
12
|
// 官方 locale 接入:注册 ponytail 命名空间双语字典(真源 locale/*.json,构建期内嵌)
|
|
13
13
|
// 技能描述不翻译(用户边界):由 configForms 快照与快照通道下发,字典不含技能描述键
|
|
14
14
|
var NS = "ponytail";
|
|
15
|
-
var ZH = {"button.reset":"恢复默认配置","chain.hit":"生效中","chain.shadowed":"被覆盖","chain.unset":"未设置","chain.valueUnset":"(未设置)","confirm.reset":"确定恢复默认配置吗?等级回到标准(full),并重新启用全部 6 个技能。","error.operation":"操作失败:","error.rejected":"本部署没有接受这次修改,值已保留供你核对。","lang.auto":"跟随宿主(自动)","lang.changed":"技能描述语言已切为「{name}」","lang.en":"English","lang.followHost":"已切为跟随宿主语言","lang.title":"
|
|
16
|
-
var EN = {"button.reset":"Restore defaults","chain.hit":"In effect","chain.shadowed":"Shadowed","chain.unset":"Unset","chain.valueUnset":"(unset)","confirm.reset":"Restore default config? Level returns to Standard (full) and all 6 skills are re-enabled.","error.operation":"Operation failed: ","error.rejected":"This deployment did not accept the change; your value was kept for you to review.","lang.auto":"Follow host (auto)","lang.changed":"Skill description language switched to {name}","lang.en":"English","lang.followHost":"Now following the host language","lang.title":"Skill
|
|
15
|
+
var ZH = {"button.reset":"恢复默认配置","chain.hit":"生效中","chain.shadowed":"被覆盖","chain.unset":"未设置","chain.valueUnset":"(未设置)","confirm.reset":"确定恢复默认配置吗?等级回到标准(full),并重新启用全部 6 个技能。","error.operation":"操作失败:","error.rejected":"本部署没有接受这次修改,值已保留供你核对。","lang.auto":"跟随宿主(自动)","lang.changed":"技能描述语言已切为「{name}」","lang.en":"English","lang.followHost":"已切为跟随宿主语言","lang.note":"仅控制输入「/」唤出时展示的技能介绍(用户与模型可见),技能正文保持英文原版。","lang.title":"技能介绍语言(用户「/」唤出菜单及模型可见)","lang.unsetHint":"未配置:当前跟随宿主语言({lang}),可在上方显式切换。仅控制「/」唤出时展示的技能介绍(用户与模型可见),技能正文保持英文原版。","lang.zh":"中文","level.env":"环境变量","level.fallback":"内置兜底","level.patch":"Profile 补丁","meta":{"title":"懒人模式","description":"DietrichGebert/ponytail 懒人 senior 模式与七阶梯子完美移植,6 个技能描述双语自由切换,各个技能自由开关,零 tool 注册,全场景零缓存破坏。"},"meta.description":"DietrichGebert/ponytail 的 DSH 完整移植:常驻懒人 senior 模式与七阶梯子(YAGNI 到最小实现),6 个中文原生技能(本体、评审、审计、债务、收益、帮助),零 tool 注册。","meta.title":"懒人模式(ponytail)","mode.full":"标准","mode.hint":"控制梯子提示词的注入强度,改动即时生效并写入配置文件,对所有会话生效。","mode.lite":"轻量","mode.lockedHint":"当前有更高优先级的配置在生效,此处的修改不会改变实际运行等级。","mode.off":"关闭","mode.title":"运行强度等级","mode.ultra":"激进","mode.unset":"未设置","mode.unsetHint":"Profile 补丁未配置运行等级,当前由内置兜底决定。点上方任一档位即写入补丁。","panel.title":"懒人模式配置","priority.intro":"运行等级按下列顺序取第一个有效值;被更高优先级压制的项,在界面上修改不会生效。当前生效:","priority.title":"配置优先级","priority.unavailable":"诊断信息不可用,请确认宿主版本已包含优先级诊断接口。","problem.env":"值无效,已忽略","problem.patch":"值无效,已忽略","skills.enabledToast":"技能 {name} 已启用","skills.hiddenToast":"技能 {name} 已隐藏","skills.hint":"关闭后该技能不会出现在斜杠菜单,也不会被模型加载。","skills.title":"原生技能开关","skills.toggleOn":"启用 {name}","state.loading":"读取中…","state.readOnly":"本部署的设置为只读。","state.saved":"配置保存在当前 profile 的 ponytail 目录","toast.modeChanged":"运行等级已切为「{name}」","toast.resetDone":"已恢复默认配置"};
|
|
16
|
+
var EN = {"button.reset":"Restore defaults","chain.hit":"In effect","chain.shadowed":"Shadowed","chain.unset":"Unset","chain.valueUnset":"(unset)","confirm.reset":"Restore default config? Level returns to Standard (full) and all 6 skills are re-enabled.","error.operation":"Operation failed: ","error.rejected":"This deployment did not accept the change; your value was kept for you to review.","lang.auto":"Follow host (auto)","lang.changed":"Skill description language switched to {name}","lang.en":"English","lang.followHost":"Now following the host language","lang.note":"Controls only skill descriptions in '/' slash menu and to the model; skill bodies stay the English originals.","lang.title":"Skill introduction language (visible in '/' slash menu & model)","lang.unsetHint":"Not set: follows the host language ({lang}); switch explicitly above. Controls only skill descriptions in '/' slash menu and to the model; skill bodies stay the English originals.","lang.zh":"中文","level.env":"Environment variable","level.fallback":"Built-in fallback","level.patch":"Profile patch","meta":{"title":"Lazy Senior Dev Mode","description":"DietrichGebert/ponytail lazy senior mode & 7-rung ladder port, 6 skills with bilingual descriptions & per-skill toggles, zero tools, zero-cache-miss."},"meta.description":"A full DSH port of DietrichGebert/ponytail: the always-on lazy senior developer mode and its seven-rung ladder (YAGNI down to the minimum implementation), with six native Chinese skills (core, review, audit, debt, gain, help) and zero tool registrations.","meta.title":"Ponytail (lazy senior mode)","mode.full":"Standard","mode.hint":"Controls how strongly the ladder prompt is injected. Changes apply immediately and are written to the config file for all sessions.","mode.lite":"Lite","mode.lockedHint":"A higher-priority configuration is in effect; changes here will not affect the actual runtime level.","mode.off":"Off","mode.title":"Intensity Level","mode.ultra":"Ultra","mode.unset":"Unset","mode.unsetHint":"The profile patch has no intensity level; the built-in fallback decides it now. Picking any level above writes it to the patch.","panel.title":"Lazy Senior Dev Mode settings","priority.intro":"The runtime level takes the first valid value in the following order; items shadowed by a higher-priority source cannot be changed from the UI. Current: ","priority.title":"Config Priority","priority.unavailable":"Diagnostics unavailable. Please confirm the host version ships the priority diagnostics endpoint.","problem.env":"Invalid value, ignored","problem.patch":"Invalid value, ignored","skills.enabledToast":"Skill {name} enabled","skills.hiddenToast":"Skill {name} hidden","skills.hint":"Disabled skills disappear from the slash menu and are not loaded by the model.","skills.title":"Native Skills","skills.toggleOn":"Enable {name}","state.loading":"Loading…","state.readOnly":"This deployment stores settings read-only.","state.saved":"Config is stored in the ponytail directory of the current profile","toast.modeChanged":"Level switched to {name}","toast.resetDone":"Defaults restored"};
|
|
17
17
|
// t 在 apply 时经 ctx.locale.bind 赋值;组件读取 factory 级变量(不接收 ctx,铁律)
|
|
18
18
|
var localeCtx = null;
|
|
19
19
|
var t = function (key, params) {
|
|
@@ -362,16 +362,19 @@ window.__ModuleLoader__.load({
|
|
|
362
362
|
}));
|
|
363
363
|
|
|
364
364
|
// 描述语言:三态(src/ponytail.ts 已去 Schema 默认值)。快照里读得到字段 = 显式配置
|
|
365
|
-
// (zh/en,锁定);读不到 =
|
|
365
|
+
// (zh/en,锁定);读不到 = 未配置(跟随宿主)。
|
|
366
366
|
// remote.skillLang 是服务端解析后的实际语言(显式值或按宿主对齐值),
|
|
367
367
|
// 未配置时用它提示「当前跟随到 zh/en」。
|
|
368
368
|
var descLangConfigured = typeof config.skillDescriptionLang === "string";
|
|
369
369
|
var descLang = descLangConfigured ? config.skillDescriptionLang : "auto";
|
|
370
|
+
// 「跟随宿主」是三态之一,不是一次性选项:用户配过一次 zh/en 后仍必须能切回来。
|
|
371
|
+
// 因此第三段常驻,不按是否配置追加(等级控件的「未设置」段是「没配过」的状态标记,
|
|
372
|
+
// 那里随配置收走合理,这里不行)。auto 固定排在末尾,zh/en 继续占 0、1 段。
|
|
370
373
|
var descLangOptions = [
|
|
371
374
|
{ value: "zh", label: t("lang.zh") },
|
|
372
375
|
{ value: "en", label: t("lang.en") },
|
|
376
|
+
{ value: "auto", label: t("lang.auto") },
|
|
373
377
|
];
|
|
374
|
-
if (!descLangConfigured) descLangOptions.push({ value: "auto", label: t("lang.auto") });
|
|
375
378
|
var setDescLang = React.useCallback(function (lang) {
|
|
376
379
|
if (lang === "auto") {
|
|
377
380
|
applyOps([{ op: "unset", path: ["skillDescriptionLang"] }], t("lang.followHost"));
|
|
@@ -419,6 +422,7 @@ window.__ModuleLoader__.load({
|
|
|
419
422
|
{ style: L.section },
|
|
420
423
|
e("h4", { style: L.title }, t("skills.title")),
|
|
421
424
|
e("p", { style: L.hint }, t("skills.hint")),
|
|
425
|
+
e("span", { style: Object.assign({}, L.title, { fontSize: "12px", marginTop: "4px" }) }, t("lang.title")),
|
|
422
426
|
e(P.SegmentedControl, {
|
|
423
427
|
id: "ponytail-desc-lang",
|
|
424
428
|
label: t("lang.title"),
|
|
@@ -429,7 +433,7 @@ window.__ModuleLoader__.load({
|
|
|
429
433
|
}),
|
|
430
434
|
!descLangConfigured
|
|
431
435
|
? e("p", { style: L.hint }, t("lang.unsetHint", { lang: t("lang." + (remote && (remote.skillLang === "en" || remote.skillLang === "zh") ? remote.skillLang : "zh")) }))
|
|
432
|
-
:
|
|
436
|
+
: e("p", { style: L.hint }, t("lang.note")),
|
|
433
437
|
e(
|
|
434
438
|
"div",
|
|
435
439
|
{ style: { display: "flex", flexDirection: "column", gap: "6px" } },
|
|
@@ -50,13 +50,39 @@ export interface CommandDispatchResult {
|
|
|
50
50
|
switched: boolean;
|
|
51
51
|
}
|
|
52
52
|
export interface CommandDispatcher {
|
|
53
|
-
dispatchText: (rawText: string) => CommandDispatchResult;
|
|
54
|
-
dispatchContent: (content: unknown) => CommandDispatchResult;
|
|
55
|
-
dispatchMessages: (messages: unknown) => CommandDispatchResult;
|
|
53
|
+
dispatchText: (rawText: string, sessionId?: string) => CommandDispatchResult;
|
|
54
|
+
dispatchContent: (content: unknown, sessionId?: string) => CommandDispatchResult;
|
|
55
|
+
dispatchMessages: (messages: unknown, sessionId?: string) => CommandDispatchResult;
|
|
56
56
|
}
|
|
57
57
|
/**
|
|
58
58
|
* 创建高内聚的命令调度器深模块
|
|
59
59
|
* 将文本提取、指令语法解析、状态机流转与副作用执行完整封装
|
|
60
|
+
* 支持可选的 sessionId 会话作用域,实现多会话模式隔离与零缓存破坏调度
|
|
60
61
|
*/
|
|
61
62
|
export declare function createCommandDispatcher(env: CommandDispatcherEnv): CommandDispatcher;
|
|
63
|
+
/** 统一从多层级宿主上下文对象中安全提取会话 ID */
|
|
64
|
+
export declare function resolveSessionId(target: unknown): string | undefined;
|
|
65
|
+
export interface TurnCoordinatorEnv extends CommandDispatcherEnv {
|
|
66
|
+
skillDir: string;
|
|
67
|
+
}
|
|
68
|
+
export interface TurnCoordinator {
|
|
69
|
+
handlePreStep(payload: unknown, next: () => Promise<unknown>): Promise<unknown>;
|
|
70
|
+
handleSessionEvent(session: unknown, event: unknown): void;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 轮次生命周期协作者深模块 (TurnCoordinator)
|
|
74
|
+
*
|
|
75
|
+
* 核心架构杠杆:
|
|
76
|
+
* 将用户指令解析、会话状态机流转、宿主 waterfall 穿透、变动对比、
|
|
77
|
+
* <system-reminder> 瞬态提醒构造、单轮原地替换与已发射标记回写完整内聚于此。
|
|
78
|
+
*
|
|
79
|
+
* 严守 6 大不变量:
|
|
80
|
+
* 1. Waterfall 不断链(异常捕获并穿透);
|
|
81
|
+
* 2. KV Cache 保护(顶层基线不可变,所有动态变动收敛在当前轮次尾部);
|
|
82
|
+
* 3. 单通知幂等(同轮重试时原地替换,绝不重复 push);
|
|
83
|
+
* 4. 发射标记收敛时机(仅在 downstream.kind === 'enter' 后标记已发射);
|
|
84
|
+
* 5. 多会话隔离(基于 sessionId 独立闭环);
|
|
85
|
+
* 6. 纯命令只读安全(裸 /ponytail 无副作用)。
|
|
86
|
+
*/
|
|
87
|
+
export declare function createTurnCoordinator(env: TurnCoordinatorEnv): TurnCoordinator;
|
|
62
88
|
//# sourceMappingURL=ponytail-commands.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ponytail-commands.d.ts","sourceRoot":"","sources":["../src/ponytail-commands.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ponytail-commands.d.ts","sourceRoot":"","sources":["../src/ponytail-commands.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAA;AAG7B;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG3D;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;IACjB,IAAI,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAA;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,cAAc,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;CACzC;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAS/D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,CAOrD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,UAAU,EAAE,MAAM,WAAW,GAC5B,kBAAkB,CAiDpB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3B,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,aAAa,CAAA;IACpB,MAAM,EAAE,uBAAuB,CAAA;IAC/B,cAAc,CAAC,EAAE,MAAM,WAAW,CAAA;IAClC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,GAAG,IAAI,CAAA;IACvD,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAA;CAChD;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,qBAAqB,CAAA;IAC5E,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,qBAAqB,CAAA;IAChF,gBAAgB,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,qBAAqB,CAAA;CACnF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,oBAAoB,GAAG,iBAAiB,CAsEpF;AAED,8BAA8B;AAC9B,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAOpE;AAED,MAAM,WAAW,kBAAmB,SAAQ,oBAAoB;IAC9D,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC/E,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;CAC3D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,kBAAkB,GAAG,eAAe,CAkF9E"}
|