claude-code-rust 0.14.2 → 0.14.3
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.
|
@@ -8,7 +8,7 @@ import { linkTaskToolUse, unlinkTaskToolUse } from "./task_links.js";
|
|
|
8
8
|
import { emitAuthRequired, classifyTurnErrorKind, emitFastModeUpdate, emitFastModeUpdateIfChanged, setFastModeSnapshotIfChanged, } from "./error_classification.js";
|
|
9
9
|
import { mapAvailableAgentsFromNames, emitAvailableAgentsIfChanged, refreshAvailableAgents } from "./agents.js";
|
|
10
10
|
import { mapInitSlashCommands, mapSdkSlashCommands, updateAvailableCommands, } from "./available_commands.js";
|
|
11
|
-
import { buildApiRetryUpdate, buildRateLimitUpdate, buildSubagentRetryUpdate, normalizeSettingsParseErrors, numberField, parseApiRetryError, parseRuntimeSessionState, } from "./state_parsing.js";
|
|
11
|
+
import { buildApiRetryUpdate, buildRateLimitUpdate, buildSubagentRetryUpdate, normalizeSettingsParseErrors, nonNegativeIntegerField, numberField, parseApiRetryError, parseRuntimeSessionState, } from "./state_parsing.js";
|
|
12
12
|
import { looksLikeAuthRequired } from "./auth.js";
|
|
13
13
|
import { emitCurrentModelUpdate, refreshCurrentModel, updateSessionId } from "./session_lifecycle.js";
|
|
14
14
|
import { bridgeLogger, LOG_TARGETS } from "./logger.js";
|
|
@@ -576,6 +576,18 @@ function logContentBlockLinkage(session, blockType, toolUseId, toolName, linkage
|
|
|
576
576
|
},
|
|
577
577
|
});
|
|
578
578
|
}
|
|
579
|
+
function resolveToolProgressTarget(session, taskToolUseId, toolUseId, parentToolUseId) {
|
|
580
|
+
if (taskToolUseId && session.toolCalls.has(taskToolUseId)) {
|
|
581
|
+
return { toolUseId: taskToolUseId, source: "task" };
|
|
582
|
+
}
|
|
583
|
+
if (toolUseId && session.toolCalls.has(toolUseId)) {
|
|
584
|
+
return { toolUseId, source: "tool" };
|
|
585
|
+
}
|
|
586
|
+
if (parentToolUseId && session.toolCalls.has(parentToolUseId)) {
|
|
587
|
+
return { toolUseId: parentToolUseId, source: "parent" };
|
|
588
|
+
}
|
|
589
|
+
return null;
|
|
590
|
+
}
|
|
579
591
|
function hideToolUse(session, toolUseId) {
|
|
580
592
|
if (toolUseId) {
|
|
581
593
|
session.hiddenToolUseIds.add(toolUseId);
|
|
@@ -1036,12 +1048,31 @@ export function handleSdkMessage(session, message) {
|
|
|
1036
1048
|
emitSessionUpdate(session.sessionId, { type: "current_mode_update", current_mode_id: mode });
|
|
1037
1049
|
}
|
|
1038
1050
|
if (msg.status === "compacting") {
|
|
1039
|
-
emitSessionUpdate(session.sessionId, { type: "
|
|
1051
|
+
emitSessionUpdate(session.sessionId, { type: "compaction_update", phase: "started" });
|
|
1040
1052
|
}
|
|
1041
1053
|
else if (msg.status === "requesting") {
|
|
1042
1054
|
emitSessionUpdate(session.sessionId, { type: "session_status_update", status: "requesting" });
|
|
1043
1055
|
}
|
|
1044
1056
|
else if (msg.status === null) {
|
|
1057
|
+
if (msg.compact_result === "success") {
|
|
1058
|
+
emitSessionUpdate(session.sessionId, {
|
|
1059
|
+
type: "compaction_update",
|
|
1060
|
+
phase: "finished",
|
|
1061
|
+
result: "success",
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
else if (msg.compact_result === "failed") {
|
|
1065
|
+
const compactError = typeof msg.compact_error === "string" && msg.compact_error.trim().length > 0
|
|
1066
|
+
? msg.compact_error.trim()
|
|
1067
|
+
: undefined;
|
|
1068
|
+
emitSessionUpdate(session.sessionId, {
|
|
1069
|
+
type: "compaction_update",
|
|
1070
|
+
phase: "finished",
|
|
1071
|
+
result: "failed",
|
|
1072
|
+
error_code: compactError === "too_few_groups" ? "too_few_groups" : "unknown",
|
|
1073
|
+
...(compactError ? { error: compactError } : {}),
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1045
1076
|
emitSessionUpdate(session.sessionId, { type: "session_status_update", status: "idle" });
|
|
1046
1077
|
}
|
|
1047
1078
|
emitFastModeUpdateIfChanged(session, msg.fast_mode_state, msg.fast_mode_disabled_reason);
|
|
@@ -1053,12 +1084,17 @@ export function handleSdkMessage(session, message) {
|
|
|
1053
1084
|
return;
|
|
1054
1085
|
}
|
|
1055
1086
|
const trigger = compactMetadata.trigger;
|
|
1056
|
-
const preTokens =
|
|
1087
|
+
const preTokens = nonNegativeIntegerField(compactMetadata, "pre_tokens", "preTokens");
|
|
1088
|
+
const postTokens = nonNegativeIntegerField(compactMetadata, "post_tokens", "postTokens");
|
|
1089
|
+
const durationMs = nonNegativeIntegerField(compactMetadata, "duration_ms", "durationMs");
|
|
1057
1090
|
if ((trigger === "manual" || trigger === "auto") && preTokens !== undefined) {
|
|
1058
1091
|
emitSessionUpdate(session.sessionId, {
|
|
1059
|
-
type: "
|
|
1092
|
+
type: "compaction_update",
|
|
1093
|
+
phase: "boundary",
|
|
1060
1094
|
trigger,
|
|
1061
1095
|
pre_tokens: preTokens,
|
|
1096
|
+
...(postTokens !== undefined ? { post_tokens: postTokens } : {}),
|
|
1097
|
+
...(durationMs !== undefined ? { duration_ms: durationMs } : {}),
|
|
1062
1098
|
});
|
|
1063
1099
|
}
|
|
1064
1100
|
return;
|
|
@@ -1141,25 +1177,29 @@ export function handleSdkMessage(session, message) {
|
|
|
1141
1177
|
if (type === "tool_progress") {
|
|
1142
1178
|
const toolUseId = typeof msg.tool_use_id === "string" ? msg.tool_use_id : "";
|
|
1143
1179
|
const toolName = typeof msg.tool_name === "string" ? msg.tool_name : "Tool";
|
|
1180
|
+
const parentToolUseId = typeof msg.parent_tool_use_id === "string" ? msg.parent_tool_use_id : "";
|
|
1144
1181
|
const taskId = typeof msg.task_id === "string" ? msg.task_id : "";
|
|
1145
1182
|
const taskToolUseId = taskId ? session.taskToolUseIds.get(taskId) ?? "" : "";
|
|
1146
|
-
|
|
1147
|
-
if (isHiddenToolUse(session, resolvedToolUseId, toolName)) {
|
|
1183
|
+
if (isHiddenToolUse(session, toolUseId, toolName)) {
|
|
1148
1184
|
return;
|
|
1149
1185
|
}
|
|
1186
|
+
const progressTarget = resolveToolProgressTarget(session, taskToolUseId, toolUseId, parentToolUseId);
|
|
1187
|
+
const resolvedToolUseId = progressTarget?.toolUseId ?? "";
|
|
1150
1188
|
bridgeLogger.debug({
|
|
1151
1189
|
target: LOG_TARGETS.APP_TOOL,
|
|
1152
1190
|
eventName: "sdk_tool_progress_linkage_observed",
|
|
1153
1191
|
message: "SDK tool progress linkage observed",
|
|
1154
|
-
outcome:
|
|
1192
|
+
outcome: progressTarget?.source ?? "orphaned",
|
|
1155
1193
|
sessionId: session.sessionId,
|
|
1156
|
-
toolCallId: resolvedToolUseId || undefined,
|
|
1194
|
+
toolCallId: resolvedToolUseId || toolUseId || undefined,
|
|
1157
1195
|
fields: {
|
|
1158
1196
|
tool_name: toolName,
|
|
1159
1197
|
tool_use_id: toolUseId || undefined,
|
|
1160
|
-
parent_tool_use_id:
|
|
1198
|
+
parent_tool_use_id: parentToolUseId || undefined,
|
|
1161
1199
|
task_id: taskId || undefined,
|
|
1162
1200
|
task_resolved_tool_use_id: taskToolUseId || undefined,
|
|
1201
|
+
resolved_tool_use_id: resolvedToolUseId || undefined,
|
|
1202
|
+
correlation_source: progressTarget?.source,
|
|
1163
1203
|
},
|
|
1164
1204
|
});
|
|
1165
1205
|
if (resolvedToolUseId) {
|
|
@@ -1178,7 +1218,7 @@ export function handleSdkMessage(session, message) {
|
|
|
1178
1218
|
const subagentType = typeof msg.subagent_type === "string" && msg.subagent_type.trim()
|
|
1179
1219
|
? msg.subagent_type.trim()
|
|
1180
1220
|
: undefined;
|
|
1181
|
-
emitToolProgressUpdate(session, resolvedToolUseId,
|
|
1221
|
+
emitToolProgressUpdate(session, resolvedToolUseId, {
|
|
1182
1222
|
...(subagentRetry
|
|
1183
1223
|
? { subagentRetry }
|
|
1184
1224
|
: hasSubagentRetry
|
|
@@ -15,7 +15,7 @@ function nonNegativeNumberField(record, ...keys) {
|
|
|
15
15
|
}
|
|
16
16
|
return value;
|
|
17
17
|
}
|
|
18
|
-
function nonNegativeIntegerField(record, ...keys) {
|
|
18
|
+
export function nonNegativeIntegerField(record, ...keys) {
|
|
19
19
|
const value = numberField(record, ...keys);
|
|
20
20
|
return value !== undefined && value >= 0 && Number.isInteger(value) ? value : undefined;
|
|
21
21
|
}
|
|
@@ -339,14 +339,15 @@ export function finalizeOpenToolCalls(session, status) {
|
|
|
339
339
|
emitToolCallUpdate(session, toolUseId, { status }, "finalize");
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
|
-
|
|
343
|
-
|
|
342
|
+
/**
|
|
343
|
+
* Apply advisory progress only to a tool created by an authoritative tool-use event.
|
|
344
|
+
*/
|
|
345
|
+
export function emitToolProgressUpdate(session, toolUseId, progress = {}) {
|
|
346
|
+
const existing = session.toolCalls.get(toolUseId);
|
|
344
347
|
if (!existing) {
|
|
345
|
-
|
|
346
|
-
existing = session.toolCalls.get(toolUseId);
|
|
348
|
+
return;
|
|
347
349
|
}
|
|
348
|
-
if (
|
|
349
|
-
existing.status === "completed" ||
|
|
350
|
+
if (existing.status === "completed" ||
|
|
350
351
|
existing.status === "failed" ||
|
|
351
352
|
existing.status === "killed") {
|
|
352
353
|
return;
|
|
@@ -23,6 +23,19 @@ const WORKFLOW_TOOL_NAME = "Workflow";
|
|
|
23
23
|
const PROJECTS_TOOL_NAME = "Projects";
|
|
24
24
|
const ARTIFACT_TOOL_NAME = "Artifact";
|
|
25
25
|
const SHOW_ONBOARDING_ROLE_PICKER_TOOL_NAME = "ShowOnboardingRolePicker";
|
|
26
|
+
const SKILL_TOOL_NAME = "Skill";
|
|
27
|
+
const SKILL_WORD_OVERRIDES = {
|
|
28
|
+
api: "API",
|
|
29
|
+
ci: "CI",
|
|
30
|
+
cli: "CLI",
|
|
31
|
+
gh: "GH",
|
|
32
|
+
github: "GitHub",
|
|
33
|
+
mcp: "MCP",
|
|
34
|
+
pdf: "PDF",
|
|
35
|
+
sdk: "SDK",
|
|
36
|
+
ui: "UI",
|
|
37
|
+
ux: "UX",
|
|
38
|
+
};
|
|
26
39
|
const READ_MCP_RESOURCE_TOOL_NAME = "ReadMcpResource";
|
|
27
40
|
const READ_MCP_RESOURCE_DIR_TOOL_NAME = "ReadMcpResourceDir";
|
|
28
41
|
const SEARCH_OUTPUT_MODES = new Set(["content", "files_with_matches", "count"]);
|
|
@@ -183,6 +196,7 @@ export function normalizeToolKind(name) {
|
|
|
183
196
|
case "Projects":
|
|
184
197
|
case "Artifact":
|
|
185
198
|
case "ShowOnboardingRolePicker":
|
|
199
|
+
case SKILL_TOOL_NAME:
|
|
186
200
|
return "other";
|
|
187
201
|
case "Task":
|
|
188
202
|
case "Agent":
|
|
@@ -194,6 +208,34 @@ export function normalizeToolKind(name) {
|
|
|
194
208
|
return "think";
|
|
195
209
|
}
|
|
196
210
|
}
|
|
211
|
+
function skillDisplayName(rawName) {
|
|
212
|
+
const trimmed = rawName.trim();
|
|
213
|
+
const segments = trimmed.split(":");
|
|
214
|
+
if (segments.length > 2 ||
|
|
215
|
+
segments.some((segment) => !segment || !/^[a-zA-Z0-9]+(?:[-_][a-zA-Z0-9]+)*$/.test(segment))) {
|
|
216
|
+
return trimmed;
|
|
217
|
+
}
|
|
218
|
+
const displaySegments = segments.map((segment) => segment
|
|
219
|
+
.split(/[-_]/)
|
|
220
|
+
.map((word) => skillDisplayWord(word))
|
|
221
|
+
.join(" "));
|
|
222
|
+
if (displaySegments.length === 2 &&
|
|
223
|
+
displaySegments[0].toLowerCase() === displaySegments[1].toLowerCase()) {
|
|
224
|
+
return displaySegments[1];
|
|
225
|
+
}
|
|
226
|
+
return displaySegments.join(" / ");
|
|
227
|
+
}
|
|
228
|
+
function skillDisplayWord(word) {
|
|
229
|
+
const override = SKILL_WORD_OVERRIDES[word.toLowerCase()];
|
|
230
|
+
if (override) {
|
|
231
|
+
return override;
|
|
232
|
+
}
|
|
233
|
+
if (/^[A-Z0-9]+$/.test(word) ||
|
|
234
|
+
(/[a-z]/.test(word) && /[A-Z]/.test(word) && !/^[A-Z][a-z0-9]*$/.test(word))) {
|
|
235
|
+
return word;
|
|
236
|
+
}
|
|
237
|
+
return `${word.charAt(0).toUpperCase()}${word.slice(1).toLowerCase()}`;
|
|
238
|
+
}
|
|
197
239
|
export function toolTitle(name, input, context = {}) {
|
|
198
240
|
const agentTitle = agentInputTitle(name, input);
|
|
199
241
|
if (agentTitle) {
|
|
@@ -263,6 +305,12 @@ export function toolTitle(name, input, context = {}) {
|
|
|
263
305
|
if (name === SHOW_ONBOARDING_ROLE_PICKER_TOOL_NAME) {
|
|
264
306
|
return SHOW_ONBOARDING_ROLE_PICKER_TOOL_NAME;
|
|
265
307
|
}
|
|
308
|
+
if (name === SKILL_TOOL_NAME) {
|
|
309
|
+
const skillName = nonEmptyString(input.skill);
|
|
310
|
+
return skillName
|
|
311
|
+
? `${SKILL_TOOL_NAME}: ${skillDisplayName(skillName)}`
|
|
312
|
+
: SKILL_TOOL_NAME;
|
|
313
|
+
}
|
|
266
314
|
if (name === "EnterWorktree") {
|
|
267
315
|
const worktreeName = typeof input.name === "string" ? input.name.trim() : "";
|
|
268
316
|
return worktreeName || "EnterWorktree";
|
|
@@ -369,6 +417,17 @@ function resultRecordCandidates(rawResult, rawContent) {
|
|
|
369
417
|
pushNestedRecords(rawContent);
|
|
370
418
|
return candidates;
|
|
371
419
|
}
|
|
420
|
+
function imageReadResultText(rawResult, rawContent, rawInput) {
|
|
421
|
+
const isImage = resultRecordCandidates(rawResult, rawContent).some((candidate) => candidate.type === "image");
|
|
422
|
+
if (!isImage) {
|
|
423
|
+
return undefined;
|
|
424
|
+
}
|
|
425
|
+
const input = asRecordOrNull(rawInput);
|
|
426
|
+
const filePath = typeof input?.file_path === "string" ? input.file_path.trim() : "";
|
|
427
|
+
const normalizedPath = filePath.replaceAll("\\", "/");
|
|
428
|
+
const fileName = normalizedPath.slice(normalizedPath.lastIndexOf("/") + 1);
|
|
429
|
+
return fileName ? `Viewed Image ${fileName}` : "Viewed Image";
|
|
430
|
+
}
|
|
372
431
|
function parseJsonCandidate(value) {
|
|
373
432
|
const text = typeof value === "string" ? value : extractText(value);
|
|
374
433
|
const trimmed = text.trim();
|
|
@@ -1593,6 +1652,51 @@ function collectResultCandidates(rawResult, rawContent) {
|
|
|
1593
1652
|
}
|
|
1594
1653
|
return candidates;
|
|
1595
1654
|
}
|
|
1655
|
+
function parseSkillResult(toolName, rawResult, rawContent) {
|
|
1656
|
+
if (toolName !== SKILL_TOOL_NAME) {
|
|
1657
|
+
return undefined;
|
|
1658
|
+
}
|
|
1659
|
+
for (const candidate of collectResultCandidates(rawResult, rawContent)) {
|
|
1660
|
+
const commandName = nonEmptyString(candidate.commandName);
|
|
1661
|
+
if (!commandName || typeof candidate.success !== "boolean") {
|
|
1662
|
+
continue;
|
|
1663
|
+
}
|
|
1664
|
+
if (candidate.status === "forked") {
|
|
1665
|
+
const agentId = nonEmptyString(candidate.agentId);
|
|
1666
|
+
if (!agentId || typeof candidate.result !== "string") {
|
|
1667
|
+
continue;
|
|
1668
|
+
}
|
|
1669
|
+
if (candidate.background !== undefined && typeof candidate.background !== "boolean") {
|
|
1670
|
+
continue;
|
|
1671
|
+
}
|
|
1672
|
+
return {
|
|
1673
|
+
success: candidate.success,
|
|
1674
|
+
commandName,
|
|
1675
|
+
status: "forked",
|
|
1676
|
+
agentId,
|
|
1677
|
+
result: candidate.result,
|
|
1678
|
+
...(typeof candidate.background === "boolean"
|
|
1679
|
+
? { background: candidate.background }
|
|
1680
|
+
: {}),
|
|
1681
|
+
};
|
|
1682
|
+
}
|
|
1683
|
+
if (candidate.status === undefined || candidate.status === "inline") {
|
|
1684
|
+
const allowedToolsValid = candidate.allowedTools === undefined ||
|
|
1685
|
+
(Array.isArray(candidate.allowedTools) &&
|
|
1686
|
+
candidate.allowedTools.every((tool) => typeof tool === "string"));
|
|
1687
|
+
const modelValid = candidate.model === undefined || typeof candidate.model === "string";
|
|
1688
|
+
if (!allowedToolsValid || !modelValid) {
|
|
1689
|
+
continue;
|
|
1690
|
+
}
|
|
1691
|
+
return {
|
|
1692
|
+
success: candidate.success,
|
|
1693
|
+
commandName,
|
|
1694
|
+
status: "inline",
|
|
1695
|
+
};
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
return undefined;
|
|
1699
|
+
}
|
|
1596
1700
|
function monitorResultFields(toolName, rawResult, rawContent) {
|
|
1597
1701
|
if (toolName !== MONITOR_TOOL_NAME) {
|
|
1598
1702
|
return undefined;
|
|
@@ -1797,6 +1901,32 @@ export function buildToolResultFields(isError, rawContent, base, rawResult, _con
|
|
|
1797
1901
|
if (outputMetadata) {
|
|
1798
1902
|
fields.output_metadata = outputMetadata;
|
|
1799
1903
|
}
|
|
1904
|
+
const skillResult = !isError ? parseSkillResult(toolName, rawResult, rawContent) : undefined;
|
|
1905
|
+
if (skillResult) {
|
|
1906
|
+
fields.title = `${SKILL_TOOL_NAME}: ${skillDisplayName(skillResult.commandName)}`;
|
|
1907
|
+
if (!skillResult.success) {
|
|
1908
|
+
fields.status = "failed";
|
|
1909
|
+
}
|
|
1910
|
+
else if (skillResult.status === "inline") {
|
|
1911
|
+
return fields;
|
|
1912
|
+
}
|
|
1913
|
+
else {
|
|
1914
|
+
const output = skillResult.result.trim();
|
|
1915
|
+
if (output) {
|
|
1916
|
+
fields.raw_output = output;
|
|
1917
|
+
fields.content = [{ type: "content", content: { type: "text", text: output } }];
|
|
1918
|
+
}
|
|
1919
|
+
return fields;
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
const imageReadText = !isError && toolName === "Read"
|
|
1923
|
+
? imageReadResultText(rawResult, rawContent, base?.raw_input)
|
|
1924
|
+
: undefined;
|
|
1925
|
+
if (imageReadText !== undefined) {
|
|
1926
|
+
fields.raw_output = imageReadText;
|
|
1927
|
+
fields.content = [{ type: "content", content: { type: "text", text: imageReadText } }];
|
|
1928
|
+
return fields;
|
|
1929
|
+
}
|
|
1800
1930
|
const fileUnchangedText = !isError && toolName === "Read" ? fileUnchangedResultText(rawResult, rawContent) : "";
|
|
1801
1931
|
if (fileUnchangedText) {
|
|
1802
1932
|
fields.raw_output = fileUnchangedText;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-code-rust",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.3",
|
|
4
4
|
"description": "Claude Code Rust - native Rust terminal interface for Claude Code",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -36,12 +36,12 @@
|
|
|
36
36
|
"@anthropic-ai/claude-agent-sdk": "0.3.220"
|
|
37
37
|
},
|
|
38
38
|
"optionalDependencies": {
|
|
39
|
-
"@srothgan/claude-code-rust-darwin-arm64": "0.14.
|
|
40
|
-
"@srothgan/claude-code-rust-darwin-x64": "0.14.
|
|
41
|
-
"@srothgan/claude-code-rust-linux-x64-gnu": "0.14.
|
|
42
|
-
"@srothgan/claude-code-rust-linux-arm64-gnu": "0.14.
|
|
43
|
-
"@srothgan/claude-code-rust-win32-x64-msvc": "0.14.
|
|
44
|
-
"@srothgan/claude-code-rust-win32-arm64-msvc": "0.14.
|
|
39
|
+
"@srothgan/claude-code-rust-darwin-arm64": "0.14.3",
|
|
40
|
+
"@srothgan/claude-code-rust-darwin-x64": "0.14.3",
|
|
41
|
+
"@srothgan/claude-code-rust-linux-x64-gnu": "0.14.3",
|
|
42
|
+
"@srothgan/claude-code-rust-linux-arm64-gnu": "0.14.3",
|
|
43
|
+
"@srothgan/claude-code-rust-win32-x64-msvc": "0.14.3",
|
|
44
|
+
"@srothgan/claude-code-rust-win32-arm64-msvc": "0.14.3"
|
|
45
45
|
},
|
|
46
46
|
"engines": {
|
|
47
47
|
"node": ">=24"
|