@maci0/dsh-caveman 0.16.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +192 -0
  3. package/cordis.patch.yml +13 -0
  4. package/icon.svg +6 -0
  5. package/lib/client.js +488 -0
  6. package/lib/compress-detect.js +98 -0
  7. package/lib/compress-files.js +155 -0
  8. package/lib/compress-pipeline.js +109 -0
  9. package/lib/compress-rules.js +308 -0
  10. package/lib/compress-validate.js +227 -0
  11. package/lib/frontmatter.js +347 -0
  12. package/lib/host.js +15 -0
  13. package/lib/index.js +616 -0
  14. package/lib/modes.js +126 -0
  15. package/lib/skills.js +177 -0
  16. package/lib/types/compress-detect.d.ts +18 -0
  17. package/lib/types/compress-files.d.ts +76 -0
  18. package/lib/types/compress-pipeline.d.ts +32 -0
  19. package/lib/types/compress-rules.d.ts +65 -0
  20. package/lib/types/compress-validate.d.ts +36 -0
  21. package/lib/types/frontmatter.d.ts +57 -0
  22. package/lib/types/host.d.ts +201 -0
  23. package/lib/types/index.d.ts +87 -0
  24. package/lib/types/modes.d.ts +102 -0
  25. package/lib/types/skills.d.ts +56 -0
  26. package/locale/en.json +6 -0
  27. package/locale/zh.json +6 -0
  28. package/package.json +112 -0
  29. package/scripts/sync-upstream.mjs +158 -0
  30. package/skills/cavecrew/SKILL.md +91 -0
  31. package/skills/cavecrew/cavecrew-builder.md +46 -0
  32. package/skills/cavecrew/cavecrew-investigator.md +56 -0
  33. package/skills/cavecrew/cavecrew-reviewer.md +47 -0
  34. package/skills/caveman/SKILL.md +103 -0
  35. package/skills/caveman-commit/SKILL.md +63 -0
  36. package/skills/caveman-compress/SKILL.md +105 -0
  37. package/skills/caveman-explore/SKILL.md +42 -0
  38. package/skills/caveman-help/SKILL.md +68 -0
  39. package/skills/caveman-review/SKILL.md +53 -0
  40. package/skills/caveman-stats/SKILL.md +30 -0
  41. package/skills/investigate-first/SKILL.md +16 -0
  42. package/skills/lean-build/SKILL.md +18 -0
  43. package/skills/migration/SKILL.md +17 -0
  44. package/skills/safe-refactor/SKILL.md +16 -0
  45. package/skills/surgical-patch/SKILL.md +16 -0
  46. package/skills/verify-and-stop/SKILL.md +16 -0
  47. package/sync.manifest.json +25 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dsh-caveman contributors
4
+ Copyright (c) 2026 Julius Brussee (https://github.com/JuliusBrussee/caveman)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,192 @@
1
+ # dsh-caveman
2
+
3
+ Your agent writes three paragraphs where one line would do. This plugin makes it
4
+ talk like a caveman: same meaning, fewer tokens. Code, commands, file paths, and
5
+ exact error strings are never compressed, only the prose around them. Adapted
6
+ from [JuliusBrussee/caveman](https://github.com/JuliusBrussee/caveman) (MIT):
7
+ "why use many token when few do trick".
8
+
9
+ ## What you get
10
+
11
+ - **A talking style on every request.** While any level except `off` is active,
12
+ the mode-filtered ruleset joins the system prompt.
13
+ - **Fourteen skills** the `skill` tool can load, so they also appear as
14
+ `/caveman-review`, `/caveman-commit`, … in the composer: `caveman`, `cavecrew`,
15
+ `caveman-commit`, `caveman-review`, `caveman-compress`, `caveman-explore`,
16
+ `caveman-stats`, `caveman-help`, plus six work patterns (`investigate-first`,
17
+ `lean-build`, `surgical-patch`, `safe-refactor`, `migration`, `verify-and-stop`).
18
+ - **Two ways to switch level.** The model calls the `caveman` tool; you type
19
+ `/caveman <level>` or just say **stop caveman**.
20
+ - **A settings card and a composer chip**, so the active level is visible without
21
+ opening Settings.
22
+ - **`/caveman-compress <file>`** shrinks a memory file or todo list with local
23
+ rules. No model call, original backed up out of tree. A relative path resolves
24
+ against the session's working directory. The model-facing `caveman-compress`
25
+ tool only rewrites files inside that workspace (symlinks resolved); the
26
+ command you type is not confined.
27
+
28
+ ## Install
29
+
30
+ > **Install it as a bundle.** `dsh plugin add …` mounts the row from the
31
+ > package's own patch layer, which is what the settings editor can write to. A
32
+ > row added with `--patch` is an overlay: it disappears at the next start, and
33
+ > the Plugins card cannot save into it (the editor refuses a write an overlay
34
+ > would win).
35
+
36
+ ```sh
37
+ dsh plugin --profile web add @maci0/dsh-caveman@0.16.2
38
+ ```
39
+
40
+ This installs the public npm package; no GitHub token or `~/.secrets` setup is needed.
41
+ The version is pinned. To upgrade, run the same command with a newer version,
42
+ then restart `dsh web` (bundle layers compose at boot).
43
+
44
+ ## Use it
45
+
46
+ ```
47
+ /caveman ultra -> Caveman level: ultra (was full).
48
+ /caveman wenyan -> Caveman level: wenyan-full (was ultra).
49
+ /caveman -> Caveman level: wenyan-full.
50
+ /caveman off -> Caveman off (was wenyan-full). Normal behavior.
51
+ ```
52
+
53
+ Typing **stop caveman** or **normal mode** as an ordinary message has the same
54
+ effect as `/caveman off`, and it lands on the turn that carried it. Only the
55
+ human's own words count: injected context riding the same event stream cannot
56
+ toggle the level, and the message must *be* the command, so "add a normal mode
57
+ toggle" is left alone.
58
+
59
+ Model side, the tool takes `mode` (persist a level), `once` (this call only, not
60
+ persisted), and `usage` (session token totals). `{"usage": true}` appends input,
61
+ output, cache read, and cache write totals from the harness's `tokenUsage`
62
+ projection: counts only, never a saving.
63
+
64
+ ### Levels
65
+
66
+ | Level | Behavior | Persisted |
67
+ |---|---|---|
68
+ | `lite` | Drop filler. Keep sentence structure. | yes |
69
+ | `full` | Drop articles, filler, pleasantries, hedging. Fragments OK. Default. | yes |
70
+ | `ultra` | Extreme compression. Bare fragments. | yes |
71
+ | `wenyan-lite` | Classical Chinese style, light compression. | yes |
72
+ | `wenyan-full` | Full 文言文. Maximum classical terseness. (`/caveman wenyan` shorthand.) | yes |
73
+ | `wenyan-ultra` | Extreme. Ancient scholar on a budget. | yes |
74
+ | `off` | No injection. Normal behavior. | yes |
75
+
76
+ Every level persists, so the card, the chip, the tool, and `/caveman` agree and
77
+ the choice survives a restart. The card and the chip show the level the host is
78
+ using: one that came from `CAVEMAN_DEFAULT_MODE` or `~/.config/caveman/config.json`
79
+ is labelled as such (choosing a level on the card overrides it), and so is a level
80
+ held only for this session because the settings write failed. Security warnings, irreversible-action
81
+ confirmations, and anything where compression would change the meaning drop back
82
+ to full sentences.
83
+
84
+ ## Configure
85
+
86
+ | Field | Default | Meaning |
87
+ |---|---|---|
88
+ | `defaultMode` | unset | Startup level. Absent means "ask the chain below". One of the seven levels when set. |
89
+ | `maxFileSize` | `500000` | Size cap in bytes for `/caveman-compress`. Positive number, editable from the card, and read on every compress call. |
90
+
91
+ The row schema declares no default for `defaultMode` and the bundle's row sets
92
+ none, so an absent field stays absent and the level resolves in this order: the
93
+ row's `defaultMode`, then `CAVEMAN_DEFAULT_MODE`, then
94
+ `~/.config/caveman/config.json`'s `defaultMode`, then `full`. The env and the
95
+ file are read once at mount; the row is read at every use, so the card's Reset
96
+ falls back to them. An invalid value
97
+ fails while the plugin loads rather than silently doing the wrong thing.
98
+
99
+ Override the row from your profile's own `cordis.patch.yml` with a
100
+ `- id: caveman` row, which replaces the row's whole `config`. Do **not** paste
101
+ the bundle's `insert` of that row there: `insert` does not dedupe ids, and a
102
+ second row mounts the plugin twice.
103
+
104
+ ## How it works
105
+
106
+ The package declares `dsh.bundle`, so `dsh plugin add` appends it to
107
+ `dsh.profile.bundles` and the row in its own `cordis.patch.yml` applies as a layer.
108
+
109
+ The host half mounts through public Cordis extension points: `systemPrompt.section`,
110
+ `skills.registerProvider`, `tools.register`, `commands.register`,
111
+ `loader/volatile-update` (the settings document writes the row's volatile
112
+ `defaultMode`), `session/event` for the message switch, and `webServer` for
113
+ `GET /caveman/level`, which answers `{ mode, source }` (`settings`, `env`,
114
+ `config-file`, `default`, or `session`) behind the `connection` trust fence. The
115
+ browser half reads that route on every settings change and every 5 seconds, draws
116
+ its card into the public `plugins.row.config` slot from `configForms`, registers its
117
+ copy through `locale.register`, and draws its chip into `conversation.input.left`, so
118
+ this plugin needs no client change of its own.
119
+
120
+ The entry point is the built `lib/index.js` (declarations in `lib/types/`); `bun run
121
+ build` regenerates it from `src/`. `lib/client.js` is hand-authored plain JavaScript:
122
+ the client module system serves it as a lazy-CJS factory on `window.__ModuleLoader__`
123
+ because the package exports `./client`, and it is not built. Skills come from
124
+ `skills/<name>/SKILL.md` with frontmatter parsed by `yaml`; the provider takes its rank
125
+ and name grammar from `@deepseek-ai/dsh-skill`, projects `disable-model-invocation`,
126
+ `user-invocable`, and `whenToUse`, and settles on the lookup's abort signal. Tools use
127
+ `defineTool` from `@deepseek-ai/dsh-tools` and forward `exec.signal`. Only
128
+ `skills/caveman/SKILL.md` is the source of truth for the ruleset; this README keeps no
129
+ second copy.
130
+
131
+ ## Limits
132
+
133
+ - **No proxy, no CLI verbs, no Cloud engine.** Upstream's
134
+ `caveman-setup/-discover/-learn/-manage/-optimize/-evidence-review` need an
135
+ external runtime the harness has no extension point for, so they are not bundled.
136
+ - **Savings are not measured.** `/caveman-stats` reports what the provider reported this
137
+ session, never a percentage, and it says unavailable when the host mounts no token meter.
138
+ - **The level is process-wide.** One prompt section, one namespace value: every
139
+ agent in the process shares it.
140
+ - **External subagents ignore it.** In-process children inherit the ruleset, but
141
+ `subagent-claude-code`/`subagent-codex` spawn their own CLI with its own prompt.
142
+ - **Two locales.** The card and the chip ship `en` and `zh`; any other locale
143
+ falls back through the service's own chain.
144
+ - **Host source edits need `bun run build` and a restart**; browser-half edits need a page refresh.
145
+
146
+ ## Development
147
+
148
+ ```sh
149
+ bun install # the client packages are optional peers and stay uninstalled
150
+ bun run build # tsc -p tsconfig.build.json -> lib/index.js + lib/types/
151
+ bun test # every tests/*.test.ts, no build step
152
+ bun run typecheck # tsc -p tsconfig.json
153
+ bun run sync:check # diff bundled files against upstream main (needs network)
154
+ bun run sync # overwrite stale verbatim files (refuses dirty tree w/o --force)
155
+ ```
156
+
157
+ dsh loads plugins on Node ^22.19.0 || >=24.0.0; development and tests run on bun.
158
+
159
+ The harness packages this plugin imports at runtime (`@deepseek-ai/dsh-tools`,
160
+ `@deepseek-ai/dsh-skill`, `@deepseek-ai/schemastery`) are **dependencies
161
+ pinned to the harness's own versions**, so the profile resolves one physical
162
+ copy; `yaml` is the only non-harness dependency. The pin is deliberate.
163
+ `@deepseek-ai/dsh-tools` keys its runtime scheduler on a module-level `Symbol`,
164
+ so a second physical copy in the profile hands the tool layer a different
165
+ symbol than the host's and every tool call dies with
166
+ `Cannot read properties of undefined (reading 'prepare')`.
167
+
168
+ For local development, install the checkout into a profile with
169
+ `dsh plugin --profile <name> add <path-to-checkout>`.
170
+
171
+ The suite covers level normalization and filtering, the fake-host surface, the skills
172
+ provider, the compress pipeline, and a real Cordis composition mount next to the real
173
+ skill registry. `sync:check` exits 1 and lists stale files (2 on a usage or fetch error); `sync` rewrites verbatim
174
+ copies and leaves adapted ones for manual re-adaptation. Both accept `--ref <tag|sha>`
175
+ (default `main`). The network assertion runs only with `DSH_SYNC_CHECK=1`; plain
176
+ `bun test` stays offline. To uninstall, run `dsh plugin --profile web remove @maci0/dsh-caveman`
177
+ and drop any `id: caveman` override from `~/.dsh/profiles/<profile>/cordis.patch.yml`.
178
+
179
+ ## Attribution and license
180
+
181
+ MIT. Skill content: © JuliusBrussee
182
+ ([caveman](https://github.com/JuliusBrussee/caveman)). DSH port: see `LICENSE`.
183
+
184
+ The fourteen `skills/*/SKILL.md` files track upstream; nine are verbatim copies
185
+ and five carry small DSH adaptations (`caveman`, `caveman-compress`, `cavecrew`,
186
+ `caveman-stats`, `caveman-help`). The `cavecrew-*.md` prompts are verbatim too.
187
+ The compress pipeline (`src/compress-*.ts`) is a port, not a copy: same behavior,
188
+ local rules instead of a model call, no `python3` needed.
189
+
190
+ Upstream's numbers (JetBrains: 8.5% fewer output tokens, skill only; Adobe CAVEWOMAN:
191
+ 1.4–2.4× output-side cost cut; proxy: −33.2% input tokens) are upstream's, not this
192
+ package's: this port ships the skill half only, so only the skill-side figures apply.
@@ -0,0 +1,13 @@
1
+ # The dsh-caveman bundle patch: applied automatically when a profile lists
2
+ # this bundle (`dsh plugin add`/`update` appends the package to
3
+ # dsh.profile.bundles). Users override this row from their profile's own
4
+ # cordis.patch.yml (live-watched; dsh.profile.bundles is frozen at boot) with a
5
+ # `- id: caveman` row, which replaces the row's whole `config`.
6
+ # `name` stays a bare package specifier: the browser half is served by the
7
+ # client module system, which resolves the Loader entry's package, reads its
8
+ # `dsh.client` manifest, and serves `exports["./client"]`.
9
+ # Do not also insert this same row into the profile patch: insert does not
10
+ # dedupe ids, and a second row would register the plugin twice.
11
+ - insert:
12
+ - id: caveman
13
+ name: '@maci0/dsh-caveman'
package/icon.svg ADDED
@@ -0,0 +1,6 @@
1
+ <svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M8 22.5c1.2-6.2 5.4-10 10-10 3.2 0 5.6 1.6 7.2 4.2" stroke="#8C6239" stroke-width="2.2" stroke-linecap="round"/>
3
+ <circle cx="23.5" cy="13.2" r="5.4" fill="#C4A574"/>
4
+ <circle cx="23.5" cy="13.2" r="5.4" stroke="#8C6239" stroke-width="1.5"/>
5
+ <path d="M10 24.5h9.5" stroke="#8C6239" stroke-width="2.2" stroke-linecap="round"/>
6
+ </svg>