odai-dsh-agent 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -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.0-rc.8`, then adds the scoped Odai runtime in default `auto` mode. For rc.7, the installer restores that release's optional-provider wording; for rc.6, it additionally restores the two disabled-provider fields before hashing and publishing the managed preset. 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, identical gaps are consumed once, 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 and latest successful test are newer than the last write. An incomplete packet keeps the current controller route so it can gather project-available evidence 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.0-rc.8`, then adds the scoped Odai runtime in default `auto` mode. 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.5`. 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, identical gaps are consumed once, 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 and latest successful test are newer than the last write. An incomplete packet keeps the current controller route so it can gather project-available evidence 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.0-rc.6`, `0.1.0-rc.7`, or `0.1.0-rc.8`. It records the detected version in the managed manifest and renders that release's exact Standard composition; any other developer-preview version fails closed.
34
+ The installer checks `dsh -V` and currently accepts exactly `0.1.0-rc.7` or `0.1.0-rc.8`; `0.2.5` rejects rc.6. It records the detected version in the managed manifest and renders that release's exact Standard composition; any other developer-preview version fails closed.
35
35
 
36
36
  `DSH_HOME` is honored. An explicit location can be supplied without changing the environment:
37
37
 
@@ -41,7 +41,7 @@ npx odai-dsh-agent install --dsh-home /path/to/dsh-home
41
41
 
42
42
  Open a new DSH session and select `Odai` from the Agent preset picker. Existing sessions retain the preset they were composed with.
43
43
 
44
- In supported DSH rc.6, rc.7, and rc.8 releases, 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.
44
+ In supported DSH rc.7 and rc.8 releases, 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.
45
45
 
46
46
  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.
47
47
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "odai-dsh-agent",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "完整继承 DSH 标准模式 全部能力的 Odai Agent preset。主要用于治理、规划、测试、验证 等,可当成默认总控使用。",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -49,7 +49,7 @@
49
49
  "yaml": "^2.8.1"
50
50
  },
51
51
  "peerDependencies": {
52
- "@deepseek-ai/dsh": "0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8"
52
+ "@deepseek-ai/dsh": "0.1.0-rc.7 || 0.1.0-rc.8"
53
53
  },
54
54
  "peerDependenciesMeta": {
55
55
  "@deepseek-ai/dsh": {
@@ -53,6 +53,7 @@ import { createSessionEvidence, resolveSessionEvidenceRoot } from "./session-evi
53
53
  import { classifyModelRouteFailure, probeModelRoute } from "./model-route.mjs";
54
54
  import { RESPONSIBILITY_GAP_PROMPT, createResponsibilityGapTool } from "./responsibility-gap.mjs";
55
55
  import {
56
+ ODAI_CONTEXTUAL_TOOL_NAMES,
56
57
  ODAI_CORE_TOOL_NAMES,
57
58
  activeOdaiToolNames,
58
59
  classifyContextActivation,
@@ -640,6 +641,32 @@ function routedRoleOf(agent) {
640
641
  return undefined;
641
642
  }
642
643
 
644
+ const ODAI_ADAPTIVE_TOOL_NAMES = new Set([...ODAI_CONTEXTUAL_TOOL_NAMES, ...ODAI_CORE_TOOL_NAMES]);
645
+
646
+ function reconcileAdaptiveToolSchemas(assembly, activeNames, executableSchemas = []) {
647
+ if (!assembly || !Array.isArray(assembly.tools)) return assembly;
648
+ const active = new Set(activeNames);
649
+ const executableByName = new Map(
650
+ (Array.isArray(executableSchemas) ? executableSchemas : [])
651
+ .filter((tool) => active.has(tool?.name))
652
+ .map((tool) => [tool.name, tool]),
653
+ );
654
+ const tools = assembly.tools.filter((tool) => !ODAI_ADAPTIVE_TOOL_NAMES.has(tool?.name)
655
+ || (active.has(tool.name) && executableByName.has(tool.name)));
656
+ const present = new Set(tools.map((tool) => tool?.name));
657
+ const missing = activeNames
658
+ .filter((name) => !present.has(name) && executableByName.has(name))
659
+ .map((name) => executableByName.get(name));
660
+ if (missing.length > 0) {
661
+ const lastAdaptiveIndex = tools.reduce(
662
+ (last, tool, index) => ODAI_ADAPTIVE_TOOL_NAMES.has(tool?.name) ? index : last,
663
+ -1,
664
+ );
665
+ tools.splice(lastAdaptiveIndex < 0 ? tools.length : lastAdaptiveIndex + 1, 0, ...missing);
666
+ }
667
+ return tools.length === assembly.tools.length && missing.length === 0 ? assembly : { ...assembly, tools };
668
+ }
669
+
643
670
  export function apply(ctx, rawConfig) {
644
671
  const config = resolveConfig(rawConfig);
645
672
  const logger = loggerFor(ctx);
@@ -951,12 +978,28 @@ export function apply(ctx, rawConfig) {
951
978
  return state;
952
979
  };
953
980
  ctx.on("system-prompt/assemble", async (assembly, context, next) => {
954
- const downstream = await next();
955
981
  const agent = context.agent;
956
- if (!agent) return downstream;
957
- const selection = await selectSharedSkillForTurn(agent, () => selectForAgent(agent, context));
982
+ if (!agent) return next();
958
983
  const turn = currentAgentTurn(agent);
959
- const outputSelection = isSubagentSession(agent)
984
+ const childSession = isSubagentSession(agent);
985
+ const directMessage = latestDirectUserMessage(agent);
986
+ const activation = contextActivationFor(agent, directMessage ? extractLatestUserText([directMessage]) : "", turn);
987
+ const proposedStep = (currentAgentStep(agent) ?? 0) + 1;
988
+ const exposureEvents = evidence.events(agent);
989
+ const routeCardNeeded = !childSession && (Boolean(activeRouteCard(exposureEvents))
990
+ || ["planner", "executor"].includes(pendingResponsibilityGap(agent, turn, proposedStep)?.responsibility)
991
+ || pendingResponsibilityInterruption(exposureEvents)?.responsibility === "executor");
992
+ // DSH builds assembly.tools before this middleware runs. Filter that snapshot and the execution registry together.
993
+ const activeToolNames = syncToolExposure(agent, activation, { turn, step: proposedStep, routeCard: routeCardNeeded });
994
+ const executableSchemas = typeof ctx.tools.schemas === "function" ? ctx.tools.schemas(agent) : [];
995
+ const visibleAssembly = reconcileAdaptiveToolSchemas(assembly, activeToolNames, executableSchemas);
996
+ if (visibleAssembly !== assembly) assembly.tools = visibleAssembly.tools;
997
+
998
+ const downstream = await next();
999
+ const finalExecutableSchemas = typeof ctx.tools.schemas === "function" ? ctx.tools.schemas(agent) : [];
1000
+ const reconciledDownstream = reconcileAdaptiveToolSchemas(downstream, activeToolNames, finalExecutableSchemas);
1001
+ const selection = await selectSharedSkillForTurn(agent, () => selectForAgent(agent, context));
1002
+ const outputSelection = childSession
960
1003
  ? Object.freeze({ policy: DEFAULT_OUTPUT_POLICY, source: "default" })
961
1004
  : await selectSharedOutputPolicyForTurn(agent, turn, selectOutputForAgent);
962
1005
  const selectionEvidence = {
@@ -986,12 +1029,6 @@ export function apply(ctx, rawConfig) {
986
1029
  logger.warn(`Odai skill source ${selection.mode} fell back to bundled governance (${selection.reasonCode})`);
987
1030
  }
988
1031
  const outputPrompt = renderOutputPolicyPrompt(outputSelection.policy);
989
- const childSession = isSubagentSession(agent);
990
- const directMessage = latestDirectUserMessage(agent);
991
- const activation = contextActivationFor(agent, directMessage ? extractLatestUserText([directMessage]) : "", turn);
992
- const proposedStep = (currentAgentStep(agent) ?? 0) + 1;
993
- const routeCardNeeded = !childSession && (Boolean(activeRouteCard(evidence.events(agent)))
994
- || ["planner", "executor"].includes(pendingResponsibilityGap(agent, turn, proposedStep)?.responsibility));
995
1032
  const routingPrompt = !activation.routingConfig
996
1033
  ? ""
997
1034
  : childSession
@@ -1018,8 +1055,8 @@ export function apply(ctx, rawConfig) {
1018
1055
  });
1019
1056
  }
1020
1057
  return {
1021
- ...downstream,
1022
- sections: downstream.sections.map((section) => {
1058
+ ...reconciledDownstream,
1059
+ sections: reconciledDownstream.sections.map((section) => {
1023
1060
  if (section.name === "odai:canonical-governance") return { ...section, text: canonicalPrompt(selection) };
1024
1061
  if (section.name === "odai:routing-configuration") return { ...section, text: routingPrompt };
1025
1062
  if (section.name === "odai:human-safety-continuity") return { ...section, text: continuityPrompt };
@@ -1307,7 +1344,7 @@ export function apply(ctx, rawConfig) {
1307
1344
  activeTools: activeNames,
1308
1345
  });
1309
1346
  } catch (error) {
1310
- logger.warn(`Odai adaptive tool exposure is unavailable; retaining the complete tool catalog: ${error instanceof Error ? error.message : String(error)}`);
1347
+ logger.warn(`Odai adaptive execution restriction is unavailable; prompt schemas remain limited while the executable catalog stays complete: ${error instanceof Error ? error.message : String(error)}`);
1311
1348
  toolExposureStates.set(agent, Object.freeze({ key: "fallback", dispose: undefined }));
1312
1349
  }
1313
1350
  return activeNames;
@@ -1884,11 +1921,6 @@ export function apply(ctx, rawConfig) {
1884
1921
  });
1885
1922
  }
1886
1923
  }
1887
- const activation = contextActivationFor(agent, directText, turn);
1888
- const routeCardNeeded = !subagentSession && (Boolean(activeRouteCard(responsibilityEvents))
1889
- || ["planner", "executor"].includes(responsibilityGap?.responsibility)
1890
- || responsibilityContinuation?.responsibility === "executor");
1891
- syncToolExposure(agent, activation, { turn, step, routeCard: routeCardNeeded });
1892
1924
  if (interruptionNotice) {
1893
1925
  downstream = { ...downstream, messages: [...downstream.messages, interruptionNotice] };
1894
1926
  }
@@ -186,7 +186,7 @@ if (existsSync(developmentRuntime) && existsSync(developmentSkill)) {
186
186
  }
187
187
  await installAgentPreset({ dshHome: home, sourceRoot, dshVersion: targetDshVersion });
188
188
 
189
- const probePlugin = `import { existsSync, writeFileSync } from "node:fs";\nimport { bindScopeParent } from ${JSON.stringify(pathToFileURL(scopeModule).href)};\n\nexport const name = "odai-agent-scope-probe";\nexport const inject = ["systemPrompt", "tools"];\n\nexport function apply(ctx, config) {\n const results = {};\n let writing = Promise.resolve();\n\n ctx.on("agent/created", ({ agent }) => {\n writing = writing.then(async () => {\n const preset = agent.session?.header?.agentPreset;\n if (preset !== "standard" && preset !== "odai") return;\n\n const assembly = await ctx.systemPrompt.assemble({ scope: agent });\n const canonicalSections = assembly.sections.filter((section) => section.name === "odai:canonical-governance");\n const writePath = preset === "odai" ? config.odaiWritePath : config.standardWritePath;\n const childSession = new Proxy(agent.session, {\n get(target, property) {\n if (property === "header") {\n return { ...target.header, origin: "subagent", delegationDepth: 1 };\n }\n return Reflect.get(target, property, target);\n },\n });\n const child = { id: agent.id, session: childSession };\n bindScopeParent(child, agent);\n const toolResult = await ctx.tools.execute({\n callId: \`scope-probe-\${preset}\`,\n name: "write",\n arguments: { file_path: writePath, content: \`\${preset} child write reached body\\n\` },\n agent: child,\n signal: new AbortController().signal,\n });\n\n let routingProtected;\n if (preset === "odai") {\n const routingResult = await ctx.tools.execute({\n callId: "scope-probe-odai-routing-config",\n name: "odai_routing_config",\n arguments: { action: "set", responsibility: "executor", provider: "probe-provider", model: "probe-executor", reasoningEffort: "high" },\n agent,\n signal: new AbortController().signal,\n });\n routingProtected = routingResult.isError === true\n && /NO_ADAPTER/u.test(routingResult.error?.message ?? "")\n && !existsSync(config.routingConfigPath);\n }\n\n results[preset] = {\n canonicalSectionCount: canonicalSections.length,\n toolIsError: toolResult.isError === true,\n toolError: toolResult.isError === true ? toolResult.error?.message : undefined,\n writeReachedBody: existsSync(writePath),\n ...(routingProtected === undefined ? {} : { routingProtected }),\n };\n if (results.standard && results.odai) {\n writeFileSync(config.markerPath, JSON.stringify(results, null, 2) + "\\n", "utf8");\n }\n }).catch((error) => {\n writeFileSync(config.markerPath, JSON.stringify({ probeError: error?.stack ?? String(error) }, null, 2) + "\\n", "utf8");\n });\n }, { global: true });\n}\n`;
189
+ const probePlugin = `import { existsSync, writeFileSync } from "node:fs";\nimport { bindScopeParent } from ${JSON.stringify(pathToFileURL(scopeModule).href)};\n\nexport const name = "odai-agent-scope-probe";\nexport const inject = ["systemPrompt", "tools"];\n\nexport function apply(ctx, config) {\n const results = {};\n let writing = Promise.resolve();\n\n ctx.on("agent/created", ({ agent }) => {\n writing = writing.then(async () => {\n const preset = agent.session?.header?.agentPreset;\n if (preset !== "standard" && preset !== "odai") return;\n\n const assembly = await ctx.systemPrompt.assemble({ agent, scope: agent });\n const canonicalSections = assembly.sections.filter((section) => section.name === "odai:canonical-governance");\n if (preset === "odai") {\n const coldNames = assembly.tools.map((tool) => tool.name).filter((toolName) => toolName.startsWith("odai_")).sort();\n const expectedColdNames = ["odai_context_capability", "odai_responsibility_gap"];\n if (JSON.stringify(coldNames) !== JSON.stringify(expectedColdNames)) {\n throw new Error(\`cold Odai tool schema mismatch: \${JSON.stringify(coldNames)}\`);\n }\n const hiddenResult = await ctx.tools.execute({\n callId: "scope-probe-odai-hidden-routing",\n name: "odai_routing_config",\n arguments: { action: "show" },\n agent,\n signal: new AbortController().signal,\n });\n if (!hiddenResult.isError || !/unknown tool/u.test(hiddenResult.error?.message ?? "")) {\n throw new Error(\`hidden Odai routing tool remained executable: \${JSON.stringify(hiddenResult)}\`);\n }\n agent.session.append("turn/start", { turn: 1 });\n agent.session.append("step/start", { turn: 1, step: 1 });\n const gatewayResult = await ctx.tools.execute({\n callId: "scope-probe-odai-routing-gateway",\n name: "odai_context_capability",\n arguments: { capability: "routing-config" },\n agent,\n signal: new AbortController().signal,\n });\n if (gatewayResult.isError) throw new Error(\`Odai capability gateway failed: \${JSON.stringify(gatewayResult)}\`);\n const activatedAssembly = await ctx.systemPrompt.assemble({ agent, scope: agent });\n const activatedNames = activatedAssembly.tools.map((tool) => tool.name).filter((toolName) => toolName.startsWith("odai_")).sort();\n const expectedActivatedNames = ["odai_context_capability", "odai_responsibility_gap", "odai_routing_config"].sort();\n if (JSON.stringify(activatedNames) !== JSON.stringify(expectedActivatedNames)) {\n throw new Error(\`activated Odai tool schema mismatch: \${JSON.stringify(activatedNames)}\`);\n }\n }\n const writePath = preset === "odai" ? config.odaiWritePath : config.standardWritePath;\n const childSession = new Proxy(agent.session, {\n get(target, property) {\n if (property === "header") {\n return { ...target.header, origin: "subagent", delegationDepth: 1 };\n }\n return Reflect.get(target, property, target);\n },\n });\n const child = { id: agent.id, session: childSession };\n bindScopeParent(child, agent);\n const toolResult = await ctx.tools.execute({\n callId: \`scope-probe-\${preset}\`,\n name: "write",\n arguments: { file_path: writePath, content: \`\${preset} child write reached body\\n\` },\n agent: child,\n signal: new AbortController().signal,\n });\n\n let routingProtected;\n if (preset === "odai") {\n const routingResult = await ctx.tools.execute({\n callId: "scope-probe-odai-routing-config",\n name: "odai_routing_config",\n arguments: { action: "set", responsibility: "executor", provider: "probe-provider", model: "probe-executor", reasoningEffort: "high" },\n agent,\n signal: new AbortController().signal,\n });\n routingProtected = routingResult.isError === true\n && /NO_ADAPTER/u.test(routingResult.error?.message ?? "")\n && !existsSync(config.routingConfigPath);\n }\n\n results[preset] = {\n canonicalSectionCount: canonicalSections.length,\n toolIsError: toolResult.isError === true,\n toolError: toolResult.isError === true ? toolResult.error?.message : undefined,\n writeReachedBody: existsSync(writePath),\n ...(routingProtected === undefined ? {} : { routingProtected }),\n ...(preset === "odai" ? { toolExposureSynchronized: true } : {}),\n };\n if (results.standard && results.odai) {\n writeFileSync(config.markerPath, JSON.stringify(results, null, 2) + "\\n", "utf8");\n }\n }).catch((error) => {\n writeFileSync(config.markerPath, JSON.stringify({ probeError: error?.stack ?? String(error) }, null, 2) + "\\n", "utf8");\n });\n }, { global: true });\n}\n`;
190
190
  await writeFile(probePluginPath, probePlugin, "utf8");
191
191
  await writeFile(patchPath, [
192
192
  "- insert:",
@@ -245,6 +245,9 @@ try {
245
245
  || !results.odai?.toolError?.startsWith("ODAI_SUBAGENT_BOUNDARY:")) {
246
246
  throw new Error(`odai child write was not denied by odai guard: ${JSON.stringify(results)}`);
247
247
  }
248
+ if (results.odai?.toolExposureSynchronized !== true) {
249
+ throw new Error(`odai tool schemas and execution visibility were not synchronized: ${JSON.stringify(results)}`);
250
+ }
248
251
  if (results.odai?.routingProtected !== true) {
249
252
  throw new Error(`odai routing tool did not reject an unavailable route without mutation: ${JSON.stringify(results)}`);
250
253
  }
package/src/installer.mjs CHANGED
@@ -33,7 +33,6 @@ if (SUPPORTED_DSH_VERSIONS.length === 0 || SUPPORTED_DSH_VERSIONS.some((version)
33
33
  }
34
34
  const SOURCE_DSH_VERSION = "0.1.0-rc.8";
35
35
  const OPTIONAL_PROVIDER_COMMENTS = Object.freeze({
36
- "0.1.0-rc.6": " # Product providers are host-plane singletons. Copy this preset, then\n # remove `disabled` from either ordinary tool row to expose that product\n # only to agents composed from the copy.",
37
36
  "0.1.0-rc.7": " # Production dsh does not install these optional providers. An opting-in\n # Profile mounts each provider once on the host plane; copy this preset,\n # then remove `disabled` from the matching tool row.",
38
37
  "0.1.0-rc.8": " # Production dsh does not install these optional providers. Install the\n # matching Bundle in this Profile and restart the Host, then copy this\n # preset and remove `disabled` from the matching tool row. Host availability\n # alone grants no tool.",
39
38
  });
@@ -85,19 +84,7 @@ export function renderAgentCompositionForDsh(composition, dshVersion = SUPPORTED
85
84
  targetComment,
86
85
  "optional-provider comment",
87
86
  );
88
- if (dshVersion === "0.1.0-rc.7") return rendered;
89
- rendered = replaceCompositionContract(
90
- rendered,
91
- " provider: codex\n toolName: subagent_codex\n backgroundMode: one-shot",
92
- " provider: codex\n toolName: subagent_codex\n enableRunInBackground: false",
93
- "Codex provider",
94
- );
95
- return replaceCompositionContract(
96
- rendered,
97
- " provider: claude-code\n toolName: subagent_claude_code\n backgroundMode: one-shot",
98
- " provider: claude-code\n toolName: subagent_claude_code\n enableRunInBackground: false",
99
- "Claude Code provider",
100
- );
87
+ return rendered;
101
88
  }
102
89
 
103
90
  export function resolveDshHome(configured, env = process.env) {