@vidge/dsh-agent-hub 0.1.0-rc1 → 0.1.0-rc3
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 +24 -7
- package/README.zh.md +23 -5
- package/lib/index.js +137 -27
- package/lib/types/engine-claude/agent.d.ts +60 -11
- package/package.json +20 -8
package/README.md
CHANGED
|
@@ -64,19 +64,36 @@ runtime state — switching never requires a restart again.
|
|
|
64
64
|
> can take the factory slot and re-mount that loop itself. Everything else in
|
|
65
65
|
> that file is preserved byte for byte.
|
|
66
66
|
|
|
67
|
-
###
|
|
67
|
+
### Engine dependencies
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
Each engine's SDK is an **optional peer** — installing this plugin pulls in the
|
|
70
|
+
router only. Add the engines you actually want:
|
|
70
71
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
```sh
|
|
73
|
+
# Claude Code
|
|
74
|
+
pnpm add @anthropic-ai/claude-agent-sdk
|
|
75
|
+
# Codex
|
|
76
|
+
pnpm add @openai/codex
|
|
77
|
+
# Pi
|
|
78
|
+
pnpm add @earendil-works/pi-coding-agent
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The `in-process` engine needs nothing beyond dsh itself, so a profile that
|
|
82
|
+
installs no SDK at all still works.
|
|
83
|
+
|
|
84
|
+
Selecting an engine whose SDK is missing fails that turn with a message naming
|
|
85
|
+
the package to install; it never affects other sessions or engines.
|
|
86
|
+
|
|
87
|
+
### Authentication
|
|
88
|
+
|
|
89
|
+
Only for the engines you use:
|
|
90
|
+
|
|
91
|
+
- **Claude Code** — credentials are derived from dsh's own LLM provider
|
|
92
|
+
configuration (see below); a CLI login is a fallback, not a requirement.
|
|
74
93
|
- **Codex** — authenticated via `codex login`, or a `CODEX_API_KEY` entry.
|
|
75
94
|
- **Pi** — authenticated the way `pi` expects: its own `~/.pi/agent/auth.json`,
|
|
76
95
|
or the provider's API-key environment variable.
|
|
77
96
|
|
|
78
|
-
The in-process engine needs nothing beyond dsh itself.
|
|
79
|
-
|
|
80
97
|
## Usage
|
|
81
98
|
|
|
82
99
|
Choose an engine in the composer when starting a session. To change engines,
|
package/README.zh.md
CHANGED
|
@@ -55,18 +55,36 @@ dsh plugin --profile web add @vidge/dsh-agent-hub
|
|
|
55
55
|
> `agent-loop` 行,以便路由器接管 factory 槽位并由它自己重新挂载该 loop。文件中
|
|
56
56
|
> 其余内容逐字节保留。
|
|
57
57
|
|
|
58
|
-
###
|
|
58
|
+
### 引擎依赖
|
|
59
|
+
|
|
60
|
+
各引擎的 SDK 都是**可选 peer 依赖**——安装本插件只会装入路由器本身。按需添加你
|
|
61
|
+
真正要用的引擎:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
# Claude Code
|
|
65
|
+
pnpm add @anthropic-ai/claude-agent-sdk
|
|
66
|
+
# Codex
|
|
67
|
+
pnpm add @openai/codex
|
|
68
|
+
# Pi
|
|
69
|
+
pnpm add @earendil-works/pi-coding-agent
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`in-process` 引擎除 dsh 本身外无任何额外要求,因此一个 SDK 都不装的 profile 仍可
|
|
73
|
+
正常工作。
|
|
74
|
+
|
|
75
|
+
选择了 SDK 未安装的引擎时,只有该次对话失败,并给出需要安装哪个包的提示;不会影响
|
|
76
|
+
其他会话或其他引擎。
|
|
77
|
+
|
|
78
|
+
### 认证
|
|
59
79
|
|
|
60
80
|
仅针对你实际使用的引擎:
|
|
61
81
|
|
|
62
|
-
- **Claude Code** ——
|
|
63
|
-
|
|
82
|
+
- **Claude Code** —— 凭证由 dsh 自身的 LLM provider 配置派生(见下文);CLI 登录
|
|
83
|
+
只是兜底,不是必需。
|
|
64
84
|
- **Codex** —— 通过 `codex login` 认证,或提供 `CODEX_API_KEY`。
|
|
65
85
|
- **Pi** —— 按 pi 自己的方式认证:`~/.pi/agent/auth.json`,或对应 provider 的
|
|
66
86
|
API-key 环境变量。
|
|
67
87
|
|
|
68
|
-
in-process 引擎除 dsh 本身外无任何额外要求。
|
|
69
|
-
|
|
70
88
|
## 使用
|
|
71
89
|
|
|
72
90
|
在 composer 中开始会话时选择引擎。要换引擎,开一个新会话——当前会话保持它的引擎,
|
package/lib/index.js
CHANGED
|
@@ -61,11 +61,10 @@ import { MAX_TIMER_DELAY_MS } from "@deepseek-ai/dsh-timeout";
|
|
|
61
61
|
import { SessionPreparation } from "@deepseek-ai/dsh-session";
|
|
62
62
|
|
|
63
63
|
// src/engine-claude/agent.ts
|
|
64
|
-
import { Inbox, agentEvents } from "@deepseek-ai/dsh-agent";
|
|
64
|
+
import { Inbox, agentEvents, assembleContextFor } from "@deepseek-ai/dsh-agent";
|
|
65
65
|
import { LlmError, createAssistantMessage, createUserMessage, errorChain } from "@deepseek-ai/dsh-llm";
|
|
66
66
|
import { createScope } from "@deepseek-ai/dsh-scope";
|
|
67
|
-
import { canonicalHeader } from "@deepseek-ai/dsh-session";
|
|
68
|
-
import { query as officialQuery } from "@anthropic-ai/claude-agent-sdk";
|
|
67
|
+
import { canonicalHeader, headerEquals } from "@deepseek-ai/dsh-session";
|
|
69
68
|
|
|
70
69
|
// src/engine-claude/mapping.ts
|
|
71
70
|
import {
|
|
@@ -693,7 +692,21 @@ function invokedSkillNames(messages) {
|
|
|
693
692
|
|
|
694
693
|
// src/engine-claude/agent.ts
|
|
695
694
|
var PROVIDER = "claude-code";
|
|
695
|
+
var claudeQueryPromise;
|
|
696
|
+
async function loadClaudeQuery() {
|
|
697
|
+
claudeQueryPromise ??= import("@anthropic-ai/claude-agent-sdk").then(
|
|
698
|
+
(mod) => mod.query,
|
|
699
|
+
(error) => {
|
|
700
|
+
claudeQueryPromise = void 0;
|
|
701
|
+
throw new Error(
|
|
702
|
+
`the Claude Code engine requires "@anthropic-ai/claude-agent-sdk", which is not installed. Add it to this profile, or pick another engine for this session. (${String(error)})`
|
|
703
|
+
);
|
|
704
|
+
}
|
|
705
|
+
);
|
|
706
|
+
return claudeQueryPromise;
|
|
707
|
+
}
|
|
696
708
|
var NATIVE_MODEL_LABEL = "claude-code-native";
|
|
709
|
+
var NATIVE_PROVIDER_LABEL = PROVIDER;
|
|
697
710
|
function failureCode(subtype) {
|
|
698
711
|
switch (subtype) {
|
|
699
712
|
case "error_during_execution":
|
|
@@ -1024,19 +1037,35 @@ var ClaudeCodeAgent = class {
|
|
|
1024
1037
|
return true;
|
|
1025
1038
|
}
|
|
1026
1039
|
/**
|
|
1027
|
-
* Resolve the model one query runs on, session
|
|
1040
|
+
* Resolve the model one query runs on, per-session selection first.
|
|
1041
|
+
*
|
|
1042
|
+
* The layers, in precedence order:
|
|
1028
1043
|
*
|
|
1029
|
-
* The
|
|
1030
|
-
*
|
|
1031
|
-
*
|
|
1032
|
-
*
|
|
1033
|
-
*
|
|
1034
|
-
*
|
|
1044
|
+
* 1. **The `agent/request` waterfall.** This is the seam the dsh model
|
|
1045
|
+
* picker actually drives. api-proxy installs `installModelSelection` on
|
|
1046
|
+
* every agent's own context, which listens on `system-prompt/assemble`
|
|
1047
|
+
* to *snapshot* the session's selection and on `agent/request` to *apply*
|
|
1048
|
+
* the snapshot — two stages, so a mid-turn switch lands on a later step
|
|
1049
|
+
* rather than splitting the prompt from the route. Both must be
|
|
1050
|
+
* dispatched, and in that order: the request listener reads
|
|
1051
|
+
* `selection.assembled`, which only the assemble listener writes, so
|
|
1052
|
+
* dispatching the request waterfall alone yields nothing.
|
|
1053
|
+
* 2. `AgentOptions.model` — the create-time seed.
|
|
1054
|
+
* 3. `agentDefaultModel` — the global default.
|
|
1055
|
+
* 4. The deployment's pinned `config.model`.
|
|
1056
|
+
* 5. Nothing, leaving the CLI on its own model.
|
|
1035
1057
|
*
|
|
1058
|
+
* Every layer is optional and every failure degrades to the next one: a
|
|
1059
|
+
* minimal profile mounts neither service, and a listener that throws must
|
|
1060
|
+
* cost this session its turn no more than a missing service does.
|
|
1061
|
+
*
|
|
1062
|
+
* @param signal - the step's cancellation signal, forwarded to prompt assembly.
|
|
1036
1063
|
* @returns the chosen id (undefined leaves the CLI on its own default),
|
|
1037
1064
|
* its provider route, and the layer that chose it.
|
|
1038
1065
|
*/
|
|
1039
|
-
resolveModel() {
|
|
1066
|
+
async resolveModel(signal) {
|
|
1067
|
+
const selected = await this.selectionFromWaterfall(signal);
|
|
1068
|
+
if (selected !== void 0) return selected;
|
|
1040
1069
|
if (this.options.model !== void 0) {
|
|
1041
1070
|
return { model: this.options.model, provider: this.options.provider, source: "session" };
|
|
1042
1071
|
}
|
|
@@ -1056,22 +1085,88 @@ var ClaudeCodeAgent = class {
|
|
|
1056
1085
|
}
|
|
1057
1086
|
return { model: void 0, provider: void 0, source: "native" };
|
|
1058
1087
|
}
|
|
1059
|
-
/**
|
|
1060
|
-
|
|
1061
|
-
|
|
1088
|
+
/**
|
|
1089
|
+
* Ask the host what this session is routed to, through the two waterfalls
|
|
1090
|
+
* that carry a per-session selection.
|
|
1091
|
+
*
|
|
1092
|
+
* The seed handed to `agent/request` is the same one the in-process loop
|
|
1093
|
+
* seeds with — the agent's own options — so a host that installs no listener
|
|
1094
|
+
* gets its own answer back and this returns undefined, leaving the layers
|
|
1095
|
+
* below untouched. A listener that replaces it wins.
|
|
1096
|
+
*
|
|
1097
|
+
* The assemble pass is dispatched for its *side effect* on the selection
|
|
1098
|
+
* state; its returned prompt is discarded, because Claude Code builds its own
|
|
1099
|
+
* prompt and dsh's assembly never reaches the child. That makes this a real
|
|
1100
|
+
* (if small) cost per step: the host's prompt providers run and their output
|
|
1101
|
+
* is dropped. It is the price of reaching a selection whose only publisher is
|
|
1102
|
+
* that listener pair.
|
|
1103
|
+
*
|
|
1104
|
+
* @param signal - the step's cancellation signal.
|
|
1105
|
+
* @returns the selection when a listener supplied one, else undefined.
|
|
1106
|
+
*/
|
|
1107
|
+
async selectionFromWaterfall(signal) {
|
|
1108
|
+
const phase = this.phase;
|
|
1109
|
+
if (phase.kind !== "running") return void 0;
|
|
1110
|
+
const { turn, step } = phase;
|
|
1111
|
+
const seed = {
|
|
1112
|
+
provider: this.options.provider ?? "",
|
|
1113
|
+
model: this.options.model ?? ""
|
|
1114
|
+
};
|
|
1115
|
+
try {
|
|
1116
|
+
const systemPrompt = this.loopCtx.get("systemPrompt");
|
|
1117
|
+
if (systemPrompt !== void 0) {
|
|
1118
|
+
await systemPrompt.assemble(assembleContextFor(this, signal));
|
|
1119
|
+
}
|
|
1120
|
+
const proposed = await this.dispatch.waterfall(
|
|
1121
|
+
"agent/request",
|
|
1122
|
+
{ turn, step, signal },
|
|
1123
|
+
() => Promise.resolve(seed)
|
|
1124
|
+
);
|
|
1125
|
+
if (proposed.model === "" || proposed.provider === "") return void 0;
|
|
1126
|
+
if (proposed.provider === seed.provider && proposed.model === seed.model) return void 0;
|
|
1127
|
+
return { model: proposed.model, provider: proposed.provider, source: "selection" };
|
|
1128
|
+
} catch (error) {
|
|
1129
|
+
this.ctx.logger.warn("claude-code: per-session model selection unavailable: %s", error);
|
|
1130
|
+
return void 0;
|
|
1131
|
+
}
|
|
1062
1132
|
}
|
|
1063
|
-
/**
|
|
1064
|
-
|
|
1065
|
-
|
|
1133
|
+
/**
|
|
1134
|
+
* Append the request header, and re-append it whenever the route changes.
|
|
1135
|
+
*
|
|
1136
|
+
* The provider written here is the **real** dsh route (`copilot-proxy`,
|
|
1137
|
+
* `amazon-bedrock`, …), not this engine's name. That is not cosmetic:
|
|
1138
|
+
* api-proxy re-reads this field on every read as "the model this session is
|
|
1139
|
+
* on", resolves it against `ctx.llm.listProviders()`, and locks the composer
|
|
1140
|
+
* when the name is not a registered provider — so writing the engine name
|
|
1141
|
+
* here made every session demand a fresh model pick after each turn. The
|
|
1142
|
+
* engine that ran the turn is recorded in the `*.loop-engine.json` sidecar,
|
|
1143
|
+
* which is where per-session engine provenance already lives.
|
|
1144
|
+
*
|
|
1145
|
+
* Re-logging on change mirrors the in-process loop: the header is the log's
|
|
1146
|
+
* record of what each request ran under, so a mid-session model switch has to
|
|
1147
|
+
* produce a new snapshot or the log misattributes every later turn.
|
|
1148
|
+
*
|
|
1149
|
+
* @param selected - the model resolved for the step about to run.
|
|
1150
|
+
*/
|
|
1151
|
+
noteRequestHeader(selected) {
|
|
1066
1152
|
const header = canonicalHeader({
|
|
1067
|
-
config: {
|
|
1153
|
+
config: {
|
|
1154
|
+
provider: selected.provider ?? NATIVE_PROVIDER_LABEL,
|
|
1155
|
+
model: selected.model ?? NATIVE_MODEL_LABEL
|
|
1156
|
+
}
|
|
1068
1157
|
});
|
|
1069
1158
|
const baseline = this.session.requestHeader();
|
|
1070
|
-
this.
|
|
1071
|
-
header,
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1159
|
+
if (!this.requestHeaderLogged) {
|
|
1160
|
+
this.session.append("request/header", {
|
|
1161
|
+
header,
|
|
1162
|
+
reason: baseline === void 0 ? "initial" : "resume"
|
|
1163
|
+
});
|
|
1164
|
+
this.requestHeaderLogged = true;
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
if (baseline === void 0 || !headerEquals(baseline, header)) {
|
|
1168
|
+
this.session.append("request/header", { header, reason: "change" });
|
|
1169
|
+
}
|
|
1075
1170
|
}
|
|
1076
1171
|
/** Run one Claude Code query for the current step and map its transcript into the session log. */
|
|
1077
1172
|
async step() {
|
|
@@ -1087,7 +1182,9 @@ var ClaudeCodeAgent = class {
|
|
|
1087
1182
|
if (prompt.length === 0) {
|
|
1088
1183
|
throw new Error(`agent "${this.id}": cannot derive a prompt from an empty session log`);
|
|
1089
1184
|
}
|
|
1090
|
-
this.
|
|
1185
|
+
const selected = await this.resolveModel(signal);
|
|
1186
|
+
signal.throwIfAborted();
|
|
1187
|
+
this.noteRequestHeader(selected);
|
|
1091
1188
|
signal.throwIfAborted();
|
|
1092
1189
|
const controller = new AbortController();
|
|
1093
1190
|
const cancel = () => {
|
|
@@ -1098,7 +1195,6 @@ var ClaudeCodeAgent = class {
|
|
|
1098
1195
|
signal.addEventListener("abort", cancel, { once: true });
|
|
1099
1196
|
const diagnostics = [];
|
|
1100
1197
|
try {
|
|
1101
|
-
const selected = this.resolveModel();
|
|
1102
1198
|
const derived = await deriveProviderEnv(this.loopCtx, selected.provider);
|
|
1103
1199
|
if (derived !== void 0) diagnostics.push(derived.diagnostic);
|
|
1104
1200
|
const options = claudeQueryOptions({
|
|
@@ -1116,6 +1212,7 @@ var ClaudeCodeAgent = class {
|
|
|
1116
1212
|
diagnostics.push(line);
|
|
1117
1213
|
}
|
|
1118
1214
|
}, controller);
|
|
1215
|
+
const officialQuery = await loadClaudeQuery();
|
|
1119
1216
|
const query = officialQuery({ prompt, options });
|
|
1120
1217
|
let finished = false;
|
|
1121
1218
|
const chunkSeqs = [];
|
|
@@ -1606,7 +1703,13 @@ import { dirname, join } from "node:path";
|
|
|
1606
1703
|
import { createInterface } from "node:readline";
|
|
1607
1704
|
var require2 = createRequire(import.meta.url);
|
|
1608
1705
|
function codexCliEntrypoint() {
|
|
1609
|
-
|
|
1706
|
+
try {
|
|
1707
|
+
return join(dirname(require2.resolve("@openai/codex/package.json")), "bin", "codex.js");
|
|
1708
|
+
} catch (error) {
|
|
1709
|
+
throw new Error(
|
|
1710
|
+
`the Codex engine requires "@openai/codex", which is not installed. Add it to this profile, or pick another engine for this session. (${String(error)})`
|
|
1711
|
+
);
|
|
1712
|
+
}
|
|
1610
1713
|
}
|
|
1611
1714
|
var AppServerClient = class _AppServerClient {
|
|
1612
1715
|
process;
|
|
@@ -3609,7 +3712,14 @@ function resolveConfig3(config) {
|
|
|
3609
3712
|
};
|
|
3610
3713
|
}
|
|
3611
3714
|
function piCliEntrypoint() {
|
|
3612
|
-
|
|
3715
|
+
let mainUrl;
|
|
3716
|
+
try {
|
|
3717
|
+
mainUrl = import.meta.resolve("@earendil-works/pi-coding-agent");
|
|
3718
|
+
} catch (error) {
|
|
3719
|
+
throw new Error(
|
|
3720
|
+
`the Pi engine requires "@earendil-works/pi-coding-agent", which is not installed. Add it to this profile, or pick another engine for this session. (${String(error)})`
|
|
3721
|
+
);
|
|
3722
|
+
}
|
|
3613
3723
|
const root = dirname2(dirname2(fileURLToPath(mainUrl)));
|
|
3614
3724
|
const pkg = JSON.parse(readFileSync(join2(root, "package.json"), "utf8"));
|
|
3615
3725
|
const bin = pkg.bin;
|
|
@@ -93,23 +93,72 @@ export declare class ClaudeCodeAgent implements Agent {
|
|
|
93
93
|
/** Open one turn before claiming its first proposed step. */
|
|
94
94
|
private turn;
|
|
95
95
|
/**
|
|
96
|
-
* Resolve the model one query runs on, session
|
|
96
|
+
* Resolve the model one query runs on, per-session selection first.
|
|
97
97
|
*
|
|
98
|
-
* The
|
|
99
|
-
* `agentDefaultModel` holds the global default; reading both is what makes
|
|
100
|
-
* the dsh model picker mean something for this engine. The service is
|
|
101
|
-
* optional — a minimal profile may not mount it — so it is resolved through
|
|
102
|
-
* `ctx.get` rather than `inject`, and a faulting provider degrades to the
|
|
103
|
-
* next layer instead of failing the turn.
|
|
98
|
+
* The layers, in precedence order:
|
|
104
99
|
*
|
|
100
|
+
* 1. **The `agent/request` waterfall.** This is the seam the dsh model
|
|
101
|
+
* picker actually drives. api-proxy installs `installModelSelection` on
|
|
102
|
+
* every agent's own context, which listens on `system-prompt/assemble`
|
|
103
|
+
* to *snapshot* the session's selection and on `agent/request` to *apply*
|
|
104
|
+
* the snapshot — two stages, so a mid-turn switch lands on a later step
|
|
105
|
+
* rather than splitting the prompt from the route. Both must be
|
|
106
|
+
* dispatched, and in that order: the request listener reads
|
|
107
|
+
* `selection.assembled`, which only the assemble listener writes, so
|
|
108
|
+
* dispatching the request waterfall alone yields nothing.
|
|
109
|
+
* 2. `AgentOptions.model` — the create-time seed.
|
|
110
|
+
* 3. `agentDefaultModel` — the global default.
|
|
111
|
+
* 4. The deployment's pinned `config.model`.
|
|
112
|
+
* 5. Nothing, leaving the CLI on its own model.
|
|
113
|
+
*
|
|
114
|
+
* Every layer is optional and every failure degrades to the next one: a
|
|
115
|
+
* minimal profile mounts neither service, and a listener that throws must
|
|
116
|
+
* cost this session its turn no more than a missing service does.
|
|
117
|
+
*
|
|
118
|
+
* @param signal - the step's cancellation signal, forwarded to prompt assembly.
|
|
105
119
|
* @returns the chosen id (undefined leaves the CLI on its own default),
|
|
106
120
|
* its provider route, and the layer that chose it.
|
|
107
121
|
*/
|
|
108
122
|
private resolveModel;
|
|
109
|
-
/**
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
123
|
+
/**
|
|
124
|
+
* Ask the host what this session is routed to, through the two waterfalls
|
|
125
|
+
* that carry a per-session selection.
|
|
126
|
+
*
|
|
127
|
+
* The seed handed to `agent/request` is the same one the in-process loop
|
|
128
|
+
* seeds with — the agent's own options — so a host that installs no listener
|
|
129
|
+
* gets its own answer back and this returns undefined, leaving the layers
|
|
130
|
+
* below untouched. A listener that replaces it wins.
|
|
131
|
+
*
|
|
132
|
+
* The assemble pass is dispatched for its *side effect* on the selection
|
|
133
|
+
* state; its returned prompt is discarded, because Claude Code builds its own
|
|
134
|
+
* prompt and dsh's assembly never reaches the child. That makes this a real
|
|
135
|
+
* (if small) cost per step: the host's prompt providers run and their output
|
|
136
|
+
* is dropped. It is the price of reaching a selection whose only publisher is
|
|
137
|
+
* that listener pair.
|
|
138
|
+
*
|
|
139
|
+
* @param signal - the step's cancellation signal.
|
|
140
|
+
* @returns the selection when a listener supplied one, else undefined.
|
|
141
|
+
*/
|
|
142
|
+
private selectionFromWaterfall;
|
|
143
|
+
/**
|
|
144
|
+
* Append the request header, and re-append it whenever the route changes.
|
|
145
|
+
*
|
|
146
|
+
* The provider written here is the **real** dsh route (`copilot-proxy`,
|
|
147
|
+
* `amazon-bedrock`, …), not this engine's name. That is not cosmetic:
|
|
148
|
+
* api-proxy re-reads this field on every read as "the model this session is
|
|
149
|
+
* on", resolves it against `ctx.llm.listProviders()`, and locks the composer
|
|
150
|
+
* when the name is not a registered provider — so writing the engine name
|
|
151
|
+
* here made every session demand a fresh model pick after each turn. The
|
|
152
|
+
* engine that ran the turn is recorded in the `*.loop-engine.json` sidecar,
|
|
153
|
+
* which is where per-session engine provenance already lives.
|
|
154
|
+
*
|
|
155
|
+
* Re-logging on change mirrors the in-process loop: the header is the log's
|
|
156
|
+
* record of what each request ran under, so a mid-session model switch has to
|
|
157
|
+
* produce a new snapshot or the log misattributes every later turn.
|
|
158
|
+
*
|
|
159
|
+
* @param selected - the model resolved for the step about to run.
|
|
160
|
+
*/
|
|
161
|
+
private noteRequestHeader;
|
|
113
162
|
/** Run one Claude Code query for the current step and map its transcript into the session log. */
|
|
114
163
|
private step;
|
|
115
164
|
}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.1.0-
|
|
7
|
+
"version": "0.1.0-rc3",
|
|
8
8
|
"repository": "github:vidgewong/dsh-agent-hub",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"main": "lib/index.js",
|
|
@@ -61,12 +61,8 @@
|
|
|
61
61
|
"@anthropic-ai/sdk": "0.93.0",
|
|
62
62
|
"@deepseek-ai/schemastery": "3.18.1"
|
|
63
63
|
},
|
|
64
|
-
"optionalDependencies": {
|
|
65
|
-
"@anthropic-ai/claude-agent-sdk": "0.3.220",
|
|
66
|
-
"@earendil-works/pi-coding-agent": "0.84.3",
|
|
67
|
-
"@openai/codex": "0.149.1"
|
|
68
|
-
},
|
|
69
64
|
"peerDependencies": {
|
|
65
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.220",
|
|
70
66
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
71
67
|
"@deepseek-ai/dsh-agent": "0.1.1-rc.2",
|
|
72
68
|
"@deepseek-ai/dsh-agent-loop": "0.1.1-rc.2",
|
|
@@ -77,11 +73,14 @@
|
|
|
77
73
|
"@deepseek-ai/dsh-session-persistence": "0.1.1-rc.2",
|
|
78
74
|
"@deepseek-ai/dsh-settings": "0.1.1-rc.2",
|
|
79
75
|
"@deepseek-ai/dsh-subprocess": "0.1.1-rc.2",
|
|
80
|
-
"@deepseek-ai/dsh-timeout": "0.1.1-rc.2"
|
|
76
|
+
"@deepseek-ai/dsh-timeout": "0.1.1-rc.2",
|
|
77
|
+
"@earendil-works/pi-coding-agent": "0.84.3",
|
|
78
|
+
"@openai/codex": "0.149.1"
|
|
81
79
|
},
|
|
82
80
|
"devDependencies": {
|
|
83
|
-
"@
|
|
81
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.220",
|
|
84
82
|
"@deepseek-ai/dsh-agent-loop": "0.1.1-rc.2",
|
|
83
|
+
"@deepseek-ai/dsh-attachment": "0.1.1-rc.2",
|
|
85
84
|
"@deepseek-ai/dsh-client-locale": "0.1.1-rc.2",
|
|
86
85
|
"@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
|
|
87
86
|
"@deepseek-ai/dsh-client-store": "0.1.2-alpha.2",
|
|
@@ -93,6 +92,8 @@
|
|
|
93
92
|
"@deepseek-ai/dsh-session-persistence-jsonl": "0.1.1-rc.2",
|
|
94
93
|
"@deepseek-ai/dsh-subprocess-local": "0.1.1-rc.2",
|
|
95
94
|
"@deepseek-ai/dsh-system-prompt": "0.1.1-rc.2",
|
|
95
|
+
"@earendil-works/pi-coding-agent": "0.84.3",
|
|
96
|
+
"@openai/codex": "0.149.1",
|
|
96
97
|
"@types/node": "^22.20.0",
|
|
97
98
|
"@types/react": "^19.0.0",
|
|
98
99
|
"@vitest/coverage-v8": "^4.1.8",
|
|
@@ -103,5 +104,16 @@
|
|
|
103
104
|
"vite-tsconfig-paths": "^6.1.1",
|
|
104
105
|
"vitest": "^4.1.8",
|
|
105
106
|
"yaml": "^2.9.0"
|
|
107
|
+
},
|
|
108
|
+
"peerDependenciesMeta": {
|
|
109
|
+
"@anthropic-ai/claude-agent-sdk": {
|
|
110
|
+
"optional": true
|
|
111
|
+
},
|
|
112
|
+
"@earendil-works/pi-coding-agent": {
|
|
113
|
+
"optional": true
|
|
114
|
+
},
|
|
115
|
+
"@openai/codex": {
|
|
116
|
+
"optional": true
|
|
117
|
+
}
|
|
106
118
|
}
|
|
107
119
|
}
|