odai-dsh-agent 0.0.8 → 0.0.10

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 (48) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +120 -118
  3. package/bin/odai-dsh-agent.mjs +105 -105
  4. package/package.json +69 -68
  5. package/preset/odai/agent.cordis.yml +260 -260
  6. package/preset/odai/preset.yml +3 -3
  7. package/preset/odai/runtime/compaction-config.mjs +41 -20
  8. package/preset/odai/runtime/governance.mjs +121 -120
  9. package/preset/odai/runtime/index.mjs +1104 -863
  10. package/preset/odai/runtime/output-config.mjs +1 -1
  11. package/preset/odai/runtime/research-packet.mjs +150 -0
  12. package/preset/odai/runtime/role-overlays.mjs +27 -0
  13. package/preset/odai/runtime/route-card.mjs +125 -0
  14. package/preset/odai/runtime/router.mjs +449 -349
  15. package/preset/odai/runtime/routing-config.mjs +326 -323
  16. package/preset/odai/runtime/routing-context.mjs +209 -0
  17. package/preset/odai/runtime/session-compat.mjs +2 -0
  18. package/preset/odai/runtime/skill-bundle.mjs +11 -2
  19. package/preset/odai/skills/odai/SKILL.md +66 -66
  20. package/preset/odai/skills/odai/agents/openai.yaml +4 -4
  21. package/preset/odai/skills/odai/assets/claude-agents/agent.md +11 -11
  22. package/preset/odai/skills/odai/assets/codex-agents/config.toml +11 -11
  23. package/preset/odai/skills/odai/assets/codex-agents/role.toml +5 -5
  24. package/preset/odai/skills/odai/assets/copilot-agents/agent.md +13 -13
  25. package/preset/odai/skills/odai/assets/hooks-policy.example.json +24 -24
  26. package/preset/odai/skills/odai/assets/routing-roles/controller.md +15 -15
  27. package/preset/odai/skills/odai/assets/routing-roles/executor.md +11 -11
  28. package/preset/odai/skills/odai/assets/routing-roles/frontend.md +7 -0
  29. package/preset/odai/skills/odai/assets/routing-roles/planner.md +29 -29
  30. package/preset/odai/skills/odai/assets/routing-roles/researcher.md +7 -0
  31. package/preset/odai/skills/odai/assets/routing-roles/reviewer.md +11 -11
  32. package/preset/odai/skills/odai/assets/task-state.md +14 -12
  33. package/preset/odai/skills/odai/manifest.json +4 -2
  34. package/preset/odai/skills/odai/references/craft.md +54 -54
  35. package/preset/odai/skills/odai/references/dao.md +30 -30
  36. package/preset/odai/skills/odai/references/leverage.md +51 -46
  37. package/preset/odai/skills/odai/references/planning.md +2 -0
  38. package/preset/odai/skills/odai/references/support.md +36 -36
  39. package/preset/odai/skills/odai/references/verification.md +23 -23
  40. package/preset/odai/skills/odai/scripts/build-hooks.mjs +273 -273
  41. package/preset/odai/skills/odai/scripts/build-routing.mjs +274 -239
  42. package/preset/odai/skills/odai/scripts/install-routing.mjs +397 -375
  43. package/preset/odai/skills/odai/scripts/odai-hook.mjs +457 -457
  44. package/preset/odai/skills/odai/scripts/run-role.mjs +336 -336
  45. package/preset/odai/skills/odai/scripts/run-routing.mjs +1154 -1154
  46. package/preset/odai/skills/odai/scripts/verify-routing.mjs +103 -103
  47. package/scripts/verify-agent-load.mjs +246 -246
  48. package/src/installer.mjs +328 -328
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 orziz
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 orziz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,118 +1,120 @@
1
- # odai dsh agent
2
-
3
- `odai-dsh-agent` installs a selectable, session-scoped Odai Agent preset for DeepSeek Harness (`dsh`). It is independent from the profile-wide `odai-dsh-plugin`: installing this package does not edit any DSH profile or activate a global bundle.
4
-
5
- The installed preset is self-contained:
6
-
7
- ```text
8
- $DSH_HOME/.agent-presets/odai/
9
- agent.cordis.yml
10
- preset.yml
11
- runtime/*.mjs
12
- skills/odai/**
13
- .odai-agent.json
14
- ```
15
-
16
- The composition preserves every capability row and setting from the `standard` agent surface in `@deepseek-ai/dsh@0.1.0-rc.6`, then adds the scoped Odai runtime in default `auto` mode. Release verification compares the complete derived composition against that exact DSH Standard source; a missing, added, reordered, or changed Standard row fails the probe. Host-owned persistence, sandbox, approval, registries, and base controller selection remain in the selected DSH profile. Ordinary requests stay on that controller. A complete contextual high-impact decision gap upgrades the same turn only when a planner mapping exists; the controller's durable `request/header` proves the actual route. Explicit independent planning/review requests still start a verified child when their mappings exist. `execute` remains an explicit all-delegation comparison mode. `observe` changes no model and starts no child; it injects a local evidence-and-decision protocol and makes an unresolved high-impact turn read-only. For DSH compaction on the same provider/model, an omitted summarizer reasoning setting inherits the session's current user-selected reasoning effort so the auxiliary call remains cache-compatible. A user-selected cross-model target removes an effort matching that durable route; a distinct preselected effort is preserved because the request envelope exposes no stronger provenance.
17
-
18
- ## Install
19
-
20
- With DSH already installed, run the single Agent package command below. The package already contains the canonical skill and shared runtime; it does not require the Plugin or a separate skill installation:
21
-
22
- ```sh
23
- npx odai-dsh-agent install
24
- ```
25
-
26
- The installer checks `dsh -V` and currently requires exactly `0.1.0-rc.6`; a preset built from one developer-preview composition is not silently installed into another version.
27
-
28
- `DSH_HOME` is honored. An explicit location can be supplied without changing the environment:
29
-
30
- ```sh
31
- npx odai-dsh-agent install --dsh-home /path/to/dsh-home
32
- ```
33
-
34
- Open a new DSH session and select `Odai` from the Agent preset picker. Existing sessions retain the preset they were composed with.
35
-
36
- In `dsh@0.1.0-rc.6`, the one-shot `--profile headless` driver creates a global agent directly and neither mounts nor accepts a session Agent preset. Automated Agent runs must create a Web session with `agentPreset: odai`; use the profile-wide Plugin for one-shot headless tasks.
37
-
38
- The installer copies through a mode-tightened staging directory and atomically publishes the preset. Updates verify every previously managed file first, refuse to overwrite local edits, and always change the composition generation key so new sessions in a running DSH process do not reuse stale runtime code. If install or update finds recognized historical Odai audit records, it refuses to change the preset until every DSH process is stopped and the command is rerun with `--yes`. The confirmed migration adds DSH's official `ignorable: true` envelope marker, covers both plaintext and concatenated-frame Zstandard session artifacts, verifies each replacement, and retains a content-addressed backup without deleting messages or evidence. Confirmation alone is insufficient: migration also refuses when local process inspection fails or finds any active DSH process. Keep DSH stopped until the installer exits because historical runtimes do not participate in a migration lock. An unknown unmarked `odai/*` type blocks the operation instead of being assumed safe to ignore.
39
-
40
- DSH classifies this as a `trust: user` preset. User presets have the same privileges as shell access, so install only reviewed package versions; the installer repeats this trust notice in both plain and JSON output.
41
-
42
- ## Responsibility models
43
-
44
- The Agent ships no planner, executor, or reviewer model mapping. It stays quiet when an unconfigured responsibility is not needed. If a real task gap needs one, Odai says which responsibility is missing, confirms that no route ran, and asks for the provider, model, and optional reasoning effort in natural language. For example:
45
-
46
- ```text
47
- 规划用 provider-x/model-plan,推理档 high。
48
- 执行模型设为 provider-x/model-y。
49
- 验收改用 provider-z/model-review,推理档 max。
50
- ```
51
-
52
- The controller calls `odai_routing_config` to persist that explicit choice. The user does not edit Agent files, YAML, or JSON and does not add trigger terms to later tasks. Mappings live in `$DSH_HOME/odai/routing.json`, outside the managed preset, so installer updates do not report them as drift. Audit evidence likewise lives under `$DSH_HOME/odai/session-evidence/` instead of using private DSH session-event types, so changing or removing the preset cannot make a session unreadable. Changes apply from the next user turn. If reasoning effort is omitted, the target provider/model uses its own default rather than inheriting the source controller's setting. Plugin and Agent read the same stores when both are deliberately present.
53
-
54
- Planner, executor, and reviewer are independent optional responsibilities. If any needed one has no mapping, high-impact work fails closed and remains read-only; lower-impact work continues only where it does not depend on the missing independent responsibility. Odai never chooses a model on the user's behalf.
55
-
56
- ## Controller output policy
57
-
58
- The Agent defaults to **soft concise** output and shares three controller output modes with the Plugin. A user can naturally ask to inspect or change the mode; `odai_output_config` persists an explicit override in `$DSH_HOME/odai/output.json`:
59
-
60
- | Mode | Policy | Behavior |
61
- |---|---|---|
62
- | normal | `concise: false`, no `maxTokens` | use the host's normal presentation and controller budget |
63
- | soft concise (default) | `concise: true`, no `maxTokens` | shorten only the final user-facing presentation without relaxing required results, evidence, risks, blockers, or verification |
64
- | economy (optional) | `concise: true`, positive `maxTokens` | add a provider output-ceiling request; default to `500` when the user names economy without another value, or use the user's supplied positive value |
65
-
66
- Natural requests include `use normal output`, `use soft concise output`, `enable economy mode`, and `set economy mode to 1200 tokens`. Removing the persisted override restores soft concise. Existing pre-mode stores that combined `concise: false` with a ceiling remain readable for compatibility, but new named-mode changes cannot create that legacy combination. The selected mode is stable within one turn and changes from the next user turn.
67
-
68
- An economy ceiling only tightens an existing lower host request value and is not a locally enforceable hard billing boundary. A provider may count hidden reasoning inside it, exceed or ignore it, or end before useful final text, especially at a high reasoning effort; strict compliance must be checked from per-request usage. Odai enables economy only when requested and never invents a non-default custom value. The mode does not alter child-agent role budgets, compaction, checkpoints, or other internal context; an incomplete token-capped compaction fails closed instead of replacing history.
69
-
70
- A same-provider/model compaction inherits controller reasoning while keeping its independent summary budget. Odai leaves prompt-cache retention unset by default; `ODAI_COMPACTION_CACHE_RETENTION` can explicitly select `short`, `long`, or `none`. `provider-default` means Odai adds no retention, while any explicit incoming retention remains authoritative; configured retention still applies when host routing has already supplied reasoning. Custom preset compositions can set the same value through runtime `compaction.cacheRetention`. The first controller request after a landed summary still rebuilds the changed summary prefix.
71
-
72
- ## Compaction model
73
-
74
- The default compaction-summary model is `inherit`, which preserves the conversation's current provider/model behavior. A user can explicitly set a separate target in natural language, such as `压缩模型用 provider-x/model-summary`; `odai_compaction_config` persists that provider/model pair in `$DSH_HOME/odai/compaction.json`. Removing it restores inheritance. Agent and Plugin share the store when both are deliberately present.
75
-
76
- The target applies only to future `compaction` summary requests. It does not change the controller, planner, executor, reviewer, ordinary conversation, summary output budget, or cache-retention policy, never selects a new reasoning effort, and a cross-model target removes only reasoning proven by equality with the durable controller route while preserving a distinct preselected effort. Each configured target receives one provider-neutral integrity suffix that keeps current facts above superseded/rejected history, preserves continuation-critical opaque values exactly, and self-checks contradictions; duplicate Agent/Plugin runtime instances add it only once. Odai never chooses the target on the user's behalf. An invalid store is reported by the tool while runtime requests inherit safely until `set` or `remove` repairs it. An unavailable route, provider error, or incomplete summary fails closed: DSH retains the original history rather than replacing it with a partial checkpoint.
77
-
78
- ## Skill sources
79
-
80
- The Agent keeps the managed preset's complete skill copy as its `bundled` default, so existing installations do not change behavior. When the user explicitly asks to show, set, or reset the Odai skill source, the controller uses `odai_skill_source_config` and stores the choice in `$DSH_HOME/odai/source.json`, outside the managed preset:
81
-
82
- - `bundled`: use the skill shipped with this Agent release.
83
- - `auto`: allow a compatible current-project `.dsh/skills/odai` or `.agents/skills/odai` bundle, then DSH custom roots and newer user installs under `$DSH_HOME/skills/odai` or `$DSH_AGENTS_HOME/skills/odai` (default `~/.agents/skills/odai`), with bundled fallback.
84
- - `user`: ignore project roots and require a compatible custom or user-level bundle. An unusable source produces an explicit bundled fallback diagnostic so it can be repaired through the same tool.
85
-
86
- An independent install must be a complete directory bundle containing `SKILL.md`, `manifest.json`, and every manifest-declared file. The runtime checks SemVer 2.0.0 `skillVersion`, an exact supported `runtimeContract`, complete-file SHA-256 integrity, and same-version content conflicts. Prompt governance and routing role contracts are selected atomically for one agent turn; project sources are scoped by that session's cwd, and changes are reconsidered on the next user turn. Explicit deployment `skillPath` or `ODAI_SKILL_PATH` remains highest priority and requires a DSH restart.
87
-
88
- ## Status and uninstall
89
-
90
- ```sh
91
- npx odai-dsh-agent status
92
- npx odai-dsh-agent status --json
93
- npx odai-dsh-agent uninstall
94
- ```
95
-
96
- `status` reports `absent`, `installed`, or `drifted`. Update and uninstall fail closed when managed files were changed or unmanaged files were added. Uninstall first checks for legacy Odai session events and, when any exist, requires the same stopped-DSH `--yes` confirmation before making them ignorable; a failed inspection or migration refuses removal. It also refuses while `agent-presets.default` still names `odai`; select another default first so the next session cannot fail on a missing preset. Stop DSH before install, update, or uninstall so session artifacts are not being written concurrently.
97
-
98
- ## Plugin versus Agent
99
-
100
- Use only the surface that matches the desired scope:
101
-
102
- - `odai-dsh-plugin`: profile-wide governance for every preset in that profile.
103
- - `odai-dsh-agent`: selectable Odai governance for only sessions using this preset.
104
- - both: supported only for a deliberate combination of profile-wide and Agent-scoped behavior; normally redundant, so it is not the default recommendation.
105
-
106
- When both are deliberate, a process-shared per-agent/per-turn skill snapshot keeps prompt governance and role contracts identical, the compatibility-safe evidence store deduplicates tool and route records, and denials remain monotonic. Neither package installs or changes the provider-neutral `odai-cli`.
107
-
108
- ## Development
109
-
110
- `dsh/runtime/` and `skills/odai/` remain the only editable sources. `npm pack` generates the preset's `runtime/` and `skills/` directories and removes them immediately afterward:
111
-
112
- ```sh
113
- npm --prefix dsh/agent test
114
- npm --prefix dsh/agent run verify:dsh
115
- npm --prefix dsh/agent run pack:dry-run
116
- ```
117
-
118
- The DSH verification uses a temporary home and one isolated Web process. It creates standard and Odai sessions, proves the canonical prompt appears only for Odai, dispatches `odai_routing_config` through the live Odai session and checks its persisted mapping, and proves the child write guard does not leak into the standard preset.
1
+ # odai dsh agent
2
+
3
+ `odai-dsh-agent` installs a selectable, session-scoped Odai Agent preset for DeepSeek Harness (`dsh`). It is independent from the profile-wide `odai-dsh-plugin`: installing this package does not edit any DSH profile or activate a global bundle.
4
+
5
+ The installed preset is self-contained:
6
+
7
+ ```text
8
+ $DSH_HOME/.agent-presets/odai/
9
+ agent.cordis.yml
10
+ preset.yml
11
+ runtime/*.mjs
12
+ skills/odai/**
13
+ .odai-agent.json
14
+ ```
15
+
16
+ The composition preserves every capability row and setting from the `standard` agent surface in `@deepseek-ai/dsh@0.1.0-rc.6`, then adds the scoped Odai runtime in default `auto` mode. Release verification compares the complete derived composition against that exact DSH Standard source; a missing, added, reordered, or changed Standard row fails the probe. Host-owned persistence, sandbox, approval, registries, and base controller selection remain in the selected DSH profile. Ordinary requests stay on that controller. A complete contextual high-impact decision gap upgrades the same turn only when a planner mapping exists; the controller's durable `request/header` proves the actual route. Explicit independent planning/review requests still start a verified child when their mappings exist. `execute` remains an explicit all-delegation comparison mode. `observe` changes no model and starts no child; it injects a local evidence-and-decision protocol and makes an unresolved high-impact turn read-only. For DSH compaction, an explicit user-selected summary reasoning effort overrides only that auxiliary call. When omitted, same-provider/model compaction inherits the session's current reasoning effort for cache compatibility; a cross-model target removes an effort matching that durable route, while a distinct preselected effort is preserved because the request envelope exposes no stronger provenance.
17
+
18
+ ## Install
19
+
20
+ With DSH already installed, run the single Agent package command below. The package already contains the canonical skill and shared runtime; it does not require the Plugin or a separate skill installation:
21
+
22
+ ```sh
23
+ npx odai-dsh-agent install
24
+ ```
25
+
26
+ The installer checks `dsh -V` and currently requires exactly `0.1.0-rc.6`; a preset built from one developer-preview composition is not silently installed into another version.
27
+
28
+ `DSH_HOME` is honored. An explicit location can be supplied without changing the environment:
29
+
30
+ ```sh
31
+ npx odai-dsh-agent install --dsh-home /path/to/dsh-home
32
+ ```
33
+
34
+ Open a new DSH session and select `Odai` from the Agent preset picker. Existing sessions retain the preset they were composed with.
35
+
36
+ In `dsh@0.1.0-rc.6`, the one-shot `--profile headless` driver creates a global agent directly and neither mounts nor accepts a session Agent preset. Automated Agent runs must create a Web session with `agentPreset: odai`; use the profile-wide Plugin for one-shot headless tasks.
37
+
38
+ The installer copies through a mode-tightened staging directory and atomically publishes the preset. Updates verify every previously managed file first, refuse to overwrite local edits, and always change the composition generation key so new sessions in a running DSH process do not reuse stale runtime code. If install or update finds recognized historical Odai audit records, it refuses to change the preset until every DSH process is stopped and the command is rerun with `--yes`. The confirmed migration adds DSH's official `ignorable: true` envelope marker, covers both plaintext and concatenated-frame Zstandard session artifacts, verifies each replacement, and retains a content-addressed backup without deleting messages or evidence. Confirmation alone is insufficient: migration also refuses when local process inspection fails or finds any active DSH process. Keep DSH stopped until the installer exits because historical runtimes do not participate in a migration lock. An unknown unmarked `odai/*` type blocks the operation instead of being assumed safe to ignore.
39
+
40
+ DSH classifies this as a `trust: user` preset. User presets have the same privileges as shell access, so install only reviewed package versions; the installer repeats this trust notice in both plain and JSON output.
41
+
42
+ ## Responsibility models
43
+
44
+ The Agent ships no researcher, planner, executor, reviewer, or frontend model mapping. It stays quiet when an unconfigured responsibility is not needed. If a real task gap needs one, Odai says which responsibility is missing, confirms that no route ran, and asks for the provider, model, and optional reasoning effort in natural language. For example:
45
+
46
+ ```text
47
+ 证据调查用 provider-r/model-research,推理档 high。
48
+ 规划用 provider-x/model-plan,推理档 high。
49
+ 执行模型设为 provider-x/model-y。
50
+ 验收改用 provider-z/model-review,推理档 max。
51
+ 前端制作用 provider-f/model-frontend,输出上限 4096。
52
+ ```
53
+
54
+ The controller calls `odai_routing_config` to persist that explicit choice. Researcher activation is task-gated but not price-aware: its mapping enables the narrow trigger and does not guarantee lower cost. The tool repeats that warning whenever a researcher mapping is shown; Odai must use authoritative provider prices and measured usage instead of inventing either. The user does not edit Agent files, YAML, or JSON and does not add trigger terms to later tasks. Mappings live in `$DSH_HOME/odai/routing.json`, outside the managed preset, so installer updates do not report them as drift. Audit evidence likewise lives under `$DSH_HOME/odai/session-evidence/` instead of using private DSH session-event types, so changing or removing the preset cannot make a session unreadable. Changes apply from the next user turn. If reasoning effort is omitted, the target provider/model uses its own default rather than inheriting the source controller's setting. Plugin and Agent read the same stores when both are deliberately present.
55
+
56
+ Researcher and frontend are optional prefetch/production upgrades whose missing mappings keep the original route without claiming success. Planner, executor, and reviewer are independent optional responsibilities; if a needed one has no mapping, high-impact work fails closed and remains read-only, while lower-impact work continues only where it does not depend on the missing independent responsibility. Odai never chooses a model or price on the user's behalf.
57
+
58
+ ## Controller output policy
59
+
60
+ The Agent defaults to **soft concise** output and shares three controller output modes with the Plugin. A user can naturally ask to inspect or change the mode; `odai_output_config` persists an explicit override in `$DSH_HOME/odai/output.json`:
61
+
62
+ | Mode | Policy | Behavior |
63
+ |---|---|---|
64
+ | normal | `concise: false`, no `maxTokens` | use the host's normal presentation and controller budget |
65
+ | soft concise (default) | `concise: true`, no `maxTokens` | shorten only the final user-facing presentation without relaxing required results, evidence, risks, blockers, or verification |
66
+ | economy (optional) | `concise: true`, positive `maxTokens` | add a provider output-ceiling request; default to `500` when the user names economy without another value, or use the user's supplied positive value |
67
+
68
+ Natural requests include `use normal output`, `use soft concise output`, `enable economy mode`, and `set economy mode to 1200 tokens`. Removing the persisted override restores soft concise. Existing pre-mode stores that combined `concise: false` with a ceiling remain readable for compatibility, but new named-mode changes cannot create that legacy combination. The selected mode is stable within one turn and changes from the next user turn.
69
+
70
+ An economy ceiling only tightens an existing lower host request value and is not a locally enforceable hard billing boundary. A provider may count hidden reasoning inside it, exceed or ignore it, or end before useful final text, especially at a high reasoning effort; strict compliance must be checked from per-request usage. Odai enables economy only when requested and never invents a non-default custom value. The mode does not alter child-agent role budgets, compaction, checkpoints, or other internal context; an incomplete token-capped compaction fails closed instead of replacing history.
71
+
72
+ A same-provider/model compaction inherits controller reasoning while keeping its independent summary budget. Odai leaves prompt-cache retention unset by default; `ODAI_COMPACTION_CACHE_RETENTION` can explicitly select `short`, `long`, or `none`. `provider-default` means Odai adds no retention, while any explicit incoming retention remains authoritative; configured retention still applies when host routing has already supplied reasoning. Custom preset compositions can set the same value through runtime `compaction.cacheRetention`. The first controller request after a landed summary still rebuilds the changed summary prefix.
73
+
74
+ ## Compaction model
75
+
76
+ The default compaction-summary model is `inherit`, which preserves the conversation's current provider/model behavior. A user can explicitly set a separate target and optional reasoning effort in natural language, such as `压缩模型用 provider-x/model-summary,推理档 high`; `odai_compaction_config` persists those explicit values in `$DSH_HOME/odai/compaction.json`. Removing the target restores inheritance. Agent and Plugin share the store when both are deliberately present.
77
+
78
+ The target applies only to future `compaction` summary requests. It does not change the controller, researcher, planner, executor, reviewer, frontend, ordinary conversation, summary output budget, or cache-retention policy. An explicitly configured `reasoningEffort` overrides reasoning only for those summaries. When omitted, existing behavior remains: same-route summaries can inherit controller reasoning, while a cross-model target removes only reasoning proven by equality with the durable controller route and preserves a distinct preselected effort. Each configured target receives one provider-neutral integrity suffix that keeps current facts above superseded/rejected history, preserves continuation-critical opaque values exactly, and self-checks contradictions; duplicate Agent/Plugin runtime instances add it only once. Odai never chooses the provider, model, or reasoning effort on the user's behalf. An invalid store is reported by the tool while runtime requests inherit safely until `set` or `remove` repairs it. An unavailable route, provider error, or incomplete summary fails closed: DSH retains the original history rather than replacing it with a partial checkpoint.
79
+
80
+ ## Skill sources
81
+
82
+ The Agent keeps the managed preset's complete skill copy as its `bundled` default, so existing installations do not change behavior. When the user explicitly asks to show, set, or reset the Odai skill source, the controller uses `odai_skill_source_config` and stores the choice in `$DSH_HOME/odai/source.json`, outside the managed preset:
83
+
84
+ - `bundled`: use the skill shipped with this Agent release.
85
+ - `auto`: allow a compatible current-project `.dsh/skills/odai` or `.agents/skills/odai` bundle, then DSH custom roots and newer user installs under `$DSH_HOME/skills/odai` or `$DSH_AGENTS_HOME/skills/odai` (default `~/.agents/skills/odai`), with bundled fallback.
86
+ - `user`: ignore project roots and require a compatible custom or user-level bundle. An unusable source produces an explicit bundled fallback diagnostic so it can be repaired through the same tool.
87
+
88
+ An independent install must be a complete directory bundle containing `SKILL.md`, `manifest.json`, and every manifest-declared file. The runtime checks SemVer 2.0.0 `skillVersion`, an exact supported `runtimeContract`, complete-file SHA-256 integrity, and same-version content conflicts. Prompt governance and routing role contracts are selected atomically for one agent turn; project sources are scoped by that session's cwd, and changes are reconsidered on the next user turn. Explicit deployment `skillPath` or `ODAI_SKILL_PATH` remains highest priority and requires a DSH restart.
89
+
90
+ ## Status and uninstall
91
+
92
+ ```sh
93
+ npx odai-dsh-agent status
94
+ npx odai-dsh-agent status --json
95
+ npx odai-dsh-agent uninstall
96
+ ```
97
+
98
+ `status` reports `absent`, `installed`, or `drifted`. Update and uninstall fail closed when managed files were changed or unmanaged files were added. Uninstall first checks for legacy Odai session events and, when any exist, requires the same stopped-DSH `--yes` confirmation before making them ignorable; a failed inspection or migration refuses removal. It also refuses while `agent-presets.default` still names `odai`; select another default first so the next session cannot fail on a missing preset. Stop DSH before install, update, or uninstall so session artifacts are not being written concurrently.
99
+
100
+ ## Plugin versus Agent
101
+
102
+ Use only the surface that matches the desired scope:
103
+
104
+ - `odai-dsh-plugin`: profile-wide governance for every preset in that profile.
105
+ - `odai-dsh-agent`: selectable Odai governance for only sessions using this preset.
106
+ - both: supported only for a deliberate combination of profile-wide and Agent-scoped behavior; normally redundant, so it is not the default recommendation.
107
+
108
+ When both are deliberate, a process-shared per-agent/per-turn skill snapshot keeps prompt governance and role contracts identical, the compatibility-safe evidence store deduplicates tool and route records, and denials remain monotonic. Neither package installs or changes the provider-neutral `odai-cli`.
109
+
110
+ ## Development
111
+
112
+ `dsh/runtime/` and `skills/odai/` remain the only editable sources. `npm pack` generates the preset's `runtime/` and `skills/` directories and removes them immediately afterward:
113
+
114
+ ```sh
115
+ npm --prefix dsh/agent test
116
+ npm --prefix dsh/agent run verify:dsh
117
+ npm --prefix dsh/agent run pack:dry-run
118
+ ```
119
+
120
+ The DSH verification uses a temporary home and one isolated Web process. It creates standard and Odai sessions, proves the canonical prompt appears only for Odai, dispatches `odai_routing_config` through the live Odai session and checks its persisted mapping, and proves the child write guard does not leak into the standard preset.
@@ -1,106 +1,106 @@
1
1
  #!/usr/bin/env node
2
-
3
- import { readDshVersion } from "../src/dsh-version.mjs";
4
- import {
5
- inspectAgentInstallation,
6
- installAgentPreset,
7
- SUPPORTED_DSH_VERSION,
8
- uninstallAgentPreset,
9
- } from "../src/installer.mjs";
10
-
11
- const HELP = `Usage: odai-dsh-agent <command> [options]
12
-
13
- Commands:
14
- install Install or update the managed Odai preset
15
- status Inspect the managed Odai preset
16
- uninstall Remove the preset when its managed files are unchanged
17
-
18
- Options:
19
- --dsh-home <path> Override DSH_HOME
20
- --json Print JSON
21
- --yes Confirm DSH is stopped; active-process verification still applies
22
- -h, --help Show this help
23
- `;
24
-
25
- try {
26
- const args = parseArgs(process.argv.slice(2));
27
- if (args.help) {
28
- process.stdout.write(HELP);
29
- } else if (args.command === "install") {
30
- assertDshVersion();
31
- print(await installAgentPreset({
32
- dshHome: args.dshHome,
33
- confirmDshStopped: args.yes,
34
- }), args.json);
35
- } else if (args.command === "status") {
36
- const result = await inspectAgentInstallation({ dshHome: args.dshHome });
37
- print(result, args.json);
38
- if (result.status === "drifted") process.exitCode = 2;
39
- } else if (args.command === "uninstall") {
40
- print(await uninstallAgentPreset({
41
- dshHome: args.dshHome,
42
- confirmDshStopped: args.yes,
43
- }), args.json);
44
- } else {
45
- throw new Error("a command is required\n\n" + HELP);
46
- }
47
- } catch (error) {
48
- process.stderr.write(`odai-dsh-agent: ${error instanceof Error ? error.message : String(error)}\n`);
49
- process.exitCode = 1;
50
- }
51
-
52
- function assertDshVersion() {
53
- const dsh = process.env.DSH_BIN ?? "dsh";
54
- let actual;
55
- try {
56
- actual = readDshVersion({ dsh });
57
- } catch (error) {
58
- throw new Error(`cannot run ${dsh} -V; install DSH ${SUPPORTED_DSH_VERSION} before installing the preset`);
59
- }
60
- if (actual !== SUPPORTED_DSH_VERSION) {
61
- throw new Error(`unsupported DSH version ${actual || "<empty>"}; expected ${SUPPORTED_DSH_VERSION}`);
62
- }
63
- }
64
-
65
- function parseArgs(argv) {
66
- const parsed = { command: undefined, dshHome: undefined, json: false, yes: false, help: false };
67
- for (let index = 0; index < argv.length; index += 1) {
68
- const arg = argv[index];
69
- if (arg === "-h" || arg === "--help") parsed.help = true;
70
- else if (arg === "--json") parsed.json = true;
71
- else if (arg === "--yes") parsed.yes = true;
72
- else if (arg === "--dsh-home") parsed.dshHome = argv[++index];
73
- else if (!parsed.command && ["install", "status", "uninstall"].includes(arg)) parsed.command = arg;
74
- else throw new Error(`unknown argument: ${arg}`);
75
- }
76
- if (parsed.dshHome !== undefined && (typeof parsed.dshHome !== "string" || parsed.dshHome.trim() === "")) {
77
- throw new Error("--dsh-home requires a non-empty path");
78
- }
79
- return parsed;
80
- }
81
-
82
- function print(result, json) {
83
- if (json) {
84
- process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
85
- return;
86
- }
87
- if (result.status) {
88
- process.stdout.write(`${result.status}: ${result.target}\n`);
89
- for (const issue of result.issues ?? []) process.stdout.write(`- ${issue}\n`);
90
- return;
91
- }
92
- process.stdout.write(`${result.operation}: ${result.target}\n`);
93
- if (result.sessionCompatibility?.repairedEvents > 0) {
94
- process.stdout.write(`session compatibility: made ${result.sessionCompatibility.repairedEvents} legacy Odai event(s) ignorable in ${result.sessionCompatibility.repairedArtifacts} session artifact(s)\n`);
95
- }
96
- if (result.sessionCompatibility?.backupPaths?.length > 0) {
97
- process.stdout.write(`session compatibility: retained ${result.sessionCompatibility.backupPaths.length} verified backup artifact(s)\n`);
98
- }
99
- for (const path of result.sessionCompatibility?.tornArtifacts ?? []) {
100
- process.stdout.write(`session compatibility warning: preserved DSH-recoverable torn tail: ${path}\n`);
101
- }
102
- for (const failure of result.sessionCompatibility?.failures ?? []) {
103
- process.stdout.write(`session compatibility warning: ${failure.path}: ${failure.error}\n`);
104
- }
105
- if (result.security) process.stdout.write(`security: ${result.security}\n`);
106
- }
2
+
3
+ import { readDshVersion } from "../src/dsh-version.mjs";
4
+ import {
5
+ inspectAgentInstallation,
6
+ installAgentPreset,
7
+ SUPPORTED_DSH_VERSION,
8
+ uninstallAgentPreset,
9
+ } from "../src/installer.mjs";
10
+
11
+ const HELP = `Usage: odai-dsh-agent <command> [options]
12
+
13
+ Commands:
14
+ install Install or update the managed Odai preset
15
+ status Inspect the managed Odai preset
16
+ uninstall Remove the preset when its managed files are unchanged
17
+
18
+ Options:
19
+ --dsh-home <path> Override DSH_HOME
20
+ --json Print JSON
21
+ --yes Confirm DSH is stopped; active-process verification still applies
22
+ -h, --help Show this help
23
+ `;
24
+
25
+ try {
26
+ const args = parseArgs(process.argv.slice(2));
27
+ if (args.help) {
28
+ process.stdout.write(HELP);
29
+ } else if (args.command === "install") {
30
+ assertDshVersion();
31
+ print(await installAgentPreset({
32
+ dshHome: args.dshHome,
33
+ confirmDshStopped: args.yes,
34
+ }), args.json);
35
+ } else if (args.command === "status") {
36
+ const result = await inspectAgentInstallation({ dshHome: args.dshHome });
37
+ print(result, args.json);
38
+ if (result.status === "drifted") process.exitCode = 2;
39
+ } else if (args.command === "uninstall") {
40
+ print(await uninstallAgentPreset({
41
+ dshHome: args.dshHome,
42
+ confirmDshStopped: args.yes,
43
+ }), args.json);
44
+ } else {
45
+ throw new Error("a command is required\n\n" + HELP);
46
+ }
47
+ } catch (error) {
48
+ process.stderr.write(`odai-dsh-agent: ${error instanceof Error ? error.message : String(error)}\n`);
49
+ process.exitCode = 1;
50
+ }
51
+
52
+ function assertDshVersion() {
53
+ const dsh = process.env.DSH_BIN ?? "dsh";
54
+ let actual;
55
+ try {
56
+ actual = readDshVersion({ dsh });
57
+ } catch (error) {
58
+ throw new Error(`cannot run ${dsh} -V; install DSH ${SUPPORTED_DSH_VERSION} before installing the preset`);
59
+ }
60
+ if (actual !== SUPPORTED_DSH_VERSION) {
61
+ throw new Error(`unsupported DSH version ${actual || "<empty>"}; expected ${SUPPORTED_DSH_VERSION}`);
62
+ }
63
+ }
64
+
65
+ function parseArgs(argv) {
66
+ const parsed = { command: undefined, dshHome: undefined, json: false, yes: false, help: false };
67
+ for (let index = 0; index < argv.length; index += 1) {
68
+ const arg = argv[index];
69
+ if (arg === "-h" || arg === "--help") parsed.help = true;
70
+ else if (arg === "--json") parsed.json = true;
71
+ else if (arg === "--yes") parsed.yes = true;
72
+ else if (arg === "--dsh-home") parsed.dshHome = argv[++index];
73
+ else if (!parsed.command && ["install", "status", "uninstall"].includes(arg)) parsed.command = arg;
74
+ else throw new Error(`unknown argument: ${arg}`);
75
+ }
76
+ if (parsed.dshHome !== undefined && (typeof parsed.dshHome !== "string" || parsed.dshHome.trim() === "")) {
77
+ throw new Error("--dsh-home requires a non-empty path");
78
+ }
79
+ return parsed;
80
+ }
81
+
82
+ function print(result, json) {
83
+ if (json) {
84
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
85
+ return;
86
+ }
87
+ if (result.status) {
88
+ process.stdout.write(`${result.status}: ${result.target}\n`);
89
+ for (const issue of result.issues ?? []) process.stdout.write(`- ${issue}\n`);
90
+ return;
91
+ }
92
+ process.stdout.write(`${result.operation}: ${result.target}\n`);
93
+ if (result.sessionCompatibility?.repairedEvents > 0) {
94
+ process.stdout.write(`session compatibility: made ${result.sessionCompatibility.repairedEvents} legacy Odai event(s) ignorable in ${result.sessionCompatibility.repairedArtifacts} session artifact(s)\n`);
95
+ }
96
+ if (result.sessionCompatibility?.backupPaths?.length > 0) {
97
+ process.stdout.write(`session compatibility: retained ${result.sessionCompatibility.backupPaths.length} verified backup artifact(s)\n`);
98
+ }
99
+ for (const path of result.sessionCompatibility?.tornArtifacts ?? []) {
100
+ process.stdout.write(`session compatibility warning: preserved DSH-recoverable torn tail: ${path}\n`);
101
+ }
102
+ for (const failure of result.sessionCompatibility?.failures ?? []) {
103
+ process.stdout.write(`session compatibility warning: ${failure.path}: ${failure.error}\n`);
104
+ }
105
+ if (result.security) process.stdout.write(`security: ${result.security}\n`);
106
+ }