odai-dsh-agent 0.2.13 → 0.2.16

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 (123) hide show
  1. package/README.md +25 -12
  2. package/build/bin/odai-dsh-agent.mjs +88 -7
  3. package/build/bin/odai-dsh-agent.mjs.map +1 -1
  4. package/build/src/control-center-installer.d.mts +32 -0
  5. package/build/src/control-center-installer.d.mts.map +1 -0
  6. package/build/src/control-center-installer.mjs +112 -0
  7. package/build/src/control-center-installer.mjs.map +1 -0
  8. package/build/src/control-center-prompt.d.mts +4 -0
  9. package/build/src/control-center-prompt.d.mts.map +1 -0
  10. package/build/src/control-center-prompt.mjs +15 -0
  11. package/build/src/control-center-prompt.mjs.map +1 -0
  12. package/build/src/installer.d.mts +3 -1
  13. package/build/src/installer.d.mts.map +1 -1
  14. package/build/src/installer.mjs +46 -4
  15. package/build/src/installer.mjs.map +1 -1
  16. package/client/client.js +517 -0
  17. package/control-center.cordis.patch.yml +3 -0
  18. package/package.json +24 -5
  19. package/preset/odai/agent.cordis.yml +12 -7
  20. package/preset/odai/runtime/canonical-reference.d.mts +15 -0
  21. package/preset/odai/runtime/canonical-reference.d.mts.map +1 -0
  22. package/preset/odai/runtime/canonical-reference.mjs +64 -0
  23. package/preset/odai/runtime/canonical-reference.mjs.map +1 -0
  24. package/preset/odai/runtime/compaction-config.mjs +1 -1
  25. package/preset/odai/runtime/compaction-config.mjs.map +1 -1
  26. package/preset/odai/runtime/context-activation.d.mts +2 -3
  27. package/preset/odai/runtime/context-activation.d.mts.map +1 -1
  28. package/preset/odai/runtime/context-activation.mjs +8 -5
  29. package/preset/odai/runtime/context-activation.mjs.map +1 -1
  30. package/preset/odai/runtime/control-center-host.d.mts +10 -0
  31. package/preset/odai/runtime/control-center-host.d.mts.map +1 -0
  32. package/preset/odai/runtime/control-center-host.mjs +15 -0
  33. package/preset/odai/runtime/control-center-host.mjs.map +1 -0
  34. package/preset/odai/runtime/control-center-runtime.d.mts +26 -0
  35. package/preset/odai/runtime/control-center-runtime.d.mts.map +1 -0
  36. package/preset/odai/runtime/control-center-runtime.mjs +118 -0
  37. package/preset/odai/runtime/control-center-runtime.mjs.map +1 -0
  38. package/preset/odai/runtime/governance.d.mts +1 -1
  39. package/preset/odai/runtime/governance.d.mts.map +1 -1
  40. package/preset/odai/runtime/governance.mjs +0 -1
  41. package/preset/odai/runtime/governance.mjs.map +1 -1
  42. package/preset/odai/runtime/human-care.d.mts +0 -1
  43. package/preset/odai/runtime/human-care.d.mts.map +1 -1
  44. package/preset/odai/runtime/human-care.mjs +0 -1
  45. package/preset/odai/runtime/human-care.mjs.map +1 -1
  46. package/preset/odai/runtime/human-safety.d.mts +0 -1
  47. package/preset/odai/runtime/human-safety.d.mts.map +1 -1
  48. package/preset/odai/runtime/human-safety.mjs +0 -1
  49. package/preset/odai/runtime/human-safety.mjs.map +1 -1
  50. package/preset/odai/runtime/index.d.mts.map +1 -1
  51. package/preset/odai/runtime/index.mjs +10 -1
  52. package/preset/odai/runtime/index.mjs.map +1 -1
  53. package/preset/odai/runtime/lifecycle-runtime.d.mts +0 -2
  54. package/preset/odai/runtime/lifecycle-runtime.d.mts.map +1 -1
  55. package/preset/odai/runtime/lifecycle-runtime.mjs +3 -74
  56. package/preset/odai/runtime/lifecycle-runtime.mjs.map +1 -1
  57. package/preset/odai/runtime/output-config.d.mts +1 -1
  58. package/preset/odai/runtime/output-config.d.mts.map +1 -1
  59. package/preset/odai/runtime/output-config.mjs +2 -2
  60. package/preset/odai/runtime/output-config.mjs.map +1 -1
  61. package/preset/odai/runtime/prompt-runtime.d.mts +0 -1
  62. package/preset/odai/runtime/prompt-runtime.d.mts.map +1 -1
  63. package/preset/odai/runtime/prompt-runtime.mjs +1 -13
  64. package/preset/odai/runtime/prompt-runtime.mjs.map +1 -1
  65. package/preset/odai/runtime/responsibility-return.d.mts +1 -4
  66. package/preset/odai/runtime/responsibility-return.d.mts.map +1 -1
  67. package/preset/odai/runtime/responsibility-return.mjs +10 -25
  68. package/preset/odai/runtime/responsibility-return.mjs.map +1 -1
  69. package/preset/odai/runtime/responsibility-scope.d.mts +1 -5
  70. package/preset/odai/runtime/responsibility-scope.d.mts.map +1 -1
  71. package/preset/odai/runtime/responsibility-scope.mjs +4 -24
  72. package/preset/odai/runtime/responsibility-scope.mjs.map +1 -1
  73. package/preset/odai/runtime/role-overlays.d.mts.map +1 -1
  74. package/preset/odai/runtime/role-overlays.mjs +1 -4
  75. package/preset/odai/runtime/role-overlays.mjs.map +1 -1
  76. package/preset/odai/runtime/router.d.mts +3 -13
  77. package/preset/odai/runtime/router.d.mts.map +1 -1
  78. package/preset/odai/runtime/router.mjs +9 -22
  79. package/preset/odai/runtime/router.mjs.map +1 -1
  80. package/preset/odai/runtime/routing-config.d.mts +11 -2
  81. package/preset/odai/runtime/routing-config.d.mts.map +1 -1
  82. package/preset/odai/runtime/routing-config.mjs +96 -86
  83. package/preset/odai/runtime/routing-config.mjs.map +1 -1
  84. package/preset/odai/runtime/routing-context.d.mts.map +1 -1
  85. package/preset/odai/runtime/routing-context.mjs +3 -24
  86. package/preset/odai/runtime/routing-context.mjs.map +1 -1
  87. package/preset/odai/runtime/runtime-config.d.mts +1 -1
  88. package/preset/odai/runtime/runtime-config.d.mts.map +1 -1
  89. package/preset/odai/runtime/runtime-support.d.mts.map +1 -1
  90. package/preset/odai/runtime/runtime-support.mjs +1 -3
  91. package/preset/odai/runtime/runtime-support.mjs.map +1 -1
  92. package/preset/odai/runtime/runtime-types.d.mts +1 -4
  93. package/preset/odai/runtime/runtime-types.d.mts.map +1 -1
  94. package/preset/odai/runtime/skill-bundle.d.mts +8 -2
  95. package/preset/odai/runtime/skill-bundle.d.mts.map +1 -1
  96. package/preset/odai/runtime/skill-bundle.mjs +56 -22
  97. package/preset/odai/runtime/skill-bundle.mjs.map +1 -1
  98. package/preset/odai/runtime/skill-evolution.d.mts.map +1 -1
  99. package/preset/odai/runtime/skill-evolution.mjs +15 -4
  100. package/preset/odai/runtime/skill-evolution.mjs.map +1 -1
  101. package/preset/odai/runtime/tool-runtime.d.mts +0 -1
  102. package/preset/odai/runtime/tool-runtime.d.mts.map +1 -1
  103. package/preset/odai/runtime/tool-runtime.mjs +17 -53
  104. package/preset/odai/runtime/tool-runtime.mjs.map +1 -1
  105. package/preset/odai/skills/odai/SKILL.md +31 -34
  106. package/preset/odai/skills/odai/assets/routing-roles/controller.md +4 -4
  107. package/preset/odai/skills/odai/assets/routing-roles/planner.md +2 -3
  108. package/preset/odai/skills/odai/assets/routing-roles/researcher.md +1 -1
  109. package/preset/odai/skills/odai/assets/routing-roles/reviewer.md +2 -2
  110. package/preset/odai/skills/odai/manifest.json +20 -5
  111. package/preset/odai/skills/odai/references/leverage.md +9 -12
  112. package/preset/odai/skills/odai/references/support.md +7 -13
  113. package/preset/odai/skills/odai/references/verification.md +1 -0
  114. package/preset/odai/skills/odai/scripts/build-routing.mjs +71 -30
  115. package/preset/odai/skills/odai/scripts/install-routing.mjs +18 -22
  116. package/preset/odai/skills/odai/scripts/run-role.mjs +8 -59
  117. package/preset/odai/skills/odai/scripts/verify-routing.mjs +3 -3
  118. package/preset/odai/runtime/route-card.d.mts +0 -42
  119. package/preset/odai/runtime/route-card.d.mts.map +0 -1
  120. package/preset/odai/runtime/route-card.mjs +0 -180
  121. package/preset/odai/runtime/route-card.mjs.map +0 -1
  122. package/preset/odai/skills/odai/assets/routing-roles/executor.md +0 -11
  123. package/preset/odai/skills/odai/scripts/run-routing.mjs +0 -1154
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # odai dsh agent
2
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.
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`: the preset install does not activate global governance. In an interactive terminal, the command separately offers to add the same package's Control Center to the Web profile and performs that profile change only after confirmation.
4
4
 
5
5
  The installed preset is self-contained:
6
6
 
@@ -13,7 +13,7 @@ $DSH_HOME/.agent-presets/odai/
13
13
  .odai-agent.json
14
14
  ```
15
15
 
16
- The source composition preserves every capability row and setting from the `standard` agent surface in `@deepseek-ai/dsh@0.1.1-rc.2`, then adds the scoped Odai runtime in default `auto` mode. The rc.2 Standard composition is byte-identical to rc.1 and the historical rc.8 composition; for rc.7, the installer restores that release's optional-provider wording before hashing and publishing the managed preset; rc.6 is no longer supported as of `0.2.6`. Release verification compares each rendered composition against its 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. Responsibility words are optional signals rather than commands: evidence-grounded task-state gaps route at any step, the gap tool records rather than claims a route start, terminal decisions consume the proposal, an incomplete reviewer proposal waits for changed native evidence, and an identical planner/controller model remains inline without another model call. An original request that already authorizes implementation automatically continues from a frozen planner card to executor; plan-only, new-task, expanded-scope, and unknown authorization cannot do so. Reviewer children require a current hash-addressed evidence packet whose diff is newer than the last write and whose latest successful test follows that diff. An incomplete packet keeps the current controller route, reports why native evidence was excluded, suppresses unchanged repeat notices, and reassesses the pending proposal after decisive evidence changes without claiming independent acceptance or terminating the authorized task. Every route is resolved before provider I/O; deterministic invalid persisted mappings are backed up and exact-match removed, while recoverable provider failures preserve them. Frontend route failure becomes an explicit local controller fallback without a routed receipt. `execute` remains an explicit comparison mode and `observe` changes no model or child while retaining fail-closed high-impact protection. Configured compaction streams are buffered so partial failed output cannot contaminate the inherited-route retry or replace original history.
16
+ The source composition preserves every capability row and setting from the `standard` agent surface in `@deepseek-ai/dsh@0.1.2-alpha.2`, then adds the scoped Odai runtime in default `auto` mode. For `0.1.1-rc.2`, the installer deterministically removes alpha.2-only goal-command and subagent-model rows and restores the rc.2 Web setting before hashing and publishing the managed preset. Release verification resolves each release's own Standard package path and compares the rendered composition against that exact 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. Responsibility words are optional signals rather than commands: evidence-grounded task-state gaps route at any step, the gap tool records rather than claims a route start, terminal decisions consume the proposal, an incomplete reviewer proposal waits for changed native evidence, and an identical planner/controller model remains inline without another model call. After planner handback, the controller resumes implementation only when the current user task authorizes it; plan-only, new-task, expanded-scope, and unknown authorization remain non-implementing. Reviewer children require a current hash-addressed evidence packet whose diff is newer than the last write and whose latest successful test follows that diff. An incomplete packet keeps the current controller route, reports why native evidence was excluded, suppresses unchanged repeat notices, and reassesses the pending proposal after decisive evidence changes without claiming independent acceptance or terminating the authorized task. Every route is resolved before provider I/O; deterministic invalid persisted mappings are backed up and exact-match removed, while recoverable provider failures preserve them. Frontend route failure becomes an explicit local controller fallback without a routed receipt. `execute` remains an explicit comparison mode and `observe` changes no model or child while retaining fail-closed high-impact protection. Configured compaction streams are buffered so partial failed output cannot contaminate the inherited-route retry or replace original history.
17
17
 
18
18
  The preset includes the same local long-term semantic memory runtime as the Plugin. Default `auto` mode performs no hidden model call: it automatically captures only high-confidence durable statements from the direct-human message authenticated by the latest open-turn session event, keeps ambiguous or conflicting candidates inert, and recalls only bounded active global/project records as untrusted historical context. Matching direct intent, or the compact capability gateway on a later step, exposes the controller-only `odai_memory` tool for inspection, search, confirmation, correction, physical forgetting, exact-phrase clearing, and `auto`/`off` mode changes. Recognized secrets, contact identifiers, health/crisis content, temporary instructions, hypotheses, quotes, and code are rejected; the current user and project authority always override memory. State lives at `$DSH_HOME/odai/memory/store.json`, outside `.agent-presets`, so install, update, and uninstall preserve it. An invalid or symlinked store fails closed. The matcher is not a replacement for protecting the underlying DSH session history from sensitive input.
19
19
 
@@ -31,7 +31,7 @@ With DSH already installed, run the single Agent package command below. The pack
31
31
  npx odai-dsh-agent install
32
32
  ```
33
33
 
34
- The installer checks `dsh -V` and currently accepts exactly `0.1.1-rc.2`; `0.2.13` rejects rc.7, rc.1, and every other developer-preview release. It records the detected version in the managed manifest and installs the rc.2 Standard composition directly.
34
+ The installer checks `dsh -V`; the `0.2.16` candidate accepts exactly `0.1.1-rc.2` and `0.1.2-alpha.2` and rejects every other developer-preview release. It records the detected version in the managed manifest and renders the Standard composition for that exact release. In an interactive terminal it then asks `同时把 Odai 控制中心安装到 DSH profile “web”?[Y/n]`; Enter or `y` installs it, while `n` leaves the profile unchanged. Non-interactive and `--json` installs never infer consent: automation can use `--with-control-center` or `--without-control-center` explicitly, with `--profile <name>` selecting a profile other than `web`.
35
35
 
36
36
  `DSH_HOME` is honored. An explicit location can be supplied without changing the environment:
37
37
 
@@ -47,23 +47,36 @@ The installer copies through a mode-tightened staging directory and atomically p
47
47
 
48
48
  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.
49
49
 
50
+ ## Control Center
51
+
52
+ The optional profile entry ships inside `odai-dsh-agent`; it is not a third package. It adds one Chinese Control Center launcher to DSH Web with a real current-turn responsibility graph, session evidence timeline, structured event inspector, and routing controls for the four optional responsibilities. The controller remains host-managed and read-only. Routing writes use the same validated, locked, atomic routing action as the conversation tool and apply on the next user turn. Configured models alone are never displayed as execution evidence.
53
+
54
+ The main `install` prompt is the recommended entry. These lifecycle commands remain available for inspection, recovery, and automation:
55
+
56
+ ```sh
57
+ npx odai-dsh-agent control-center install [--profile web]
58
+ npx odai-dsh-agent control-center status [--profile web]
59
+ npx odai-dsh-agent control-center uninstall [--profile web]
60
+ ```
61
+
62
+ A Control Center profile change requires one normal DSH Web process restart. Removing it does not remove the Agent preset, routing configuration, or session evidence.
63
+
50
64
  ## Responsibility models
51
65
 
52
- 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:
66
+ The Agent ships no researcher, planner, 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:
53
67
 
54
68
  ```text
55
69
  证据调查用 provider-r/model-research,推理档 high。
56
70
  规划用 provider-x/model-plan,推理档 high。
57
- 执行模型设为 provider-x/model-y。
58
71
  验收改用 provider-z/model-review,推理档 max。
59
72
  前端制作用 provider-f/model-frontend,输出上限 4096。
60
73
  规划职责改成 child,前端职责保持 same-turn。
61
74
  研究和验收职责改成 same-turn。
62
75
  ```
63
76
 
64
- The controller calls `odai_routing_config` to persist that explicit choice. Researcher, planner, reviewer, and frontend each accept an explicit `same-turn` or `child` dispatch override; executor accepts `same-turn` only. The tool uses separate `set-dispatch`/`reset-dispatch` actions, so changing a dispatch override does not remove its model mapping. 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. Whenever routing or explicit mapping management needs it, runtime resolves a fresh merged effective-mapping snapshot, with persisted mappings preferred over deployment mappings; the full snapshot enters the model prompt only for mapping-management intent and remains authoritative over stale compaction text. The tool also exposes the latest current-session actual route receipt; configured targets alone never prove that a responsibility ran. 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.
77
+ The controller calls `odai_routing_config` to persist that explicit choice. Researcher, planner, reviewer, and frontend each accept an explicit `same-turn` or `child` dispatch override; implementation remains with the controller. The tool uses separate `set-dispatch`/`reset-dispatch` actions, so changing a dispatch override does not remove its model mapping. 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. A legacy Executor mapping is ignored without invalidating current responsibilities and is removed on the next configuration write. 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. Whenever routing or explicit mapping management needs it, runtime resolves a fresh merged effective-mapping snapshot, with persisted mappings preferred over deployment mappings; the full snapshot enters the model prompt only for mapping-management intent and remains authoritative over stale compaction text. The tool also exposes the latest current-session actual route receipt; configured targets alone never prove that a responsibility ran. 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.
65
78
 
66
- Researcher and frontend are optional evidence/production upgrades whose missing mappings keep the original route without claiming success. A researcher child is limited to a bounded multi-source repository question; technical facts available through controller tools are investigated directly instead of manufacturing a role call. 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 responsibility. Same-turn routes and child outputs require actual request-header evidence. Same-turn researcher, planner, and reviewer are read-only and must return through `odai_responsibility_return`; planner may return directly to executor only through an authorized frozen route card. Missing handback restores and continues the controller instead of treating the read-only text as final delivery. Deterministic invalid persisted mappings are backed up and exact-match removed; credentials, quota, rate-limit, server, timeout, and transport failures preserve configuration and fall back only for the current call. A generic subagent is not a responsibility route. A manual responsibility child must use an `odai-<responsibility>` label and cannot finish successfully without a matching actual-route receipt. Odai never chooses a model or price on the user's behalf.
79
+ Researcher and frontend are optional evidence/production upgrades whose missing mappings keep the original route without claiming success. A researcher child is limited to a bounded multi-source repository question; technical facts available through controller tools are investigated directly instead of manufacturing a role call. Planner 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 responsibility. Same-turn routes and child outputs require actual request-header evidence. Same-turn researcher, planner, and reviewer are read-only and must return through `odai_responsibility_return` to the controller, which resumes any authorized implementation. Missing handback restores and continues the controller instead of treating the read-only text as final delivery. Deterministic invalid persisted mappings are backed up and exact-match removed; credentials, quota, rate-limit, server, timeout, and transport failures preserve configuration and fall back only for the current call. A generic subagent is not a responsibility route. A manual responsibility child must use an `odai-<responsibility>` label and cannot finish successfully without a matching actual-route receipt. Odai never chooses a model or price on the user's behalf.
67
80
 
68
81
  ## Controller output policy
69
82
 
@@ -87,7 +100,7 @@ A same-provider/model compaction inherits controller reasoning while keeping its
87
100
 
88
101
  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.
89
102
 
90
- 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. The configured stream is buffered until a valid terminal result. Partial failed chunks are discarded before one retry with the untouched inherited request; deterministic invalid persisted targets are backed up and exact-match removed, transient failures preserve them, and DSH retains original history until a complete summary lands.
103
+ The target applies only to future `compaction` summary requests. It does not change the controller, researcher, planner, 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. The configured stream is buffered until a valid terminal result. Partial failed chunks are discarded before one retry with the untouched inherited request; deterministic invalid persisted targets are backed up and exact-match removed, transient failures preserve them, and DSH retains original history until a complete summary lands.
91
104
 
92
105
  ## Skill sources
93
106
 
@@ -121,13 +134,13 @@ npx odai-dsh-agent uninstall
121
134
 
122
135
  ## Plugin versus Agent
123
136
 
124
- Use only the surface that matches the desired scope:
137
+ Choose either package or install both when their scopes are useful:
125
138
 
126
139
  - `odai-dsh-plugin`: profile-wide governance for every preset in that profile.
127
- - `odai-dsh-agent`: selectable Odai governance for only sessions using this preset.
128
- - both: supported only for a deliberate combination of profile-wide and Agent-scoped behavior; normally redundant, so it is not the default recommendation.
140
+ - `odai-dsh-agent`: selectable Odai governance for sessions using this preset.
141
+ - both: supported even when users arrive at the combination independently; Plugin provides the single Control Center surface while the Agent preset remains selectable.
129
142
 
130
- 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`.
143
+ When both are present, 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, host RPC registration is reference-counted, and denials remain monotonic. Removing either package leaves the other package and shared routing/evidence stores usable. Neither package installs or changes the provider-neutral `odai-cli`.
131
144
 
132
145
  ## Development
133
146
 
@@ -1,16 +1,24 @@
1
1
  #!/usr/bin/env node
2
+ import { promptForControlCenterInstall } from "../src/control-center-prompt.mjs";
3
+ import { inspectAgentControlCenter, installAgentControlCenter, uninstallAgentControlCenter, } from "../src/control-center-installer.mjs";
2
4
  import { readDshVersion } from "../src/dsh-version.mjs";
3
5
  import { inspectAgentInstallation, installAgentPreset, SUPPORTED_DSH_VERSIONS, uninstallAgentPreset, } from "../src/installer.mjs";
4
6
  const HELP = `Usage: odai-dsh-agent <command> [options]
5
7
 
6
8
  Commands:
7
- install Install or update the managed Odai preset
8
- status Inspect the managed Odai preset
9
- uninstall Remove the preset when its managed files are unchanged
9
+ install Install or update the managed Odai preset
10
+ status Inspect the managed Odai preset
11
+ uninstall Remove the preset when its managed files are unchanged
12
+ control-center install Add the Agent package's Control Center to a DSH profile
13
+ control-center status Inspect the Agent Control Center profile state
14
+ control-center uninstall Remove only the Agent Control Center profile state
10
15
 
11
16
  Options:
12
17
  --dsh-home <path> Override DSH_HOME
13
- --json Print JSON
18
+ --profile <name> Control Center profile (default: web)
19
+ --with-control-center Install Control Center without prompting
20
+ --without-control-center Skip the interactive Control Center prompt
21
+ --json Print JSON; never prompts
14
22
  --yes Confirm DSH is stopped; active-process verification still applies
15
23
  -h, --help Show this help
16
24
  `;
@@ -21,11 +29,27 @@ try {
21
29
  }
22
30
  else if (args.command === "install") {
23
31
  const dshVersion = assertDshVersion();
24
- print(await installAgentPreset({
32
+ const preset = await installAgentPreset({
25
33
  dshHome: args.dshHome,
26
34
  dshVersion,
27
35
  confirmDshStopped: args.yes,
28
- }), args.json);
36
+ });
37
+ if (args.json) {
38
+ const controlCenter = args.controlCenter === true
39
+ ? await installAgentControlCenter({ dshHome: args.dshHome, profile: args.profile })
40
+ : undefined;
41
+ process.stdout.write(`${JSON.stringify({
42
+ ...preset,
43
+ ...(controlCenter ? { controlCenter } : {}),
44
+ }, null, 2)}\n`);
45
+ }
46
+ else {
47
+ print(preset, false);
48
+ const installControlCenter = await shouldInstallControlCenter(args);
49
+ if (installControlCenter) {
50
+ print(await installAgentControlCenter({ dshHome: args.dshHome, profile: args.profile }), false);
51
+ }
52
+ }
29
53
  }
30
54
  else if (args.command === "status") {
31
55
  const result = await inspectAgentInstallation({ dshHome: args.dshHome });
@@ -39,6 +63,18 @@ try {
39
63
  confirmDshStopped: args.yes,
40
64
  }), args.json);
41
65
  }
66
+ else if (args.command === "control-center" && args.controlCenterCommand === "install") {
67
+ print(await installAgentControlCenter({ dshHome: args.dshHome, profile: args.profile }), args.json);
68
+ }
69
+ else if (args.command === "control-center" && args.controlCenterCommand === "status") {
70
+ const result = await inspectAgentControlCenter({ dshHome: args.dshHome, profile: args.profile });
71
+ print(result, args.json);
72
+ if (result.status === "drifted")
73
+ process.exitCode = 2;
74
+ }
75
+ else if (args.command === "control-center" && args.controlCenterCommand === "uninstall") {
76
+ print(await uninstallAgentControlCenter({ dshHome: args.dshHome, profile: args.profile }), args.json);
77
+ }
42
78
  else {
43
79
  throw new Error("a command is required\n\n" + HELP);
44
80
  }
@@ -47,6 +83,27 @@ catch (error) {
47
83
  process.stderr.write(`odai-dsh-agent: ${error instanceof Error ? error.message : String(error)}\n`);
48
84
  process.exitCode = 1;
49
85
  }
86
+ async function shouldInstallControlCenter(args) {
87
+ if (args.controlCenter !== undefined)
88
+ return args.controlCenter;
89
+ if (args.json || !process.stdin.isTTY || !process.stdout.isTTY)
90
+ return false;
91
+ const current = await inspectAgentControlCenter({ dshHome: args.dshHome, profile: args.profile });
92
+ if (current.status === "installed") {
93
+ process.stdout.write(`Control Center 已安装:${current.target}\n`);
94
+ return false;
95
+ }
96
+ if (current.status === "drifted") {
97
+ process.stdout.write(`Control Center profile 状态存在漂移,已跳过:${current.target}\n`);
98
+ for (const issue of current.issues)
99
+ process.stdout.write(`- ${issue}\n`);
100
+ return false;
101
+ }
102
+ const accepted = await promptForControlCenterInstall(process.stdin, process.stdout, args.profile ?? "web");
103
+ if (!accepted)
104
+ process.stdout.write("已跳过 Control Center;稍后可运行 odai-dsh-agent control-center install。\n");
105
+ return accepted;
106
+ }
50
107
  function assertDshVersion() {
51
108
  const dsh = process.env.DSH_BIN ?? "dsh";
52
109
  let actual;
@@ -71,16 +128,40 @@ function parseArgs(argv) {
71
128
  parsed.json = true;
72
129
  else if (arg === "--yes")
73
130
  parsed.yes = true;
131
+ else if (arg === "--with-control-center") {
132
+ if (parsed.controlCenter === false)
133
+ throw new Error("--with-control-center conflicts with --without-control-center");
134
+ parsed.controlCenter = true;
135
+ }
136
+ else if (arg === "--without-control-center") {
137
+ if (parsed.controlCenter === true)
138
+ throw new Error("--without-control-center conflicts with --with-control-center");
139
+ parsed.controlCenter = false;
140
+ }
74
141
  else if (arg === "--dsh-home")
75
142
  parsed.dshHome = argv[++index];
76
- else if (!parsed.command && (arg === "install" || arg === "status" || arg === "uninstall"))
143
+ else if (arg === "--profile")
144
+ parsed.profile = argv[++index];
145
+ else if (!parsed.command && (arg === "install" || arg === "status" || arg === "uninstall" || arg === "control-center"))
77
146
  parsed.command = arg;
147
+ else if (parsed.command === "control-center" && !parsed.controlCenterCommand
148
+ && (arg === "install" || arg === "status" || arg === "uninstall"))
149
+ parsed.controlCenterCommand = arg;
78
150
  else
79
151
  throw new Error(`unknown argument: ${arg}`);
80
152
  }
81
153
  if (parsed.dshHome !== undefined && parsed.dshHome.trim() === "") {
82
154
  throw new Error("--dsh-home requires a non-empty path");
83
155
  }
156
+ if (parsed.profile !== undefined && parsed.profile.trim() === "") {
157
+ throw new Error("--profile requires a non-empty name");
158
+ }
159
+ if (parsed.command === "control-center" && !parsed.controlCenterCommand && !parsed.help) {
160
+ throw new Error("control-center requires install, status, or uninstall");
161
+ }
162
+ if (parsed.controlCenter !== undefined && parsed.command !== "install" && !parsed.help) {
163
+ throw new Error("--with-control-center and --without-control-center are valid only with install");
164
+ }
84
165
  return parsed;
85
166
  }
86
167
  function print(result, json) {
@@ -1 +1 @@
1
- {"version":3,"file":"odai-dsh-agent.mjs","sourceRoot":"","sources":["../../bin/odai-dsh-agent.mts"],"names":[],"mappings":";AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAoB9B,MAAM,IAAI,GAAG;;;;;;;;;;;;CAYZ,CAAC;AAEF,IAAI,CAAC;IACH,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;SAAM,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC;QACtC,KAAK,CAAC,MAAM,kBAAkB,CAAC;YAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,UAAU;YACV,iBAAiB,EAAE,IAAI,CAAC,GAAG;SAC5B,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;SAAM,IAAI,IAAI,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACzE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACzB,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACxD,CAAC;SAAM,IAAI,IAAI,CAAC,OAAO,KAAK,WAAW,EAAE,CAAC;QACxC,KAAK,CAAC,MAAM,oBAAoB,CAAC;YAC/B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,iBAAiB,EAAE,IAAI,CAAC,GAAG;SAC5B,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,IAAI,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpG,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,gBAAgB;IACvB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,KAAK,CAAC;IACzC,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,cAAc,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,cAAc,GAAG,uBAAuB,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAC5H,CAAC;IACD,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,2BAA2B,MAAM,IAAI,SAAS,qBAAqB,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1H,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,SAAS,CAAC,IAAuB;IACxC,MAAM,MAAM,GAAiB,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACtE,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,QAAQ;YAAE,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;aACpD,IAAI,GAAG,KAAK,QAAQ;YAAE,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;aACzC,IAAI,GAAG,KAAK,OAAO;YAAE,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC;aACvC,IAAI,GAAG,KAAK,YAAY;YAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;aACzD,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,WAAW,CAAC;YAAE,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC;;YAC5G,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACjE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,KAAK,CAAC,MAAqB,EAAE,IAAa;IACjD,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC7D,OAAO;IACT,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;QAC7D,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,IAAI,EAAE;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;QAC9E,OAAO;IACT,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,SAAS,KAAK,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;IAChE,MAAM,aAAa,GAAG,MAAM,CAAC,oBAAoB,CAAC;IAClD,IAAI,CAAC,aAAa,EAAE,cAAc,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,aAAa,EAAE,cAAc,IAAI,CAAC,sCAAsC,aAAa,EAAE,iBAAiB,IAAI,CAAC,wBAAwB,CAAC,CAAC;IAC7L,CAAC;IACD,IAAI,CAAC,aAAa,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;QAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,aAAa,EAAE,WAAW,CAAC,MAAM,IAAI,CAAC,gCAAgC,CAAC,CAAC;IAClI,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,aAAa,IAAI,EAAE,EAAE,CAAC;QACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uEAAuE,IAAI,IAAI,CAAC,CAAC;IACxG,CAAC;IACD,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,QAAQ,IAAI,EAAE,EAAE,CAAC;QACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC;IAC7F,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;AAC9E,CAAC"}
1
+ {"version":3,"file":"odai-dsh-agent.mjs","sourceRoot":"","sources":["../../bin/odai-dsh-agent.mts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { ExecFileSyncOptionsWithStringEncoding } from "node:child_process";
2
+ type CommandExecutor = (command: string, args: string[], options: ExecFileSyncOptionsWithStringEncoding) => string;
3
+ export interface AgentControlCenterOptions {
4
+ dshHome?: string;
5
+ profile?: string;
6
+ packageSpec?: string;
7
+ dshBin?: string;
8
+ platform?: NodeJS.Platform;
9
+ execute?: CommandExecutor;
10
+ }
11
+ export interface AgentControlCenterInspection {
12
+ status: "absent" | "installed" | "drifted";
13
+ issues: string[];
14
+ dshHome: string;
15
+ profile: string;
16
+ target: string;
17
+ dependency?: string;
18
+ }
19
+ export declare function inspectAgentControlCenter(options?: AgentControlCenterOptions): Promise<AgentControlCenterInspection>;
20
+ export declare function installAgentControlCenter(options?: AgentControlCenterOptions): Promise<Readonly<{
21
+ operation: "installed" | "unchanged";
22
+ target: string;
23
+ profile: string;
24
+ dependency: string;
25
+ }>>;
26
+ export declare function uninstallAgentControlCenter(options?: AgentControlCenterOptions): Promise<Readonly<{
27
+ operation: "uninstalled" | "absent";
28
+ target: string;
29
+ profile: string;
30
+ }>>;
31
+ export {};
32
+ //# sourceMappingURL=control-center-installer.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-center-installer.d.mts","sourceRoot":"","sources":["../../src/control-center-installer.mts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,oBAAoB,CAAC;AAiBhF,KAAK,eAAe,GAAG,CACrB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,qCAAqC,KAC3C,MAAM,CAAC;AAEZ,MAAM,WAAW,yBAAyB;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,OAAO,CAAC,EAAE,eAAe,CAAC;CAC3B;AAED,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAC;IAC3C,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA0CD,wBAAsB,yBAAyB,CAC7C,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,4BAA4B,CAAC,CAoBvC;AAmBD,wBAAsB,yBAAyB,CAC7C,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,QAAQ,CAAC;IAAE,SAAS,EAAE,WAAW,GAAG,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAelH;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,QAAQ,CAAC;IAAE,SAAS,EAAE,aAAa,GAAG,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAY7F"}
@@ -0,0 +1,112 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { readFile } from "node:fs/promises";
3
+ import { dirname, resolve, sep } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { resolveDshHome } from "./installer.mjs";
6
+ const moduleDirectory = dirname(fileURLToPath(import.meta.url));
7
+ const packageRoot = resolve(moduleDirectory, moduleDirectory.endsWith(`${sep}build${sep}src`) ? "../.." : "..");
8
+ const parsedMetadata = JSON.parse(await readFile(resolve(packageRoot, "package.json"), "utf8"));
9
+ if (!isRecord(parsedMetadata) || typeof parsedMetadata.name !== "string" || typeof parsedMetadata.version !== "string") {
10
+ throw new Error("odai-dsh-agent package metadata is invalid for Control Center management");
11
+ }
12
+ const packageMetadata = { name: parsedMetadata.name, version: parsedMetadata.version };
13
+ function isRecord(value) {
14
+ return typeof value === "object" && value !== null && !Array.isArray(value);
15
+ }
16
+ function assertProfile(value) {
17
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(value)) {
18
+ throw new TypeError("profile must contain only letters, digits, dots, underscores, or hyphens");
19
+ }
20
+ return value;
21
+ }
22
+ async function profileMetadata(path) {
23
+ let source;
24
+ try {
25
+ source = await readFile(path, "utf8");
26
+ }
27
+ catch (error) {
28
+ if (isRecord(error) && error.code === "ENOENT")
29
+ return undefined;
30
+ throw error;
31
+ }
32
+ const parsed = JSON.parse(source);
33
+ if (!isRecord(parsed))
34
+ throw new TypeError(`DSH profile package metadata ${path} must be an object`);
35
+ const dependencies = isRecord(parsed.dependencies)
36
+ ? Object.fromEntries(Object.entries(parsed.dependencies).filter((entry) => typeof entry[1] === "string"))
37
+ : undefined;
38
+ const dsh = isRecord(parsed.dsh) && isRecord(parsed.dsh.profile)
39
+ ? { profile: { bundles: Array.isArray(parsed.dsh.profile.bundles)
40
+ ? parsed.dsh.profile.bundles.filter((entry) => typeof entry === "string")
41
+ : undefined } }
42
+ : undefined;
43
+ return { dependencies, dsh };
44
+ }
45
+ export async function inspectAgentControlCenter(options = {}) {
46
+ const dshHome = resolveDshHome(options.dshHome);
47
+ const profile = assertProfile(options.profile ?? "web");
48
+ const target = resolve(dshHome, "profiles", profile);
49
+ const metadata = await profileMetadata(resolve(target, "package.json"));
50
+ if (!metadata)
51
+ return { status: "absent", issues: [], dshHome, profile, target };
52
+ const dependency = metadata.dependencies?.[packageMetadata.name];
53
+ const bundled = metadata.dsh?.profile?.bundles?.includes(packageMetadata.name) === true;
54
+ if (!dependency && !bundled)
55
+ return { status: "absent", issues: [], dshHome, profile, target };
56
+ const issues = [];
57
+ if (!dependency)
58
+ issues.push(`missing ${packageMetadata.name} profile dependency`);
59
+ if (!bundled)
60
+ issues.push(`missing ${packageMetadata.name} profile bundle entry`);
61
+ return {
62
+ status: issues.length === 0 ? "installed" : "drifted",
63
+ issues,
64
+ dshHome,
65
+ profile,
66
+ target,
67
+ ...(dependency ? { dependency } : {}),
68
+ };
69
+ }
70
+ function runPluginCommand(action, operand, options) {
71
+ const dsh = options.dshBin ?? process.env.DSH_BIN ?? "dsh";
72
+ const platform = options.platform ?? process.platform;
73
+ const command = platform === "win32" && dsh === "dsh" ? "dsh.cmd" : dsh;
74
+ const execute = options.execute ?? execFileSync;
75
+ const processOptions = {
76
+ encoding: "utf8",
77
+ env: { ...process.env, DSH_HOME: resolveDshHome(options.dshHome) },
78
+ ...(platform === "win32" ? { shell: true } : {}),
79
+ };
80
+ execute(command, ["plugin", "--profile", assertProfile(options.profile ?? "web"), action, operand], processOptions);
81
+ }
82
+ export async function installAgentControlCenter(options = {}) {
83
+ const current = await inspectAgentControlCenter(options);
84
+ if (current.status === "drifted") {
85
+ throw new Error(`refusing to replace drifted Control Center profile state at ${current.target}: ${current.issues.join("; ")}`);
86
+ }
87
+ if (current.status === "installed") {
88
+ return Object.freeze({ operation: "unchanged", target: current.target, profile: current.profile, dependency: current.dependency ?? "" });
89
+ }
90
+ const packageSpec = options.packageSpec ?? `${packageMetadata.name}@${packageMetadata.version}`;
91
+ runPluginCommand("add", packageSpec, options);
92
+ const installed = await inspectAgentControlCenter(options);
93
+ if (installed.status !== "installed" || !installed.dependency) {
94
+ throw new Error(`DSH plugin manager did not install the Agent Control Center completely: ${installed.issues.join("; ") || installed.status}`);
95
+ }
96
+ return Object.freeze({ operation: "installed", target: installed.target, profile: installed.profile, dependency: installed.dependency });
97
+ }
98
+ export async function uninstallAgentControlCenter(options = {}) {
99
+ const current = await inspectAgentControlCenter(options);
100
+ if (current.status === "absent")
101
+ return Object.freeze({ operation: "absent", target: current.target, profile: current.profile });
102
+ if (current.status === "drifted") {
103
+ throw new Error(`refusing to remove drifted Control Center profile state at ${current.target}: ${current.issues.join("; ")}`);
104
+ }
105
+ runPluginCommand("remove", packageMetadata.name, options);
106
+ const removed = await inspectAgentControlCenter(options);
107
+ if (removed.status !== "absent") {
108
+ throw new Error(`DSH plugin manager did not remove the Agent Control Center completely: ${removed.issues.join("; ") || removed.status}`);
109
+ }
110
+ return Object.freeze({ operation: "uninstalled", target: removed.target, profile: removed.profile });
111
+ }
112
+ //# sourceMappingURL=control-center-installer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-center-installer.mjs","sourceRoot":"","sources":["../../src/control-center-installer.mts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Readable, Writable } from "node:stream";
2
+ export declare function acceptsControlCenterInstall(answer: string): boolean;
3
+ export declare function promptForControlCenterInstall(input?: Readable, output?: Writable, profile?: string): Promise<boolean>;
4
+ //# sourceMappingURL=control-center-prompt.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-center-prompt.d.mts","sourceRoot":"","sources":["../../src/control-center-prompt.mts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEtD,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED,wBAAsB,6BAA6B,CACjD,KAAK,GAAE,QAAwB,EAC/B,MAAM,GAAE,QAAyB,EACjC,OAAO,SAAQ,GACd,OAAO,CAAC,OAAO,CAAC,CAQlB"}
@@ -0,0 +1,15 @@
1
+ import { createInterface } from "node:readline/promises";
2
+ export function acceptsControlCenterInstall(answer) {
3
+ return /^(?:|y|yes)$/iu.test(answer.trim());
4
+ }
5
+ export async function promptForControlCenterInstall(input = process.stdin, output = process.stdout, profile = "web") {
6
+ const readline = createInterface({ input, output });
7
+ try {
8
+ const answer = await readline.question(`同时把 Odai 控制中心安装到 DSH profile “${profile}”?[Y/n] `);
9
+ return acceptsControlCenterInstall(answer);
10
+ }
11
+ finally {
12
+ readline.close();
13
+ }
14
+ }
15
+ //# sourceMappingURL=control-center-prompt.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-center-prompt.mjs","sourceRoot":"","sources":["../../src/control-center-prompt.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,MAAM,UAAU,2BAA2B,CAAC,MAAc;IACxD,OAAO,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,KAAK,GAAa,OAAO,CAAC,KAAK,EAC/B,MAAM,GAAa,OAAO,CAAC,MAAM,EACjC,OAAO,GAAG,KAAK;IAEf,MAAM,QAAQ,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACpD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,iCAAiC,OAAO,UAAU,CAAC,CAAC;QAC3F,OAAO,2BAA2B,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;YAAS,CAAC;QACT,QAAQ,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -9,8 +9,10 @@ export interface AgentInstallerOptions {
9
9
  }
10
10
  export declare const DEFAULT_PRESET_ID = "odai";
11
11
  export declare const MANIFEST_FILE = ".odai-agent.json";
12
+ export declare const inject: string[];
13
+ export declare function apply(ctx: unknown, rawConfig?: unknown): Promise<void>;
12
14
  export declare const SUPPORTED_DSH_VERSIONS: readonly string[];
13
- export declare const SUPPORTED_DSH_VERSION = "0.1.1-rc.2";
15
+ export declare const SUPPORTED_DSH_VERSION = "0.1.2-alpha.2";
14
16
  export declare function renderAgentCompositionForDsh(composition: string, dshVersion?: string): string;
15
17
  export declare function resolveDshHome(configured?: string, env?: NodeJS.ProcessEnv): string;
16
18
  export declare function inspectAgentInstallation(options?: AgentInstallerOptions): Promise<Readonly<{
@@ -1 +1 @@
1
- {"version":3,"file":"installer.d.mts","sourceRoot":"","sources":["../../src/installer.mts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,wCAAwC,CAAC;AAQhD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;CACzD;AAgCD,eAAO,MAAM,iBAAiB,SAAS,CAAC;AACxC,eAAO,MAAM,aAAa,qBAAqB,CAAC;AAqBhD,eAAO,MAAM,sBAAsB,mBAElC,CAAC;AAQF,eAAO,MAAM,qBAAqB,eAAqB,CAAC;AAgBxD,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,SAAwB,GAAG,MAAM,CAQ5G;AAED,wBAAgB,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAShG;AAED,wBAAsB,wBAAwB,CAAC,OAAO,GAAE,qBAA0B;YAzFxE,QAAQ,GAAG,WAAW,GAAG,SAAS;YAClC,MAAM,EAAE;cACN,MAAM;iBACH,MAAM;;;;IA4FpB;AAED,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,qBAA0B;;;;;;;;;;IAsF3E;AAED,wBAAsB,oBAAoB,CAAC,OAAO,GAAE,qBAA0B;;;;;;;;;IAyB7E"}
1
+ {"version":3,"file":"installer.d.mts","sourceRoot":"","sources":["../../src/installer.mts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,wCAAwC,CAAC;AAQhD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;CACzD;AAgCD,eAAO,MAAM,iBAAiB,SAAS,CAAC;AACxC,eAAO,MAAM,aAAa,qBAAqB,CAAC;AAKhD,eAAO,MAAM,MAAM,UAAwB,CAAC;AAE5C,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,GAAE,OAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAOhF;AAmBD,eAAO,MAAM,sBAAsB,mBAElC,CAAC;AAWF,eAAO,MAAM,qBAAqB,kBAAqB,CAAC;AAqBxD,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,SAAwB,GAAG,MAAM,CAiC5G;AAED,wBAAgB,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAShG;AAED,wBAAsB,wBAAwB,CAAC,OAAO,GAAE,qBAA0B;YAtIxE,QAAQ,GAAG,WAAW,GAAG,SAAS;YAClC,MAAM,EAAE;cACN,MAAM;iBACH,MAAM;;;;IAyIpB;AAED,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,qBAA0B;;;;;;;;;;IAsF3E;AAED,wBAAsB,oBAAoB,CAAC,OAAO,GAAE,qBAA0B;;;;;;;;;IAyB7E"}
@@ -17,6 +17,15 @@ export const DEFAULT_PRESET_ID = "odai";
17
17
  export const MANIFEST_FILE = ".odai-agent.json";
18
18
  const moduleDirectory = dirname(fileURLToPath(import.meta.url));
19
19
  const packageRoot = resolve(moduleDirectory, moduleDirectory.endsWith(`${sep}build${sep}src`) ? "../.." : "..");
20
+ export const inject = ["connection", "llm"];
21
+ export async function apply(ctx, rawConfig = {}) {
22
+ const moduleUrl = pathToFileURL(resolve(packageRoot, "preset/odai/runtime/control-center-host.mjs")).href;
23
+ const host = await import(moduleUrl);
24
+ if (!isRecord(host) || typeof host.apply !== "function") {
25
+ throw new Error("odai-dsh-agent Control Center host artifact is invalid");
26
+ }
27
+ await host.apply(ctx, rawConfig);
28
+ }
20
29
  const defaultSourceRoot = resolve(packageRoot, "preset/odai");
21
30
  const parsedPackageMetadata = JSON.parse(await readFile(resolve(packageRoot, "package.json"), "utf8"));
22
31
  if (!isRecord(parsedPackageMetadata) || typeof parsedPackageMetadata.name !== "string"
@@ -37,9 +46,12 @@ export const SUPPORTED_DSH_VERSIONS = Object.freeze(peerRange.split(/\s*\|\|\s*/
37
46
  if (SUPPORTED_DSH_VERSIONS.length === 0 || SUPPORTED_DSH_VERSIONS.some((version) => !DSH_VERSION_PATTERN.test(version))) {
38
47
  throw new Error("odai-dsh-agent peer dependency must list exact supported DSH versions");
39
48
  }
40
- const SOURCE_DSH_VERSION = "0.1.1-rc.2";
41
- if (SUPPORTED_DSH_VERSIONS.length !== 1 || SUPPORTED_DSH_VERSIONS[0] !== SOURCE_DSH_VERSION) {
42
- throw new Error(`Odai Agent peer must target only source composition ${SOURCE_DSH_VERSION}`);
49
+ const SOURCE_DSH_VERSION = "0.1.2-alpha.2";
50
+ const LEGACY_DSH_VERSION = "0.1.1-rc.2";
51
+ if (!SUPPORTED_DSH_VERSIONS.includes(SOURCE_DSH_VERSION)
52
+ || !SUPPORTED_DSH_VERSIONS.includes(LEGACY_DSH_VERSION)
53
+ || SUPPORTED_DSH_VERSIONS.length !== 2) {
54
+ throw new Error(`Odai Agent peer must target exactly ${LEGACY_DSH_VERSION} and source composition ${SOURCE_DSH_VERSION}`);
43
55
  }
44
56
  export const SUPPORTED_DSH_VERSION = SOURCE_DSH_VERSION;
45
57
  const requiredFiles = Object.freeze([
@@ -56,6 +68,11 @@ const requiredFiles = Object.freeze([
56
68
  "skills/odai/SKILL.md",
57
69
  "skills/odai/manifest.json",
58
70
  ]);
71
+ function replaceRequired(value, oldString, newString, label) {
72
+ if (!value.includes(oldString))
73
+ throw new Error(`agent source composition is missing ${label}`);
74
+ return value.replace(oldString, newString);
75
+ }
59
76
  export function renderAgentCompositionForDsh(composition, dshVersion = SUPPORTED_DSH_VERSION) {
60
77
  if (typeof composition !== "string" || composition.trim() === "") {
61
78
  throw new TypeError("agent composition must be a non-empty string");
@@ -63,7 +80,32 @@ export function renderAgentCompositionForDsh(composition, dshVersion = SUPPORTED
63
80
  if (!SUPPORTED_DSH_VERSIONS.includes(dshVersion)) {
64
81
  throw new Error(`unsupported DSH version ${dshVersion || "<empty>"}; expected one of ${SUPPORTED_DSH_VERSIONS.join(", ")}`);
65
82
  }
66
- return composition.replace(/\r\n/gu, "\n");
83
+ let rendered = composition.replace(/\r\n/gu, "\n");
84
+ if (dshVersion === SOURCE_DSH_VERSION)
85
+ return rendered;
86
+ rendered = replaceRequired(rendered, [
87
+ "# The goal service and session driver stay on the host plane, where the Gateway",
88
+ "# can resolve them. The human command and model-facing tool register into this",
89
+ "# preset's scoped layers.",
90
+ "- id: command-goal",
91
+ " name: '@deepseek-ai/dsh-command-goal'",
92
+ ].join("\n") + "\n\n", [
93
+ "# Only the model-facing tool. The goal SERVICE, its session driver, and the",
94
+ "# `/goal` command stay on the host plane: the Gateway serves the goal domain as",
95
+ "# Remote endpoints whose receiver comes from a generated descriptor, so it",
96
+ "# resolves `goals` on the host and an entry-local realm here would hide it. The",
97
+ "# registry is keyed by session anyway, so one host instance serves every",
98
+ "# session. What a preset chooses is whether its agent can call the goal tool.",
99
+ ].join("\n") + "\n", "alpha.2 goal command block");
100
+ rendered = replaceRequired(rendered, " modelSelectionSettings: true\n", "", "alpha.2 spawn model selection setting");
101
+ rendered = replaceRequired(rendered, [
102
+ " # Fork omits model selection so provider/model stay equal to the parent and",
103
+ " # the inherited history remains eligible for KV Cache reuse. This preset",
104
+ " # keeps fork continuable and accepts its child-scoped `report` additions invalidating",
105
+ " # that prefix; issue #2124 tracks cache-preserving continuable fork.",
106
+ ].join("\n") + "\n", "", "alpha.2 fork cache guidance");
107
+ rendered = replaceRequired(rendered, " fetch: true\n", " fetch: false\n", "alpha.2 web fetch setting");
108
+ return rendered;
67
109
  }
68
110
  export function resolveDshHome(configured, env = process.env) {
69
111
  const value = configured ?? env.DSH_HOME ?? resolve(homedir(), ".dsh");