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 +3 -3
- package/package.json +2 -2
- package/preset/odai/runtime/index.mjs +50 -18
- package/scripts/verify-agent-load.mjs +4 -1
- package/src/installer.mjs +1 -14
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
|
|
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.
|
|
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.
|
|
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
|
+
"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.
|
|
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
|
|
957
|
-
const selection = await selectSharedSkillForTurn(agent, () => selectForAgent(agent, context));
|
|
982
|
+
if (!agent) return next();
|
|
958
983
|
const turn = currentAgentTurn(agent);
|
|
959
|
-
const
|
|
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
|
-
...
|
|
1022
|
-
sections:
|
|
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
|
|
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
|
-
|
|
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) {
|