@ai-sdk/harness-claude-code 1.0.102 → 1.0.104
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 +17 -0
- package/dist/bridge/index.mjs +28 -5
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/bridge/create-emit-stream-event.ts +50 -22
- package/src/claude-code-harness.ts +6 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/harness-claude-code",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.104",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@ai-sdk/harness": "1.0.
|
|
30
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
29
|
+
"@ai-sdk/harness": "1.0.100",
|
|
30
|
+
"@ai-sdk/provider-utils": "5.0.36",
|
|
31
31
|
"ws": "^8.21.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
@@ -298,25 +298,15 @@ export function createEmitStreamEvent({
|
|
|
298
298
|
const toolName = toCommonName(nativeName);
|
|
299
299
|
const dynamic = state.externalMcpToolUseIds.delete(block.tool_use_id);
|
|
300
300
|
const isError = !!block.is_error;
|
|
301
|
-
const content = stringifyContent(block.content);
|
|
302
|
-
/*
|
|
303
|
-
* Claude Code's Bash tool does not report the command's real
|
|
304
|
-
* numeric exit code — the SDK exposes only stdout/stderr text and
|
|
305
|
-
* an is_error flag. Consumers (and the example UI) render bash
|
|
306
|
-
* failures from an `exitCode` field on a structured result, the
|
|
307
|
-
* shape Codex's shell tool provides natively. When Claude omits
|
|
308
|
-
* `tool_use_result`, derive a binary code from is_error: 1 on
|
|
309
|
-
* failure, 0 on success. This fallback is a stand-in for
|
|
310
|
-
* failed/succeeded, not the process's true exit status.
|
|
311
|
-
*/
|
|
312
|
-
const contentResult =
|
|
313
|
-
toolName === 'bash'
|
|
314
|
-
? { exitCode: isError ? 1 : 0, stdout: content }
|
|
315
|
-
: dynamic
|
|
316
|
-
? parseMcpToolResult(content)
|
|
317
|
-
: content;
|
|
318
301
|
const result =
|
|
319
|
-
toolUseResult !== undefined
|
|
302
|
+
toolUseResult !== undefined
|
|
303
|
+
? toolUseResult
|
|
304
|
+
: resolveToolResult({
|
|
305
|
+
toolName,
|
|
306
|
+
dynamic,
|
|
307
|
+
isError,
|
|
308
|
+
rawContent: block.content,
|
|
309
|
+
});
|
|
320
310
|
emit({
|
|
321
311
|
type: 'tool-result',
|
|
322
312
|
toolCallId: block.tool_use_id,
|
|
@@ -501,23 +491,61 @@ function handleStreamEvent({
|
|
|
501
491
|
}
|
|
502
492
|
}
|
|
503
493
|
|
|
494
|
+
function isTextEntry(entry: unknown): entry is { text?: unknown } {
|
|
495
|
+
return entry != null && typeof entry === 'object' && 'text' in entry;
|
|
496
|
+
}
|
|
497
|
+
|
|
504
498
|
function stringifyContent(content: unknown): string {
|
|
505
499
|
if (typeof content === 'string') return content;
|
|
506
500
|
if (Array.isArray(content)) {
|
|
507
501
|
return content
|
|
508
502
|
.map(entry =>
|
|
509
|
-
entry
|
|
510
|
-
? String((entry as { text?: unknown }).text ?? '')
|
|
511
|
-
: JSON.stringify(entry),
|
|
503
|
+
isTextEntry(entry) ? String(entry.text ?? '') : JSON.stringify(entry),
|
|
512
504
|
)
|
|
513
505
|
.join('');
|
|
514
506
|
}
|
|
515
507
|
return JSON.stringify(content);
|
|
516
508
|
}
|
|
517
509
|
|
|
510
|
+
function hasNonTextContent(content: unknown): boolean {
|
|
511
|
+
return Array.isArray(content) && content.some(entry => !isTextEntry(entry));
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function resolveToolResult({
|
|
515
|
+
toolName,
|
|
516
|
+
dynamic,
|
|
517
|
+
isError,
|
|
518
|
+
rawContent,
|
|
519
|
+
}: {
|
|
520
|
+
toolName: string;
|
|
521
|
+
dynamic: boolean;
|
|
522
|
+
isError: boolean;
|
|
523
|
+
rawContent: unknown;
|
|
524
|
+
}): unknown {
|
|
525
|
+
/*
|
|
526
|
+
* Claude Code's Bash tool does not report the command's real numeric exit
|
|
527
|
+
* code — the SDK exposes only stdout/stderr text and an is_error flag.
|
|
528
|
+
* Consumers (and the example UI) render bash failures from an `exitCode`
|
|
529
|
+
* field on a structured result, the shape Codex's shell tool provides
|
|
530
|
+
* natively. When Claude omits `tool_use_result`, derive a binary code from
|
|
531
|
+
* is_error: 1 on failure, 0 on success. This fallback is a stand-in for
|
|
532
|
+
* failed/succeeded, not the process's true exit status.
|
|
533
|
+
*/
|
|
534
|
+
if (toolName === 'bash') {
|
|
535
|
+
return { exitCode: isError ? 1 : 0, stdout: stringifyContent(rawContent) };
|
|
536
|
+
}
|
|
537
|
+
// Must precede the MCP branch: flattening a non-text block to base64 text
|
|
538
|
+
// is not recoverable by parsing it back.
|
|
539
|
+
if (hasNonTextContent(rawContent)) return rawContent;
|
|
540
|
+
const content = stringifyContent(rawContent);
|
|
541
|
+
return dynamic ? parseMcpToolResult(content) : content;
|
|
542
|
+
}
|
|
543
|
+
|
|
518
544
|
function parseMcpToolResult(content: string): unknown {
|
|
519
545
|
try {
|
|
520
|
-
|
|
546
|
+
const parsed = JSON.parse(content);
|
|
547
|
+
// `JSON.parse` also succeeds on scalars; keep those as the string sent.
|
|
548
|
+
return parsed !== null && typeof parsed === 'object' ? parsed : content;
|
|
521
549
|
} catch {
|
|
522
550
|
return content;
|
|
523
551
|
}
|
|
@@ -921,13 +921,18 @@ export function createClaudeCode(
|
|
|
921
921
|
);
|
|
922
922
|
}
|
|
923
923
|
} else {
|
|
924
|
-
warnCredentialBrokeringUnavailable();
|
|
925
924
|
sandboxClaudeEnvironment = await applyCredentialForwarding({
|
|
926
925
|
environment: sandboxClaudeEnvironment,
|
|
927
926
|
credentialEnvironmentVariables:
|
|
928
927
|
CLAUDE_CODE_CREDENTIAL_ENVIRONMENT_VARIABLES,
|
|
929
928
|
credentialForwarding: settings.credentialForwarding,
|
|
930
929
|
});
|
|
930
|
+
warnCredentialBrokeringUnavailable({
|
|
931
|
+
environment: claudeEnvironment,
|
|
932
|
+
forwardedEnvironment: sandboxClaudeEnvironment,
|
|
933
|
+
credentialEnvironmentVariables:
|
|
934
|
+
CLAUDE_CODE_CREDENTIAL_ENVIRONMENT_VARIABLES,
|
|
935
|
+
});
|
|
931
936
|
}
|
|
932
937
|
const bootstrapDir = posix.resolve(
|
|
933
938
|
defaultWorkingDirectory,
|