@ai-sdk/harness-claude-code 1.0.95 → 1.0.97
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/CHANGELOG.md +24 -0
- package/dist/bridge/index.mjs +60 -13
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/bridge/package.json +3 -3
- package/dist/bridge/pnpm-lock.yaml +128 -126
- package/dist/bridge/pnpm-workspace.yaml +1 -1
- package/dist/index.d.ts +6 -20
- package/dist/index.js +59 -73
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/bridge/index.ts +69 -8
- package/src/bridge/package.json +3 -3
- package/src/bridge/pnpm-lock.yaml +128 -126
- package/src/bridge/pnpm-workspace.yaml +1 -1
- package/src/claude-code-auth.ts +38 -82
- package/src/claude-code-harness.ts +51 -37
- package/src/index.ts +1 -4
package/src/claude-code-auth.ts
CHANGED
|
@@ -3,12 +3,14 @@ import { readFileSync } from 'node:fs';
|
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import type {
|
|
6
|
+
HarnessV1Authentication,
|
|
6
7
|
HarnessV1RequestTransformation,
|
|
7
8
|
HarnessV1RequestTransformationSources,
|
|
8
9
|
} from '@ai-sdk/harness';
|
|
9
10
|
import {
|
|
10
11
|
createCredentialRequestTransformation,
|
|
11
12
|
getAiGatewayAuthFromEnv,
|
|
13
|
+
isHarnessAuthenticationEnvironment,
|
|
12
14
|
} from '@ai-sdk/harness/utils';
|
|
13
15
|
|
|
14
16
|
export const CLAUDE_CODE_CREDENTIAL_ENVIRONMENT_VARIABLES = [
|
|
@@ -67,36 +69,14 @@ export function createClaudeCodeRequestTransformations({
|
|
|
67
69
|
|
|
68
70
|
export type ClaudeCodeResolvedAuthenticationMode = 'direct' | 'ai-gateway';
|
|
69
71
|
|
|
70
|
-
export type ClaudeCodeAuthenticationMode =
|
|
71
|
-
| ClaudeCodeResolvedAuthenticationMode
|
|
72
|
-
| 'auto';
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* @deprecated Passing an object to auth options is deprecated. Use a `ClaudeCodeAuthenticationMode` string value ("auto" | "direct" | "ai-gateway") instead, and pass credentials via environment variables.
|
|
76
|
-
*/
|
|
77
|
-
export type LegacyClaudeCodeAuthOptions = {
|
|
78
|
-
readonly anthropic?: {
|
|
79
|
-
readonly apiKey?: string;
|
|
80
|
-
readonly authToken?: string;
|
|
81
|
-
readonly baseUrl?: string;
|
|
82
|
-
};
|
|
83
|
-
readonly gateway?: {
|
|
84
|
-
readonly apiKey?: string;
|
|
85
|
-
readonly baseUrl?: string;
|
|
86
|
-
};
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
export type ClaudeCodeAuthOptions =
|
|
90
|
-
| ClaudeCodeAuthenticationMode
|
|
91
|
-
| LegacyClaudeCodeAuthOptions;
|
|
72
|
+
export type ClaudeCodeAuthenticationMode = HarnessV1Authentication;
|
|
92
73
|
|
|
93
74
|
/**
|
|
94
75
|
* Resolve the environment-variable blob the bridge needs to authenticate
|
|
95
76
|
* with Anthropic (directly or via the Vercel AI Gateway). Precedence:
|
|
96
77
|
*
|
|
97
|
-
* 1.
|
|
98
|
-
* 2.
|
|
99
|
-
* 3. Auto-detect from the host process env: gateway first
|
|
78
|
+
* 1. An explicit authentication mode pins the selected route.
|
|
79
|
+
* 2. Auto-detect from the host process env: gateway first
|
|
100
80
|
* (`AI_GATEWAY_API_KEY` / `VERCEL_OIDC_TOKEN`), then direct
|
|
101
81
|
* (`ANTHROPIC_API_KEY` / `ANTHROPIC_AUTH_TOKEN`).
|
|
102
82
|
*/
|
|
@@ -112,46 +92,50 @@ export type ResolveClaudeCodeEnvOptions = {
|
|
|
112
92
|
};
|
|
113
93
|
|
|
114
94
|
export function resolveClaudeCodeEnv(
|
|
115
|
-
auth:
|
|
95
|
+
auth: ClaudeCodeAuthenticationMode | undefined,
|
|
116
96
|
processEnv: Record<string, string | undefined> = process.env,
|
|
117
97
|
options: ResolveClaudeCodeEnvOptions = {},
|
|
118
98
|
): Record<string, string> {
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
99
|
+
const suppliedEnvironment = isHarnessAuthenticationEnvironment(auth);
|
|
100
|
+
const authenticationEnvironment = suppliedEnvironment ? auth : processEnv;
|
|
101
|
+
|
|
102
|
+
const readApiKey =
|
|
103
|
+
suppliedEnvironment || auth === 'direct'
|
|
104
|
+
? () => undefined
|
|
105
|
+
: (options.readApiKeyHelper ?? readApiKeyHelper);
|
|
106
|
+
if (auth === 'direct') {
|
|
123
107
|
return pickAnthropic({
|
|
124
|
-
|
|
125
|
-
processEnv,
|
|
108
|
+
processEnv: authenticationEnvironment,
|
|
126
109
|
readApiKey,
|
|
127
110
|
});
|
|
128
111
|
}
|
|
129
112
|
|
|
130
|
-
const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
if (gatewayAuthFromEnv.apiKey) {
|
|
138
|
-
return pickGateway({
|
|
139
|
-
explicit: {},
|
|
140
|
-
gatewayAuthFromEnv,
|
|
141
|
-
});
|
|
113
|
+
const gatewayAuthFromEnv = getAiGatewayAuthFromEnv({
|
|
114
|
+
env: authenticationEnvironment,
|
|
115
|
+
});
|
|
116
|
+
if (auth === 'ai-gateway' || gatewayAuthFromEnv.apiKey) {
|
|
117
|
+
return pickGateway({ gatewayAuthFromEnv });
|
|
142
118
|
}
|
|
143
119
|
|
|
144
|
-
return pickAnthropic({
|
|
120
|
+
return pickAnthropic({
|
|
121
|
+
processEnv: authenticationEnvironment,
|
|
122
|
+
readApiKey,
|
|
123
|
+
});
|
|
145
124
|
}
|
|
146
125
|
|
|
147
126
|
export function resolveClaudeCodeAuthenticationMode(
|
|
148
|
-
auth:
|
|
127
|
+
auth: ClaudeCodeAuthenticationMode | undefined,
|
|
149
128
|
processEnv: Record<string, string | undefined> = process.env,
|
|
150
129
|
): ClaudeCodeResolvedAuthenticationMode {
|
|
151
|
-
if (
|
|
130
|
+
if (isHarnessAuthenticationEnvironment(auth)) {
|
|
131
|
+
return getAiGatewayAuthFromEnv({ env: auth }).apiKey
|
|
132
|
+
? 'ai-gateway'
|
|
133
|
+
: 'direct';
|
|
134
|
+
}
|
|
135
|
+
if (auth === 'direct') {
|
|
152
136
|
return 'direct';
|
|
153
137
|
}
|
|
154
|
-
if (auth === 'ai-gateway'
|
|
138
|
+
if (auth === 'ai-gateway') {
|
|
155
139
|
return 'ai-gateway';
|
|
156
140
|
}
|
|
157
141
|
return getAiGatewayAuthFromEnv({ env: processEnv }).apiKey
|
|
@@ -159,46 +143,20 @@ export function resolveClaudeCodeAuthenticationMode(
|
|
|
159
143
|
: 'direct';
|
|
160
144
|
}
|
|
161
145
|
|
|
162
|
-
function normalizeClaudeCodeAuthToLegacyAuth(
|
|
163
|
-
auth: ClaudeCodeAuthOptions | undefined,
|
|
164
|
-
): LegacyClaudeCodeAuthOptions | undefined {
|
|
165
|
-
if (auth == null || auth === 'auto') {
|
|
166
|
-
return undefined;
|
|
167
|
-
}
|
|
168
|
-
if (typeof auth === 'string') {
|
|
169
|
-
switch (auth) {
|
|
170
|
-
case 'direct':
|
|
171
|
-
return { anthropic: {} };
|
|
172
|
-
case 'ai-gateway':
|
|
173
|
-
return { gateway: {} };
|
|
174
|
-
default:
|
|
175
|
-
return undefined;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
console.warn(
|
|
180
|
-
'[claude-code] Passing an object to auth options is deprecated. Use a string mode ("auto" | "direct" | "ai-gateway") instead, and pass credentials via environment variables.',
|
|
181
|
-
);
|
|
182
|
-
return auth;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
146
|
function pickAnthropic({
|
|
186
|
-
explicit,
|
|
187
147
|
processEnv,
|
|
188
148
|
readApiKey,
|
|
189
149
|
}: {
|
|
190
|
-
explicit?: NonNullable<LegacyClaudeCodeAuthOptions['anthropic']>;
|
|
191
150
|
processEnv: Record<string, string | undefined>;
|
|
192
151
|
readApiKey: () => string | undefined;
|
|
193
152
|
}): Record<string, string> {
|
|
194
153
|
const env: Record<string, string> = {};
|
|
195
|
-
const helperKey =
|
|
196
|
-
const apiKey =
|
|
197
|
-
const authToken =
|
|
198
|
-
explicit?.authToken ?? processEnv.ANTHROPIC_AUTH_TOKEN ?? helperKey;
|
|
154
|
+
const helperKey = readApiKey();
|
|
155
|
+
const apiKey = processEnv.ANTHROPIC_API_KEY ?? helperKey;
|
|
156
|
+
const authToken = processEnv.ANTHROPIC_AUTH_TOKEN ?? helperKey;
|
|
199
157
|
if (apiKey) env.ANTHROPIC_API_KEY = apiKey;
|
|
200
158
|
if (authToken) env.ANTHROPIC_AUTH_TOKEN = authToken;
|
|
201
|
-
const baseUrl =
|
|
159
|
+
const baseUrl = processEnv.ANTHROPIC_BASE_URL;
|
|
202
160
|
if (baseUrl) env.ANTHROPIC_BASE_URL = baseUrl;
|
|
203
161
|
return env;
|
|
204
162
|
}
|
|
@@ -240,14 +198,12 @@ function readApiKeyHelper(): string | undefined {
|
|
|
240
198
|
}
|
|
241
199
|
|
|
242
200
|
function pickGateway({
|
|
243
|
-
explicit,
|
|
244
201
|
gatewayAuthFromEnv,
|
|
245
202
|
}: {
|
|
246
|
-
explicit: NonNullable<LegacyClaudeCodeAuthOptions['gateway']>;
|
|
247
203
|
gatewayAuthFromEnv: ReturnType<typeof getAiGatewayAuthFromEnv>;
|
|
248
204
|
}): Record<string, string> {
|
|
249
|
-
const apiKey =
|
|
250
|
-
const baseUrl =
|
|
205
|
+
const apiKey = gatewayAuthFromEnv.apiKey;
|
|
206
|
+
const baseUrl = gatewayAuthFromEnv.baseUrl;
|
|
251
207
|
const env: Record<string, string> = {};
|
|
252
208
|
if (apiKey) {
|
|
253
209
|
env.AI_GATEWAY_API_KEY = apiKey;
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
createClaudeCodeRequestTransformations,
|
|
57
57
|
resolveClaudeCodeAuthenticationMode,
|
|
58
58
|
resolveClaudeCodeEnv,
|
|
59
|
-
type
|
|
59
|
+
type ClaudeCodeAuthenticationMode,
|
|
60
60
|
} from './claude-code-auth';
|
|
61
61
|
import {
|
|
62
62
|
outboundMessageSchema,
|
|
@@ -75,7 +75,7 @@ type ClaudeCodeRespawnStrategy = 'replay' | 'rerun';
|
|
|
75
75
|
const CLAUDE_CODE_CLIENT_APP = `ai-sdk/harness-claude-code/${VERSION}`;
|
|
76
76
|
|
|
77
77
|
export type ClaudeCodeHarnessSettings = {
|
|
78
|
-
readonly auth?:
|
|
78
|
+
readonly auth?: ClaudeCodeAuthenticationMode;
|
|
79
79
|
/**
|
|
80
80
|
* Customizes each credential value before it is forwarded into a sandbox
|
|
81
81
|
* process. This does not restrict which credentials the harness adapter can
|
|
@@ -90,6 +90,8 @@ export type ClaudeCodeHarnessSettings = {
|
|
|
90
90
|
/**
|
|
91
91
|
* Anthropic model id the underlying `claude` CLI should use. Leaving this
|
|
92
92
|
* unset defers to the CLI's default.
|
|
93
|
+
*
|
|
94
|
+
* @deprecated Use `model` on `HarnessAgent` instead.
|
|
93
95
|
*/
|
|
94
96
|
readonly model?: string;
|
|
95
97
|
/**
|
|
@@ -829,6 +831,7 @@ export function createClaudeCode(
|
|
|
829
831
|
lifecycleStateSchema: claudeCodeResumeStateSchema,
|
|
830
832
|
getBootstrap: getClaudeCodeBootstrap,
|
|
831
833
|
doStart: async startOpts => {
|
|
834
|
+
const model = startOpts.model ?? settings.model;
|
|
832
835
|
const sandboxSession = startOpts.sandboxSession;
|
|
833
836
|
const toolSafeSandboxSession =
|
|
834
837
|
getRestrictedSandboxSession(sandboxSession);
|
|
@@ -920,6 +923,10 @@ export function createClaudeCode(
|
|
|
920
923
|
);
|
|
921
924
|
|
|
922
925
|
const workDir = startOpts.sessionWorkDir;
|
|
926
|
+
const sandboxHomeDir = await resolveSandboxHomeDir({
|
|
927
|
+
sandbox: toolSafeSandboxSession,
|
|
928
|
+
abortSignal: startOpts.abortSignal,
|
|
929
|
+
});
|
|
923
930
|
const sessionDataDir = `${defaultWorkingDirectory}/.agent-runs/${startOpts.sessionId}`;
|
|
924
931
|
const bridgeStateDir = `${sessionDataDir}/bridge`;
|
|
925
932
|
const timeoutMs = settings.startupTimeoutMs ?? 120_000;
|
|
@@ -991,7 +998,7 @@ export function createClaudeCode(
|
|
|
991
998
|
// process handle. The session lifecycle method decides whether the
|
|
992
999
|
// sandbox is left running, stopped, or destroyed.
|
|
993
1000
|
proc: undefined,
|
|
994
|
-
model
|
|
1001
|
+
model,
|
|
995
1002
|
maxTurns: settings.maxTurns,
|
|
996
1003
|
env: sandboxClaudeEnvironment,
|
|
997
1004
|
thinking,
|
|
@@ -1006,7 +1013,8 @@ export function createClaudeCode(
|
|
|
1006
1013
|
debug: startOpts.observability?.debug,
|
|
1007
1014
|
permissionMode: startOpts.permissionMode,
|
|
1008
1015
|
builtinToolFiltering: startOpts.builtinToolFiltering,
|
|
1009
|
-
|
|
1016
|
+
sandbox: toolSafeSandboxSession,
|
|
1017
|
+
sandboxHomeDir,
|
|
1010
1018
|
mcpServers: settings.mcpServers,
|
|
1011
1019
|
supportsUserMessageResponses: () => supportsUserMessageResponses,
|
|
1012
1020
|
});
|
|
@@ -1039,13 +1047,6 @@ export function createClaudeCode(
|
|
|
1039
1047
|
}
|
|
1040
1048
|
}
|
|
1041
1049
|
|
|
1042
|
-
const sandboxHomeDir =
|
|
1043
|
-
startOpts.skills && startOpts.skills.length > 0
|
|
1044
|
-
? await resolveSandboxHomeDir({
|
|
1045
|
-
sandbox: toolSafeSandboxSession,
|
|
1046
|
-
abortSignal: startOpts.abortSignal,
|
|
1047
|
-
})
|
|
1048
|
-
: undefined;
|
|
1049
1050
|
const port = resolveBridgePort({
|
|
1050
1051
|
sandboxSession,
|
|
1051
1052
|
override: settings.port,
|
|
@@ -1057,35 +1058,21 @@ export function createClaudeCode(
|
|
|
1057
1058
|
const env = {
|
|
1058
1059
|
BRIDGE_CHANNEL_TOKEN: token,
|
|
1059
1060
|
BRIDGE_WS_PORT: String(port),
|
|
1060
|
-
...(sandboxHomeDir ? { HOME: sandboxHomeDir } : {}),
|
|
1061
1061
|
...(respawnStrategy === 'replay'
|
|
1062
1062
|
? { BRIDGE_REPLAY_FROM_DISK: '1' }
|
|
1063
1063
|
: {}),
|
|
1064
1064
|
};
|
|
1065
1065
|
|
|
1066
1066
|
/*
|
|
1067
|
-
* On a fresh start the workdir
|
|
1068
|
-
*
|
|
1069
|
-
*
|
|
1070
|
-
* spawn — `BRIDGE_CHANNEL_TOKEN` rotates per start.
|
|
1067
|
+
* On a fresh start the workdir and bridge-state directory must be
|
|
1068
|
+
* created. The env is sent fresh on every spawn —
|
|
1069
|
+
* `BRIDGE_CHANNEL_TOKEN` rotates per start.
|
|
1071
1070
|
*/
|
|
1072
1071
|
if (respawnStrategy === undefined) {
|
|
1073
1072
|
await toolSafeSandboxSession.run({
|
|
1074
1073
|
command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)}`,
|
|
1075
1074
|
abortSignal: startOpts.abortSignal,
|
|
1076
1075
|
});
|
|
1077
|
-
|
|
1078
|
-
if (startOpts.skills && startOpts.skills.length > 0) {
|
|
1079
|
-
if (!sandboxHomeDir) {
|
|
1080
|
-
throw new Error('Unable to resolve sandbox HOME directory.');
|
|
1081
|
-
}
|
|
1082
|
-
await writeClaudeCodeSkills({
|
|
1083
|
-
sandbox: toolSafeSandboxSession,
|
|
1084
|
-
homeDir: sandboxHomeDir,
|
|
1085
|
-
skills: startOpts.skills,
|
|
1086
|
-
abortSignal: startOpts.abortSignal,
|
|
1087
|
-
});
|
|
1088
|
-
}
|
|
1089
1076
|
}
|
|
1090
1077
|
|
|
1091
1078
|
await markBridgeStarting({
|
|
@@ -1162,7 +1149,7 @@ export function createClaudeCode(
|
|
|
1162
1149
|
sessionId: startOpts.sessionId,
|
|
1163
1150
|
channel,
|
|
1164
1151
|
proc,
|
|
1165
|
-
model
|
|
1152
|
+
model,
|
|
1166
1153
|
maxTurns: settings.maxTurns,
|
|
1167
1154
|
env: sandboxClaudeEnvironment,
|
|
1168
1155
|
thinking,
|
|
@@ -1177,7 +1164,8 @@ export function createClaudeCode(
|
|
|
1177
1164
|
debug: startOpts.observability?.debug,
|
|
1178
1165
|
permissionMode: startOpts.permissionMode,
|
|
1179
1166
|
builtinToolFiltering: startOpts.builtinToolFiltering,
|
|
1180
|
-
|
|
1167
|
+
sandbox: toolSafeSandboxSession,
|
|
1168
|
+
sandboxHomeDir,
|
|
1181
1169
|
mcpServers: settings.mcpServers,
|
|
1182
1170
|
supportsUserMessageResponses: () => supportsUserMessageResponses,
|
|
1183
1171
|
});
|
|
@@ -1506,7 +1494,8 @@ function createSession({
|
|
|
1506
1494
|
debug,
|
|
1507
1495
|
permissionMode,
|
|
1508
1496
|
builtinToolFiltering,
|
|
1509
|
-
|
|
1497
|
+
sandbox,
|
|
1498
|
+
sandboxHomeDir,
|
|
1510
1499
|
mcpServers,
|
|
1511
1500
|
supportsUserMessageResponses,
|
|
1512
1501
|
}: {
|
|
@@ -1529,7 +1518,8 @@ function createSession({
|
|
|
1529
1518
|
debug: HarnessV1DebugConfig | undefined;
|
|
1530
1519
|
permissionMode: HarnessV1PermissionMode | undefined;
|
|
1531
1520
|
builtinToolFiltering: HarnessV1BuiltinToolFiltering | undefined;
|
|
1532
|
-
|
|
1521
|
+
sandbox: SandboxSession;
|
|
1522
|
+
sandboxHomeDir: string;
|
|
1533
1523
|
mcpServers: Record<string, unknown> | undefined;
|
|
1534
1524
|
supportsUserMessageResponses: () => boolean;
|
|
1535
1525
|
}): HarnessV1Session {
|
|
@@ -1705,11 +1695,27 @@ function createSession({
|
|
|
1705
1695
|
harnessId: 'claude-code',
|
|
1706
1696
|
});
|
|
1707
1697
|
}
|
|
1698
|
+
await writeClaudeCodeSkills({
|
|
1699
|
+
sandbox,
|
|
1700
|
+
homeDir: sandboxHomeDir,
|
|
1701
|
+
skills: promptOpts.skills,
|
|
1702
|
+
abortSignal: promptOpts.abortSignal,
|
|
1703
|
+
});
|
|
1708
1704
|
const control = wireTurn({
|
|
1709
1705
|
emit: promptOpts.emit,
|
|
1710
1706
|
abortSignal: promptOpts.abortSignal,
|
|
1711
1707
|
});
|
|
1712
1708
|
|
|
1709
|
+
/*
|
|
1710
|
+
* A signal that was already aborted has settled the turn inside
|
|
1711
|
+
* `wireTurn`. Sending `start` anyway would run a full unattended turn
|
|
1712
|
+
* in the bridge — consuming tokens and possibly acting on the
|
|
1713
|
+
* workspace — after the caller has already observed the abort.
|
|
1714
|
+
*/
|
|
1715
|
+
if (promptOpts.abortSignal?.aborted) {
|
|
1716
|
+
return control;
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1713
1719
|
const startMessage = {
|
|
1714
1720
|
type: 'start' as const,
|
|
1715
1721
|
prompt: extractUserText(promptOpts.prompt),
|
|
@@ -1729,8 +1735,8 @@ function createSession({
|
|
|
1729
1735
|
...(env !== undefined ? { env } : {}),
|
|
1730
1736
|
thinking,
|
|
1731
1737
|
...(effort !== undefined ? { effort } : {}),
|
|
1732
|
-
...(skills.length > 0
|
|
1733
|
-
? { skills: skills.map(skill => skill.name) }
|
|
1738
|
+
...(promptOpts.skills.length > 0
|
|
1739
|
+
? { skills: promptOpts.skills.map(skill => skill.name) }
|
|
1734
1740
|
: {}),
|
|
1735
1741
|
...(mcpServers == null ? {} : { mcpServers }),
|
|
1736
1742
|
...(permissionMode ? { permissionMode } : {}),
|
|
@@ -1754,6 +1760,12 @@ function createSession({
|
|
|
1754
1760
|
harnessId: 'claude-code',
|
|
1755
1761
|
});
|
|
1756
1762
|
}
|
|
1763
|
+
await writeClaudeCodeSkills({
|
|
1764
|
+
sandbox,
|
|
1765
|
+
homeDir: sandboxHomeDir,
|
|
1766
|
+
skills: continueOpts.skills,
|
|
1767
|
+
abortSignal: continueOpts.abortSignal,
|
|
1768
|
+
});
|
|
1757
1769
|
const control = wireTurn({
|
|
1758
1770
|
emit: continueOpts.emit,
|
|
1759
1771
|
abortSignal: continueOpts.abortSignal,
|
|
@@ -1772,7 +1784,9 @@ function createSession({
|
|
|
1772
1784
|
* recomputed. This is the rare bridge-died fallback; the common slice path
|
|
1773
1785
|
* is `attach`.
|
|
1774
1786
|
*/
|
|
1775
|
-
|
|
1787
|
+
// Same as `doPromptTurn`: an already-aborted signal settled the turn in
|
|
1788
|
+
// `wireTurn`, so don't re-drive the thread nobody is waiting on.
|
|
1789
|
+
if (rerunContinue && !continueOpts.abortSignal?.aborted) {
|
|
1776
1790
|
pendingResumeFlag = false;
|
|
1777
1791
|
channel.send({
|
|
1778
1792
|
type: 'start' as const,
|
|
@@ -1800,8 +1814,8 @@ function createSession({
|
|
|
1800
1814
|
...(env !== undefined ? { env } : {}),
|
|
1801
1815
|
thinking,
|
|
1802
1816
|
...(effort !== undefined ? { effort } : {}),
|
|
1803
|
-
...(skills.length > 0
|
|
1804
|
-
? { skills: skills.map(skill => skill.name) }
|
|
1817
|
+
...(continueOpts.skills.length > 0
|
|
1818
|
+
? { skills: continueOpts.skills.map(skill => skill.name) }
|
|
1805
1819
|
: {}),
|
|
1806
1820
|
...(mcpServers == null ? {} : { mcpServers }),
|
|
1807
1821
|
...(permissionMode ? { permissionMode } : {}),
|
package/src/index.ts
CHANGED
|
@@ -10,8 +10,5 @@ export const claudeCode = createClaudeCode();
|
|
|
10
10
|
export { createClaudeCode } from './claude-code-harness';
|
|
11
11
|
export { VERSION } from './version';
|
|
12
12
|
export type { ClaudeCodeHarnessSettings } from './claude-code-harness';
|
|
13
|
-
export type {
|
|
14
|
-
ClaudeCodeAuthenticationMode,
|
|
15
|
-
ClaudeCodeAuthOptions,
|
|
16
|
-
} from './claude-code-auth';
|
|
13
|
+
export type { ClaudeCodeAuthenticationMode } from './claude-code-auth';
|
|
17
14
|
export type { ClaudeCodeThinkingConfig } from './claude-code-thinking';
|